fix: Replace empty arg names with argN (#9748)

* fix: Replace empty arg names with argN

* Fix dialyzer

* Remove dbg

* Fix dialyzer

* Fix test

* Fix test

---------

Co-authored-by: Maxim Filonov <53992153+sl1depengwyn@users.noreply.github.com>
pull/10236/head
nikitosing 5 months ago committed by GitHub
parent e292873f79
commit d231ca62bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 26
      apps/explorer/lib/explorer/chain/log.ex
  2. 13
      apps/explorer/lib/explorer/chain/transaction.ex
  3. 56
      apps/explorer/test/explorer/chain/log_test.exs
  4. 34
      apps/explorer/test/explorer/chain/transaction_test.exs

@ -232,8 +232,8 @@ defmodule Explorer.Chain.Log do
log.fourth_topic && log.fourth_topic.bytes,
log.data.bytes
),
selector <- %{selector | method_id: first_four_bytes} do
{:ok, selector, mapping}
selector <- %FunctionSelector{selector | method_id: first_four_bytes} do
{:ok, alter_inputs_names(selector), alter_mapping_names(mapping)}
end
rescue
e ->
@ -261,6 +261,28 @@ defmodule Explorer.Chain.Log do
IO.iodata_to_binary([name, "(", text, ")"])
end
defp alter_inputs_names(%FunctionSelector{input_names: names} = selector) do
names =
names
|> Enum.with_index()
|> Enum.map(fn {name, index} ->
if name == "", do: "arg#{index}", else: name
end)
%FunctionSelector{selector | input_names: names}
end
defp alter_mapping_names(mapping) when is_list(mapping) do
mapping
|> Enum.with_index()
|> Enum.map(fn {{name, type, indexed?, value}, index} ->
name = if name == "", do: "arg#{index}", else: name
{name, type, indexed?, value}
end)
end
defp alter_mapping_names(mapping), do: mapping
defp decode_event_via_sig_provider(
log,
transaction,

@ -988,7 +988,7 @@ defmodule Explorer.Chain.Transaction do
abi
|> ABI.parse_specification()
|> ABI.find_and_decode(data) do
{:ok, result}
{:ok, alter_inputs_names(result)}
end
rescue
e ->
@ -1003,6 +1003,17 @@ defmodule Explorer.Chain.Transaction do
{:error, :could_not_decode}
end
defp alter_inputs_names({%FunctionSelector{input_names: names} = selector, mapping}) do
names =
names
|> Enum.with_index()
|> Enum.map(fn {name, index} ->
if name == "", do: "arg#{index}", else: name
end)
{%FunctionSelector{selector | input_names: names}, mapping}
end
defp selector_mapping(selector, values, hash) do
types = Enum.map(selector.types, &FunctionSelector.encode_type/1)

@ -129,6 +129,62 @@ defmodule Explorer.Chain.LogTest do
]}, _, _} = Log.decode(log, transaction, [], false)
end
test "replace arg names with argN if it's empty string" do
to_address = insert(:address, contract_code: "0x")
insert(:smart_contract,
abi: [
%{
"anonymous" => false,
"inputs" => [
%{"indexed" => true, "name" => "", "type" => "string"},
%{"indexed" => false, "name" => "", "type" => "uint256"},
%{"indexed" => true, "name" => "", "type" => "bool"}
],
"name" => "WantsPets",
"type" => "event"
}
],
address_hash: to_address.hash,
contract_code_md5: "123"
)
topic1_bytes = ExKeccak.hash_256("WantsPets(string,uint256,bool)")
topic1 = "0x" <> Base.encode16(topic1_bytes, case: :lower)
topic2_bytes = ExKeccak.hash_256("bob")
topic2 = "0x" <> Base.encode16(topic2_bytes, case: :lower)
topic3 = "0x0000000000000000000000000000000000000000000000000000000000000001"
data = "0x0000000000000000000000000000000000000000000000000000000000000000"
transaction =
:transaction_to_verified_contract
|> insert(to_address: to_address)
|> Repo.preload(to_address: :smart_contract)
log =
insert(:log,
address: to_address,
transaction: transaction,
first_topic: topic(topic1),
second_topic: topic(topic2),
third_topic: topic(topic3),
fourth_topic: nil,
data: data
)
TestHelper.get_eip1967_implementation_zero_addresses()
assert {{:ok, "eb9b3c4c", "WantsPets(string indexed arg0, uint256 arg1, bool indexed arg2)",
[
{"arg0", "string", true,
{:dynamic,
<<56, 228, 122, 123, 113, 157, 206, 99, 102, 42, 234, 244, 52, 64, 50, 111, 85, 27, 138, 126, 225,
152, 206, 227, 92, 181, 213, 23, 242, 210, 150, 162>>}},
{"arg1", "uint256", false, 0},
{"arg2", "bool", true, true}
]}, _, _} = Log.decode(log, transaction, [], false)
end
test "finds decoding candidates" do
params =
params_for(:smart_contract, %{

@ -298,6 +298,40 @@ defmodule Explorer.Chain.TransactionTest do
assert {{:ok, "60fe47b1", "set(uint256 x)", [{"x", "uint256", 10}]}, _, _} =
Transaction.decoded_input_data(transaction, [])
end
test "arguments name in function call replaced with argN if it's empty string" do
contract =
insert(:smart_contract,
contract_code_md5: "123",
abi: [
%{
"constant" => false,
"inputs" => [%{"name" => "", "type" => "uint256"}],
"name" => "set",
"outputs" => [],
"payable" => false,
"stateMutability" => "nonpayable",
"type" => "function"
}
]
)
|> Repo.preload(:address)
input_data =
"set(uint)"
|> ABI.encode([10])
|> Base.encode16(case: :lower)
transaction =
:transaction
|> insert(to_address: contract.address, input: "0x" <> input_data)
|> Repo.preload(to_address: :smart_contract)
TestHelper.get_eip1967_implementation_zero_addresses()
assert {{:ok, "60fe47b1", "set(uint256 arg0)", [{"arg0", "uint256", 10}]}, _, _} =
Transaction.decoded_input_data(transaction, [])
end
end
describe "Poison.encode!/1" do

Loading…
Cancel
Save