Solidity tips and tricks #2: Avoid storage data mutations and operations

EVM has three types of data storage locations: 

  • Storage
  • Memory
  • Calldata

Each data location has a different purpose and using them appropriately will save us gas and money. Keep in mind that, in some situations, Solidity strictly enforces a default location.

Storage

When placed in storage, a variable is written on the blockchain. Everything that is on the chain, stays there. Every contract has its own storage, so these variables are persistent. To explain simply, the variables stored in storage will have a lifetime scope of a contract. Its value is the same for all calls to the contract.

Memory

Variables stored in memory are declared inside a function. They are temporary and their ‘lifetime’ is dependent on the runtime of the function they correspond to. They are only accessible inside that method. Their purpose is to assist local logic inside function blocks. 

Calldata

Calldata is also a temporary data location in Solidity. It acts like memory, in terms of its block scope. The variables stored in calldata are only available inside the function they were declared in.

Now, it’s obvious from the above definitions that changing storage data costs a lot more gas than changing memory or calldata variables. So we should minimize the number of times we are modifying the storage data. Especially in the case of loops. 

The following solidity code will help you understand the difference between a poor code and better – optimized code.

// Solidity program to demonstrate
// how modifying storage items is expensive
pragma solidity ^ 0.8.5;
contract StorageVariableDemo
{
uint public temp;
/*
* @description:Below function runs the for loop 100 times and updates
* storage variable temp each time.
*/
function expensiveFunction() external {
for (uint i = 0; i < 100; i++){
temp++;
}
}
/*
* @description: Below function runs the for loop 100 times and
* memory variable 100 times. This memory variable is then assigned back to temp.
*/
function cheaperFunction() external {
uint j = temp;
for (uint i = 0; i < 100; i++){
j++;
}
temp = j;
}
}

Want some proof? Here we go: 

Call for cheaperFunction():

Call for expensiveFunction(): 

Unlike first tips and tricks article, this solidity tip is fairly simple however, can make your contracts pretty expensive in terms of interactions. Do follow on twitter or linkedIn for more such informative and hopefully not so boring content.


Discover more from BitsByBlocks

Subscribe to get the latest posts sent to your email.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Discover more from BitsByBlocks

Subscribe now to keep reading and get access to the full archive.

Continue reading