Error when decoding array of uint256
guidomb opened this issue · 6 comments
Hi, I'm a new at elixir development so maybe I'm missing something in my bug description but I'm currently using ExWeb3 that ends up depending on this package. I'm using version 0.5.11
of this package.
While attempting to call a contract method that returns uint256[]
I get the following error only if the array is not empty:
[error] GenServer ContractManager terminating
** (MatchError) no match of right hand side value: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2>>
(ex_abi 0.5.11) lib/abi/type_decoder.ex:371: ABI.TypeDecoder.decode_uint/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:271: anonymous fn/3 in ABI.TypeDecoder.decode_type/2
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:266: ABI.TypeDecoder.decode_type/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:311: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:333: anonymous fn/3 in ABI.TypeDecoder.decode_type/3
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:331: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:188: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:185: ABI.TypeDecoder.do_decode_raw/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:179: ABI.TypeDecoder.decode_raw/2
(exw3 0.6.1) lib/exw3/abi.ex:52: ExW3.Abi.decode_output/3
(exw3 0.6.1) lib/exw3/contract.ex:214: ExW3.Contract.eth_call_helper/4
(exw3 0.6.1) lib/exw3/contract.ex:480: ExW3.Contract.handle_call/3
(stdlib 3.17.1) gen_server.erl:721: :gen_server.try_handle_call/4
(stdlib 3.17.1) gen_server.erl:750: :gen_server.handle_msg/6
(stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
This is the raw JSON-RPC response from the ethereum node
{"jsonrpc":"2.0","id":5,"result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"}
@guidomb Hello. Can you please attach json abi and the data that you want to decode
ZimentoERC1155.json.zip is the contract's ABI. The method I'm calling is getHoldings(address): uint256[]
.
The contract's address on the ropsten network is 0x807505c10AA5E541D1C761518BaE4a47a92B30E8
. If you call the getHoldings
method on this contract passing '0x79F72bf22c6B8bd0Cd6F786Ad8C44fe6282Ec558' as the address parameter, you should get back [1, 2]
as a response. This is the call that when I execute on my elixir code fails with the mentioned error but works fine in my hardhat script.
This is the full stacktrace that I get when calling the get_holdings
method on iex
BlockchainService.get_holdings("0x79F72bf22c6B8bd0Cd6F786Ad8C44fe6282Ec558")
[error] GenServer ContractManager terminating
** (MatchError) no match of right hand side value: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2>>
(ex_abi 0.5.11) lib/abi/type_decoder.ex:371: ABI.TypeDecoder.decode_uint/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:271: anonymous fn/3 in ABI.TypeDecoder.decode_type/2
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:266: ABI.TypeDecoder.decode_type/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:311: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:333: anonymous fn/3 in ABI.TypeDecoder.decode_type/3
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:331: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:188: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:185: ABI.TypeDecoder.do_decode_raw/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:179: ABI.TypeDecoder.decode_raw/2
(exw3 0.6.1) lib/exw3/abi.ex:52: ExW3.Abi.decode_output/3
(exw3 0.6.1) lib/exw3/contract.ex:214: ExW3.Contract.eth_call_helper/4
(exw3 0.6.1) lib/exw3/contract.ex:480: ExW3.Contract.handle_call/3
(stdlib 3.17.1) gen_server.erl:721: :gen_server.try_handle_call/4
(stdlib 3.17.1) gen_server.erl:750: :gen_server.handle_msg/6
(stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.621.0>): {:call, {:ERC1155, :getHoldings, [696299995569393950282255116538730296933411112280]}}
State: %{ERC1155: [address: "0x807505c10AA5E541D1C761518BaE4a47a92B30E8", abi: %{:constructor => %{"inputs" => [%{"internalType" => "string", "name" => "baseURI", "type" => "string"}], "stateMutability" => "nonpayable", "type" => "constructor"}, "ApprovalForAll" => %{"anonymous" => false, "inputs" => [%{"indexed" => true, "internalType" => "address", "name" => "account", "type" => "address"}, %{"indexed" => true, "internalType" => "address", "name" => "operator", "type" => "address"}, %{"indexed" => false, "internalType" => "bool", "name" => "approved", "type" => "bool"}], "name" => "ApprovalForAll", "type" => "event"}, "FTMinted" => %{"anonymous" => false, "inputs" => [%{"indexed" => true, "internalType" => "address", "name" => "receiver", "type" => "address"}, %{"indexed" => true, "internalType" => "uint256", "name" => "id", "type" => "uint256"}, %{"indexed" => false, "internalType" => "uint256", "name" => "amount", "type" => "uint256"}, %{"indexed" => false, "internalType" => "uint256", "name" => "totalBalance", "type" => "uint256"}, %{"indexed" => false, "internalType" => "bool", "name" => "firstMint", "type" => "bool"}, %{"indexed" => true, "internalType" => "address", "name" => "minter", "type" => "address"}], "name" => "FTMinted", "type" => "event"}, "NFTMinted" => %{"anonymous" => false, "inputs" => [%{"indexed" => true, "internalType" => "address", "name" => "receiver", "type" => "address"}, %{"indexed" => true, "internalType" => "uint256", "name" => "id", "type" => "uint256"}, %{"indexed" => true, "internalType" => "address", "name" => "minter", "type" => "address"}], "name" => "NFTMinted", "type" => "event"}, "TransferBatch" => %{"anonymous" => false, "inputs" => [%{"indexed" => true, "internalType" => "address", "name" => "operator", "type" => "address"}, %{"indexed" => true, "internalType" => "address", "name" => "from", "type" => "address"}, %{"indexed" => true, "internalType" => "address", "name" => "to", "type" => "address"}, %{"indexed" => false, "internalType" => "uint256[]", "name" => "ids", "type" => "uint256[]"}, %{"indexed" => false, "internalType" => "uint256[]", "name" => "values", "type" => "uint256[]"}], "name" => "TransferBatch", "type" => "event"}, "TransferSingle" => %{"anonymous" => false, "inputs" => [%{"indexed" => true, "internalType" => "address", "name" => "operator", "type" => "address"}, %{"indexed" => true, "internalType" => "address", "name" => "from", "type" => "address"}, %{"indexed" => true, "internalType" => "address", "name" => "to", "type" => "address"}, %{"indexed" => false, "internalType" => "uint256", "name" => "id", "type" => "uint256"}, %{"indexed" => false, "internalType" => "uint256", "name" => "value", "type" => "uint256"}], "name" => "TransferSingle", "type" => "event"}, "URI" => %{"anonymous" => false, "inputs" => [%{"indexed" => false, "internalType" => "string", "name" => "value", "type" => "string"}, %{"indexed" => true, "internalType" => "uint256", "name" => "id", "type" => "uint256"}], "name" => "URI", "type" => "event"}, "balanceOf" => %{"inputs" => [%{"internalType" => "address", "name" => "account", "type" => "address"}, %{"internalType" => "uint256", "name" => "id", "type" => "uint256"}], "name" => "balanceOf", "outputs" => [%{"internalType" => "uint256", "name" => "", "type" => "uint256"}], "stateMutability" => "view", "type" => "function"}, "balanceOfBatch" => %{"inputs" => [%{"internalType" => "address[]", "name" => "accounts", "type" => "address[]"}, %{"internalType" => "uint256[]", "name" => "ids", "type" => "uint256[]"}], "name" => "balanceOfBatch", "outputs" => [%{"internalType" => "uint256[]", "name" => "", "type" => "uint256[]"}], "stateMutability" => "view", "type" => "function"}, "getHoldings" => %{"inputs" => [%{"internalType" => "address", "name" => "account", "type" => "address"}], "name" => "getHoldings", "outputs" => [%{"internalType" => "uint256[]", "name" => "", "type" => "uint256[]"}], "stateMutability" => "view", "type" => "function"}, "hasHoldings" => %{"inputs" => [%{"internalType" => "address", "name" => "account", "type" => "address"}], "name" => "hasHoldings", "outputs" => [%{"internalType" => "bool", "name" => "", "type" => "bool"}], "stateMutability" => "view", "type" => "function"}, "isApprovedForAll" => %{"inputs" => [%{"internalType" => "address", "name" => "account", "type" => "address"}, %{"internalType" => "address", "name" => "operator", "type" => "address"}], "name" => "isApprovedForAll", "outputs" => [%{"internalType" => "bool", "name" => "", "type" => "bool"}], "stateMutability" => "view", "type" => "function"}, "mintFungibleToken" => %{"inputs" => [%{"internalType" => "address", "name" => "to", "type" => "address"}, %{"internalType" => "uint256", "name" => "amount", "type" => "uint256"}], "name" => "mintFungibleToken", "outputs" => [%{"internalType" => "uint256", "name" => "", "type" => "uint256"}], "stateMutability" => "nonpayable", "type" => "function"}, "mintNonFungibleToken" => %{"inputs" => [%{"internalType" => "address", "name" => "to", "type" => "address"}], "name" => "mintNonFungibleToken", "outputs" => [%{"internalType" => "uint256", "name" => "", "type" => "uint256"}], "stateMutability" => "nonpayable", "type" => "function"}, "safeBatchTransferFrom" => %{"inputs" => [%{"internalType" => "address", "name" => "from", "type" => "address"}, %{"internalType" => "address", "name" => "to", "type" => "address"}, %{"internalType" => "uint256[]", "name" => "ids", "type" => "uint256[]"}, %{"internalType" => "uint256[]", "name" => "amounts", "type" => "uint256[]"}, %{"internalType" => "bytes", "name" => "data", "type" => "bytes"}], "name" => "safeBatchTransferFrom", "outputs" => [], "stateMutability" => "nonpayable", "type" => "function"}, "safeTransferFrom" => %{"inputs" => [%{"internalType" => "address", "name" => "from", "type" => "address"}, %{"internalType" => "address", "name" => "to", "type" => "address"}, %{"internalType" => "uint256", "name" => "id", "type" => "uint256"}, %{"internalType" => "uint256", "name" => "amount", "type" => "uint256"}, %{"internalType" => "bytes", "name" => "data", "type" => "bytes"}], "name" => "safeTransferFrom", "outputs" => [], "stateMutability" => "nonpayable", "type" => "function"}, "setApprovalForAll" => %{"inputs" => [%{"internalType" => "address", "name" => "operator", "type" => "address"}, %{"internalType" => "bool", "name" => "appr (truncated)
** (exit) exited in: GenServer.call(ContractManager, {:call, {:ERC1155, :getHoldings, [696299995569393950282255116538730296933411112280]}}, :infinity)
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2>>
(ex_abi 0.5.11) lib/abi/type_decoder.ex:371: ABI.TypeDecoder.decode_uint/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:271: anonymous fn/3 in ABI.TypeDecoder.decode_type/2
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:266: ABI.TypeDecoder.decode_type/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:311: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:333: anonymous fn/3 in ABI.TypeDecoder.decode_type/3
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:331: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:188: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.11) lib/abi/type_decoder.ex:185: ABI.TypeDecoder.do_decode_raw/2
(ex_abi 0.5.11) lib/abi/type_decoder.ex:179: ABI.TypeDecoder.decode_raw/2
(exw3 0.6.1) lib/exw3/abi.ex:52: ExW3.Abi.decode_output/3
(exw3 0.6.1) lib/exw3/contract.ex:214: ExW3.Contract.eth_call_helper/4
(exw3 0.6.1) lib/exw3/contract.ex:480: ExW3.Contract.handle_call/3
(stdlib 3.17.1) gen_server.erl:721: :gen_server.try_handle_call/4
(stdlib 3.17.1) gen_server.erl:750: :gen_server.handle_msg/6
(stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
(elixir 1.13.4) lib/gen_server.ex:1030: GenServer.call/3
Let me know if you need anything else.
Here is the raw JSON-RPC request
{"jsonrpc":"2.0","id":2,"method":"eth_call","params":[{"from":"0x0000000000000000000000000000000000000000","data":"0x1be52dc400000000000000000000000079f72bf22c6b8bd0cd6f786ad8c44fe6282ec558","to":"0x807505c10aa5e541d1c761518bae4a47a92b30e8"},"latest"]}
Here is the raw JSON-RPC response
{"jsonrpc":"2.0","id":2,"result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"}
@guidomb Hello. I'm sorry for a late reply (got stressed out at work)
I just tried decoding
selector = %ABI.FunctionSelector{
function: "getHoldings",
input_names: ["account"],
inputs_indexed: nil,
method_id: <<27, 229, 45, 196>>,
returns: [array: {:uint, 256}],
type: :function,
types: [:address]
}
result = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" |> Base.decode16!(case: :lower)
ABI.decode(selector, result, :output)
[[1, 2]]
it seems to be working fine
@ayrat555 No need to be sorry and thanks for taking the time to review it. I'm don't have my computer at the moment but I will try again a double check if it was a temporary error. For the particular use case I was working on I found an alternative solution.
Just to be sure you tested the desearlization method directly and it worked but did not perform an actual method call to the contract. Because if that's the case the bug might be in ExWeb3 in how it handles the RPC response and calls ExABI. I which case I'll submit an issue in ExWeb3.
Thanks
Just to be sure you tested the desearlization method directly and it worked but did not perform an actual method call to the contract. Because if that's the case the bug might be in ExWeb3 in how it handles the RPC response and calls ExABI. I which case I'll submit an issue in ExWeb3.
Yes, I just used the data that you provided. The issue may be in the ExWeb3