Super weird Solidity gas issue about conversion between calldata and memory

41 views Asked by At

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

0

There are 0 answers