pull/8611/head
Maxim Filonov 12 months ago
parent afb6ef3f85
commit 37bebdd0f0
  1. 2
      .dialyzer-ignore
  2. 2
      CHANGELOG.md
  3. 474
      apps/explorer/test/explorer/chain/transaction_test.exs

@ -26,3 +26,5 @@ lib/indexer/fetcher/zkevm/transaction_batch.ex:252
lib/block_scout_web/views/api/v2/transaction_view.ex:431
lib/block_scout_web/views/api/v2/transaction_view.ex:472
lib/explorer/chain/transaction.ex:167
lib/explorer/chain/transaction.ex:1457
lib/explorer/chain/transaction.ex:1458

@ -7,6 +7,7 @@
### Features
- [#8900](https://github.com/blockscout/blockscout/pull/8900) - Add Compound proxy contract pattern
- [#8611](https://github.com/blockscout/blockscout/pull/8611) - Implement sorting of smart contracts, address transactions
### Fixes
@ -29,7 +30,6 @@
- [#8768](https://github.com/blockscout/blockscout/pull/8768) - Add possibility to search tokens by address hash
- [#8750](https://github.com/blockscout/blockscout/pull/8750) - Support new eth-bytecode-db request metadata fields
- [#8634](https://github.com/blockscout/blockscout/pull/8634) - API v2: NFT for address
- [#8611](https://github.com/blockscout/blockscout/pull/8611) - Implement sorting of smart contracts, address transactions
- [#8609](https://github.com/blockscout/blockscout/pull/8609) - Change logs format to JSON; Add endpoint url to the block_scout_web logging
- [#8558](https://github.com/blockscout/blockscout/pull/8558) - Add CoinBalanceDailyUpdater

@ -788,480 +788,6 @@ defmodule Explorer.Chain.TransactionTest do
end
end
describe "address_to_transactions_tasks_range_of_blocks/2" do
test "returns empty extremums if no transactions" do
address = insert(:address)
extremums = Transaction.address_to_transactions_tasks_range_of_blocks(address.hash, [])
assert extremums == %{
:min_block_number => nil,
:max_block_number => 0
}
end
test "returns correct extremums for from_address" do
address = insert(:address)
:transaction
|> insert(from_address: address)
|> with_block(insert(:block, number: 1000))
extremums = Transaction.address_to_transactions_tasks_range_of_blocks(address.hash, [])
assert extremums == %{
:min_block_number => 1000,
:max_block_number => 1000
}
end
test "returns correct extremums for to_address" do
address = insert(:address)
:transaction
|> insert(to_address: address)
|> with_block(insert(:block, number: 1000))
extremums = Transaction.address_to_transactions_tasks_range_of_blocks(address.hash, [])
assert extremums == %{
:min_block_number => 1000,
:max_block_number => 1000
}
end
test "returns correct extremums for created_contract_address" do
address = insert(:address)
:transaction
|> insert(created_contract_address: address)
|> with_block(insert(:block, number: 1000))
extremums = Transaction.address_to_transactions_tasks_range_of_blocks(address.hash, [])
assert extremums == %{
:min_block_number => 1000,
:max_block_number => 1000
}
end
test "returns correct extremums for multiple number of transactions" do
address = insert(:address)
:transaction
|> insert(created_contract_address: address)
|> with_block(insert(:block, number: 1000))
:transaction
|> insert(created_contract_address: address)
|> with_block(insert(:block, number: 999))
:transaction
|> insert(created_contract_address: address)
|> with_block(insert(:block, number: 1003))
:transaction
|> insert(from_address: address)
|> with_block(insert(:block, number: 1001))
:transaction
|> insert(from_address: address)
|> with_block(insert(:block, number: 1004))
:transaction
|> insert(to_address: address)
|> with_block(insert(:block, number: 1002))
:transaction
|> insert(to_address: address)
|> with_block(insert(:block, number: 998))
extremums = Transaction.address_to_transactions_tasks_range_of_blocks(address.hash, [])
assert extremums == %{
:min_block_number => 998,
:max_block_number => 1004
}
end
end
describe "address_to_transactions_with_rewards/2" do
test "without transactions" do
%Address{hash: address_hash} = insert(:address)
assert Repo.aggregate(Transaction, :count, :hash) == 0
assert [] == Transaction.address_to_transactions_with_rewards(address_hash)
end
test "with from transactions" do
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
|> insert(from_address: address)
|> with_block()
assert [transaction] ==
Transaction.address_to_transactions_with_rewards(address_hash, direction: :from)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to transactions" do
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
|> insert(to_address: address)
|> with_block()
assert [transaction] ==
Transaction.address_to_transactions_with_rewards(address_hash, direction: :to)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to and from transactions and direction: :from" do
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
|> insert(from_address: address)
|> with_block()
# only contains "from" transaction
assert [transaction] ==
Transaction.address_to_transactions_with_rewards(address_hash, direction: :from)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to and from transactions and direction: :to" do
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
|> insert(to_address: address)
|> with_block()
assert [transaction] ==
Transaction.address_to_transactions_with_rewards(address_hash, direction: :to)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to and from transactions and no :direction option" do
%Address{hash: address_hash} = address = insert(:address)
block = insert(:block)
transaction1 =
:transaction
|> insert(to_address: address)
|> with_block(block)
transaction2 =
:transaction
|> insert(from_address: address)
|> with_block(block)
assert [transaction2, transaction1] ==
Transaction.address_to_transactions_with_rewards(address_hash)
|> Repo.preload([:block, :to_address, :from_address])
end
test "does not include non-contract-creation parent transactions" do
transaction =
%Transaction{} =
:transaction
|> insert()
|> with_block()
%InternalTransaction{created_contract_address: address} =
insert(:internal_transaction_create,
transaction: transaction,
index: 0,
block_number: transaction.block_number,
block_hash: transaction.block_hash,
block_index: 0,
transaction_index: transaction.index
)
assert [] == Transaction.address_to_transactions_with_rewards(address.hash)
end
test "returns transactions that have token transfers for the given to_address" do
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
|> insert(to_address: address, to_address_hash: address.hash)
|> with_block()
insert(
:token_transfer,
to_address: address,
transaction: transaction
)
assert [transaction.hash] ==
Transaction.address_to_transactions_with_rewards(address_hash)
|> Enum.map(& &1.hash)
end
test "with transactions can be paginated" do
%Address{hash: address_hash} = address = insert(:address)
second_page_hashes =
2
|> insert_list(:transaction, from_address: address)
|> with_block()
|> Enum.map(& &1.hash)
%Transaction{block_number: block_number, index: index} =
:transaction
|> insert(from_address: address)
|> with_block()
assert second_page_hashes ==
address_hash
|> Transaction.address_to_transactions_with_rewards(
paging_options: %PagingOptions{
key: {block_number, index},
page_size: 2
}
)
|> Enum.map(& &1.hash)
|> Enum.reverse()
end
test "returns results in reverse chronological order by block number and transaction index" do
%Address{hash: address_hash} = address = insert(:address)
a_block = insert(:block, number: 6000)
%Transaction{hash: first} =
:transaction
|> insert(to_address: address)
|> with_block(a_block)
%Transaction{hash: second} =
:transaction
|> insert(to_address: address)
|> with_block(a_block)
%Transaction{hash: third} =
:transaction
|> insert(to_address: address)
|> with_block(a_block)
%Transaction{hash: fourth} =
:transaction
|> insert(to_address: address)
|> with_block(a_block)
b_block = insert(:block, number: 2000)
%Transaction{hash: fifth} =
:transaction
|> insert(to_address: address)
|> with_block(b_block)
%Transaction{hash: sixth} =
:transaction
|> insert(to_address: address)
|> with_block(b_block)
result =
address_hash
|> Transaction.address_to_transactions_with_rewards()
|> Enum.map(& &1.hash)
assert [fourth, third, second, first, sixth, fifth] == result
end
test "with emission rewards" do
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: true)
Application.put_env(:explorer, Explorer.Chain.Block.Reward,
validators_contract_address: "0x0000000000000000000000000000000000000005",
keys_manager_contract_address: "0x0000000000000000000000000000000000000006"
)
consumer_pid = start_supervised!(Explorer.Chain.Fetcher.FetchValidatorInfoOnDemand)
:erlang.trace(consumer_pid, true, [:receive])
block = insert(:block)
block_miner_hash_string = Base.encode16(block.miner_hash.bytes, case: :lower)
block_miner_hash = block.miner_hash
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :validator
)
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :emission_funds
)
# isValidator => true
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn [%{id: id, method: _, params: [%{data: _, to: _}, _]}], _options ->
{:ok,
[%{id: id, jsonrpc: "2.0", result: "0x0000000000000000000000000000000000000000000000000000000000000001"}]}
end
)
# getPayoutByMining => 0x0000000000000000000000000000000000000001
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn [%{id: id, method: _, params: [%{data: _, to: _}, _]}], _options ->
{:ok, [%{id: id, result: "0x000000000000000000000000" <> block_miner_hash_string}]}
end
)
res = Transaction.address_to_transactions_with_rewards(block.miner.hash)
assert [{_, _}] = res
assert_receive {:trace, ^consumer_pid, :receive, {:"$gen_cast", {:fetch_or_update, ^block_miner_hash}}}, 1000
:timer.sleep(500)
on_exit(fn ->
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: false)
Application.put_env(:explorer, Explorer.Chain.Block.Reward,
validators_contract_address: nil,
keys_manager_contract_address: nil
)
end)
end
test "with emission rewards and transactions" do
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: true)
Application.put_env(:explorer, Explorer.Chain.Block.Reward,
validators_contract_address: "0x0000000000000000000000000000000000000005",
keys_manager_contract_address: "0x0000000000000000000000000000000000000006"
)
consumer_pid = start_supervised!(Explorer.Chain.Fetcher.FetchValidatorInfoOnDemand)
:erlang.trace(consumer_pid, true, [:receive])
block = insert(:block)
block_miner_hash_string = Base.encode16(block.miner_hash.bytes, case: :lower)
block_miner_hash = block.miner_hash
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :validator
)
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :emission_funds
)
:transaction
|> insert(to_address: block.miner)
|> with_block(block)
|> Repo.preload(:token_transfers)
# isValidator => true
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn [%{id: id, method: _, params: [%{data: _, to: _}, _]}], _options ->
{:ok,
[%{id: id, jsonrpc: "2.0", result: "0x0000000000000000000000000000000000000000000000000000000000000001"}]}
end
)
# getPayoutByMining => 0x0000000000000000000000000000000000000001
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn [%{id: id, method: _, params: [%{data: _, to: _}, _]}], _options ->
{:ok, [%{id: id, result: "0x000000000000000000000000" <> block_miner_hash_string}]}
end
)
assert [_, {_, _}] = Transaction.address_to_transactions_with_rewards(block.miner.hash, direction: :to)
assert_receive {:trace, ^consumer_pid, :receive, {:"$gen_cast", {:fetch_or_update, ^block_miner_hash}}}, 1000
:timer.sleep(500)
on_exit(fn ->
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: false)
Application.put_env(:explorer, Explorer.Chain.Block.Reward,
validators_contract_address: nil,
keys_manager_contract_address: nil
)
end)
end
test "with transactions if rewards are not in the range of blocks" do
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: true)
block = insert(:block)
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :validator
)
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :emission_funds
)
:transaction
|> insert(from_address: block.miner)
|> with_block()
|> Repo.preload(:token_transfers)
assert [_] = Transaction.address_to_transactions_with_rewards(block.miner.hash, direction: :from)
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: false)
end
test "with emissions rewards, but feature disabled" do
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: false)
block = insert(:block)
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :validator
)
insert(
:reward,
address_hash: block.miner_hash,
block_hash: block.hash,
address_type: :emission_funds
)
assert [] == Transaction.address_to_transactions_with_rewards(block.miner.hash)
end
end
# EIP-1967 + EIP-1822
defp request_zero_implementations do
EthereumJSONRPC.Mox

Loading…
Cancel
Save