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

如何正确构造ERC-20小数位数与符号的Multicall ABI解码存根测试响应?

如何正确构造ERC-20小数位数与符号的Multicall ABI解码存根测试响应?

我明白你在手动构造Multicall存根响应时踩的坑——ABI的嵌套编码尤其是动态数组和字符串,确实很容易搞混。让我一步步帮你理清正确的构造方式,针对你要测试的3个代币(BNB/Cake/USDC,均为18位小数)拆解清楚:

核心误区先理清

你之前出错的关键是没搞懂Multicall返回值的结构:aggregate函数返回的bytes[] returnData里,每一个元素都是对应单个ERC-20调用的完整ABI编码结果,而不是把所有调用的返回值直接拼接在一起。

举个例子:你调用了3个代币的decimals()和symbol(),总共6次调用,那returnData数组就有6个元素,每个元素单独对应一次调用的ABI编码返回值。

第一步:单独编码每个ERC-20调用的返回值

先把单个函数的返回编码搞对,再组合进Multicall的结果里:

  • decimals() returns (uint8)的编码:uint8是值类型,ABI编码后是32字节的填充值,18对应的十六进制是0x12,所以完整编码是:
    0x0000000000000000000000000000000000000000000000000000000000000012
    
  • symbol() returns (string)的编码:字符串是动态类型,需要三步编码:
    1. 偏移量(固定为0x20,表示字符串内容从下一个32字节开始)
    2. 字符串长度(比如BNB是3个字符?不对,你示例里用的是WBNB,长度4,对应十六进制0x04)
    3. 字符串的ASCII十六进制(后面补零到32字节)
      以WBNB为例,完整编码是:
    0x0000000000000000000000000000000000000000000000000000000000000020
    0000000000000000000000000000000000000000000000000000000000000004
    57424e4200000000000000000000000000000000000000000000000000000000
    

第二步:组合成完整的Multicall返回编码

Multicall的返回是(uint256 blockNumber, bytes[] returnData),按ABI规则完整编码如下(带注释,你可以直接复制用):

0x
// 1. blockNumber(示例用你之前的58256789,十六进制0x378CC49,填充到32字节)
000000000000000000000000000000000000000000000000000000000378CC49
// 2. bytes[] returnData的ABI编码
0000000000000000000000000000000000000000000000000000000000000040 // 数组偏移量:从第64字节开始
0000000000000000000000000000000000000000000000000000000000000006 // 数组长度:6个调用结果
// 3. 每个数组元素的偏移量(指向对应调用结果的起始位置)
0000000000000000000000000000000000000000000000000000000000000100 // 代币1 decimals结果的偏移
0000000000000000000000000000000000000000000000000000000000000120 // 代币1 symbol结果的偏移
0000000000000000000000000000000000000000000000000000000000000180 // 代币2 decimals结果的偏移
00000000000000000000000000000000000000000000000000000000000001A0 // 代币2 symbol结果的偏移
0000000000000000000000000000000000000000000000000000000000000200 // 代币3 decimals结果的偏移
0000000000000000000000000000000000000000000000000000000000000220 // 代币3 symbol结果的偏移
// 4. 每个调用结果的实际编码内容
0000000000000000000000000000000000000000000000000000000000000012 // 代币1 decimals(18)
0000000000000000000000000000000000000000000000000000000000000020 // 代币1 symbol(WBNB)
0000000000000000000000000000000000000000000000000000000000000004
57424e4200000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000012 // 代币2 decimals(18)
0000000000000000000000000000000000000000000000000000000000000020 // 代币2 symbol(Cake)
0000000000000000000000000000000000000000000000000000000000000004
43616b6500000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000012 // 代币3 decimals(18)
0000000000000000000000000000000000000000000000000000000000000020 // 代币3 symbol(USDC)
0000000000000000000000000000000000000000000000000000000000000004
5553444300000000000000000000000000000000000000000000000000000000

验证小技巧

如果怕手动编码出错,你可以在Remix里写个简单的Solidity测试函数,用abi.encode生成标准模板:

function generateMulticallResponse() public pure returns (bytes memory) {
    uint256 blockNumber = 58256789;
    bytes[] memory returnData = new bytes[](6);
    // 填充每个调用的编码结果
    returnData[0] = abi.encode(uint8(18));
    returnData[1] = abi.encode(string("WBNB"));
    returnData[2] = abi.encode(uint8(18));
    returnData[3] = abi.encode(string("Cake"));
    returnData[4] = abi.encode(uint8(18));
    returnData[5] = abi.encode(string("USDC"));
    return abi.encode(blockNumber, returnData);
}

编译后调用这个函数,复制返回的十六进制字符串作为WireMock的存根响应,绝对不会出错。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 03:07:59