Learning Objectives – after this chapter you will be able to:
  • Differentiate state, local and global variables.
  • Use constant and immutable to save gas.
  • Choose between the storage, memory and calldata data locations.
  • Predict whether an assignment copies data or creates a reference.
Three Kinds of Variables
KindWhere declaredWhere stored / lifetimeGas
StateAt contract level, outside functionsPermanently in the contract’s storage on the blockchainExpensive to write
LocalInside a functionOnly while the function runs (stack or memory)Cheap
GlobalPre-defined by SolidityProvide information about the blockchain and the call, e.g. msg.sender, block.timestamp (Chapter 14)Reading is cheap
State Variables
  • Declared at contract level.
  • Permanently stored in contract storage, so their values remain between function calls and transactions.
  • Writing (and the first read in a transaction) is expensive because the data is kept by every node.
  • They can be initialised at declaration, in the constructor, or later by calling setter functions.
  • They can be declared constant or immutable (see below).
Local Variables
  • Declared inside functions (including function parameters and return variables).
  • Value-type local variables (uint, bool, address …) need no location keyword – they live on the EVM stack.
  • Reference-type local variables (string, bytes, arrays, structs) must specify a data location: memory, storage or calldata.
  • The keywords memory and calldata cannot be used for state variables – state variables are always in storage.
Constant and Immutable
KeywordWhen is the value set?Can it change?Benefit
constantFixed in the source code at compile timeNeverNo storage slot; cheapest to read
immutableAssigned once, in the constructor (or at declaration)Never after deploymentStored in the contract code, not storage; cheap to read
Data Locations : storage, memory, calldata
LocationLifetimeModifiable?Typical use
storagePermanent (on the blockchain)YesState variables; local pointers to state data
memoryOnly during the function call – wiped afterwards (like RAM)YesTemporary strings, arrays and structs; return values
calldataOnly during the call; holds the call’s input dataNo (read-only)Parameters of external/public functions – cheapest because no copy is made
Copy or reference?
  • storage → memory: makes an independent copy; changing the copy does not change the state.
  • storage → local storage variable: creates a reference (pointer); changes update the state variable.
  • memory → memory: creates a reference to the same memory data.
Example : Variables and Data Locations
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract VariablesDemo {
    uint256 public constant MAX_STUDENTS = 60;   // constant: fixed at compile time
    address public immutable admin;               // immutable: set once in constructor
    string[] public students;                     // state variable (storage)

    constructor() {
        admin = msg.sender;                       // msg.sender is a global variable
    }

    function addStudent(string calldata name) external {   // calldata: read-only input
        require(students.length < MAX_STUDENTS, "Class is full");
        students.push(name);
    }

    function renameCopy(uint i) external view returns (string memory) {
        string memory copy = students[i];         // storage -> memory = COPY
        return copy;                              // state is not changed
    }

    function renameInPlace(uint i, string calldata newName) external {
        string[] storage list = students;         // storage pointer = REFERENCE
        list[i] = newName;                        // updates the state variable
    }

    function total(uint a, uint b) external pure returns (uint) {
        uint sum = a + b;                         // local value-type variable (stack)
        return sum;
    }
}
Key Takeaways
  • State variables live in storage permanently; local variables exist only during the call.
  • Use constant/immutable for values that never change – they save gas.
  • Reference types need a location: storage (permanent), memory (temporary), calldata (read-only input).
Download | Print      E-Notes

The PDF E-Notes are the earlier printable version of this chapter. The notes on this page are the latest, revised version.

Video : Solidity Variables and Data Locations
Resource File
Question / Answer (15 questions)

Answer : State variables (declared at contract level and stored permanently in storage), local variables (declared inside functions and existing only during the call) and global variables (pre-defined values such as msg.sender and block.timestamp).

Answer : State variables are stored in the contract’s storage on the blockchain. Every node must keep that data permanently, so writing to storage costs much more gas than working with temporary data.

Answer : At declaration (e.g. uint x = 5;), inside the constructor at deployment, or later through a setter function called by a transaction.

Answer : A constant’s value is fixed in the source code at compile time. An immutable variable is assigned once at deployment, normally in the constructor. Neither can change afterwards, and neither occupies a storage slot, so both are cheap to read.

Answer : storage (permanent, on-chain), memory (temporary, exists during the function call and can be modified) and calldata (temporary and read-only, holds function input data).

Answer : calldata is read directly from the transaction input without copying it into memory, and it cannot be modified, which avoids extra copy operations.

Answer : No. Value types such as uint, bool and address live on the EVM stack; only reference types (string, bytes, arrays, structs) need storage, memory or calldata.

Answer : No. State variables are always stored in storage; memory and calldata can only be used for local variables, parameters and return values.

Answer : An independent copy is created in memory. Changing the memory copy does not change the state variable.

Answer : The local variable becomes a reference (pointer) to the state variable, so changes made through it update the stored state.

Answer : string is a reference type of dynamic size, so the compiler must know where the data lives during the function call; memory or calldata (for parameters) must be stated explicitly.

Answer : msg.sender (address of the current caller) and block.timestamp (timestamp of the current block). Others include msg.value and block.number.

Answer : Memory exists only for the duration of an external function call; once execution finishes it is cleared, similar to RAM.

Answer : Its value (60) never changes, so declaring it constant avoids a storage slot and makes every read cheaper.

Answer : When the value is only known at deployment (for example the admin address taken from msg.sender) and never changes afterwards; immutable saves gas on every read.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. Which data location is READ-ONLY?

Show Answer

Correct Answer : C. calldata
calldata holds function input and cannot be modified.

Q2. A variable declared at contract level outside any function is a:

Show Answer

Correct Answer : A. State variable
Contract-level variables are state variables stored in storage.

Q3. Which keyword declares a value assigned once in the constructor and never changed?

Show Answer

Correct Answer : D. immutable
immutable values are set at deployment; constant values are set at compile time.

Q4. Assigning a storage array to a memory variable:

Show Answer

Correct Answer : B. Creates an independent copy
storage → memory always copies.

Q5. Which of these is a global variable?

Show Answer

Correct Answer : C. msg.sender
msg.sender is provided by the environment.

Bibliography/References

The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.

  1. Solidity Team. (n.d.). Types (value types, reference types, mappings, operators, conversions). Solidity Documentation. https://docs.soliditylang.org/en/latest/types.html
  2. Solidity Team. (n.d.). Contracts (creating contracts, visibility and getters, function modifiers, constant and immutable, functions, events, custom errors, inheritance, abstract contracts, interfaces, libraries). Solidity Documentation. https://docs.soliditylang.org/en/latest/contracts.html
  3. Solidity Team. (n.d.). Layout of State Variables in Storage. Solidity Documentation. https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html
  4. Solidity Team. (n.d.). Units and Globally Available Variables. Solidity Documentation. https://docs.soliditylang.org/en/latest/units-and-global-variables.html
  5. Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.