ABI.FunctionSelector (abi v1.3.0)

Module to help parse the ABI function signatures, e.g. my_function(uint64, string[]).

Summary

Functions

Decodes a function selector to a struct.

Decodes the given type-string as a simple array of types.

Decodes the given type-string as a single type.

Encodes a function call signature. If indexed=true, returns the "indexed" keyword after indexed parameters.

Parse a function selector, e.g. from an abi.json file.

Types

Link to this type

argument_type()

@type argument_type() :: %{
  :type => type(),
  optional(:name) => String.t(),
  optional(:indexed) => boolean()
}
Link to this type

function_type()

@type function_type() ::
  :function | :constructor | :fallback | :receive | :error | :event
Link to this type

state_mutability()

@type state_mutability() :: :nonpayable | :pure | :view | :payable
@type t() :: %ABI.FunctionSelector{
  function: String.t(),
  function_type: function_type() | nil,
  returns: type(),
  state_mutability: state_mutability() | nil,
  types: [argument_type()]
}
@type type() ::
  {:uint, integer()}
  | :bool
  | :bytes
  | :string
  | :address
  | {:int, integer()}
  | {:array, type()}
  | {:array, type(), non_neg_integer()}
  | {:tuple, [argument_type()]}

Functions

Link to this function

decode(signature)

Decodes a function selector to a struct.

Examples

iex> ABI.FunctionSelector.decode("bark(uint256,bool)")
%ABI.FunctionSelector{
  function: "bark",
  types: [
    %{type: {:uint, 256}},
    %{type: :bool}
  ]
}

iex> ABI.FunctionSelector.decode("bark(uint256 name, bool loud)")
%ABI.FunctionSelector{
  function: "bark",
  types: [
    %{type: {:uint, 256}, name: "name"},
    %{type: :bool, name: "loud"}
  ]
}

iex> ABI.FunctionSelector.decode("bark(uint256 name,bool indexed loud)")
%ABI.FunctionSelector{
  function: "bark",
  types: [
    %{type: {:uint, 256}, name: "name"},
    %{type: :bool, name: "loud", indexed: true}
  ]
}

iex> ABI.FunctionSelector.decode("(uint256,bool)")
%ABI.FunctionSelector{
  function: nil,
  types: [
    %{type: {:uint, 256}},
    %{type: :bool}
  ]
}

iex> ABI.FunctionSelector.decode("growl(uint,address,string[])")
%ABI.FunctionSelector{
  function: "growl",
  types: [
    %{type: {:uint, 256}},
    %{type: :address},
    %{type: {:array, :string}}
  ]
}

iex> ABI.FunctionSelector.decode("rollover()")
%ABI.FunctionSelector{
  function: "rollover",
  types: []
}

iex> ABI.FunctionSelector.decode("do_playDead3()")
%ABI.FunctionSelector{
  function: "do_playDead3",
  types: []
}

iex> ABI.FunctionSelector.decode("pet(address[])")
%ABI.FunctionSelector{
  function: "pet",
  types: [
    %{type: {:array, :address}}
  ]
}

iex> ABI.FunctionSelector.decode("paw(string[2])")
%ABI.FunctionSelector{
  function: "paw",
  types: [
    %{type: {:array, :string, 2}}
  ]
}

iex> ABI.FunctionSelector.decode("scram(uint256[])")
%ABI.FunctionSelector{
  function: "scram",
  types: [
    %{type: {:array, {:uint, 256}}}
  ]
}

iex> ABI.FunctionSelector.decode("shake((string))")
%ABI.FunctionSelector{
  function: "shake",
  types: [
    %{type: {:tuple, [%{type: :string}]}}
  ]
}
Link to this function

decode_raw(type_string)

Decodes the given type-string as a simple array of types.

Examples

iex> ABI.FunctionSelector.decode_raw("string,uint256")
[:string, {:uint, 256}]

iex> ABI.FunctionSelector.decode_raw("")
[]
Link to this function

decode_type(single_type)

Decodes the given type-string as a single type.

Examples

iex> ABI.FunctionSelector.decode_type("uint256")
{:uint, 256}

iex> ABI.FunctionSelector.decode_type("(bool,address)")
{:tuple, [%{type: :bool}, %{type: :address}]}

iex> ABI.FunctionSelector.decode_type("address[][3]")
{:array, {:array, :address}, 3}
Link to this function

encode(function_selector, indexed \\ false, names \\ false)

Encodes a function call signature. If indexed=true, returns the "indexed" keyword after indexed parameters.

Example

