Solidity Basics: Data Locations

Solidity Basics: Data Locations

Table of Content

  • Introduction

  • Storage

  • Memory

  • Stack

  • CallData

  • Summary

Introduction

In Solidity, every variable declared and used within a contract has a data location. The EVM(Ethereum Virtual Machine) allows us to store[data] variables in these four locations:

  1. Storage

  2. Memory

  3. Stack

  4. Calldata

Every declared variable is stored somewhere in these four data locations. However, where a variable is stored depends on its type and scope(where it is declared).

Storage

Storage is a global memory available to all functions and variables within a contract. Any variable(or data) stored in storage is essentially stored on the blockchain (i.e. every node within the Ethereum environment), The variable can be modified but its location can't be changed.

Example:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract Storage {

    // state variable stored in storage
    uint[2] stateArray = [uint(1), 2];

    // access stateArray from storage
    function StorageExample() public view returns(uint) {
        return stateArray[0]; // 1
    }
}

In the preceding code, the global stateArray variable is declared in the contract's global scope, which means it's stored in Storage and can accessed by any function within the contract.

Memory

Memory is a type of memory that can only be used within the scope of function. Variables declared within a function are only saved to memory temporarily—EVM deletes their location from memory after the function executes.

Example:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract Memory {

    function MemoryExample() public pure returns(uint) {

        // stored in Memory
        uint[2] memory localArray = [uint(2), 4];

        return (localArray[0]); // 2
    }
}

In the preceding code, the localArray is declared and stored locally in the MemoryExample function via memory keyword.

Stack

The Stack is also a temporary storage like memory. It can only be accessed by a function during execution. To store a variable on the Stack you simply declare it in a function without a keyword.

Example:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract Stack {

    function StackExample() public pure returns(uint) {

        // stored in Stack
        uint x = 4;

        return (x); // 4
    }
}

It is good practice to minimize the number of variables stored on the Stack because of its limited size(It has a maximum size of 1024 elements and contains words of 256 bits) to avoid stack overflow.

Calldata

According to the solidity documentation:

Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory.

Calldata is simply where all incoming data to a function is stored, including arguments(which are the only variables stored in Calldata). It is a temporary memory location that depends on a function execution—Just like Memory and Stack. However, it is a non-modifiable memory location, which means variables(i.e. function arguments) stored here can't be modified.

Example:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract CallData {

    function calldataExample(string calldata x) external pure returns(string memory) {

        // value passed to the x argument
        return x;
    }
}

A function that uses calldata must use the extenal visibility keyword(as seen in the preceding code). Using calldata instead of memory for function arguments is more gas efficient.

Summary

In solidity, where a variable is stored is determined by two factors:

  • The location where the variable is declared(i.e global contract scope or function scope)

  • The data type of the variable(i.e. value or reference).

Note, the data location of a variable is important not only for the persistence of data but also for the semantics of assignment— i.e. the data location and type of a variable affects how the assignment operator(i.e. =) operates on it. Learn more about data location and assignment behavior from the solidity docs.