Track 3 · Ethereum & the EVM · lesson 5
Storage, memory, calldata
10 min
Three places data can live inside a contract, priced so differently that the choice shapes how Solidity is written.
What each one is
storage — the contract's permanent state. Survives between transactions.
Every node keeps it, indefinitely, which is why a fresh slot costs 22,100 gas.
memory — a scratch pad for the duration of one call. Wiped the moment the
call returns. A few gas per word.
calldata — the raw, read-only bytes of the incoming call. Cannot be
modified, and costs nothing to keep, because it was already paid for as part of
the transaction's data.
The bar chart is to scale. Storage is not somewhat more expensive than memory — it is roughly seven thousand times more expensive.
That single ratio explains most of what looks like odd style in production Solidity. Values cached in locals, loops rewritten to touch state once, structs packed into single slots: all of it is people avoiding that bar.
Why Solidity makes you say which
For value types like uint256 and address, Solidity knows. For arrays,
structs, strings and bytes it demands you state the location:
function process(uint256[] calldata input) external {
uint256[] memory working = new uint256[](input.length);
...
}
Leave it out and you get Data location must be "storage", "memory" or "calldata" — one of the first errors every Solidity developer meets.
Predict
A function takes a large array it only reads. Should the parameter be `memory` or `calldata`?
The assignment trap
This one bites everyone once:
Task storage t = tasks[0]; // a reference — changes persist
Task memory t2 = tasks[0]; // a copy — changes are discarded
storage gives you a pointer into state. memory gives you a snapshot. Modify
the snapshot, and your change vanishes when the function returns, silently and
with no warning.
Check
You copy a struct out of storage with `memory`, change a field, and the function ends. What happened on-chain?
Worth remembering
- storage is permanent and ~7,000× more expensive than memory; memory is per-call scratch; calldata is read-only incoming bytes.
- Solidity requires an explicit location for arrays, structs, strings and bytes.
- Read-only external parameters should be `calldata` to avoid a copy.
- A `storage` local is a reference; a `memory` local is a copy.
- Modifying a memory copy and expecting it to persist is a silent, common bug.