具有数组输出的以太坊合约的 web3py ABI 必须是什么样子?
我必须对属于以太坊合约的未记录函数的 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
前 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.