You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity 0.8.0+中calldata与memory转换的Gas消耗不一致问题

Solidity 0.8+中Calldata转Memory的Gas消耗差异分析

问题现象

在Solidity 0.8.0及以上版本中,外部调用传入memory数组再调用内部memory参数函数,与外部调用传入calldata数组再转memory调用内部函数的Gas消耗存在显著差异;而在0.7.6版本中,两者消耗一致。

复现代码

// 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);
    }
}

部署Tester合约后调用call_test1和call_test2,可观察到:

  • call_test1执行成本约517391 Gas
  • call_test2执行成本约295126 Gas

差异原因

1. Solidity 0.8+的参数处理逻辑

  • test1路径:

    1. Tester.call_test1创建memory数组,调用Dummy.test1时,需将数组从Tester的memory复制到Dummy的calldata(外部调用的参数传递规则)。
    2. Dummy.test1的参数为memory类型,Solidity 0.8+会强制将calldata中的数组复制到Dummy的memory中,再传递给内部函数iacceptmem。
    3. 整个流程包含两次数组复制:Tester memory → Dummy calldata、Dummy calldata → Dummy memory。
  • test2路径:

    1. Tester.call_test2创建memory数组,调用Dummy.test2时,同样将数组从Tester的memory复制到Dummy的calldata。
    2. Dummy.test2的参数为calldata类型,调用iacceptmem(memory参数)时,仅需将Dummy的calldata数组复制到自身memory一次。
    3. 整个流程仅包含一次数组复制:Dummy calldata → Dummy memory(外部调用的复制与test1路径一致)。

两次复制的Gas成本差异(单个数组复制的成本包含字节复制费+内存扩展费),是导致总Gas消耗差距的核心原因。

2. 0.7.6版本的一致性原因

在Solidity 0.7.x版本中,外部函数的memory参数存在一个未严格实现的逻辑:编译器并未将calldata实际复制到memory,而是直接将calldata作为memory参数的底层存储使用(尽管memory类型理论上可修改,但实际场景中若未修改参数则不会触发错误)。因此:

  • test1路径中,Dummy.test1的memory参数直接复用calldata,无需额外复制,仅需外部调用时的一次复制。
  • test2路径的复制逻辑与0.8+一致,因此两者总Gas消耗相近。

Solidity 0.8.0修复了这一逻辑漏洞,严格区分memory与calldata的存储区域,强制外部函数的memory参数必须复制到内存,从而引入了额外的Gas消耗差异。

内容的提问来源于stack exchange,提问作者Shihao Xia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 07:20:54