Chapter 4 · Ethereum & the EVM · lesson 5
Storage, memory, calldata
10 min
Builds on Gas: the metering model
Chapter 4 · Ethereum & the EVM · lesson 5
10 min
Builds on Gas: the metering model
Three places data can live inside a contract, priced so differently that the choice shapes how Solidity is written.
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.
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
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