没有abi的事务的解码输入?



如果我得到这样的输入

0 x18cbafe5000000000000000000000000000000000000000000000001885c663d0035bce200000000000000000000000000000000000000000000000000f5666f7fdaa62600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000c0be713b48822271b362e9fac00479f5134172e80000000000000000000000000000000000000000000000000000000060e93fa900000000000000000000000000000000000000000000000000000000000000020000000000000000000000009813037ee2218799597d83d4a5b6f3b6778218d9000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2

如果我有一个像这样的函数签名"swapExactTokensForETH(uint256,uint256,address[],address,uint256)"没有ABI可以解码吗?

我知道签名的类型

"types": [
"uint256",
"uint256",
"address[]",
"address",
"uint256"
],

但是当解码后它看起来像这样:

"inputs": [
"1885c663d0035bce2",
"f5666f7fdaa626",
[
"9813037ee2218799597d83d4a5b6f3b6778218d9",
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
],
"c0be713b48822271b362e9fac00479f5134172e8",
"60e93fa9"
]

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

那么,有什么逻辑可以知道索引2中的数组是从事务输入末尾的两个地址中提取的呢?

如果可能的话,我尽量不需要ABI来解码这样的输入

我知道我可以像这样分割事务的输入:

("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0be713b48822271b362e9fac00479f5134172288","000000000000000000000000000000000000000000000000000000000000000000000000000000000060e93fa9","0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002","000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009813037ee2218799597d83d4a5b6f3b6778218d9","000000000000000000000000 c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")

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

这是abi在有用的地方像解码使用web3吗?或者没有abi也可以解码吗?

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

只有当你至少有函数签名或定义。

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

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003666f6f0000000000000000000000000000000000000000000000000000000000

是一个字符串foo

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

  • 32
  • 3
  • 46332796673528066027243215619882264990369332300865266851730502456685210107904

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

const data = web3.eth.abi.decodeParameters(
["uint256", "uint256", "address[]", "address", "uint256"],
"000000000000000000000000000000000000000000000001885c663d0035bce200000000000000000000000000000000000000000000000000f5666f7fdaa62600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000c0be713b48822271b362e9fac00479f5134172e80000000000000000000000000000000000000000000000000000000060e93fa900000000000000000000000000000000000000000000000000000000000000020000000000000000000000009813037ee2218799597d83d4a5b6f3b6778218d9000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
);

返回
Result {
'0': '28272584972907691234',
'1': '69073998366549542',
'2': [
'0x9813037ee2218799597d83D4a5B6F3b6778218d9',
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
],
'3': '0xc0Be713B48822271b362e9Fac00479f5134172e8',
'4': '1625898921',
__length__: 5
}

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

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


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

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

所有的动态值都在有效载荷的末尾排序,前面加上section的长度。

在您的例子中,2声明在这个数组中有2个值,其余的是数组的实际值。

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

最新更新