diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex index df2380b666..0d958b938c 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex @@ -1,5 +1,5 @@
- <% decoded_result = decode(@log, @transaction, @log.address) %> + <% decoded_result = decode(@log, @transaction) %> <%= case decoded_result do %> <%= {:error, :contract_not_verified, _cadidates} -> %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/transaction_log_view.ex b/apps/block_scout_web/lib/block_scout_web/views/transaction_log_view.ex index 762908ac18..50d406433c 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/transaction_log_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/transaction_log_view.ex @@ -4,7 +4,7 @@ defmodule BlockScoutWeb.TransactionLogView do alias Explorer.Chain.Log - def decode(log, transaction, address) do - Log.decode(log, transaction, address) + def decode(log, transaction) do + Log.decode(log, transaction) end end diff --git a/apps/explorer/lib/explorer/chain/log.ex b/apps/explorer/lib/explorer/chain/log.ex index 063796f734..7887fb0be0 100644 --- a/apps/explorer/lib/explorer/chain/log.ex +++ b/apps/explorer/lib/explorer/chain/log.ex @@ -119,25 +119,35 @@ defmodule Explorer.Chain.Log do @doc """ Decode transaction log data. """ - def decode(_log, %Transaction{to_address: nil}), do: {:error, :no_to_address} - def decode(log, transaction = %Transaction{to_address: %{smart_contract: %{abi: abi, address_hash: address_hash}}}) - when not is_nil(abi) do - full_abi = Chain.combine_proxy_implementation_abi(address_hash, abi) + def decode(log, transaction) do + address_options = [ + necessity_by_association: %{ + :smart_contract => :optional + } + ] - with {:ok, selector, mapping} <- find_and_decode(full_abi, log, transaction), - identifier <- Base.encode16(selector.method_id, case: :lower), - text <- function_call(selector.function, mapping), - do: {:ok, identifier, text, mapping} + case Chain.find_contract_address(log.address_hash, address_options, true) do + {:ok, %{smart_contract: %{abi: abi}}} -> + full_abi = Chain.combine_proxy_implementation_abi(log.address_hash, abi) + + with {:ok, selector, mapping} <- find_and_decode(full_abi, log, transaction), + identifier <- Base.encode16(selector.method_id, case: :lower), + text <- function_call(selector.function, mapping), + do: {:ok, identifier, text, mapping} + + _ -> + find_candidates(log, transaction) + end end - def decode(log, transaction) do + defp find_candidates(log, transaction) do case log.first_topic do "0x" <> hex_part -> case Integer.parse(hex_part, 16) do {number, ""} -> <> = :binary.encode_unsigned(number) - find_candidates(method_id, log, transaction) + find_candidates_query(method_id, log, transaction) _ -> {:error, :could_not_decode} @@ -148,26 +158,7 @@ defmodule Explorer.Chain.Log do end end - def decode(log, transaction, %Address{hash: address_hash}) do - address_options = [ - necessity_by_association: %{ - :smart_contract => :optional - } - ] - - with {:ok, %{smart_contract: %{abi: abi}}} <- Chain.find_contract_address(address_hash, address_options, true) do - full_abi = Chain.combine_proxy_implementation_abi(address_hash, abi) - - with {:ok, selector, mapping} <- find_and_decode(full_abi, log, transaction), - identifier <- Base.encode16(selector.method_id, case: :lower), - text <- function_call(selector.function, mapping), - do: {:ok, identifier, text, mapping} - end - end - - def decode(_log, _transaction, nil), do: {:error, :no_to_address} - - defp find_candidates(method_id, log, transaction) do + defp find_candidates_query(method_id, log, transaction) do candidates_query = from( contract_method in ContractMethod, diff --git a/apps/explorer/test/explorer/chain/log_test.exs b/apps/explorer/test/explorer/chain/log_test.exs index 3619476f6c..e0f0fa7c14 100644 --- a/apps/explorer/test/explorer/chain/log_test.exs +++ b/apps/explorer/test/explorer/chain/log_test.exs @@ -58,29 +58,29 @@ defmodule Explorer.Chain.LogTest do end test "that a contract call transaction that has a verified contract returns the decoded input data" do - smart_contract = - insert(:smart_contract, - abi: [ - %{ - "anonymous" => false, - "inputs" => [ - %{"indexed" => true, "name" => "_from_human", "type" => "string"}, - %{"indexed" => false, "name" => "_number", "type" => "uint256"}, - %{"indexed" => true, "name" => "_belly", "type" => "bool"} - ], - "name" => "WantsPets", - "type" => "event" - } - ] - ) + to_address = insert(:address, contract_code: "0x") + + insert(:smart_contract, + abi: [ + %{ + "anonymous" => false, + "inputs" => [ + %{"indexed" => true, "name" => "_from_human", "type" => "string"}, + %{"indexed" => false, "name" => "_number", "type" => "uint256"}, + %{"indexed" => true, "name" => "_belly", "type" => "bool"} + ], + "name" => "WantsPets", + "type" => "event" + } + ], + address_hash: to_address.hash + ) topic1 = "0x" <> Base.encode16(:keccakf1600.hash(:sha3_256, "WantsPets(string,uint256,bool)"), case: :lower) topic2 = "0x" <> Base.encode16(:keccakf1600.hash(:sha3_256, "bob"), case: :lower) topic3 = "0x0000000000000000000000000000000000000000000000000000000000000001" data = "0x0000000000000000000000000000000000000000000000000000000000000000" - to_address = insert(:address, smart_contract: smart_contract) - transaction = :transaction_to_verified_contract |> insert(to_address: to_address) @@ -88,6 +88,7 @@ defmodule Explorer.Chain.LogTest do log = insert(:log, + address: to_address, transaction: transaction, first_topic: topic1, second_topic: topic2,