# `ABI.TypeDecoder`
[🔗](https://github.com/ZenHive/hieroglyph/blob/main/lib/abi/type_decoder.ex#L1)

`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.

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `decode_bytes` | 3 | Read size_in_bytes of content from a 32-byte-aligned ABI word, skipping padding on the matching side. Used to extract address, uint/int, bytes<M>, and string payloads from their slots. | `data: value`, `size_in_bytes: value`, `padding_direction: value` |
| `tuple_value` | 3 | Combine a list of ABI argument types with decoded element values, returning either a tuple or, when decode_structs is enabled and every type carries a non-empty :name, a map keyed by snake_case atom field names. | `types: value`, `elements: value`, `decode_structs: value` |
| `decode_raw` | 3 | Decode an ABI-encoded payload directly against an explicit type list, without consulting a FunctionSelector. | `encoded_data: value`, `types: value`, `opts: value` |
| `decode` | 3 | Decode an ABI-encoded payload into a list of values, using a FunctionSelector to drive type interpretation. | `encoded_data: value`, `function_selector: value`, `opts: value` |

# `decode`

```elixir
@spec decode(binary(), ABI.FunctionSelector.t(), keyword()) :: [any()]
```

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"]

# `decode_bytes`

```elixir
@spec decode_bytes(binary(), integer(), atom()) :: {binary(), binary()}
```

Reads `size_in_bytes` of content out of `data`, skipping the 32-byte-slot
padding on whichever side matches `padding_direction` (`:left` for
left-padded types like `address` and `uint`/`int`, `:right` for
right-padded types like `bytes<M>` and `string`). Returns `{value, rest}`.

# `decode_raw`

```elixir
@spec decode_raw(binary(), [ABI.FunctionSelector.argument_type()], keyword()) :: [
  any()
]
```

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}]

# `tuple_value`

```elixir
@spec tuple_value([ABI.FunctionSelector.argument_type()], [any()], boolean()) ::
  map() | tuple()
```

Combines a list of ABI argument types with a list of decoded element values
into either a tuple or (when `decode_structs` is true and every type carries
a non-empty `:name`) a map keyed by the existing snake_case atom for each
field name.

Field-name atoms must already exist in the VM atom table — `decode_structs:
true` calls `String.to_existing_atom/1` on `Macro.underscore(name)` and
raises `ArgumentError` if the atom has not been interned. This bounds atom
creation to the set of field names the caller has explicitly referenced in
their code, closing a DoS surface for consumers that ingest ABIs from
arbitrary sources.

Used internally by `decode_type({:tuple, types}, ...)` to render the
second-pass result; exposed because event-log decoding in `ABI.Event`
reuses the same shape.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
