In the dynamic world of blockchain technology, optimizing gas usage in Solidity smart contracts is crucial for maintaining efficiency and cost-effectiveness. In this article, we will explore twenty-four techniques that can help reduce gas fees when deploying contracts. Each technique is backed by testing results obtained using the Foundry framework, led by the expert [@0xKaso](https://github.com/0xKaso).
1. Use Constant and Immutable
Using constant
and immutable
variables instead of regular state variables can lead to significant gas savings. This is akin to having a preset phone number that saves you time dialing it rather than looking it up each time.
Code available here.
Testing
Run the command below to test:
forge test --contracts 01_ConstantConstant.t.sol --gas-report
2. Use Calldata Over Memory
When handling function parameters, choosing calldata
over memory
can optimize gas costs significantly. Think of calldata
as a library, where you reference books without storing them within your own shelves, saving space and time.
Code available here.
Testing
Run the command below to test:
forge test --contracts 02_CalldataAndMemoryCalldataAndMemory.T.sol --gas-report
3. Use Bitmap
Using bitmap structures can be a more gas-efficient alternative to boolean arrays, much like using a compact file format instead of a bulky document.
Code available here.
Testing
Run the command below to test:
forge test --contracts 03_BitmapBitmap.T.sol --gas-report
4. Use Unchecked
If you are certain that no underflows/overflows will occur, using unchecked
can yield noticeable gas savings. This technique resembles confident driving, where you’re aware of the road conditions ahead.
Code available here.
Testing
Run the command below to test:
forge test --contracts 04_uncheckedUnchecked.T.sol --gas-report
5. Use uint256 Over uint8
Opt for uint256
instead of smaller integers like uint8
. This choice reduces the complexity associated with packing variables, much like choosing to use a large truck instead of multiple small cars to transport goods.
Code available here.
Testing
Run the command below to test:
forge test --contracts 05_UintUint.T.sol --gas-report
6. Use Custom Error Over Require/assert
Incorporating custom errors instead of require
and assert
statements can lead to decreased gas costs, similarly to offering a custom troubleshooting route instead of a generic map.
Code available here.
Testing
Run the command below to test:
forge test --contracts 06_ErrorError.T.sol --gas-report
7. Use Local Variable Over Storage
Utilizing local variables can save gas in comparison to storage variables. Imagine using your hand to pick up an object instead of moving an entire box to get to it.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 07_LocalDataLocalData.T.sol --gas-report
8. Use Clone Over new/Create2 to Deploy Contracts
Choosing a clone
instead of new
or create2
can minimize gas expenditures when deploying similar contracts, akin to using a photocopier rather than creating every document from scratch.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 08_CloneClone.T.sol --gas-report
9. Packing Storage Slots
Packing multiple smaller variables into a single storage slot enhances gas efficiency, similar to neatly packing items in a suitcase to maximize space.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 09_PackingPacking.T.sol --gas-report
10. Use ++i as Better Increment
Using the increment operator ++i
is often slightly more gas-efficient than i++
, comparable to moving ahead in line rather than waiting for someone behind you.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 10_IncrementIncrement.T.sol --gas-report
11. Use Uint in Reentrancy Guard
Using an uint
type in reentrancy guards can lead to better gas performance. This can be compared to utilizing a more straightforward tool to swiftly complete a task.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 11_ReentrancyGuardReentrancyGuard.T.sol --gas-report
12. Use Less Than Over Equals
When comparing values, using less than
instead of equals
could yield slight gas savings, resembling a quicker decision in a game of chess.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 12_LessThanLessThan.t.sol --gas-report
13. Optimized Selector
Utilizing optimized function selectors can reduce gas costs, much like using a more direct route to your destination.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 13_MethodNameMethodName.t.sol --gas-report
14. Selector/Method-ID Order Matters
The order of selectors can impact gas efficiency, akin to arranging items in a list from most to least important to streamline tasks.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 14_MethodIdSortMethodIdSort.t.sol --gas-report
15. Use Shorter String in Require()
Shortening strings within require()
could improve gas costs, much like giving a concise answer to save time.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 15_RequireStringRequireString.t.sol --gas-report
16. Short Circuit in Logic Operation
Implementing short-circuit evaluation in logical operations can save gas, much like taking a shortcut to avoid traffic.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 16_ShortCircuitShortCircuit.t.sol --gas-report
17. Delete Variables to Get Gas Refund
Deleting unused variables can lead to gas refunds, similar to getting cash back on a return.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 17_DeleteVarDeleteVar.t.sol --gas-report
18. Do Not Initialize State Variables with Default Values
Avoiding the initialization of state variables with default values can help save gas, akin to turning off lights in rooms you aren’t using.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 18_InitDefaultInitDefault.t.sol --gas-report
19. Swap 2 Variables in 1 Line with Destructuring Assignment
Although using destructuring assignment doesn’t save gas, it cleans up your code, making it more readable, like neatly organizing your belongings.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 19_SwapVarsSwapVars.t.sol --gas-report
20. Set Constructor to Payable to Save Gas
A payable constructor can eliminate several opcodes during contract creation, yielding gas savings. Think of it as streamlining an assembly line for efficiency.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 20_PayableConstructorPayableConstructor.t.sol --gas-report
21. Use Bytes32 for Short Strings
Utilizing bytes32
for short strings can be more gas efficient, much like choosing robotic vacuums for easy clean-up rather than large cumbersome ones.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 21_Bytes32StringBytes32String.t.sol --gas-report
22. Use Fixed-size Array Over Dynamic Array
Opting for fixed-size arrays over dynamic ones can yield gas savings, akin to having a predetermined number of boxes for storage rather than an infinite supply.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 22_FixedSizeFixedSize.t.sol --gas-report
23. Use Event to Store Data When Possible
Storing data in events can often be cheaper than storage variables, like choosing to store your memories in an album rather than cluttering your home.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 23_EventEvent.t.sol --gas-report
24. Use Mapping Over Array When Possible
Using mappings provides efficient gas usage, similar to having a personalized storage area over a common one where you have to search through more items.
Code available here.
Testing
Run the command below to test:
bash forge test --contracts 24_MappingArrayMappingArray.t.sol --gas-report
Troubleshooting
If you encounter high gas costs while testing your Solidity contracts, consider reviewing the aforementioned optimization techniques. Some common tips include:
- Reassess data types (e.g., prefer
uint256
overuint8
) - Ensure optimal variable visibility (e.g.,
constant
andimmutable
) - Utilize less complex structures, such as
mappings
instead ofarrays
For more insights, updates, or to collaborate on AI development projects, stay connected with **fxis.ai**.
Conclusion
At **fxis.ai**, we believe that such advancements are crucial for the future of AI, as they enable more comprehensive and effective solutions. Our team is continually exploring new methodologies to push the envelope in artificial intelligence, ensuring that our clients benefit from the latest technological innovations.