Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when decoding array #19

Closed
saneery opened this issue Apr 30, 2019 · 3 comments
Closed

Error when decoding array #19

saneery opened this issue Apr 30, 2019 · 3 comments

Comments

@saneery
Copy link
Contributor

saneery commented Apr 30, 2019

When I try to decode an array of addresses, I get an error

iex(1)> data = Base.decode16!("000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000aa94b687d3f9552a453b81b2834ca53778980dc0000000000000000000000000312c230e7d6db05224f60208a656e3541c5c42ba", case: :lower)
<<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, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>
iex(2)> selector = %ABI.FunctionSelector{function: nil, types: [array: :address]}                                
%ABI.FunctionSelector{
  function: nil,
  input_names: [],
  inputs_indexed: nil,
  method_id: nil,
  returns: [],
  type: nil,
  types: [array: :address]
}
iex(3)> ABI.TypeDecoder.decode(data, selector)
** (MatchError) no match of right hand side value: ""
    (ex_abi) lib/abi/type_decoder.ex:195: ABI.TypeDecoder.decode_bytes/3
    (ex_abi) lib/abi/type_decoder.ex:233: anonymous fn/2 in ABI.TypeDecoder.decode_type/2
    (elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_abi) lib/abi/type_decoder.ex:228: ABI.TypeDecoder.decode_type/2
    (ex_abi) lib/abi/type_decoder.ex:222: ABI.TypeDecoder.decode_type/2
    (ex_abi) lib/abi/type_decoder.ex:173: anonymous fn/2 in ABI.TypeDecoder.do_decode_raw/2
    (elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_abi) lib/abi/type_decoder.ex:172: ABI.TypeDecoder.do_decode_raw/2

On the 0.1.18 version all right:

...
iex(3)> ABI.TypeDecoder.decode(data, selector)
[
  [
    <<11, 47, 94, 47, 60, 189, 134, 78, 170, 44, 100, 46, 55, 105, 193, 88, 35,
      97, 202, 246>>,
    <<170, 148, 182, 135, 211, 249, 85, 42, 69, 59, 129, 178, 131, 76, 165, 55,
      120, 152, 13, 192>>,
    <<49, 44, 35, 14, 125, 109, 176, 82, 36, 246, 2, 8, 166, 86, 227, 84, 28,
      92, 66, 186>>
  ]
]
@saneery
Copy link
Contributor Author

saneery commented Apr 30, 2019

I think, there is a bug in TypeDecoder.decode_uint/2

defp decode_type({:array, type}, data) do
{count, bytes} = decode_uint(data, 256)
decode_type({:array, type, count}, bytes)
end

when I set IO.inspect(count), it returns 32

@volnyvolnyvolny
Copy link

@saneery, it seems that you trying to decode value that is wrapped in a tuple:

iex(1)> addresses = [
...(1)>     <<11, 47, 94, 47, 60, 189, 134, 78, 170, 44, 100, 46, 55, 105, 193, 88, 35,
...(1)>       97, 202, 246>>, r
...(1)>     <<170, 148, 182, 135, 211, 249, 85, 42, 69, 59, 129, 178, 131, 76, 165, 55,
...(1)>       120, 152, 13, 192>>,
...(1)>     <<49, 44, 35, 14, 125, 109, 176, 82, 36, 246, 2, 8, 166, 86, 227, 84, 28,
...(1)>       92, 66, 186>>
...(1)>   ]
iex(2)> value = "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000aa94b687d3f9552a453b81b2834ca53778980dc0000000000000000000000000312c230e7d6db05224f60208a656e3541c5c42ba"
iex(3)> value == ABI.TypeEncoder.encode_raw([{addresses}], [{:tuple, [array: :address]}]) |> Base.encode16(case: :lower)
true

If you look at the:

iex(4)> for <<b::binary-64 <- value>>, do: b 
["0000000000000000000000000000000000000000000000000000000000000020",
 "0000000000000000000000000000000000000000000000000000000000000003",
 "0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6",
 "000000000000000000000000aa94b687d3f9552a453b81b2834ca53778980dc0",
 "000000000000000000000000312c230e7d6db05224f60208a656e3541c5c42ba"]

you'll notice that the first 32 bytes represent the array offset:

 "0000000000000000000000000000000000000000000000000000000000000020"

The correct representation is:

iex(5)> enc = ABI.TypeEncoder.encode_raw([addresses], [array: :address]) |> Base.encode16(case: :lower)
iex(6)> for <<b::binary-64 <- enc>>, do: b
["0000000000000000000000000000000000000000000000000000000000000003",
 "0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6",
 "000000000000000000000000aa94b687d3f9552a453b81b2834ca53778980dc0",
 "000000000000000000000000312c230e7d6db05224f60208a656e3541c5c42ba"]

You can test it with:

iex(7)> selector = %ABI.FunctionSelector{types: [array: :address]}
iex(8)> data = Base.decode16!(String.slice(value, 64..-1), case: :lower)
iex(9)> ABI.TypeDecoder.decode(data, selector)
[
  [
    <<11, 47, 94, 47, 60, 189, 134, 78, 170, 44, 100, 46, 55, 105, 193, 88, 35,
      97, 202, 246>>,
    <<170, 148, 182, 135, 211, 249, 85, 42, 69, 59, 129, 178, 131, 76, 165, 55,
      120, 152, 13, 192>>,
    <<49, 44, 35, 14, 125, 109, 176, 82, 36, 246, 2, 8, 166, 86, 227, 84, 28,
      92, 66, 186>>
  ]
]

@vbaranov
Copy link
Collaborator

@zergera Thanks for the thorough explanation of dynamic size array ABI decoding. Nevertheless, ABI.TypeDecoder.decode(data, selector) should decode to an array without additional step which makes an offset

data = Base.decode16!(String.slice(value, 64..-1), case: :lower)

It should be made inside the decoding method. And this is done in the recently issued 0.3.0 version of the library. I am closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants