Skip to main content

Use Calldata Instead Of Memory For External Function Calls

Description

When a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly obviates the need for such a loop in the contract code and runtime execution.

Using calldata instead of memory can result in significant gas savings when the function is called externally, especially for larger arrays

Example Code

function foo(uint[] memory arr) external {
// Do something with arr
}

Here, foo takes an array of unsigned integers as a memory parameter. When this function is called externally, the calldata has to be copied to memory, which can result in higher gas usage.

By changing the function definition to use calldata, the gas cost can be reduced:

function foo(uint[] calldata arr) external {
// Do something with arr
}

Recommendation

Consider using calldata instead of memory for function parameters that are expected to be called externally. This can result in significant gas savings, especially for larger arrays.