To interact with an EVM (Ethereum Virtual Machine) blockchain, you will always have to pay gas fees. These fees can be frustrating as they can be very high. Let’s take a look at what exactly they are and how we can optimize our smart contract code to reduce gas fees.
What is Gas in Ethereum?
In the Ethereum documentation, gas is defined as follows:
“Gas refers to the unit that measures the amount of computational effort required to execute specific operations on the Ethereum network. Since each Ethereum transaction requires computational resources to execute, each transaction requires a fee. Gas refers to the fee required to conduct a transaction on Ethereum successfully.”
In other words, the more complex your code is the more it will cost.
Detailing how gas fees are calculated is complex and could be the subject of another post on its own. The most important formula to understand is:
Gas fees=Gas units*Gas price
Gas units are the total cost of computational operations measured in the unit called gas.
Gas price is the price of gas in gwei (10-9 ether). The gas price fluctuates depending on the Ethereum network utilization.
You can’t affect the gas price, so you need to focus on the gas units of your code to reduce them as much as possible.
How to Optimize Gas Fees
Gas optimization is simply favoring what is “cheap” to compute like local variables or constants and avoiding as much as possible what is “expensive” to compute like state variables stored in contract storage or loops.
Here are some tips to start optimizing your gas.
Tip #1: Don’t initialize variables
If the variable is not initialized, it is assumed to have a default value (0, false, 0x0, …). Initializing variables is then just a waste of gas.
Tip #2: Use local variables instead of state variables within loops
Reading and writing local variables is cheap, whereas reading and writing state variables that are stored in contract storage are expensive.
Tip #3: Use external and internal instead of public
external
means that you can call your function from outside your contract.internal
means that you can call your function from inside your contract.public
is a mix of external
and internal
, you can do both.
As external
and internal
grants less access than public
, they are cheaper.
We will then always prefer to use external
or internal
first and change it in public if needed.
Tip #4: Store data on memory, not storage
Choosing the perfect Data location is essential. You must know these:
- storage – variable is stored on the blockchain. It’s a persistent state variable. Costs Gas to define it and change it.
- memory – temporary variable declared inside a function. No gas for declaring. But it costs gas for changing memory variables (less than storage)
- calldata – like memory but non-modifiable and only available as an argument of external functions
If not specified data location is storage by default.
Tip #5: Order your variables
The order of your variables matters in Smart contracts. Solidity stores data in a single slot of 256 bits. If your variable is smaller than one slot, it is packed with another variable to be put in a single slot. But to do so, we need to make these variables next to each other.
Tip #6: Delete your variables to get a gas refund
This is also a great Solidity feature. Since there’s no garbage collection, you have to throw away unused data yourself. The goal here is to save space on the blockchain. The good news is that you’ll get 75% of your storing costs back.
Just use the keyword delete
.
Tip #7: Use nested if or multiple require instead of && operator
First for visibility, then because it is cheaper!
Tip #8: Use Solidity’s Optimizer
Make sure Solidity’s optimizer is enabled. It reduces gas costs. The default number is 200.
If you want to gas optimize for contract deployment (costs less to deploy a contract) then set the Solidity optimizer at a low number.
If you want to optimize for run-time gas costs (when functions are called on a contract) then set the optimizer to a high number.
Want to Hear More?
A free consulting meeting included.