|
|
@ -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 |
|
|
|
|
|
|
|
|
|
|
|