diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bb53e0..862cf2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.7.1 +* Fix parsing of nested tuples (https://github.com/poanetwork/ex_abi/pull/164) +* Fix parsing of functions the outputs field (https://github.com/poanetwork/ex_abi/pull/163) ## 0.7.0 * Store 32 byte even signatures instead of 4 bytes (https://github.com/poanetwork/ex_abi/pull/157) ## 0.6.4 diff --git a/README.md b/README.md index 58240e4..b327601 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ by adding `ex_abi` to your list of dependencies in `mix.exs`: ```elixir def deps do [ - {:ex_abi, "~> 0.7.0"} + {:ex_abi, "~> 0.7.1"} ] end ``` diff --git a/lib/abi/event.ex b/lib/abi/event.ex index 8c28356..807d8c7 100644 --- a/lib/abi/event.ex +++ b/lib/abi/event.ex @@ -91,7 +91,7 @@ defmodule ABI.Event do defp indexed_arg_values([{_, type, _} | rest_args], [topic | rest_topics], acc) do value = - if ABI.FunctionSelector.is_dynamic?(type) do + if ABI.FunctionSelector.dynamic?(type) do {bytes, _} = ABI.TypeDecoder.decode_bytes(topic, 32, :left) # This is explained in the docstring. The caller will almost certainly diff --git a/lib/abi/function_selector.ex b/lib/abi/function_selector.ex index 61068da..65789ba 100644 --- a/lib/abi/function_selector.ex +++ b/lib/abi/function_selector.ex @@ -182,28 +182,8 @@ defmodule ABI.FunctionSelector do "outputs" => named_outputs } <- item - # Workaround for ABIs that are missing the "outputs" field. - # - # For instance, consider this valid ABI: - # - # ```jsonc - # // ... - # { - # "type": "function", - # "stateMutability": "view", - # "name": "assumeLastTokenIdMatches", - # "inputs": [ - # { - # "type": "uint256", - # "name": "lastTokenId", - # "internalType": "uint256" - # } - # ] - # }, - # // ... - # ``` - # If the "outputs" field is missing, we should assume it's an empty - # list to continue parsing the ABI. + + # Workaround for ABIs that are missing the "outputs" field |> Map.put_new("outputs", []), true <- simple_types?(named_inputs, item), true <- simple_types?(named_outputs, item) do @@ -469,13 +449,13 @@ defmodule ABI.FunctionSelector do defp get_type(els), do: raise("Unsupported type: #{inspect(els)}") @doc false - @spec is_dynamic?(ABI.FunctionSelector.type()) :: boolean - def is_dynamic?(:bytes), do: true - def is_dynamic?(:string), do: true - def is_dynamic?({:array, _type}), do: true - def is_dynamic?({:array, type, len}) when len > 0, do: is_dynamic?(type) - def is_dynamic?({:tuple, types}), do: Enum.any?(types, &is_dynamic?/1) - def is_dynamic?(_), do: false + @spec dynamic?(ABI.FunctionSelector.type()) :: boolean + def dynamic?(:bytes), do: true + def dynamic?(:string), do: true + def dynamic?({:array, _type}), do: true + def dynamic?({:array, type, len}) when len > 0, do: dynamic?(type) + def dynamic?({:tuple, types}), do: Enum.any?(types, &dynamic?/1) + def dynamic?(_), do: false @doc false def from_params(params) when is_map(params) do diff --git a/lib/abi/type_decoder.ex b/lib/abi/type_decoder.ex index 4fb2d8b..edbcaae 100644 --- a/lib/abi/type_decoder.ex +++ b/lib/abi/type_decoder.ex @@ -184,7 +184,7 @@ defmodule ABI.TypeDecoder do {reversed_result, binary_rest} = Enum.reduce(types, {[], binary_data}, fn type, {acc, binary} -> {value, rest} = - if FunctionSelector.is_dynamic?(type) do + if FunctionSelector.dynamic?(type) do decode_type(type, binary, binary_data) else decode_type(type, binary) @@ -262,7 +262,7 @@ defmodule ABI.TypeDecoder do defp decode_type({:tuple, types}, data) do {reversed_result, _, binary} = Enum.reduce(types, {[], [], data}, fn type, {acc, dynamic, binary} -> - if FunctionSelector.is_dynamic?(type) do + if FunctionSelector.dynamic?(type) do {val, binary} = decode_type(type, binary, data) {[val | acc], [type | dynamic], binary} else @@ -323,7 +323,7 @@ defmodule ABI.TypeDecoder do {reversed_result, _, _binary} = Enum.reduce(types, {[], [], tuple_data}, fn type, {acc, dynamic, binary} -> - if FunctionSelector.is_dynamic?(type) do + if FunctionSelector.dynamic?(type) do {val, binary} = decode_type(type, binary, tuple_data) {[val | acc], [type | dynamic], binary} else diff --git a/lib/abi/type_encoder.ex b/lib/abi/type_encoder.ex index bbf2041..a105e7c 100644 --- a/lib/abi/type_encoder.ex +++ b/lib/abi/type_encoder.ex @@ -193,7 +193,7 @@ defmodule ABI.TypeEncoder do types = List.duplicate(type, size) result = do_encode(data, types, mode) - if FunctionSelector.is_dynamic?(type) do + if FunctionSelector.dynamic?(type) do data_bytes_size = byte_size(result) {[{:dynamic, data_bytes_size} | static_acc], [result | dynamic_acc]} @@ -227,7 +227,7 @@ defmodule ABI.TypeEncoder do when is_list(list_parameters) do result = do_encode(list_parameters, types, :standard) - if FunctionSelector.is_dynamic?(type) do + if FunctionSelector.dynamic?(type) do data_bytes_size = byte_size(result) {[{:dynamic, data_bytes_size} | static_acc], [result | dynamic_acc]} diff --git a/mix.exs b/mix.exs index 97189f5..1355868 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ABI.Mixfile do def project do [ app: :ex_abi, - version: "0.7.0", + version: "0.7.1", elixir: "~> 1.8", description: "Ethereum's ABI Interface", package: [ diff --git a/mix.lock b/mix.lock index 77da9cc..346d99c 100644 --- a/mix.lock +++ b/mix.lock @@ -1,19 +1,19 @@ %{ - "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, - "castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, - "credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"}, - "dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"}, + "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, + "castore": {:hex, :castore, "1.0.6", "ffc42f110ebfdafab0ea159cd43d31365fa0af0ce4a02ecebf1707ae619ee727", [:mix], [], "hexpm", "374c6e7ca752296be3d6780a6d5b922854ffcc74123da90f2f328996b962d33a"}, + "credo": {:hex, :credo, "1.7.5", "643213503b1c766ec0496d828c90c424471ea54da77c8a168c725686377b9545", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f799e9b5cd1891577d8c773d245668aa74a2fcd15eb277f51a0131690ebfb3fd"}, + "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, + "ex_doc": {:hex, :ex_doc, "0.31.2", "8b06d0a5ac69e1a54df35519c951f1f44a7b7ca9a5bb7a260cd8a174d6322ece", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "317346c14febaba9ca40fd97b5b5919f7751fb85d399cc8e7e8872049f37e0af"}, "ex_keccak": {:hex, :ex_keccak, "0.7.3", "33298f97159f6b0acd28f6e96ce5ea975a0f4a19f85fe615b4f4579b88b24d06", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.6.1", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "4c5e6d9d5f77b64ab48769a0166a9814180d40ced68ed74ce60a5174ab55b3fc"}, - "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"}, - "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, + "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, "propcheck": {:hex, :propcheck, "1.4.1", "c12908dbe6f572032928548089b34ff9d40672d5d70f1562e3a9e9058d226cc9", [:mix], [{:libgraph, "~> 0.13", [hex: :libgraph, repo: "hexpm", optional: false]}, {:proper, "~> 1.4", [hex: :proper, repo: "hexpm", optional: false]}], "hexpm", "e1b088f574785c3c7e864da16f39082d5599b3aaf89086d3f9be6adb54464b19"}, "proper": {:hex, :proper, "1.4.0", "89a44b8c39d28bb9b4be8e4d715d534905b325470f2e0ec5e004d12484a79434", [:rebar3], [], "hexpm", "18285842185bd33efbda97d134a5cb5a0884384db36119fee0e3cfa488568cbb"}, "rustler_precompiled": {:hex, :rustler_precompiled, "0.6.3", "f838d94bc35e1844973ee7266127b156fdc962e9e8b7ff666c8fb4fed7964d23", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "e18ecca3669a7454b3a2be75ae6c3ef01d550bc9a8cf5fbddcfff843b881d7c6"},