do not create contracts on failed parent transactions

pull/1452/head
Ayrat Badykov 6 years ago
parent dc2a0e2829
commit 366f9b7aa6
No known key found for this signature in database
GPG Key ID: B44668E265E9396F
  1. 35
      apps/indexer/lib/indexer/internal_transaction/fetcher.ex
  2. 77
      apps/indexer/test/indexer/internal_transaction/fetcher_test.exs

@ -113,7 +113,12 @@ defmodule Indexer.InternalTransaction.Fetcher do
|> EthereumJSONRPC.fetch_internal_transactions(json_rpc_named_arguments) |> EthereumJSONRPC.fetch_internal_transactions(json_rpc_named_arguments)
|> case do |> case do
{:ok, internal_transactions_params} -> {:ok, internal_transactions_params} ->
addresses_params = AddressExtraction.extract_addresses(%{internal_transactions: internal_transactions_params}) internal_transactions_params_without_failed_creations = remove_failed_creations(internal_transactions_params)
addresses_params =
AddressExtraction.extract_addresses(%{
internal_transactions: internal_transactions_params_without_failed_creations
})
address_hash_to_block_number = address_hash_to_block_number =
Enum.into(addresses_params, %{}, fn %{fetched_coin_balance_block_number: block_number, hash: hash} -> Enum.into(addresses_params, %{}, fn %{fetched_coin_balance_block_number: block_number, hash: hash} ->
@ -123,7 +128,7 @@ defmodule Indexer.InternalTransaction.Fetcher do
with {:ok, imported} <- with {:ok, imported} <-
Chain.import(%{ Chain.import(%{
addresses: %{params: addresses_params}, addresses: %{params: addresses_params},
internal_transactions: %{params: internal_transactions_params}, internal_transactions: %{params: internal_transactions_params_without_failed_creations},
timeout: :infinity timeout: :infinity
}) do }) do
async_import_coin_balances(imported, %{ async_import_coin_balances(imported, %{
@ -197,4 +202,30 @@ defmodule Indexer.InternalTransaction.Fetcher do
end end
end) end)
end end
defp remove_failed_creations(internal_transactions_params) do
internal_transactions_params
|> Enum.map(fn internal_transaction_params ->
internal_transaction_params[:trace_address]
failed_parent_index =
Enum.find(internal_transaction_params[:trace_address], fn trace_address ->
parent = Enum.at(internal_transactions_params, trace_address)
!is_nil(parent[:error])
end)
failed_parent = failed_parent_index && Enum.at(internal_transactions_params, failed_parent_index)
if failed_parent do
internal_transaction_params
|> Map.delete(:created_contract_address_hash)
|> Map.delete(:created_contract_code)
|> Map.delete(:gas_used)
|> Map.put(:error, failed_parent[:error])
else
internal_transaction_params
end
end)
end
end end

@ -5,7 +5,7 @@ defmodule Indexer.InternalTransaction.FetcherTest do
import ExUnit.CaptureLog import ExUnit.CaptureLog
import Mox import Mox
alias Explorer.Chain.{Hash, Transaction} alias Explorer.Chain.{Address, Hash, Transaction}
alias Indexer.{CoinBalance, InternalTransaction, PendingTransaction} alias Indexer.{CoinBalance, InternalTransaction, PendingTransaction}
@ -151,6 +151,81 @@ defmodule Indexer.InternalTransaction.FetcherTest do
""" """
end end
test "internal transactions with failed parent does not create a new address", %{
json_rpc_named_arguments: json_rpc_named_arguments
} do
if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options ->
{:ok,
[
%{
id: 0,
jsonrpc: "2.0",
result: %{
"output" => "0x",
"stateDiff" => nil,
"trace" => [
%{
"action" => %{
"callType" => "call",
"from" => "0xc73add416e2119d20ce80e0904fc1877e33ef246",
"gas" => "0x13388",
"input" => "0xc793bf97",
"to" => "0x2d07e106b5d280e4ccc2d10deee62441c91d4340",
"value" => "0x0"
},
"error" => "Reverted",
"subtraces" => 1,
"traceAddress" => [],
"type" => "call"
},
%{
"action" => %{
"from" => "0x2d07e106b5d280e4ccc2d10deee62441c91d4340",
"gas" => "0xb2ab",
"init" =>
"0x608060405234801561001057600080fd5b5060d38061001f6000396000f3fe6080604052600436106038577c010000000000000000000000000000000000000000000000000000000060003504633ccfd60b8114604f575b336000908152602081905260409020805434019055005b348015605a57600080fd5b5060616063565b005b33600081815260208190526040808220805490839055905190929183156108fc02918491818181858888f1935050505015801560a3573d6000803e3d6000fd5b505056fea165627a7a72305820e9a226f249def650de957dd8b4127b85a3049d6bfa818cadc4e2d3c44b6a53530029",
"value" => "0x0"
},
"result" => %{
"address" => "0xf4a5afe28b91cf928c2568805cfbb36d477f0b75",
"code" =>
"0x6080604052600436106038577c010000000000000000000000000000000000000000000000000000000060003504633ccfd60b8114604f575b336000908152602081905260409020805434019055005b348015605a57600080fd5b5060616063565b005b33600081815260208190526040808220805490839055905190929183156108fc02918491818181858888f1935050505015801560a3573d6000803e3d6000fd5b505056fea165627a7a72305820e9a226f249def650de957dd8b4127b85a3049d6bfa818cadc4e2d3c44b6a53530029",
"gasUsed" => "0xa535"
},
"subtraces" => 0,
"traceAddress" => [0],
"type" => "create"
}
],
"vmTrace" => nil
}
}
]}
end)
CoinBalance.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments)
%Transaction{hash: %Hash{bytes: bytes}} =
insert(:transaction, hash: "0x03cd5899a63b6f6222afda8705d059fd5a7d126bcabe962fb654d9736e6bcafa")
|> with_block()
:ok =
InternalTransaction.Fetcher.run(
[
{7_202_692, bytes, 0}
],
json_rpc_named_arguments
)
address = "0xf4a5afe28b91cf928c2568805cfbb36d477f0b75"
fetched_address = Repo.one(from(address in Address, where: address.hash == ^address))
assert is_nil(fetched_address)
end
end
test "duplicate transaction hashes only retry uniques", %{json_rpc_named_arguments: json_rpc_named_arguments} do test "duplicate transaction hashes only retry uniques", %{json_rpc_named_arguments: json_rpc_named_arguments} do
if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options -> expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options ->

Loading…
Cancel
Save