Solidity Data Storage Location
Tags: solidity, dynamicdata, web3, smartcontract
Published: 2022-03-25 23:46:57

When we declare dynamic data types we need to specify the location to store them. Dynamic data types in Solidity are `arrays`, `strings`, `struct` etc. One of three locations of `storage`, `memory` and `calldata` are usually specified.

Using `storage` as a location means the data is stored on the blockchain while memory means the data is saved in `memory` and will be erased after the function in which it was declared has finished executing. The other location of `calldata` is used to stored variable that is passed as an input parameter to a function.

```solidity
 //SPDX-License-Identifier: Unlicense
pragma solidity >=0.7.0 <0.9.0;

contract StorageLocation {
    Person[] public persons;

    struct Person {
        string name;
        uint age;
        address personAddress;
    }

    constructor() {
       Person memory newperson = Person({
           name: "Jamie",
           age: 33,
           personAddress: msg.sender
       });

       Person memory personTwo = Person({
           name: "Bones Man",
           age: 33,
           personAddress: msg.sender
       });
       persons.push(newperson);
       persons.push(personTwo);
    }

    function loadPerson() public view returns ( Person[] memory ){
        return persons;
    }

    function changeDataone() public view {
        Person memory person = persons[0];
        person.age = 56;
    }

    function changeDataTwo() public {
        Person storage person = persons[0];
        person.age = 76;
    }

    function receiveAsCallData(uint256[] calldata a) public {
        //you can not modify a
    }
}
```
The smart contract above is a simple smart contract. At the top of the smart contract we defined an array of `Person` which is a user defined struct. The array of `Person` is stored in a variable called `persons`. The `persons` variable is stored on the blockchain because it is a state variable so therefore, it's location is `storage`.

Looking at the constructor function and you will see that there are two `Person` type created and pushed into the `Person[]` array called `persons`. The `newperson` variable inside the constructor is saved in memory and will be destroyed after the constructor function has finished running. After creating the newperson struct it was pushed into the `persons` array for permanent storage. The temporary `newperson` variable in memory will be discarded after the constructor function finish executing. 

Take a close look at both the `changeDataone` function and the `changeDataTwo`.You will notice that `changeDataone` function creates a variable named person and saved it to memory.

`Person memory person = persons[0];`
Doing it this way reads the data of the `persons` array at index of `0` and stores it in a person variable in memory. Attempting to change `person.age` to 56 will not be successful because we are not referencing the storage location of `persons`. At the termination of the function the `persons` storage variable remains the same because the data in memory has be wiped off. 

To persist the changes we make in a dynamic data type we must reference the storage location of that variable. The function `changeDataTwo` does that. Try it out on [Remix](http://remix.ethereum.org/)

When the contract is deployed, two `Person` struct is added to the `persons` array via the constructor which you can view by running `loadPerson`. Run the function `changeDataone` and observe if the first `Person` struct changed as explained. Then run the function `changeDataTwo` and you will notice that the `persons` variable was updated.

The third location `calldata` is used to pass input parameters to functions. Storing a variable in `calldata` means that the variable cannot be modified. Using `calldata` has the potential of saving some gas as the `EVM` does not copy over the data stored on it as it does when you used `memory` as a location.

## Summary
You make use of `memory` location when you want to read a dynamic data stored in state without modification or you need a temporary store for a dynamic data type.

You make use of `storage` when you want a reference to the dynamic data stored in state for the purpose of modification.

If you won't be changing the value of the dynamic data type passed as input to a function, you can make use of `calldata`. Using`calldata` helps to save gas because the `EVM` does not do a copy of the data.