Structs in Solidity: Best Practices for Gas Efficiency by 0xLazard

Lazard
CoinsBench
Published in
4 min readAug 18, 2023

--

How can we save a significant amount of gas in our smart contract, especially when using structs and functions that interact with them?

A primary concern for Solidity developers is how to minimize gas costs for both deploying the contract and for calls made by users when they interact with the contract.

In this topic, I will attempt to explain how to achieve optimal optimization for this contract, specifically focusing on populating the struct.

The Contract

The contract in question is fairly straightforward. It contains one struct named Pool Info, which holds various parameters of different data types such as uint, bool, and address. Specifically, there are two bool parameters (IsLaunch and IsFinish), one address parameter (token), and several uint parameters (allocation, totalClaimed, and fees for both deposits and withdrawals).

Newly created pools are added to the dynamic array named poolinfo. These pools are instantiated whenever the createpool() function is called.

GasOptimisation.sol without optimization.

To test and calculate the gas costs, I wrote a script in Solidity using Foundry. Foundry enables writing tests directly in Solidity, leading to improved execution speeds. Additionally, it facilitates the creation of fuzz tests and allows for gas snapshots. This helps pinpoint the exact gas cost of individual functions or even the overall contract.

GasOptimization.t.sol

The initial test reveals this. A significant amount of gas, precisely 128,448 gas, is consumed to call the createpool() function. Given the price of ETH at $1670 and a gas price of 47 gwei, the cost to call this function amounts to $10.08.

Result forge snapshot without optimization

Firstly, there’s room for minor optimization, especially when it comes to the data types of uints. For instance, the parameters depositfees and withdrawfees will always be less than 1000. Therefore, a more efficient choice for their data type would be uint16, which can represent values ranging from 0 to 65,535.

GasOptimization.sol with uint Deposit/Withdraw modified.

With, this modification 2156 gas, will be safe, in dollars this represented $9.91.

Result forge snapshot with minor optimization

But, if we look our struct, we could improve.

Struct PoolInfo()

Let’s take a closer look at our struct. In the realm of Solidity, one of the keys to optimizing gas costs and performance lies in how storage is managed. The sequence in which variables are declared plays a pivotal role, as the Ethereum Virtual Machine (EVM) reads and processes these variables based on that sequence. Grasping this dynamic is crucial for any developer aiming to fine-tune their contract.

For example, each variable in Solidity occupies a certain amount of space as seen in its bytecode. Here’s a breakdown of the space taken by different variables:

  • bool isLaunch: 32 bytes
  • uint allocation: 32 bytes
  • uint16 withdrawfees: 32 bytes
  • bool isFinish: 32 bytes
  • uint256 totalClaimed: 32 bytes
  • address token: 32 bytes
  • uint16 depositfees: 32 bytes

This adds up to a total of 224 bytes.

In Solidity, the sequence of variable declarations impacts gas usage. By strategically grouping variables by type, we can optimize storage allocation:

  • uint256: totalClaimed and allocation take up 64 bytes combined.
  • address: token occupies 32 bytes.
  • uint16: The combined storage of withdrawfees and depositfees is 32 bytes.
  • bool: Together, isFinish and isLaunch require 32 bytes.

Now the total will be 160 bytes.

GasOptimization.sol with optimize bytes

Now that we’ve restructured the struct and the createpool() function, let's examine the difference in terms of gas cost.

Result forge snapshot with optimize bytes

This results in a 36% reduction, with a gas cost of 82,147. The transaction cost is now $6.44, a savings of $3.64.

While these adjustments might seem subtle at first glance, the strategic organization of structs and the sequence of variable declarations can have a profound impact on efficiency and gas costs in Solidity.

I hope these topics has been helpful for those new to Solidity.

Thank you for reading! :Dddddd

My twitter https://twitter.com/0xLazard

--

--