fix: abi cache for non-proxied addresses (#11065)

* fix: abi cache for non-proxied addresses

* chore: rename
pull/11074/head
Kirill Fedoseev 4 weeks ago committed by GitHub
parent 608f319765
commit a65b7f82ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 49
      apps/explorer/lib/explorer/chain/transaction.ex

@ -769,10 +769,10 @@ defmodule Explorer.Chain.Transaction do
boolean(), boolean(),
[Chain.api?()], [Chain.api?()],
methods_map, methods_map,
proxy_implementation_abi_map smart_contract_full_abi_map
) :: error_type | success_type ) :: error_type | success_type
when methods_map: map(), when methods_map: map(),
proxy_implementation_abi_map: map(), smart_contract_full_abi_map: map(),
error_type: {:error, any()} | {:error, :contract_not_verified | :contract_verified, list()}, error_type: {:error, any()} | {:error, :contract_not_verified | :contract_verified, list()},
success_type: {:ok | binary(), any()} | {:ok, binary(), binary(), list()} success_type: {:ok | binary(), any()} | {:ok, binary(), binary(), list()}
def decoded_input_data( def decoded_input_data(
@ -780,7 +780,7 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider? \\ false, skip_sig_provider? \\ false,
options, options,
methods_map \\ %{}, methods_map \\ %{},
proxy_implementation_abi_map \\ %{} smart_contract_full_abi_map \\ %{}
) )
# skip decoding if there is no to_address # skip decoding if there is no to_address
@ -831,7 +831,7 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider?, skip_sig_provider?,
options, options,
methods_map, methods_map,
proxy_implementation_abi_map smart_contract_full_abi_map
) do ) do
decoded_input_data( decoded_input_data(
%__MODULE__{ %__MODULE__{
@ -842,7 +842,7 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider?, skip_sig_provider?,
options, options,
methods_map, methods_map,
proxy_implementation_abi_map smart_contract_full_abi_map
) )
end end
@ -856,7 +856,7 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider?, skip_sig_provider?,
options, options,
methods_map, methods_map,
proxy_implementation_abi_map smart_contract_full_abi_map
) do ) do
decoded_input_data( decoded_input_data(
%__MODULE__{ %__MODULE__{
@ -867,7 +867,7 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider?, skip_sig_provider?,
options, options,
methods_map, methods_map,
proxy_implementation_abi_map smart_contract_full_abi_map
) )
end end
@ -881,7 +881,7 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider?, skip_sig_provider?,
options, options,
methods_map, methods_map,
_proxy_implementation_abi_map _smart_contract_full_abi_map
) do ) do
methods = check_methods_cache(method_id, methods_map, options) methods = check_methods_cache(method_id, methods_map, options)
@ -922,9 +922,9 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider?, skip_sig_provider?,
options, options,
methods_map, methods_map,
proxy_implementation_abi_map smart_contract_full_abi_map
) do ) do
full_abi = check_full_abi_cache(smart_contract, proxy_implementation_abi_map, options) full_abi = check_full_abi_cache(smart_contract, smart_contract_full_abi_map, options)
case do_decoded_input_data(data, full_abi, hash) do case do_decoded_input_data(data, full_abi, hash) do
# In some cases transactions use methods of some unpredictable contracts, so we can try to look up for method in a whole DB # In some cases transactions use methods of some unpredictable contracts, so we can try to look up for method in a whole DB
@ -938,7 +938,7 @@ defmodule Explorer.Chain.Transaction do
skip_sig_provider?, skip_sig_provider?,
options, options,
methods_map, methods_map,
proxy_implementation_abi_map smart_contract_full_abi_map
) do ) do
{:error, :contract_not_verified, []} -> {:error, :contract_not_verified, []} ->
decode_function_call_via_sig_provider_wrapper(input, hash, skip_sig_provider?) decode_function_call_via_sig_provider_wrapper(input, hash, skip_sig_provider?)
@ -999,10 +999,10 @@ defmodule Explorer.Chain.Transaction do
defp check_full_abi_cache( defp check_full_abi_cache(
smart_contract, smart_contract,
proxy_implementation_abi_map, smart_contract_full_abi_map,
options options
) do ) do
Map.get_lazy(proxy_implementation_abi_map, smart_contract.address_hash, fn -> Map.get_lazy(smart_contract_full_abi_map, smart_contract.address_hash, fn ->
Proxy.combine_proxy_implementation_abi(smart_contract, options) Proxy.combine_proxy_implementation_abi(smart_contract, options)
end) end)
end end
@ -1994,7 +1994,7 @@ defmodule Explorer.Chain.Transaction do
""" """
@spec decode_transactions([Transaction.t()], boolean(), Keyword.t()) :: [nil | {:ok, String.t(), String.t(), map()}] @spec decode_transactions([Transaction.t()], boolean(), Keyword.t()) :: [nil | {:ok, String.t(), String.t(), map()}]
def decode_transactions(transactions, skip_sig_provider?, opts) do def decode_transactions(transactions, skip_sig_provider?, opts) do
proxy_implementation_abi_map = combine_proxy_implementation_abi_map(transactions) smart_contract_full_abi_map = combine_smart_contract_full_abi_map(transactions)
# first we assemble an empty methods map, so that decoded_input_data will skip ContractMethod.t() lookup and decoding # first we assemble an empty methods map, so that decoded_input_data will skip ContractMethod.t() lookup and decoding
empty_methods_map = empty_methods_map =
@ -2005,12 +2005,12 @@ defmodule Explorer.Chain.Transaction do
end) end)
|> Enum.into(%{}, &{&1, []}) |> Enum.into(%{}, &{&1, []})
# try to decode transaction using full abi data from proxy_implementation_abi_map # try to decode transaction using full abi data from smart_contract_full_abi_map
decoded_transactions = decoded_transactions =
transactions transactions
|> Enum.map(fn transaction -> |> Enum.map(fn transaction ->
transaction transaction
|> decoded_input_data(skip_sig_provider?, opts, empty_methods_map, proxy_implementation_abi_map) |> decoded_input_data(skip_sig_provider?, opts, empty_methods_map, smart_contract_full_abi_map)
|> format_decoded_input() |> format_decoded_input()
end) end)
|> Enum.zip(transactions) |> Enum.zip(transactions)
@ -2032,7 +2032,7 @@ defmodule Explorer.Chain.Transaction do
{nil, transaction} -> {nil, transaction} ->
transaction transaction
|> Map.put(:to_address, %NotLoaded{}) |> Map.put(:to_address, %NotLoaded{})
|> decoded_input_data(skip_sig_provider?, opts, methods_map, proxy_implementation_abi_map) |> decoded_input_data(skip_sig_provider?, opts, methods_map, smart_contract_full_abi_map)
|> format_decoded_input() |> format_decoded_input()
{decoded, _} -> {decoded, _} ->
@ -2040,7 +2040,7 @@ defmodule Explorer.Chain.Transaction do
end) end)
end end
defp combine_proxy_implementation_abi_map(transactions) do defp combine_smart_contract_full_abi_map(transactions) do
# parse unique address hashes of smart-contracts from to_address and created_contract_address properties of the transactions list # parse unique address hashes of smart-contracts from to_address and created_contract_address properties of the transactions list
unique_to_address_hashes = unique_to_address_hashes =
transactions transactions
@ -2063,11 +2063,16 @@ defmodule Explorer.Chain.Transaction do
|> Chain.hashes_to_addresses(necessity_by_association: %{smart_contract: :optional}) |> Chain.hashes_to_addresses(necessity_by_association: %{smart_contract: :optional})
|> Enum.into(%{}, &{&1.hash, &1}) |> Enum.into(%{}, &{&1.hash, &1})
# combine map %{proxy_address_hash => combined proxy abi} # combine map %{proxy_address_hash => implementation address hashes}
proxy_implementations_map =
multiple_proxy_implementations multiple_proxy_implementations
|> Enum.into(%{}, fn proxy_implementations -> |> Enum.into(%{}, &{&1.proxy_address_hash, &1.address_hashes})
# combine map %{proxy_address_hash => combined proxy abi}
unique_to_address_hashes
|> Enum.into(%{}, fn to_address_hash ->
full_abi = full_abi =
[proxy_implementations.proxy_address_hash | proxy_implementations.address_hashes] [to_address_hash | Map.get(proxy_implementations_map, to_address_hash, [])]
|> Enum.map(&Map.get(addresses_with_smart_contracts, &1)) |> Enum.map(&Map.get(addresses_with_smart_contracts, &1))
|> Enum.flat_map(fn |> Enum.flat_map(fn
%{smart_contract: %{abi: abi}} when is_list(abi) -> abi %{smart_contract: %{abi: abi}} when is_list(abi) -> abi
@ -2075,7 +2080,7 @@ defmodule Explorer.Chain.Transaction do
end) end)
|> Enum.filter(&(!is_nil(&1))) |> Enum.filter(&(!is_nil(&1)))
{proxy_implementations.proxy_address_hash, full_abi} {to_address_hash, full_abi}
end) end)
end end

Loading…
Cancel
Save