crates/lint/docs/external-function.md
Severity: Gas
ID: external-function
public functions that are never called from inside the contract (or any of its
derivatives) can be declared external. External functions read their reference-type
arguments directly from calldata instead of copying them into memory, which saves
gas at every call site.
Flags a public function declaration when all of the following hold:
public (not external, internal, or private).struct, array, bytes, or
string) currently located in memory.override of another function (the base must be migrated first).foo()), via super.foo(...), or via a function-pointer reference
(fn = foo;).The lint runs in the Gas severity bucket and is automatically skipped on Foundry
test and script files.
Calling a public function from outside the contract is more expensive than calling
the equivalent external function:
calldata into memory before the
function body executes, even though external-only callers never need that copy.When the function is never called internally, switching public to external removes
both costs at no semantic change.
contract Vault {
mapping(address => uint256) public balances;
function deposit(address[] memory accounts, uint256[] memory amounts) public {
for (uint256 i = 0; i < accounts.length; i++) {
balances[accounts[i]] += amounts[i];
}
}
}
deposit is never called from inside Vault, but its memory arrays force an
unnecessary calldata-to-memory copy on every external call.
contract Vault {
mapping(address => uint256) public balances;
function deposit(address[] calldata accounts, uint256[] calldata amounts) external {
for (uint256 i = 0; i < accounts.length; i++) {
balances[accounts[i]] += amounts[i];
}
}
}
When you migrate public to external, also change reference-type parameters from
memory to calldata to capture the full gas saving.