ABI.TypeDecoder (abi v1.1.0)

ABI.TypeDecoder is responsible for decoding types to the format expected by Solidity. We generally take a function selector and binary data and decode that into the original arguments according to the specification.

Summary

Types

Link to this type

decode_options()

@type decode_options() :: %{optional(:decode_structs) => boolean()}

Functions

Link to this function

decode(encoded_data, function_selector, opts \\ [])

Decodes the given data based on the function selector.

Note, we don't currently try to guess the function name?

Examples

iex> "00000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: "baz",
...>        types: [
...>          %{type: {:uint, 32}},
...>          %{type: :bool}
...>        ],
...>        returns: :bool
...>      }
...>    )
[69, true]

iex> "000000000000000000000000000000000000000000000000000000000000000b68656c6c6f20776f726c64000000000000000000000000000000000000000000"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: :string}
...>        ]
...>      }
...>    )
["hello world"]

iex> "00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000001"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:tuple, [%{type: {:uint, 32}, name: "a"}, %{type: :bool, name: "b"}]}}
...>        ]
...>      }
...>    )
[{17, true}]

iex> "00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000001"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:tuple, [%{type: {:uint, 32}, name: "a"}, %{type: :bool, name: "b"}]}}
...>        ]
...>      },
...>      decode_structs: true
...>    )
[%{a: 17, b: true}]

iex> "00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000001"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:tuple, [%{type: {:uint, 32}}, %{type: :bool}]}}
...>        ]
...>      }
...>    )
[{17, true}]

iex> "00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000001"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:array, {:uint, 32}, 2}}
...>        ]
...>      }
...>    )
[[17, 1]]

iex> "000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000001"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:array, {:uint, 32}}}
...>        ]
...>      }
...>    )
[[17, 1]]

iex> "0000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011020000000000000000000000000000000000000000000000000000000000000"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:array, {:uint, 32}, 2}},
...>          %{type: :bool},
...>          %{type: {:bytes, 2}}
...>        ]
...>      }
...>    )
[[17, 1], true, <<16, 32>>]

iex> "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007617765736f6d6500000000000000000000000000000000000000000000000000"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:tuple, [%{type: :string}, %{type: :bool}]}}
...>        ]
...>      }
...>    )
[{"awesome", true}]

iex> "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [
...>          %{type: {:tuple, [%{type: {:array, :address}}]}}
...>        ]
...>      }
...>    )
[{[]}]

iex> "00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000c556e617574686f72697a656400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000204a2bf2ff0a4eaf1890c8d8679eaa446fb852c4000000000000000000000000861d9af488d5fa485bb08ab6912fff4f7450849a"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: nil,
...>        types: [%{type: {:tuple,[
...>          %{type: :string},
...>          %{type: {:array, {:uint, 256}}}
...>        ]}}]
...>      }
...>    )
[{
  "Unauthorized",
  [
    184341788326688649239867304918349890235378717380,
    765664983403968947098136133435535343021479462042,
  ]
}]

iex> "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034241540000000000000000000000000000000000000000000000000000000000"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode(
...>      %ABI.FunctionSelector{
...>        function: "price",
...>        types: [
...>          %{type: :string}
...>        ],
...>        returns: {:uint, 256}
...>      }
...>    )
["BAT"]
Link to this function

decode_bytes(data, size_in_bytes, padding_direction)

@spec decode_bytes(binary(), integer(), atom()) :: {binary(), binary()}
Link to this function

decode_raw(encoded_data, types, opts \\ [])

Similar to ABI.TypeDecoder.decode/2 except accepts a list of types instead of a function selector.

Examples

iex> "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007617765736f6d6500000000000000000000000000000000000000000000000000"
...> |> Base.decode16!(case: :lower)
...> |> ABI.TypeDecoder.decode_raw([%{type: {:tuple, [%{type: :string}, %{type: :bool}]}}])
[{"awesome", true}]
Link to this function

tuple_value(types, elements, decode_structs)