diff --git a/lib/abi.ex b/lib/abi.ex index 515c9fe..7b8cff3 100644 --- a/lib/abi.ex +++ b/lib/abi.ex @@ -212,7 +212,7 @@ defmodule ABI do ...> |> Jason.decode! ...> |> ABI.parse_specification(include_events?: true) ...> |> Enum.filter(&(&1.type == :event)) - [%ABI.FunctionSelector{type: :event, function: "WantsPets", input_names: ["_from_human", "_number", "_belly"], inputs_indexed: [true, false, true], method_id: <<235, 155, 60, 76>>, types: [:string, {:uint, 256}, :bool]}] + [%ABI.FunctionSelector{type: :event, function: "WantsPets", input_names: ["_from_human", "_number", "_belly"], inputs_indexed: [true, false, true], method_id: <<235, 155, 60, 76, 236, 41, 90, 133, 158, 131, 71, 199, 88, 206, 85, 83, 36, 105, 140, 112, 231, 125, 249, 63, 87, 99, 121, 242, 184, 82, 161, 19>>, types: [:string, {:uint, 256}, :bool]}] iex> File.read!("priv/example1.abi.json") ...> |> Jason.decode! diff --git a/lib/abi/event.ex b/lib/abi/event.ex index 1dd7c45..8c28356 100644 --- a/lib/abi/event.ex +++ b/lib/abi/event.ex @@ -54,7 +54,7 @@ defmodule ABI.Event do function: "WantsPets", input_names: ["_from_human", "_number", "_belly"], inputs_indexed: [true, false, true], - method_id: <<235, 155, 60, 76>>, + method_id: <<235, 155, 60, 76, 236, 41, 90, 133, 158, 131, 71, 199, 88, 206, 85, 83, 36, 105, 140, 112, 231, 125, 249, 63, 87, 99, 121, 242, 184, 82, 161, 19>>, types: [:string, {:uint, 256}, :bool] }, [ @@ -69,9 +69,8 @@ defmodule ABI.Event do def find_and_decode(function_selectors, topic1, topic2, topic3, topic4, data) do input_topics = [topic2, topic3, topic4] - with {:ok, method_id, _rest} <- Util.split_method_id(topic1), - {:ok, selector} when not is_nil(selector) <- - Util.find_selector_by_event_id(function_selectors, method_id, input_topics) do + with {:ok, selector} when not is_nil(selector) <- + Util.find_selector_by_event_id(function_selectors, topic1, input_topics) do args = Enum.zip([selector.input_names, selector.types, selector.inputs_indexed]) {indexed_args, unindexed_args} = diff --git a/lib/abi/function_selector.ex b/lib/abi/function_selector.ex index d64d7cc..04d1d5d 100644 --- a/lib/abi/function_selector.ex +++ b/lib/abi/function_selector.ex @@ -29,14 +29,14 @@ defmodule ABI.FunctionSelector do * `:types` - Function's input types * `:returns` - Function's return types * `:return_names` - Names of the return values (output names) - * `:method_id` - First four bits of the hashed function signature + * `:method_id` - First four bytes of the hashed function signature or full 32 byte hash for events * `:input_names` - Names of the input values (argument names) * `:type` - The type of the selector. Events are part of the ABI, but are not considered functions * `:inputs_index` - A list of true/false values denoting if each input is indexed. Only populated for events. """ @type t :: %__MODULE__{ function: String.t() | nil, - method_id: String.t() | nil, + method_id: binary | nil, input_names: [String.t()], types: [type], returns: [type], @@ -260,7 +260,7 @@ defmodule ABI.FunctionSelector do type: :event } - add_method_id(selector) + add_event_id(selector) else _ -> nil end @@ -415,6 +415,12 @@ defmodule ABI.FunctionSelector do end end + defp add_event_id(selector) do + signature = encode(selector) + + %{selector | method_id: ExKeccak.hash_256(signature)} + end + defp get_types(function_selector) do for type <- function_selector.types do get_type(type) diff --git a/test/abi/util_test.exs b/test/abi/util_test.exs index 37ed47f..600dfe7 100644 --- a/test/abi/util_test.exs +++ b/test/abi/util_test.exs @@ -4,7 +4,9 @@ defmodule ABI.UtilTest do @selectors [ %ABI.FunctionSelector{ function: "Transfer", - method_id: <<221, 242, 82, 173>>, + method_id: + <<221, 242, 82, 173, 27, 226, 200, 155, 105, 194, 176, 104, 252, 55, 141, 170, 149, 43, + 167, 241, 99, 196, 161, 22, 40, 245, 90, 77, 245, 35, 179, 239>>, type: :event, inputs_indexed: [false, false, false], state_mutability: nil, @@ -14,7 +16,9 @@ defmodule ABI.UtilTest do }, %ABI.FunctionSelector{ function: "Transfer", - method_id: <<221, 242, 82, 173>>, + method_id: + <<221, 242, 82, 173, 27, 226, 200, 155, 105, 194, 176, 104, 252, 55, 141, 170, 149, 43, + 167, 241, 99, 196, 161, 22, 40, 245, 90, 77, 245, 35, 179, 239>>, type: :event, inputs_indexed: [true, true, true], state_mutability: nil, @@ -24,7 +28,9 @@ defmodule ABI.UtilTest do }, %ABI.FunctionSelector{ function: "OwnershipTransferred", - method_id: <<139, 224, 7, 156>>, + method_id: + <<139, 224, 7, 156, 83, 22, 89, 20, 19, 68, 205, 31, 208, 164, 242, 132, 25, 73, 127, 151, + 34, 163, 218, 175, 227, 180, 24, 111, 107, 100, 87, 224>>, type: :event, inputs_indexed: [true, true], state_mutability: nil, @@ -37,14 +43,19 @@ defmodule ABI.UtilTest do describe "decode events" do test "successfully decodes ERC721 transfer event" do {:ok, selector} = - ABI.Util.find_selector_by_event_id(@selectors, <<221, 242, 82, 173>>, [ - <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 218, 29, 25, 253, 206, 193, 121, 186, 151, - 85, 242, 198, 19, 159, 143, 254, 203, 254, 176>>, - <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 47, 182, 247, 249, 220, 207, 188, 171, 157, - 153, 173, 222, 184, 132, 3, 58, 241, 27, 134>>, - <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 12, 12>> - ]) + ABI.Util.find_selector_by_event_id( + @selectors, + <<221, 242, 82, 173, 27, 226, 200, 155, 105, 194, 176, 104, 252, 55, 141, 170, 149, 43, + 167, 241, 99, 196, 161, 22, 40, 245, 90, 77, 245, 35, 179, 239>>, + [ + <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 218, 29, 25, 253, 206, 193, 121, 186, 151, + 85, 242, 198, 19, 159, 143, 254, 203, 254, 176>>, + <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 47, 182, 247, 249, 220, 207, 188, 171, 157, + 153, 173, 222, 184, 132, 3, 58, 241, 27, 134>>, + <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 12>> + ] + ) assert selector.function == "Transfer" assert selector.inputs_indexed == [true, true, true] @@ -52,13 +63,18 @@ defmodule ABI.UtilTest do test "decode OwnershipTransferred event" do {:ok, selector} = - ABI.Util.find_selector_by_event_id(@selectors, <<139, 224, 7, 156>>, [ - <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0>>, - <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 181, 74, 58, 157, 2, 63, 219, 87, 69, 216, - 158, 228, 106, 170, 82, 18, 171, 87, 125>>, - nil - ]) + ABI.Util.find_selector_by_event_id( + @selectors, + <<139, 224, 7, 156, 83, 22, 89, 20, 19, 68, 205, 31, 208, 164, 242, 132, 25, 73, 127, + 151, 34, 163, 218, 175, 227, 180, 24, 111, 107, 100, 87, 224>>, + [ + <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0>>, + <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 181, 74, 58, 157, 2, 63, 219, 87, 69, 216, + 158, 228, 106, 170, 82, 18, 171, 87, 125>>, + nil + ] + ) assert selector.function == "OwnershipTransferred" assert selector.inputs_indexed == [true, true]