Storage Locations and Copy Mechanisms: storage, memory, calldata

Storage Locations and Copy Mechanisms: storage, memory, calldata

Learning Objectives

Understand the characteristics of the three data storage locations in the EVM, and the copy rules for assigning reference types between different storage locations.

Prerequisites

Familiarity with value types and reference types (arrays, structs, mappings, strings).


Three Storage Locations

storage — Persistent Storage

  • Similar to a database, data is permanently stored on the blockchain.
  • Member variables (state variables) are stored in storage by default.
  • Highest gas cost for reading and writing.

memory — Temporary Memory

  • Exists during function execution, destroyed after the function returns.
  • Local variables are stored in memory by default.
  • Moderate gas cost.

calldata — Call Data

  • Comes from the transaction's msg.data, read-only.
  • Immutable, lowest gas cost.
  • Suitable for parameters of external functions.

Impact of Storage Locations on Reference Types

Key rules:

  • The same reference type in different locations is treated as a different type by the compiler.
  • public / external function parameters can only be memory or calldata.
  • internal / private function parameters can be storage.

Comprehensive Example

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract DataLocations {
    struct MyStruct {
        uint256 foo;
        string text;
    }

    mapping(address => MyStruct) myStructs;

    function examples(uint[] calldata y, string calldata s) external returns (uint[] memory) {
        myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"});

        // storage reference: modifications are persistent
        MyStruct storage myStruct = myStructs[msg.sender];
        myStruct.text = "foo";

        // memory copy: modifications do not affect storage
        MyStruct memory readOnly = myStructs[msg.sender];
        readOnly.foo = 456; // does not affect myStructs

        _internal(y);

        uint[] memory memArr = new uint[](3);
        memArr[0] = 234;
        return memArr;
    }

    function _internal(uint[] calldata y) private pure {
        uint x = y[0];
    }
}

Value Copy vs. Reference Copy

This is one of the most easily confusing concepts in Solidity; make sure to understand it thoroughly.

Core Concept: Special Nature of Member Variables

In the EVM, member variables (state variables) point to fixed storage data blocks (slots) and cannot switch the data block they point to like general reference variables. Therefore, assigning a value to a member variable can only be a value copy.

Determination Algorithm

For the assignment operation x = a, determine whether it's a value copy or a reference copy according to the following rules:

1. If x is a member variable → Value copy
2. If x is a local variable:
   - If x and a have the same location → Reference copy
   - If x and a have different locations → Value copy

Checking Algorithm

When determined to be a value copy, the compiler also performs the following checks:

1. Check if the type contains a mapping → If yes, compile error (mapping does not support copying)
2. Check if x is calldata → If yes, compile error (calldata is read-only)
3. If checks pass → Perform value copy

Summary in One Sentence

When an assignment is interpreted as a reference copy, it is a reference copy if it does not conflict with higher-priority design choices; otherwise, it is a value copy.

Quick Reference for Common Scenarios

Assignment Scenario Copy Type Explanation
Member variable = storage reference Value copy Member variables are always value copies.
Member variable = memory variable Value copy Member variables are always value copies.
storage local variable = member variable Reference copy Both are storage, pointing to the same data.
memory local variable = memory variable Reference copy Both are memory, pointing to the same data.
memory local variable = storage variable Value copy Different locations.
storage local variable = memory variable Compile error storage local variables can only reference existing storage data.

About Default Values and Initialization

  • Member variables: Automatically initialized to default values (uint → 0, bool → false, address → 0x0, etc.).
  • memory local variables: Automatically initialized to default values.
  • storage local variables: Must be assigned a value before use, not automatically initialized.

Historical Security Vulnerability: In early Solidity versions, unassigned storage local variables would default to pointing to slot 0, potentially overwriting data of other state variables and causing serious security issues. Modern compilers have fixed this problem.


Complete storage Interaction Example

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract DataLocations {
    uint[] public arr;
    mapping(uint => address) map;
    struct MyStruct {
        uint foo;
    }
    mapping(uint => MyStruct) myStructs;

    function f() public {
        // Pass storage variables to an internal function
        _f(arr, map, myStructs[1]);

        // storage local variable: reference copy, points to myStructs[1]
        MyStruct storage myStruct = myStructs[1];

        // memory local variable: independent copy
        MyStruct memory myMemStruct = MyStruct(0);
    }

    function _f(
        uint[] storage _arr,
        mapping(uint => address) storage _map,
        MyStruct storage _myStruct
    ) internal {
        // Operate on storage reference, modifications are persistent
    }

    function g(uint[] memory _arr) public returns (uint[] memory) {
        // Operate on memory array, destroyed after function returns
    }

    function h(uint[] calldata _arr) external {
        // Operate on calldata array (read-only, lower gas)
    }
}

Summary

Storage Location Lifetime Writable Gas Cost Typical Use
storage Permanent Yes Highest State variables
memory During function execution Yes Moderate Local variables, function parameters
calldata During function execution No Lowest external function parameters

Core Copy Rules:

  • Assigning to a member variable → Always value copy
  • Assigning between local variables → Reference copy if same location, value copy if different locations
  • mapping cannot be value copied, calldata is not writable

Previous Article: Reference Types Explained

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://walker-learn.xyz/archives/7490

(0)
Walker的头像Walker
上一篇 5 days ago
下一篇 Mar 27, 2025 15:01

Related Posts

EN
简体中文 繁體中文 English