Solidity Data locations | storage — memory — calldata
Data location is an important topic in programming field, where you need to know where are your variables stored, and how can you access it.
In solidity, which is the programming language used to write smart contracts on Ethereum virtual machine, you have three options where you can store you variables, these options are:
- storage
- memory
- calldata
We will discuss the difference between them, and when to use each on of them.
Storage
In storage
all state variables are stored (the variables that are declared on contract level), here is an example:
contract MyContract {
uint256 public myNumber; // this variable is in storage by default
}
Storage means that the variable is stored in the blockchain, where each contract has its own separate storage space, which is in the form of an array of 2^256 32-byte values, all initialized to zero.
Memory and Calldata
Otherwise, memory
and calldata
are used to store temporary variables, variables that are needed in function scope only.
You can think of it like storage
is the Hard Disk that uses to store data permanently, while memory
and calldata
are the RAM which stored temporarily.
Ok, what is the difference between them?
The difference is: in memory
you can modify the data (change the value of the variable), but in calldata
you can’t (you can just read the value), let’s take an example:
function printHelloName(string memory _name)
public
pure
returns (string memory)
{
_name = string.concat("Hello ", _name);
return _name;
}
In this example we changed _name
value and returned it, and the function worked without any problems.
function printHelloName(string calldata _name)
public
pure
returns (string calldata)
{
_name = string.concat("Hello ", _name); // TypeError: Type literal_string "hello" is not implicitly convertible to expected type string calldata.
return _name;
}
If you tried to make it using calldata
it will give you an error, since calldata
can’t be changed.
You can use calldata
if you will not change the variable, as in the following example:
function printHelloName(string calldata _name)
public
pure
returns (string calldata)
{
return _name;
}
In this example, we are not changing the variable _name
value, so you can make it of type calldata
, and you can make return type calldata
, since you are returning only _name
variable.
NOTE: return type can differs from the parameter value type, here is an example:
function printHelloName(string calldata _name)
public
pure
returns (string memory)
{
return string.concat("Hello" ,_name);
}
As you can see, we didn’t make any change to _name
variable, so we made it of type calldata
, but on the otherside, the returned value is not of type calldata
now, as we are returning "Hello" + _name
, so we should make the return string of type memory
.
Another thing you should now is that any calldata
can be of memory
type since calldata
is more restricted than memory
, so you can use memory
. But you can not replace memory
by calldata
.
Recap
- Solidity data locations are: storage, memory, and calldata
storage
is for storing variables permanently in the blockchainmemory
andcalldata
are used to store temporary variables- You can edit
memory
variable type notcalldata
- Any
calldata
can bememory
and not vice verca