Skip to content

Commit

Permalink
Fix parsing tuples (#164)
Browse files Browse the repository at this point in the history
* Fix parsing tuples

* Add regression test for `tuple` parsing

* Apply suggestions
  • Loading branch information
fedor-ivn authored Mar 12, 2024
1 parent 5d63e8a commit e3dc19b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 20 deletions.
34 changes: 14 additions & 20 deletions lib/abi/function_selector.ex
Original file line number Diff line number Diff line change
Expand Up @@ -311,34 +311,28 @@ defmodule ABI.FunctionSelector do
end
end

@doc false
def parse_specification_type(%{"type" => "tuple", "components" => components}) do
sub_types = for component <- components, do: parse_specification_type(component)
{:tuple, sub_types}
defp replace_tuple({:array, inner}, sub_types) do
{:array, replace_tuple(inner, sub_types)}
end

def parse_specification_type(%{"type" => "tuple[]", "components" => components}) do
sub_types = for component <- components, do: parse_specification_type(component)
{:array, {:tuple, sub_types}}
defp replace_tuple({:array, inner, size}, sub_types) do
{:array, replace_tuple(inner, sub_types), size}
end

def parse_specification_type(%{"type" => "tuple[][]", "components" => components}) do
sub_types = for component <- components, do: parse_specification_type(component)
{:array, {:array, {:tuple, sub_types}}}
defp replace_tuple(:tuple, sub_types) do
{:tuple, sub_types}
end

def parse_specification_type(%{
"type" => "tuple[" <> tail,
"components" => components
}) do
sub_types = for component <- components, do: parse_specification_type(component)
defp replace_tuple(other, _) do
other
end

size =
tail
|> String.replace("]", "")
|> String.to_integer()
def parse_specification_type(%{"type" => "tuple" <> _ = type, "components" => components}) do
sub_types = for component <- components, do: parse_specification_type(component)

{:array, {:tuple, sub_types}, size}
type
|> decode_type()
|> replace_tuple(sub_types)
end

def parse_specification_type(%{"type" => type}), do: decode_type(type)
Expand Down
32 changes: 32 additions & 0 deletions test/abi/function_selector_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,38 @@ defmodule ABI.FunctionSelectorTest do
assert expected_type == selector.types
end

test "parses fixed 2D array of tuples" do
function = %{
"inputs" => [],
"name" => "createTupleArray",
"outputs" => [
%{
"components" => [
%{
"internalType" => "uint256",
"name" => "element1",
"type" => "uint256"
},
%{"internalType" => "bool", "name" => "element2", "type" => "bool"}
],
"internalType" => "struct StorageB.MyTuple[2][]",
"name" => "",
"type" => "tuple[2][]"
}
],
"stateMutability" => "pure",
"type" => "function"
}

expected = [
array: {:array, {:tuple, [{:uint, 256}, :bool]}, 2}
]

selector = FunctionSelector.parse_specification_item(function)

assert expected == selector.returns
end

test "with stateMutability set" do
~w(pure view nonpayable payable)
|> Enum.zip(~w(pure view non_payable payable)a)
Expand Down

0 comments on commit e3dc19b

Please sign in to comment.