Skip to content

Commit acb4b2c

Browse files
committed
Add Data Locations
1 parent 6aa040b commit acb4b2c

File tree

1 file changed

+99
-2
lines changed

1 file changed

+99
-2
lines changed

README.md

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,19 @@ _This cheatsheet is based on version 0.8.29_
118118
- [`receive()` Function](#receive-function)
119119
- [`fallback()` Function](#fallback-function)
120120
- [Best Practices](#best-practices-3)
121-
- [Data Locations](#data-locations)
121+
- [Data Locations: `storage`, `memory`, `calldata`](#data-locations-storage-memory-calldata)
122+
- [`storage`: Persistent, On-Chain Data](#storage-persistent-on-chain-data)
123+
- [`memory`: Temporary, In-Function Workspace](#memory-temporary-in-function-workspace)
124+
- [`calldata`: Read-Only External Input](#calldata-read-only-external-input)
125+
- [Best Practices](#best-practices-4)
122126
- [Transient Storage](#transient-storage)
123127
- [Send Ether](#send-ether)
128+
- [Function Selector](#function-selector)
124129
- [Call \& Delegatecall](#call--delegatecall)
130+
- [Create, Create2, Create3, and CreateX](#create-create2-create3-and-createx)
131+
- [ABI Encode \& Decode](#abi-encode--decode)
132+
- [Bitwise Operations](#bitwise-operations)
133+
- [Assembly](#assembly)
125134
- [References](#references)
126135

127136
# Getting Started
@@ -1937,14 +1946,102 @@ fallback() external [payable] {
19371946
- **Event Logging**:
19381947
- If your contract receives Ether, consider emitting an event to easily track inbound transfers.
19391948

1940-
# Data Locations
1949+
# Data Locations: `storage`, `memory`, `calldata`
1950+
1951+
- In Solidity, **complex data types**—like arrays, structs, and mappings—require specifying a **data location**.
1952+
- This tells the compiler where the data physically resides. The three main data locations are:
1953+
1954+
1. `storage`: Persistent on-chain storage (the contract’s state).
1955+
2. `memory`: Temporary, in-memory area used within function execution. Not persisted on-chain.
1956+
3. `calldata`: Read-only area for function arguments in external functions. It directly references call data without copying it into memory.
1957+
1958+
## `storage`: Persistent, On-Chain Data
1959+
1960+
- **Location**: The contract’s long-term memory on the Ethereum blockchain.
1961+
- **Persistence**: Any changes to data in storage are permanent and cost **significant gas**.
1962+
- **State Variables**: By default, state variables declared at the contract level (e.g., `uint256 public count;`) reside in `storage`.
1963+
1964+
```solidity
1965+
contract MyContract {
1966+
// This array is in storage (part of contract state).
1967+
uint256[] public numbers;
1968+
1969+
function storeValue(uint256 value) external {
1970+
numbers.push(value); // Modifying storage costs gas
1971+
}
1972+
}
1973+
```
1974+
1975+
**Key Points:**
1976+
1977+
- **Expensive to Modify**: Writing to `storage` is the costliest operation because you’re permanently updating the blockchain state.
1978+
- **Reference Types in Storage**: Arrays, structs, and mappings can be stored in `storage`. Modifying their contents is also costly.
1979+
- **Assignments in Storage**: When you do `storageRef = someStateVar;`, you create a reference pointing to the same data. Changes to one reflect in the other.
1980+
1981+
## `memory`: Temporary, In-Function Workspace
1982+
1983+
- **Location**: A transient area used for the duration of a function call.
1984+
- **Lifecycle**: Data in `memory` is wiped after the function executes.
1985+
- **Cost**: Reading/writing `memory` is cheaper than `storage` (though not free), but the data does not persist.
1986+
1987+
```solidity
1988+
function incrementValuesMemory(uint256[] memory arr)
1989+
public
1990+
pure
1991+
returns (uint256[] memory)
1992+
{
1993+
// We can mutate the array elements because 'arr' is a mutable copy in memory.
1994+
for (uint256 i = 0; i < arr.length; ++i) {
1995+
arr[i] += 10;
1996+
}
1997+
// Returning the changed array
1998+
return arr;
1999+
}
2000+
```
2001+
2002+
## `calldata`: Read-Only External Input
2003+
2004+
- **Location**: A special data location for external function parameters.
2005+
- **Read-Only**: You cannot modify data in calldata; it’s immutable.
2006+
- **Gas Optimization**: Using calldata for external function parameters (instead of memory) can save gas, because Solidity can read directly from the transaction call data instead of making a full copy in memory.
2007+
2008+
```solidity
2009+
function sumArray(uint256[] calldata arr) external pure returns (uint256) {
2010+
uint256 sum = 0;
2011+
for (uint256 i = 0; i < arr.length; i++) {
2012+
sum += arr[i];
2013+
}
2014+
return sum;
2015+
}
2016+
```
2017+
2018+
- Any attempt to modify arr (e.g., `arr[i] = ...`) will fail to compile.
2019+
2020+
## Best Practices
2021+
2022+
- **Use `calldata` for External Read-Only Params**:
2023+
- If you only need to read from parameters, mark them as `calldata` to save gas (no copying into memory).
2024+
- **Avoid Large Copies**:
2025+
- Copying large arrays from `storage` to `memory` can be expensive. Consider streaming or chunking if you need partial data.
2026+
- **Use `storage` Wisely**:
2027+
- Minimize writes to `storage`. If possible, only store essential data. Reading from and especially writing to `storage` is the biggest cost in Solidity.
19412028

19422029
# Transient Storage
19432030

19442031
# Send Ether
19452032

2033+
# Function Selector
2034+
19462035
# Call & Delegatecall
19472036

2037+
# Create, Create2, Create3, and CreateX
2038+
2039+
# ABI Encode & Decode
2040+
2041+
# Bitwise Operations
2042+
2043+
# Assembly
2044+
19482045
# References
19492046

19502047
- [Solidity Docs](https://docs.soliditylang.org/en/latest/)

0 commit comments

Comments
 (0)