iex> ABI.FunctionSelector.encode(%ABI.FunctionSelector{
...>   function: "bark",
...>   types: [
...>     %{type: {:uint, 256}},
...>     %{type: :bool, indexed: true},
...>     %{type: {:array, :string}},
...>     %{type: {:array, :string, 3}},
...>     %{type: {:tuple, [%{type: {:uint, 256}}, %{type: :bool}]}}
...>   ]
...> })
"bark(uint256,bool,string[],string[3],(uint256,bool))"

iex> ABI.FunctionSelector.encode(%ABI.FunctionSelector{
...>   function: "bark",
...>   types: [
...>     %{type: {:uint, 256}},
...>     %{type: :bool, indexed: true},
...>     %{type: {:array, :string}},
...>     %{type: {:array, :string, 3}},
...>     %{type: {:tuple, [%{type: {:uint, 256}}, %{type: :bool}]}}
...>   ]
...> }, true)
"bark(uint256,bool indexed,string[],string[3],(uint256,bool))"

iex> ABI.FunctionSelector.encode(%ABI.FunctionSelector{
...>   function: "bark",
...>   types: [
...>     %{type: {:uint, 256}},
...>     %{type: :bool, indexed: true},
...>     %{type: {:array, :string}},
...>     %{type: {:array, :string, 3}},
...>     %{type: {:tuple, [%{type: {:uint, 256}}, %{type: :bool}]}}
...>   ]
...> }, true, true)
"bark(uint256 var0,bool indexed var1,string[] var2,string[3] var3,(uint256,bool) var4)"

iex> ABI.FunctionSelector.encode(%ABI.FunctionSelector{
...>   function: "bark",
...>   types: [
...>     %{type: {:uint, 256}},
...>     %{type: :bool, indexed: true},
...>     %{type: {:array, :string}},
...>     %{type: {:array, :string, 3}},
...>     %{type: {:tuple, [%{type: {:uint, 256}}, %{type: :bool}]}}
...>   ]
...> }, false, true)
"bark(uint256 var0,bool var1,string[] var2,string[3] var3,(uint256,bool) var4)"

iex> ABI.FunctionSelector.encode(%ABI.FunctionSelector{
...>   function: "bark",
...>   types: [
...>     %{type: {:uint, 256}, name: "a"},
...>     %{type: :bool, indexed: true, name: "b"},
...>     %{type: {:array, :string}, name: "c"},
...>     %{type: {:array, :string, 3}, name: "d"},
...>     %{type: {:tuple, [%{type: {:uint, 256}}, %{type: :bool}]}, name: "e"}
...>   ]
...> }, false, true)
"bark(uint256 a,bool b,string[] c,string[3] d,(uint256,bool) e)"
Link to this function

parse_specification_item(item)

Parse a function selector, e.g. from an abi.json file.

Examples

iex> ABI.FunctionSelector.parse_specification_item(%{"type" => "function", "name" => "fun", "inputs" => [%{"name" => "a", "type" => "uint96", "internalType" => "uint96"}]})
%ABI.FunctionSelector{
  function: "fun",
  function_type: :function,
  types: [%{type: {:uint, 96}, name: "a"}],
  returns: nil
}

iex> ABI.FunctionSelector.parse_specification_item(%{"type" => "function", "name" => "fun", "inputs" => [%{"name" => "s", "type" => "tuple", "internalType" => "tuple", "components" => [%{"name" => "a", "type" => "uint256", "internalType" => "uint256"},%{"name" => "b", "type" => "address", "internalType" => "address"},%{"name" => "c", "type" => "bytes", "internalType" => "bytes"}]},%{"name" => "d", "type" => "uint256", "internalType" => "uint256"}],"outputs" => [%{"name" => "", "type" => "bytes", "internalType" => "bytes"}],"stateMutability" => "view"})
%ABI.FunctionSelector{
  function: "fun",
  function_type: :function,
  state_mutability: :view,
  types: [
    %{
      type:
        {:tuple, [
          %{type: {:uint, 256}, name: "a"},
          %{type: :address, name: "b"},
          %{type: :bytes, name: "c"}
        ]},
        name: "s"
    }, %{
      type: {:uint, 256},
      name: "d"
    }
  ],
  returns: [%{name: "", type: :bytes}],
}

