【Solidity Yul Assembly】3.3 | Dynamic Length Arguments

  • 0xE
  • 发布于 2024-08-30 10:41
  • 阅读 848

可变长度的数据,ABI 采用了一种指针和数据分离的方式进行编码。

在 Solidity 中,函数的调用数据需要根据 ABI 规范进行编码。对于可变长度的数据(例如数组和结构体),ABI 采用了一种指针和数据分离的方式进行编码。以下通过几个具体的例子来展示不同类型的参数在 ABI 中的编码方式。

contract VariableLength {
    struct Example {
        uint256 a;
        uint256 b;
        uint256 c;
    }

    function threeArgs(uint256 a, uint256[] calldata b, uint256 c) external {}

    function threeArgsStruct(uint256 a, Example calldata b, uint256 c) external {}

    function fiveArgs(uint256 a, uint256[] calldata b, uint256 c, uint256[] calldata d, uint256 e) external {}

    function oneArg(uint256[] calldata a) external {}

    function allVariable(uint256[] calldata a, uint256[] calldata b, uint256[] calldata c) external {}
}

1. threeArgs 函数调用

function threeArgs(uint256 a, uint256[] calldata b, uint256 c) external {}

假设调用此函数,输入参数为:

  • a: 7
  • b: [1,2,3]
  • c: 9

编码后的 calldata 为:

0xc6f922d0
0000000000000000000000000000000000000000000000000000000000000007 // a = 7
0000000000000000000000000000000000000000000000000000000000000060 // b 的指针 = 0x60
0000000000000000000000000000000000000000000000000000000000000009 // c = 9
0000000000000000000000000000000000000000000000000000000000000003 // b 的长度 = 3
0000000000000000000000000000000000000000000000000000000000000001 // b[0] = 1
0000000000000000000000000000000000000000000000000000000000000002 // b[1] = 2
0000000000000000000000000000000000000000000000000000000000000003 // b[2] = 3

其中,7 b 的指针 9 依次放在 0x00 0x20 0x40 的内存槽中,b 的指针0x60 意味着 0x60 内存槽开始存放数组 b 的相关内容。可以看到 0x60 存放了数组长度 3, 然后依次是数组内的元素。

2. threeArgsStruct 函数调用

function threeArgsStruct(uint256 a, Example calldata b, uint256 c) external {}

假设调用此函数,输入参数为:

  • a: 7
  • b: [1,2,3]
  • c: 9

calldata 中的内容为:

0x01e58fb4
0000000000000000000000000000000000000000000000000000000000000007 // a = 7
0000000000000000000000000000000000000000000000000000000000000001 // b.a = 1
0000000000000000000000000000000000000000000000000000000000000002 // b.b = 2
0000000000000000000000000000000000000000000000000000000000000003 // b.c = 3
0000000000000000000000000000000000000000000000000000000000000009 // c = 9

在这个例子中,b 是一个固定长度的结构体,因此可以直接依次存放各个字段的值,而无需使用指针。

3. fiveArgs 函数调用

function fiveArgs(uint256 a, uint256[] calldata b, uint256 c, uint256[] calldata d, uint256 e) external {}

假设调用此函数,输入参数为:

  • a: 5
  • b: [2,4]
  • c: 7
  • d: [10,11,12]
  • e:9

编码后的 calldata 为:


0x37701841
0000000000000000000000000000000000000000000000000000000000000005 // a = 5
000000000000000000000000000000000000000000000...

剩余50%的内容订阅专栏后可查看

点赞 0
收藏 0
分享

0 条评论

请先 登录 后评论
0xE
0xE
0x59f6...a17e
17年进入币圈,Web3 开发者。刨根问底探链上真相,品味坎坷悟 Web3 人生。有工作机会可加v:__0xE__