Inconsistent gas usage for conversion of calldata to memory in external call and internal call. This is observed after 0.8.0. In 0.7.6, their gas usages are the consistent.
Steps to Reproduce
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Dummy {
function iacceptmem(uint256[] memory amounts) internal {
}
function test1(uint256[] memory amounts) external {
iacceptmem(amounts);
}
function test2(uint256[] calldata amounts) external {
iacceptmem(amounts);
}
}
contract Tester {
Dummy d = new Dummy();
function call_test1() external {
uint256[] memory data = new uint256[](1000);
d.test1(data);
}
function call_test2() external {
uint256[] memory data = new uint256[](1000);
d.test2(data);
}
}
If you deploy Tester and call call_test1
and call_test2
, you will find that execution cost of call_test2
is 295126, but call_test1
is 517391. From yul, we can see they both have the conversion from calldata to memory once. But what is the difference is call_test2
is converting before iacceptmem
call, call_test1
is converting at before executing the test1
.
I tried on the Remix IDE, and dump the asm and YUL from solc, cannot figure out why