Mo Ashouri
3 min readApr 15, 2022

--

Optimizing your smart contract code can be valuable in decreasing gas fees, making your smart contracts more advantageous. If you’ve ever used smart contracts on Ethereum, you know how painful outrageous fees can be. Even when you use other chains, such as BNB Chain, which offers low fees, transactions can add up. Therefore, knowing how to execute Solidity gas optimizations will significantly aid your Dapps. Furthermore, because Solidity applies to all EVM-compatible blockchains (e.g., MATIC, TRON, Avalanche, etc.) in this article, I will introduce some coding tricks on gas optimizations in Solidity. Note that you can also apply these techniques to Solana, Algorand, and other ecosystems.

The tricks are as follows:

  1. Using calldata
  2. Short-circuiting
  3. Loop increment
  4. Loading local state variables into local variables (memory)
  5. Loading array slots into memory

Before we get started with our optimization tricks, take a look at the GasOptmized contract and my comments in the code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract GasOptimized{ uint public sum; function Is_Even(uint[] memory numbers) external {
for(uint i=0; i< numbers.length; i+=1){
bool isEven=numbers[i] % 2 ==0;
bool isLess99 = numbers[i] < 99;
if(isEven && isLess99){
sum+=numbers[i];
}
}
}

If you compile and deploy the contract on Remix, and then execute the function, you will see the transaction cost, before the optimization tweaks, is 50970, keeping this number in mind, let’s start working on the optimization and see how much gas we can save!

Trick 1: Change memory to calldata in the function argument

function Is_Even(uint[] calldata numbers) external { // calldata      for(uint i=0; i< numbers.length; i+=1){          bool isEven=numbers[i] % 2 ==0;
bool isLess99 = numbers[i] < 99;
if(isEven && isLess99){
sum+=numbers[i];
}
}
}

Now if you compile and deploy the contract and execute the Is_even function the transaction cost is 49141 gas. So far we saved 1829 gas!

Trick 2: Short-Circuiting!

function Is_Even(uint[] calldata numbers) external {

uint _sum=sum;
for(uint i=0; i< numbers.length; i+=1){
// bool isEven=numbers[i] % 2 ==0; --> short circuiting
// bool isLess99 = numbers[i] < 99; --> short circuiting
if(numbers[i] % 2 ==0 && numbers[i] < 99){
_sum+=numbers[i];
}
}
sum=_sum; }

Short-circuiting means reducing the code calculation in the logical comparisons, for example, in the above code we do have an IF statement, which AND two conditions. Since her we use the AND operation, if one of the statements is false, we do not need to calculate the other statement. Thus, we remove the booleans variables holding the pre-calculated statements and bring the calculations inside of the if condition.

Now we got the transaction cost of 48612, which helped us to save 2356 gas!

Trick 3 Loop Increment!

function Is_Even(uint[] calldata numbers) external {          uint _sum=sum;
for(uint i=0; i< numbers.length; ++i){ // --> loop increment
// bool isEven=numbers[i] % 2 ==0;
// bool isLess99 = numbers[i] < 99;
if(numbers[i] % 2 ==0 && numbers[i] < 99){
_sum+=numbers[i];
}
}
sum=_sum;

}

After a simple tweak in the loop increment section, the transaction cost of the function becomes 48222, which saved us 2748 gas! Not bad : →

Trick 4: Loading local state variables into memory!

function Is_Even(uint[] calldata numbers) external {
uint _sum=sum; // < -- check here
uint _len=numbers.length;
for(uint i=0; i< _len; ++i){

// bool isEven=numbers[i] % 2 ==0;
// bool isLess99 = numbers[i] < 99;
if(numbers[i] % 2 ==0 && numbers[i] < 99){
_sum+=numbers[i];
}
}
sum=_sum; // and here <---

}

All right, the transaction cost was reduced to 48187 (saved 2783!)

Trick 5: Loading array slots into memory

function Is_Even(uint[] calldata numbers) external {           //loading the local state into the local variable (memory)           uint _sum=sum;           uint _len=numbers.length;           for(uint i=0; i< _len; ++i){ // --> loop increment              // bool isEven=numbers[i] % 2 ==0;
// bool isLess99 = numbers[i] < 99;
uint num=numbers[i]; // caching an array slot into memory if(num % 2 ==0 && num < 99){
_sum+=num;
}
}
sum=_sum;

}

After doing this trick, the transaction cost was reduced to 48025! And we saved 2945 gas!

As you can see by doing some simples tricks not only our code looks smarter but also it becomes more affordable and efficient!

There are other tricks as well, and I will introduce them in my future articles!

--

--

Mo Ashouri

Mo has a Ph.D. in Compter Science. Mo specializes in Backend Programming and Security.