没有abi的情况下解码交易输入?

Chi*_*ipe 5 transactions ethereum

如果我得到这样的输入

0x18cbafe5000000000000000000000000000000000000000000000001885c663d0035bce200000000000000000000000000000000000000000000000000f5666f7fdaa62600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000c0be713b48822271b362e9fac00479f5134172e80000000000000000000000000000000000000000000000000000000060e93fa900000000000000000000000000000000000000000000000000000000000000020000000000000000000000009813037ee2218799597d83d4a5b6f3b6778218d9000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2

如果我有这样的函数签名,"swapExactTokensForETH(uint256,uint256,address[],address,uint256)" 是否可以在没有 ABI 的情况下进行解码?

我从签名中知道类型

"types": [
    "uint256",
    "uint256",
    "address[]",
    "address",
    "uint256"
],
Run Code Online (Sandbox Code Playgroud)

但解码后看起来像这样:

"inputs": [
    "1885c663d0035bce2",
    "f5666f7fdaa626",
    [
        "9813037ee2218799597d83d4a5b6f3b6778218d9",
        "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    ],
    "c0be713b48822271b362e9fac00479f5134172e8",
    "60e93fa9"
 ]
Run Code Online (Sandbox Code Playgroud)

其中索引0是uint256,索引1是下一个uint256,索引2是address[],索引3是地址,索引4是uint256

那么有什么逻辑可以知道索引2中的数组是从交易输入末尾的两个地址中拉取的。

如果可能的话,我尝试不需要 ABI 来解码输入

我知道我可以像这样分割交易的输入:

['000000000000000000000000000000000000000000000001885c663d0035bce2','000000000000000000000000000000000000000000000000000f566 6f7fdaa626', '0000000000000000000000000000000000000000000000000000000000000a0', '000000000000000000000000c0be713b48822271b362e 9fac00479f5134172e8','0000000000000000000000000000000000000000000000000000000060e93fa9','0000000000000000000000000000000000000 000000000000000000000000002', '0000000000000000000000009813037ee2218799597d83d4a5b6f3b6778218d9', '000000000000000000000000c02 aaa39b223fe8d0a0e5c4f27ead9083c756cc2']

该数组中的最后两个是上面输入数组中索引 2 显示的地址。但是函数签名的顺序是第三,我怎么知道它是从最后的输入中拉出来的呢?

这是 abi 发挥作用的地方,就像使用 web3 进行解码一样?或者没有abi 也可以解码吗?

Pet*_*jda 6

是否可以在没有 ABI 的情况下解码?

仅当您至少具有函数签名或定义时。

如果你不知道有哪些输入类型,你就无法判断这个输入是否是

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003666f6f0000000000000000000000000000000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)

是一个字符串foo

或三个连续的无符号整数(十进制值):

  • 32
  • 3
  • 46332796673528066027243215619882264990369332300865266851730502456685210107904

如果您知道输入数据类型,一个简单的方法(无需实际的 ABI JSON)是使用 web3decodeParameters函数

const data = web3.eth.abi.decodeParameters(
    ["uint256", "uint256", "address[]", "address", "uint256"],
    "000000000000000000000000000000000000000000000001885c663d0035bce200000000000000000000000000000000000000000000000000f5666f7fdaa62600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000c0be713b48822271b362e9fac00479f5134172e80000000000000000000000000000000000000000000000000000000060e93fa900000000000000000000000000000000000000000000000000000000000000020000000000000000000000009813037ee2218799597d83d4a5b6f3b6778218d9000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
);
Run Code Online (Sandbox Code Playgroud)

回报

Result {
  '0': '28272584972907691234',
  '1': '69073998366549542',
  '2': [
    '0x9813037ee2218799597d83D4a5B6F3b6778218d9',
    '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
  ],
  '3': '0xc0Be713B48822271b362e9Fac00479f5134172e8',
  '4': '1625898921',
  __length__: 5
}
Run Code Online (Sandbox Code Playgroud)

这些值已经编码为各自的数据类型 - 例如整数是十进制的(而不是您问题中的十六进制)。它们以字符串形式返回只是因为 JS 在处理大整数时有时会遇到舍入错误。

请注意,前 4 个字节(8 个十六进制字符;在您的情况下18cbafe5)是函数选择器 - 而不是参数值。所以你不要将它传递给函数decodeParameters()


该数组中的最后两个是上面输入数组中索引 2 显示的地址。但是函数签名的顺序是第三,我怎么知道它是从最后的输入中拉出来的呢?

这就是 ABI 的工作原理。如果您有动态类型,则其实际槽包含指向值的实际位置的偏移量(包括前置长度)。在您的情况下,这是 160 (十六进制a0)字节。

所有动态值都在有效负载的末尾排序,前面加上该部分的长度。

在您的情况下,2该数组中有 2 个值,其余的是数组的实际值。

您可以在文档中找到有关排序的更多信息:https://docs.soliditylang.org/en/v0.8.7/abi-spec.html#formal-specification-of-the-encoding