iex> ABI.FunctionSelector.parse_specification_item(%{"type" => "function", "name" => "fun", "inputs" => [%{"name" => "s", "type" => "tuple", "internalType" => "struct Contract.Struct", "components" => [%{"name" => "a", "type" => "uint256", "internalType" => "uint256"},%{"name" => "b", "type" => "address", "internalType" => "address"},%{"name" => "c", "type" => "bytes", "internalType" => "bytes"}]},%{"name" => "d", "type" => "uint256", "internalType" => "uint256"}],"outputs" => [%{"name" => "", "type" => "bytes", "internalType" => "bytes"}],"stateMutability" => "pure"})
%ABI.FunctionSelector{
  function: "fun",
  function_type: :function,
  state_mutability: :pure,
  types: [
    %{
      type:
        {:tuple, [
          %{type: {:uint, 256}, name: "a"},
          %{type: :address, name: "b"},
          %{type: :bytes, name: "c"}
        ]},
        name: "s"
    }, %{
      type: {:uint, 256},
      name: "d"
    }
  ],
  returns: [%{name: "", type: :bytes}],
}

iex> ABI.FunctionSelector.parse_specification_item(%{"type" => "function", "name" => "fun", "inputs" => [%{"name" => "s", "type" => "tuple", "internalType" => "struct Contract.Struct", "components" => [%{"name" => "a", "type" => "uint256", "internalType" => "uint256"},%{"type" => "address", "internalType" => "address"},%{"name" => "c", "type" => "bytes", "internalType" => "bytes"}]},%{"name" => "d", "type" => "uint256", "internalType" => "uint256"}],"outputs" => [%{"name" => "", "type" => "bytes", "internalType" => "bytes"}],"stateMutability" => "payable"})
%ABI.FunctionSelector{
  function: "fun",
  function_type: :function,
  state_mutability: :payable,
  types: [
    %{
      type:
        {:tuple, [
          %{type: {:uint, 256}, name: "a"},
          %{type: :address},
          %{type: :bytes, name: "c"}
        ]},
        name: "s"
    }, %{
      type: {:uint, 256},
      name: "d"
    }
  ],
  returns: [%{name: "", type: :bytes}],
}

iex> ABI.FunctionSelector.parse_specification_item(%{"type" => "fallback"})
%ABI.FunctionSelector{
  function: nil,
  function_type: :fallback,
  types: [],
  returns: nil
}

iex> ABI.FunctionSelector.parse_specification_item(%{"type" => "receive"})
%ABI.FunctionSelector{
  function: nil,
  function_type: :receive,
  types: [],
  returns: nil
}

iex> ABI.FunctionSelector.parse_specification_item(%{"inputs" => [%{"internalType" => "address[]", "name" => "xs", "type" => "address[]"}, %{"internalType" => "bytes[]", "name" => "ys", "type" => "bytes[]"}, %{"components" => [%{"internalType" => "enum Z", "name" => "za", "type" => "uint8"}, %{"internalType" => "enum Z", "name" => "zb", "type" => "uint8"}], "internalType" => "struct Z.Z[]", "name" => "zs", "type" => "tuple[]"}, %{"internalType" => "bytes[]", "name" => "zz", "type" => "bytes[]"}], "name" => "go", "outputs" => [%{"internalType" => "bytes[]", "name" => "", "type" => "bytes[]"}], "stateMutability" => "nonpayable", "type" => "function"})
%ABI.FunctionSelector{
  function: "go",
  function_type: :function,
  state_mutability: :nonpayable,
  types: [
    %{name: "xs", type: {:array, :address}},
    %{name: "ys", type: {:array, :bytes}},
    %{
      name: "zs",
      type:
        {:array,
         {:tuple,
          [%{name: "za", type: {:uint, 8}}, %{name: "zb", type: {:uint, 8}}]}}
    },
    %{name: "zz", type: {:array, :bytes}}
  ],
  returns: [%{name: "", type: {:array, :bytes}}]
}

iex> ABI.FunctionSelector.parse_specification_item(%{"anonymous" => false, "inputs" => [%{"indexed" => true, "internalType" => "address", "name" => "z0", "type" => "address"}, %{"indexed" => true, "internalType" => "address", "name" => "z1", "type" => "address"}, %{"indexed" => false, "internalType" => "address", "name" => "z2", "type" => "address"}, %{"indexed" => false, "internalType" => "bytes32", "name" => "z3", "type" => "bytes32"}], "name" => "z4", "type" => "event"})
%ABI.FunctionSelector{
  function: "z4",
  function_type: :event,
  state_mutability: nil,
  types: [
    %{name: "z0", type: :address, indexed: true},
    %{name: "z1", type: :address, indexed: true},
    %{name: "z2", type: :address, indexed: false},
    %{name: "z3", type: {:bytes, 32}, indexed: false}
  ],
  returns: nil
}

iex> ABI.FunctionSelector.parse_specification_item(%{"inputs" => [], "name" => "Abc", "type" => "error"})
%ABI.FunctionSelector{function: "Abc", function_type: :error, state_mutability: nil, types: [], returns: nil}