# 10 Simple Ways to Save Gas with Solidity

--

Below is a list of just a few simple ways you can save gas in solidity contracts. The full list is seemingly endless, but all boils down to finding the most efficient way to perform an action with the minimum number of operations.

1. State data vs bytecode data
2. The power of do-while vs for loops
3. i++ vs ++i
4. Ignore safe maths — unchecked{}
5. Sticking to preferred data types
6. Calldata vs memory
7. Use memory to cache read variables
8. Efficient variable management
9. Save gas on the first write
10. Calling struct data

## 1. State data vs bytecode data

By storing `_b` as a constant it is stored as immutable data in the contract’s bytecode. The same goes for our magic number `1000`. `_a` on the other hand is stored in the contract’s state and requires a `SLOAD` operation to read it .

## 2. The power of do-while vs for loops

Loops are pretty standard in almost every coding language and that familiarity can make us complacent.

The standard `for loop` will check the condition before executing the statement. A `do while` will execute the statement at least once before and then check the conditions, allowing for gas savings.

Word of warning: Only use a do-while when you are certain the code should execute at least once and remember to handle your conditions to prevent an infinite loop and gas out.

For information on how do-while loops differ from while loops, check out this article:

## 3. i++ vs ++i

I know, I know, its a little crazy looking but the numbers dont lie — but why is it cheaper?

`i++` increments the value of `i` by storing the original value in memory, incrementing it, then storing the resulting value into temporary memory and returning the original value. Upon that return the new value of `i` is updated. All in all it takes 4 operations.

`++i` increments the value of `i` and returns that value, which takes 2 operations.

## 4. Ignore safe maths — unchecked{}

From Solidity docs:

https://docs.soliditylang.org/en/v0.8.0/control-structures.html#checked-or-unchecked-arithmetic

Prior to Solidity 0.8.0, arithmetic operations would always wrap in case of under- or overflow leading to widespread use of libraries that introduce additional checks.

Since Solidity 0.8.0, all arithmetic operations revert on over- and underflow by default, thus making the use of these libraries unnecessary.

To obtain the previous behaviour, an unchecked block can be used:

Which means you can save gas by employing the `unchecked` block to avoid unnecessary checks on your `++i`.

In the example code above it is safe to do this because we know `++i` will not overflow 2²⁵⁶, both of our loops will stop processing when `i == 200`

## 5. Sticking to preferred data types

EVM (Ethereum Virtual Machine) is driven by 256 bit (32 bytes) variables. This means that in our loop above, the `uint16` variable is converted to a `uint256` before it is used, this conversion costs gas.

As you can see, we save gas by using `uint256` for the variable `i`.

## 6. Calldata vs memory

From Solidity docs:

https://docs.soliditylang.org/en/v0.5.11/types.html?highlight=memory#data-location

Calldata is only valid for parameters of external contract functions and is required for this type of parameter. Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory.

Its is suggested to try and use calldata where possible. It avoids unnecessary copies, hence the lower gas price and ensures the data is immutable.

Worth noting that since solidity 0.6.9 usage of `memory` and `calldata` is not limited by the visibility of the function.

For more details about the differences between `storage`, `memory` and `calldata` checkout this article:

## 7. Use memory to cache read variables

Accessing a cold storage variable (first read) costs `2100 gas` and `100 gas` there after — warm storage access

You can save gas by caching the storage variable and reading the cached data instead of the storage data. This also works when reading data from a storage array.

In the above example we are storing `_arr` in memory of `SaveGas2 > loop()`. All reads are then called from our new `arr`.

This is a great gas saving method as long as the storage array is not too big. The data has to be copied to memory, so big arrays will be inefficient.

## 8. Efficient variable management

If you plan on reusing a variable like `solution` and you know it will not inherit value from the previous loop, you can save gas by defining the variable outside of the loop — compare loops in `SaveGas` and `SaveGas2`.

Additionally, if you know there is no risk of overflow you can save more gas by nesting your `solution` calculation within the `unchecked` block.

## 9. Save gas on the first write

Changing a storage value to non-zero from a zero value will cost `20000 gas` and all non-zero nth writes will cost `5000 gas`. We can save the first user to call the function some gas by defining a non-zero value for `_data`.

## 10. Calling struct data

EVM stores data sequentially, trying to pack everything into 256 bit slots (32 bytes). In the example above, the struct data is arranged so `x` and `y` will occupy a single 256 bit memory slot and `z` will occupy its own slot — nice and tidy.

When it comes to reading our values we can save gas by minimizing how many memory slots we have to read and or cache.

`SaveGas > getUserZ()` is storing the relevant `MyData` struct in memory — making a copy of both memory slots and then reading the relevant data.

`SaveGas2 > getUserZ()` is reading data from the single memory slot containing `z`.

# Where to find me

I can normally be found in the Cool Cats discord channel
https://discord.gg/WhBAAHnSz4