Skip to content

Commit

Permalink
Handle Events with same topic hash properly (#115)
Browse files Browse the repository at this point in the history
* Handle proper event handling when same event with different indexed fields exist

* Address comments in PR

* Add one more test for OwnershipTransferred event

* Small change as per PR comment
  • Loading branch information
yashh authored Oct 17, 2022
1 parent 9854a80 commit 5c1fb2f
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 3 deletions.
6 changes: 3 additions & 3 deletions lib/abi/event.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ defmodule ABI.Event do
@spec find_and_decode([FunctionSelector.t()], topic, topic, topic, topic, binary) ::
{FunctionSelector.t(), [event_value]} | {:error, any}
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_method_id(function_selectors, method_id) do
input_topics = [topic2, topic3, topic4]

Util.find_selector_by_event_id(function_selectors, method_id, input_topics) do
args = Enum.zip([selector.input_names, selector.types, selector.inputs_indexed])

{indexed_args, unindexed_args} =
Expand Down
21 changes: 21 additions & 0 deletions lib/abi/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,25 @@ defmodule ABI.Util do
{:error, :no_matching_function}
end
end

def find_selector_by_event_id(function_selectors, method_id_target, input_topics) do
# match the length of topics and indexed_args_length
topics_length = Enum.count(input_topics, fn x -> x != nil end)
# Only process function selectors that are of type event
function_selector =
Enum.find(function_selectors, fn
%{type: :event, method_id: ^method_id_target, inputs_indexed: inputs_indexed} ->
indexed_length = Enum.count(inputs_indexed, &(&1 == true))
topics_length == indexed_length

_ ->
false
end)

if function_selector do
{:ok, function_selector}
else
{:error, :no_matching_function}
end
end
end
67 changes: 67 additions & 0 deletions test/abi/util_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
defmodule ABI.UtilTest do
use ExUnit.Case, async: true

@selectors [
%ABI.FunctionSelector{
function: "Transfer",
method_id: <<221, 242, 82, 173>>,
type: :event,
inputs_indexed: [false, false, false],
state_mutability: nil,
input_names: ["from", "to", "tokenId"],
types: [:address, :address, {:uint, 256}],
returns: []
},
%ABI.FunctionSelector{
function: "Transfer",
method_id: <<221, 242, 82, 173>>,
type: :event,
inputs_indexed: [true, true, true],
state_mutability: nil,
input_names: ["from", "to", "tokenId"],
types: [:address, :address, {:uint, 256}],
returns: []
},
%ABI.FunctionSelector{
function: "OwnershipTransferred",
method_id: <<139, 224, 7, 156>>,
type: :event,
inputs_indexed: [true, true],
state_mutability: nil,
input_names: ["previousOwner", "newOwner"],
types: [:address, :address],
returns: []
}
]

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

assert selector.function == "Transfer"
assert selector.inputs_indexed == [true, true, true]
end

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

assert selector.function == "OwnershipTransferred"
assert selector.inputs_indexed == [true, true]
end
end
end

0 comments on commit 5c1fb2f

Please sign in to comment.