diff --git a/lib/ethers/contract.ex b/lib/ethers/contract.ex index f8bce3f..f808115 100644 --- a/lib/ethers/contract.ex +++ b/lib/ethers/contract.ex @@ -277,7 +277,7 @@ defmodule Ethers.Contract do func_args = generate_arguments(mod, abi.arity, aggregated_input_names) - func_typespec = generate_event_typespecs(abi.selectors, abi.arity) + func_typespec = generate_event_typespecs(abi.selectors) quote context: mod, location: :keep do if unquote(generate_docs?(name, opts[:skip_docs])) do diff --git a/lib/ethers/contract_helpers.ex b/lib/ethers/contract_helpers.ex index 85dae8f..4a53761 100644 --- a/lib/ethers/contract_helpers.ex +++ b/lib/ethers/contract_helpers.ex @@ -217,8 +217,8 @@ defmodule Ethers.ContractHelpers do |> do_generate_typescpecs() end - def generate_event_typespecs(selectors, arity) do - Enum.map(selectors, &Enum.take(&1.types, arity)) + def generate_event_typespecs(selectors) do + Enum.map(selectors, &event_indexed_types/1) |> do_generate_typescpecs(true) end diff --git a/test/ethers/contract_helpers_test.exs b/test/ethers/contract_helpers_test.exs index 1640a46..a6811c1 100644 --- a/test/ethers/contract_helpers_test.exs +++ b/test/ethers/contract_helpers_test.exs @@ -61,6 +61,28 @@ defmodule Ethers.ContractHelpersTest do end end + describe "generate_event_typespecs" do + test "uses indexed field types when indexed and non-indexed fields are interleaved" do + # Transfer(uint256 amount, address indexed sender, bool isFinal, address indexed receiver) + # from test/support/contracts/event_mixed_index.sol + selector = %ABI.FunctionSelector{ + function: "Transfer", + type: :event, + types: [{:uint, 256}, :address, :bool, :address], + inputs_indexed: [false, true, false, true], + input_names: ["amount", "sender", "isFinal", "receiver"], + returns: [] + } + + [sender_type, receiver_type] = ContractHelpers.generate_event_typespecs([selector]) + address_typespec = Ethers.Types.to_elixir_type(:address) + + # Both indexed params are address, so both typespecs should be t_address() | nil. + assert sender_type == quote(do: unquote(address_typespec) | nil) + assert receiver_type == quote(do: unquote(address_typespec) | nil) + end + end + describe "human_signature" do test "returns the human signature of a given function" do assert "name(uint256 id, address address)" ==