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/externalfunction parameters can only bememoryorcalldata.internal/privatefunction parameters can bestorage.
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