Packages
abi
1.0.0-alpha3
1.3.0
1.2.0
1.1.0
1.0.0-bravo6
1.0.0-bravo4
1.0.0-bravo3
1.0.0-bravo2
1.0.0-bravo1
1.0.0-alpha9
1.0.0-alpha8
1.0.0-alpha7
1.0.0-alpha6
1.0.0-alpha5
1.0.0-alpha4
1.0.0-alpha3
1.0.0-alpha2
1.0.0-alpha1
0.1.21
0.1.21-alpha2
0.1.21-alpha1
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Ethereum's ABI Interface
Current section
Files
Jump to
Current section
Files
lib/abi/event.ex
defmodule ABI.Event do
@doc ~S"""
Decodes an event, including handling parsing out data from topics.
## Examples
iex> "00000000000000000000000000000000000000000000000000000004a817c800"
...> |> Base.decode16!(case: :lower)
...> |> ABI.Event.decode_event(
...> [
...> "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" |> Base.decode16!(case: :lower),
...> "000000000000000000000000b2b7c1795f19fbc28fda77a95e59edbb8b3709c8" |> Base.decode16!(case: :lower),
...> "0000000000000000000000007795126b3ae468f44c901287de98594198ce38ea" |> Base.decode16!(case: :lower)
...> ],
...> %ABI.FunctionSelector{
...> function: "Transfer",
...> types: [
...> %{type: :address, name: "from", indexed: true},
...> %{type: :address, name: "to", indexed: true},
...> %{type: {:uint, 256}, name: "amount"},
...> ]
...> })
{"Transfer",
%{
"amount" => 20_000_000_000,
"from" => <<252, 55, 141, 170, 149, 43, 167, 241, 99, 196, 161, 22, 40, 245, 90, 77, 245, 35, 179, 239>>,
"to" => <<178, 183, 193, 121, 95, 25, 251, 194, 143, 218, 119, 169, 94, 89, 237, 187, 139, 55, 9, 200>>
}}
"""
def decode_event(data, topics, function_selector) do
# First, split the types into indexed and not indexed
{indexed_types, non_indexed_types} =
Enum.split_with(function_selector.types, fn t -> Map.get(t, :indexed) end)
indexed_data =
indexed_types
|> Enum.zip(topics)
|> Enum.map(fn {type, topic} ->
[value] = ABI.TypeDecoder.decode_raw(topic, [type])
{type.name, value}
end)
|> Enum.into(%{})
non_indexed_data =
data
|> ABI.TypeDecoder.decode_raw(non_indexed_types)
|> Enum.zip(non_indexed_types)
|> Enum.map(fn {res, %{name: name}} -> {name, res} end)
|> Enum.into(%{})
{function_selector.function, Map.merge(indexed_data, non_indexed_data)}
end
@doc ~S"""
Returns the topic of an event, i.e. the first item that appears
in an Ethereum log for this event.
## Examples
iex> ABI.Event.event_topic(
...> %ABI.FunctionSelector{
...> function: "Transfer",
...> types: [
...> %{type: :address, name: "from", indexed: true},
...> %{type: :address, name: "to", indexed: true},
...> %{type: {:uint, 256}, name: "amount"},
...> ]
...> }
...> )
...> |> Base.encode16(case: :lower)
"ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
"""
def event_topic(function_selector) do
function_selector
|> ABI.FunctionSelector.encode()
|> ABI.Math.kec()
end
end