WTF Gas Optimization: Mastering Solidity Gas Optimization Techniques Verified with Foundry

Sep 24, 2023 | Blockchain

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 over uint8)
  • Ensure optimal variable visibility (e.g., constant and immutable)
  • Utilize less complex structures, such as mappings instead of arrays

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.

Stay Informed with the Newest F(x) Insights and Blogs

Tech News and Blog Highlights, Straight to Your Inbox