Skip to content

Malinariy/Solidity-gas-optimizations-tips

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 

Repository files navigation

Gas optimizations tips found in open source audits 💡

REQUIRE()/REVERT() STRINGS LONGER THAN 32 BYTES COST EXTRA GAS

def utf8len(s):
    return len(s.encode('utf-8'))

utf8len('FCash to redeem must be an index component')

PRIVATE FUNCTIONS NOT CALLED BY THE CONTRACT SHOULD BE REMOVED TO SAVE DEPLOYMENT GAS


PUBLIC FUNCTIONS NOT CALLED BY THE CONTRACT SHOULD BE DECLARED EXTERNAL INSTEAD


⬜ ADDING UNCHEKED DIRECTIVE CAN SAVE GAS

For arithmetic operations that will not owerflow/underflow anyone, use unchecked, this will help save gas from unnecessary > owerflow/underflow checks in solidity version starting with 0.8


array.length SHOULD NOT BE LOOKED UP IN EVERY LOOP OF FOR-LOOP

Reading array length at each iteration of the loop takes 6 gas


++i COSTS LESS GAS COMPARED TO i++ OR i += 1 (SAME FOR --i VS i-- OR i -= 1) Increment:

  • i += 1 is the most expensive form
  • i++ costs 6 gas less than i += 1
  • ++i costs 5 gas less than i++ (11 gas less than i += 1) Decrement:
  • i -= 1 is the most expensive form
  • i-- costs 11 gas less than i -= 1
  • -i costs 5 gas less than i-- (16 gas less than i -= 1)

⬜ USE address(0) INSTEAD OF 0x00000000000000000000000000000000000000000000000000000000000000


⬜ CHECK IF AMOUNT > 0 BEFORE TOKEN TRANSFER CAN SAVE GAS

It worth cheking the AMOUNT ≠ 0, before the transfer can create an external call and spend unnecessary gas cost


> 0 CAN BE REPLACED WITH != 0 FOR GAS OPTIMIZATION

!= 0 is a cheaper operation compared to > 0, when dealing with uint


⬜ CONSIDER MAKING SOME CONSTANTS AS NON-PUBLIC TO SAVE GAS

Switching from public to private/internal can save gas when the constant is not used outside od its contract


⬜ UNUSED NAMED RETURN VARIABLES - 3 gas per instance


⬜ CONSTRUCTOR PARAMETERS SHOULD BE AVOIDED WHEN POSSIBLE

Constructor parameters are expensive. The contract deployment will be cheaper in gas if they are hard coded instead of using constructor parameters


⬜ CALLDATA INSTEAD OF MEMORY FOR READ-ONLY FUNCTION PARAMETERS

If a reference type function parameter is read-only, it is cheaper in gas to use calldata instead of memory. (Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory)


⬜ CACHING STORAGE VARIABLES IN MEMORY TO SAVE GAS

Anytime you are reading from storage more than once, it is cheaper in gas cost to cache the variable in memory: a SLOAD cost 100gas, while MLOAD and MSTORE cost 3 gas.


uint256 instead of uint8

The EVM works with 256bit/32byte words. Every operation is based on these base units. If the data used is smaller, further operation are needed to downscale from 256 bits to 8 bits.


X = X + Y IS CHEAPER THAN X += Y (Same for X = X - Y is cheaper than X -= Y)

X += Y costs 3,more gas than X = X + Y.


⬜ UNNECESSARY COMPUTATION

Gas can be saved by avoiding using local variables when they are not necessary.


⬜ AVOID A SLOAD OPTIMISTICALLY - 2.1k gas saved


⬜ CHECK msg.value FIRST - 1 gas per instance

Reading msg.value costs 2 gas, while reading from memory costs 3, this will save 1 gas with no downside if (weth == asset && msg.value > 0) change to if (msg.value > 0 && weth == asset)


⬜ MIXING RETURN AND NAMED RETURNS

Using both named returns and a return statement isn't necessary. Removing unused named return variables can reduce gas usage (MSTOREs/MLOADs) and improve code clarity. To save gas and improve code quality: consider using only one of those.


⬜ INLINE A MODIFIER THAT’S ONLY USED ONCE

If modifier is only used once in this contract, it should get inlined to save gas


⬜ USE abi.encodePacked() not abi.encode()


⬜ USE NESTED IF AND, AVOID MULTIPLE CHECK COMBINATIONS

Using nested if cheaper then using && multiple check combinations. There are more advantages, such as easier to read code and better coverage reports.


⬜ UNINITIALIZED VARIABLES ARE ASSIGNED WITH THE TYPES DEFAULT VALUE

Explicitly initializing a variable with it's default value costs unnecesary gas


⬜ USE CUSTOM ERRORS INSTEAD OF REVERT STRINGS TO SAVE GAS

Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met) while providing the same amount of information


⬜ STATE VARIABLES ONLY SET IN THE CONSTRUCTOR SHOULD BE DECLARED IMMUTABLE

Avoids a Gsset (20000 gas) in the constructor, and replaces each Gwarmacces (100 gas) with a PUSH32 (3 gas).


INTERNAL FUNCTIONS ONLY CALLED ONCE CAN BE INLINED TO SAVE GAS

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.


⬜ OPERATORS: AND/OR

When having a require statement with 2 or more expressions needed, place the expression that cost less gas first. For example:

  • require ( A || B ): If a is true, Solidity compiler won’t check the next statement because it’s not needed.
  • require ( A && B ): If a is false, Solidity compiler won’t check the next statement because it’s not needed. In this examples, the best approach would be placing the cheapest expression as A.

⬜ Always try reverting transactions as early as possible when using require statements (most preferably before writing in storage).

In case a transaction revert occurs, the user will pay the gas up until the revert was executed (not afterwards).


⬜ USE mapping INSTEAD OF array (5000 gas saved per value)

Mappings are usually less expensive than arrays, but you can’t iterate over them.


⬜ USE require INSTEAD OF assert

Assert should NOT be used by other mean than testing purposes. (because when the assertion fails, gas is NOT refunded contrary to require)


⬜ Look for dead code (saves a variable amount of gas on deployment)

Sometimes, developers forget to remove useless code like:

require(a == 0)
if (a == 0) {
  return true;
} else {
  return false
}

⬜ STORING DATA IN events (up to 20 000 gas saved on function call)

If you don’t need to access the data onchain in solidity, you can store it using events.


About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published