具有数组输出的以太坊合约的 web3py ABI 必须是什么样子?

发布于 2025-01-15 15:13:33 字数 5927 浏览 4 评论 0原文

我必须对属于以太坊合约的未记录函数的 ABI 进行逆向工程。

这就是分割成 256 位块的原始输出的样子:

'0000000000000000000000000000000000000000000000000000000000000060' # unknown
'0000000000000000000000000000000000000000000000000000000000000220' # unknown
'00000000000000000000000000000000000000000000000000000000000003e0' # unknown
'000000000000000000000000000000000000000000000000000000000000000d' # 13, the array size
'0000000000000000000000000000000000000000000000000000000000000001' # array of quantities
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'000000000000000000000000000000000000000000000000000000000000000d' # 13, the array size
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251' # array of addresses
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000000000000000000000000000000000000000000d' # 13, the array size
'0000000000000000000000000000000100000000000000000000000000000405' # array of indices
'0000000000000000000000000000000d00000000000000000000000000000409'
'0000000000000000000000000000000d0000000000000000000000000000040b'
'0000000000000000000000000000001c000000000000000000000000000003a7'
'0000000000000000000000000000001c000000000000000000000000000003a8'
'00000000000000000000000000000064000000000000000000000000000003f2'
'00000000000000000000000000000067000000000000000000000000000003b0'
'00000000000000000000000000000070000000000000000000000000000003c4'
'000000000000000000000000000000850000000000000000000000000000038e'
'0000000000000000000000000000008e000000000000000000000000000003ea'
'0000000000000000000000000000009a000000000000000000000000000003d6'
'0000000000000000000000000000009d000000000000000000000000000003a2'
'0000000000000000000000000000009d000000000000000000000000000003a3'

数组大小各不相同。大多数呼叫的值为 1。 这是我使用的 ABI:

abi = {"constant":True,"inputs":[{"internalType":"uint256","name":"dataIndex","type":"uint256"}],
    "name":"getData", "outputs":[{"internalType":"uint256","name":"parameter0","type":"uint256"},
                                 {"internalType":"uint256","name":"parameter1","type":"uint256"},
                                 {"internalType":"uint256","name":"parameter2","type":"uint256"},
                                 {"internalType":"uint256","name":"amountArraySize","type":"uint256"},
                                 {"internalType":"uint256","name":"amount","type":"uint256"},
                                 {"internalType":"uint256","name":"addressArraySize","type":"uint256"},
                                 {"internalType":"address","name":"address","type":"address"},
                                 {"internalType":"uint256","name":"indexArraySize","type":"uint256"},
                                 {"internalType":"uint256","name":"index","type":"uint256"}],
    "payable":False, "stateMutability":"view", "type":"function"},

只要所有数组大小均为 1,它就可以正常工作。但是当数组较大时,它只会用第一个数组的值填充所有输出字段并丢弃其余的。

我查看了其他合约的 ABI,对于数组,只需将 [] 添加到类型名称中。 但是将输出更改为

[
    {"internalType":"uint256","name":"parameter0","type":"uint256"},
    {"internalType":"uint256","name":"parameter1","type":"uint256"},
    {"internalType":"uint256","name":"parameter2","type":"uint256"},
    {"internalType":"uint256","name":"amountArraySize","type":"uint256"},
    {"internalType":"uint256[]","name":"amount","type":"uint256[]"},        #changed
    {"internalType":"uint256","name":"addressArraySize","type":"uint256"},
    {"internalType":"address[]","name":"address","type":"address[]"},       #changed
    {"internalType":"uint256","name":"indexArraySize","type":"uint256"},
    {"internalType":"uint256[]","name":"index","type":"uint256[]"}          #changed
] 

仅引发 web3.exceptions.BadFunctionCallOutput: Could not debug Contract function call to getData with return data:

我查看的其他带有数组的 ABI 在输出列表中没有大小字段,因此我的猜测是它是隐含的。 所以我删除了这些行:

[
    {"internalType":"uint256","name":"parameter0","type":"uint256"},
    {"internalType":"uint256","name":"parameter1","type":"uint256"},
    {"internalType":"uint256","name":"parameter2","type":"uint256"},
    {"internalType":"uint256[]","name":"amount","type":"uint256[]"},       
    {"internalType":"address[]","name":"address","type":"address[]"},       
    {"internalType":"uint256[]","name":"index","type":"uint256[]"}
]        

但它仍然引发相同的错误。

输出和输入数组的正确 ABI 声明是什么?

I have to reverse engineer the ABI of an undocumented function belonging to an ethereum contract.

This is what the raw output split into 256-bit chunks looks like:

