Memory v calldata
Memory
Used for storing variables that are only needed temporarily during the execution of a function, and cannot be accessed outside the function.
can be used for both declaring function parameters and within function logic
mutable (variable values are modifiable)
non-persistent (the value does not persist after the transaction has completed)
Calldata
Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory.
used to hold function arguments passed in from an external caller; user or another contract.
immutable: calldata is read-only and cannot be modified by the function.
calldata is cheaper than memory.
memory vs calldata
function doSome(bytes calldata data) external {} // uses less gas
function doSome(bytes memory data) external {}
By declaring
calldata
, you can avoid the overhead of copying data intomemory
and reduce the amount of gas needed to execute the function. [CALLDATALOAD]
memory
is more expensive thancalldata
. Because, it will copy the data from calldata into local memory, as an additional step. [CALLDATACOPY]

Why bother using memory then?
// this will not compile
function testImmutable(bytes calldata myBytes) external {
myBytes[0] = 0xab;
}
We cannot modify
calldata
; read-onlyIf you need to modify function arguments that are stored in
calldata
, you must first copy them intomemory
.So in this scenario, we are better served declaring
myBytes
asmemory
Alternatively
// this is more gas intensive
function testCallData(bytes calldata data) external {
bytes memory localData = data; //create a mutable copy in memory
localData[0] = 0xab;
}
// this is less gas intensive
function testMemory(bytes memory data) external {
data[0] = 0xab;
}
memory can be cheaper than calldata if you need to do modifications to the external data passed to the function.
use
calldata
when you are not going to modify the value of the variable passed ascalldata
inside the function.
More on calldata
calldata
is where data from external calls to functions are stored.calldata
contains parameters of a function as allocated by the external callermsg.data
of an external call is held incalldata
A byte of calldata costs either 4 gas (if it is zero) or 16 gas (if it is any other value).
Gotcha!
One gotcha on this is that if you pass in a string (or bytes) from an internal function, where you had just created that string in memory, then you can't use calldata
here.
Example
contract X {
function sendString() internal {
string memory y = "Calnix is cool";
callFunction(y);
}
// ERROR: because calldata is only used from external calls,
// and y was created in memory before
function callFunction(string calldata y) {
// ....do something
}
}
when execution moves from line 4 to 5, it is not an external call. There is no
msg.data
that holdscalldata
to be passed intocallFunction
so in the absence of msg.data, there is no calldata that can be accessed.
Why is calldata cheaper?
calldata are only parameters of a function which is declared as external, which value is allocated by the caller, that's why it's gas cost is lower.
EXCEPTION: Layer-2
In the context of a rollups/layer-2, calldata goes from the cheapest resource to the most-expensive resource.
Links
Last updated