'0000000000000000000000000000000000000000000000000000000000000060' # unknown
'0000000000000000000000000000000000000000000000000000000000000220' # unknown
'00000000000000000000000000000000000000000000000000000000000003e0' # unknown
'000000000000000000000000000000000000000000000000000000000000000d' # 13, the array size
'0000000000000000000000000000000000000000000000000000000000000001' # array of quantities
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'0000000000000000000000000000000000000000000000000000000000000001'
'000000000000000000000000000000000000000000000000000000000000000d' # 13, the array size
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251' # array of addresses
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000a96760f0efa3a9bc2388915d045acd4da9e23251'
'000000000000000000000000000000000000000000000000000000000000000d' # 13, the array size
'0000000000000000000000000000000100000000000000000000000000000405' # array of indices
'0000000000000000000000000000000d00000000000000000000000000000409'
'0000000000000000000000000000000d0000000000000000000000000000040b'
'0000000000000000000000000000001c000000000000000000000000000003a7'
'0000000000000000000000000000001c000000000000000000000000000003a8'
'00000000000000000000000000000064000000000000000000000000000003f2'
'00000000000000000000000000000067000000000000000000000000000003b0'
'00000000000000000000000000000070000000000000000000000000000003c4'
'000000000000000000000000000000850000000000000000000000000000038e'
'0000000000000000000000000000008e000000000000000000000000000003ea'
'0000000000000000000000000000009a000000000000000000000000000003d6'
'0000000000000000000000000000009d000000000000000000000000000003a2'
'0000000000000000000000000000009d000000000000000000000000000003a3'

The array size varies. It's 1 for most calls.
This is the ABI I used:

abi = {"constant":True,"inputs":[{"internalType":"uint256","name":"dataIndex","type":"uint256"}],
    "name":"getData", "outputs":[{"internalType":"uint256","name":"parameter0","type":"uint256"},
                                 {"internalType":"uint256","name":"parameter1","type":"uint256"},
                                 {"internalType":"uint256","name":"parameter2","type":"uint256"},
                                 {"internalType":"uint256","name":"amountArraySize","type":"uint256"},
                                 {"internalType":"uint256","name":"amount","type":"uint256"},
                                 {"internalType":"uint256","name":"addressArraySize","type":"uint256"},
                                 {"internalType":"address","name":"address","type":"address"},
                                 {"internalType":"uint256","name":"indexArraySize","type":"uint256"},
                                 {"internalType":"uint256","name":"index","type":"uint256"}],
    "payable":False, "stateMutability":"view", "type":"function"},

This works just fine as long as all array sizes are 1. But when the arrays are larger it will just fill all output fields with values of the first array and discard the rest.

I have looked at ABIs of other contracts and for arrays there is simply [] added to the type name.
But changing the outputs to

[
    {"internalType":"uint256","name":"parameter0","type":"uint256"},
    {"internalType":"uint256","name":"parameter1","type":"uint256"},
    {"internalType":"uint256","name":"parameter2","type":"uint256"},
    {"internalType":"uint256","name":"amountArraySize","type":"uint256"},
    {"internalType":"uint256[]","name":"amount","type":"uint256[]"},        #changed
    {"internalType":"uint256","name":"addressArraySize","type":"uint256"},
    {"internalType":"address[]","name":"address","type":"address[]"},       #changed
    {"internalType":"uint256","name":"indexArraySize","type":"uint256"},
    {"internalType":"uint256[]","name":"index","type":"uint256[]"}          #changed
] 

only raises web3.exceptions.BadFunctionCallOutput: Could not decode contract function call to getData with return data:

The other ABIs with arrays I looked at have no size fields in the output list, so my guess was that it's implicit.
So I removed those lines:

[
    {"internalType":"uint256","name":"parameter0","type":"uint256"},
    {"internalType":"uint256","name":"parameter1","type":"uint256"},
    {"internalType":"uint256","name":"parameter2","type":"uint256"},
    {"internalType":"uint256[]","name":"amount","type":"uint256[]"},       
    {"internalType":"address[]","name":"address","type":"address[]"},       
    {"internalType":"uint256[]","name":"index","type":"uint256[]"}
]        

But it still raises the same error.

What's the correct ABI declaration for output and input arrays?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晚雾 2025-01-22 15:13:33

前 3 个返回值是二进制返回数据中 3 个数组的起始位置。
这些也是隐式的,不需要在输出字段中声明。

删除前 3 行也修复了错误,web3py 现在可以正确返回大于 1 的数组的结果。

The first 3 return values are the starting locations of the 3 arrays within the binary return data.
These are also implicit and need not to be declared in the output fields.

Removing the first 3 lines as well fixed the error and web3py now correctly returns the results for arrays that are larger than 1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文