Bridged tokens status fetcher refactoring

pull/3276/head
Victor Baranov 4 years ago
parent 3685e95cc0
commit bf448fa74f
  1. 1
      CHANGELOG.md
  2. 219
      apps/explorer/lib/explorer/chain.ex
  3. 9
      apps/explorer/lib/explorer/chain/block/reward.ex
  4. 1
      apps/explorer/lib/explorer/chain/token.ex

@ -6,6 +6,7 @@
- [#3261](https://github.com/poanetwork/blockscout/pull/3261) - Bridged tokens table
### Fixes
- [#3276](https://github.com/poanetwork/blockscout/pull/3276) - Bridged tokens status/metadata fetcher refactoring
- [#3264](https://github.com/poanetwork/blockscout/pull/3264) - Fix encoding of address output if function input exists
- [#3259](https://github.com/poanetwork/blockscout/pull/3259), [#3269](https://github.com/poanetwork/blockscout/pull/3269) - Contract interaction: array input type parsing fix
- [#3257](https://github.com/poanetwork/blockscout/pull/3257) - Contracts read/write: method_id instead function_name as a key

@ -3581,11 +3581,11 @@ defmodule Explorer.Chain do
end
@doc """
Fetches bridges status for tokens.
Fetches bridged status for tokens and metadata.
"""
def fetch_tokens_bridged_status(token_addresses) do
Enum.each(token_addresses, fn token_address_hash ->
created_from_factory_query =
created_from_int_tx_success_query =
from(
it in InternalTransaction,
inner_join: t in assoc(it, :transaction),
@ -3593,104 +3593,145 @@ defmodule Explorer.Chain do
where: t.status == ^1
)
created_from_factory =
created_from_factory_query
created_from_int_tx_success =
created_from_int_tx_success_query
|> Repo.one()
if created_from_factory do
multi_token_bridge_mediator = Application.get_env(:block_scout_web, :multi_token_bridge_mediator)
%{transaction_hash: transaction_hash} = created_from_factory
created_from_tx_query =
from(
t in Transaction,
where: t.created_contract_address_hash == ^token_address_hash
)
if multi_token_bridge_mediator && multi_token_bridge_mediator !== "" do
{:ok, multi_token_bridge_mediator_hash} = Chain.string_to_address_hash(multi_token_bridge_mediator)
created_from_tx =
created_from_tx_query
|> Repo.all()
|> Enum.count() > 0
created_by_amb_mediator_query =
from(
it in InternalTransaction,
where: it.transaction_hash == ^transaction_hash,
where: it.to_address_hash == ^multi_token_bridge_mediator_hash
)
created_from_int_tx_query =
from(
it in InternalTransaction,
where: it.created_contract_address_hash == ^token_address_hash
)
created_by_amb_mediator =
created_by_amb_mediator_query
|> Repo.all()
if Enum.count(created_by_amb_mediator) > 0 do
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
# keccak 256 from getTokenInterfacesVersion()
get_token_interfaces_version_signature = "0x859ba28c"
# keccak 256 from foreignTokenAddress(address)
foreign_token_address_signature = "0x47ac7d6a"
# keccak 256 from bridgeContract()
bridge_contract_signature = "0xcd596583"
# keccak 256 from destinationChainId()
destination_chain_id_signature = "0xb0750611"
token_address_hash_abi_encoded =
[token_address_hash.bytes]
|> TypeEncoder.encode([:address])
|> Base.encode16()
foreign_token_address_method = foreign_token_address_signature <> token_address_hash_abi_encoded
with {:ok, _} <-
get_token_interfaces_version_signature
|> Contract.eth_call_request(token_address_hash, 1, nil, nil)
|> json_rpc(json_rpc_named_arguments),
{:ok, foreign_token_address_abi_encoded} <-
foreign_token_address_method
|> Contract.eth_call_request(
multi_token_bridge_mediator,
1,
nil,
nil
)
|> json_rpc(json_rpc_named_arguments),
{:ok, bridge_contract} <-
bridge_contract_signature
|> Contract.eth_call_request(multi_token_bridge_mediator_hash, 1, nil, nil)
|> json_rpc(json_rpc_named_arguments) do
"0x" <> foreign_token_address_no_prefix = foreign_token_address_abi_encoded
<<_prefix::binary-size(24), foreign_token_address_hash_string_raw::binary()>> =
foreign_token_address_no_prefix
foreign_token_address_hash_string = "0x" <> foreign_token_address_hash_string_raw
{:ok, foreign_token_address_hash} = Chain.string_to_address_hash(foreign_token_address_hash_string)
"0x" <> bridge_contract_no_prefix = bridge_contract
<<_prefix::binary-size(24), multi_token_bridge_hash_string_raw::binary()>> = bridge_contract_no_prefix
multi_token_bridge_hash_string = "0x" <> multi_token_bridge_hash_string_raw
{:ok, foreign_chain_id_abi_encoded} =
destination_chain_id_signature
|> Contract.eth_call_request(multi_token_bridge_hash_string, 1, nil, nil)
|> json_rpc(json_rpc_named_arguments)
"0x" <> foreign_chain_id_abi_encoded_no_prefix = foreign_chain_id_abi_encoded
{foreign_chain_id, _} = Integer.parse(foreign_chain_id_abi_encoded_no_prefix, 16)
set_bridged_token_metadata(token_address_hash, %{
foreign_chain_id: foreign_chain_id,
foreign_token_address_hash: foreign_token_address_hash
})
set_token_bridged_status(token_address_hash, true)
end
else
set_token_bridged_status(token_address_hash, false)
end
end
else
set_token_bridged_status(token_address_hash, false)
created_from_int_tx =
created_from_int_tx_query
|> Repo.all()
|> Enum.count() > 0
cond do
created_from_tx ->
set_token_bridged_status(token_address_hash, false)
created_from_int_tx && !created_from_int_tx_success ->
set_token_bridged_status(token_address_hash, false)
created_from_int_tx && created_from_int_tx_success ->
extract_bridged_token_metadata_wrapper(token_address_hash, created_from_int_tx_success)
true ->
:ok
end
end)
:ok
end
defp extract_bridged_token_metadata_wrapper(token_address_hash, created_from_int_tx_success) do
multi_token_bridge_mediator = Application.get_env(:block_scout_web, :multi_token_bridge_mediator)
%{transaction_hash: transaction_hash} = created_from_int_tx_success
if multi_token_bridge_mediator && multi_token_bridge_mediator !== "" do
{:ok, multi_token_bridge_mediator_hash} = Chain.string_to_address_hash(multi_token_bridge_mediator)
created_by_amb_mediator_query =
from(
it in InternalTransaction,
where: it.transaction_hash == ^transaction_hash,
where: it.to_address_hash == ^multi_token_bridge_mediator_hash
)
created_by_amb_mediator =
created_by_amb_mediator_query
|> Repo.all()
if Enum.count(created_by_amb_mediator) > 0 do
extract_bridged_token_metadata(
token_address_hash,
multi_token_bridge_mediator,
multi_token_bridge_mediator_hash
)
else
set_token_bridged_status(token_address_hash, false)
end
end
end
defp extract_bridged_token_metadata(token_address_hash, multi_token_bridge_mediator, multi_token_bridge_mediator_hash) do
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
# keccak 256 from getTokenInterfacesVersion()
get_token_interfaces_version_signature = "0x859ba28c"
# keccak 256 from foreignTokenAddress(address)
foreign_token_address_signature = "0x47ac7d6a"
# keccak 256 from bridgeContract()
bridge_contract_signature = "0xcd596583"
# keccak 256 from destinationChainId()
destination_chain_id_signature = "0xb0750611"
token_address_hash_abi_encoded =
[token_address_hash.bytes]
|> TypeEncoder.encode([:address])
|> Base.encode16()
foreign_token_address_method = foreign_token_address_signature <> token_address_hash_abi_encoded
with {:ok, _} <-
get_token_interfaces_version_signature
|> Contract.eth_call_request(token_address_hash, 1, nil, nil)
|> json_rpc(json_rpc_named_arguments),
{:ok, foreign_token_address_abi_encoded} <-
foreign_token_address_method
|> Contract.eth_call_request(
multi_token_bridge_mediator,
1,
nil,
nil
)
|> json_rpc(json_rpc_named_arguments),
{:ok, bridge_contract} <-
bridge_contract_signature
|> Contract.eth_call_request(multi_token_bridge_mediator_hash, 1, nil, nil)
|> json_rpc(json_rpc_named_arguments) do
"0x" <> foreign_token_address_no_prefix = foreign_token_address_abi_encoded
<<_prefix::binary-size(24), foreign_token_address_hash_string_raw::binary()>> = foreign_token_address_no_prefix
foreign_token_address_hash_string = "0x" <> foreign_token_address_hash_string_raw
{:ok, foreign_token_address_hash} = Chain.string_to_address_hash(foreign_token_address_hash_string)
"0x" <> bridge_contract_no_prefix = bridge_contract
<<_prefix::binary-size(24), multi_token_bridge_hash_string_raw::binary()>> = bridge_contract_no_prefix
multi_token_bridge_hash_string = "0x" <> multi_token_bridge_hash_string_raw
{:ok, foreign_chain_id_abi_encoded} =
destination_chain_id_signature
|> Contract.eth_call_request(multi_token_bridge_hash_string, 1, nil, nil)
|> json_rpc(json_rpc_named_arguments)
"0x" <> foreign_chain_id_abi_encoded_no_prefix = foreign_chain_id_abi_encoded
{foreign_chain_id, _} = Integer.parse(foreign_chain_id_abi_encoded_no_prefix, 16)
set_bridged_token_metadata(token_address_hash, %{
foreign_chain_id: foreign_chain_id,
foreign_token_address_hash: foreign_token_address_hash
})
set_token_bridged_status(token_address_hash, true)
end
end
defp set_token_bridged_status(token_address_hash, status) do
target_token = Repo.get!(Token, token_address_hash)
token = Changeset.change(target_token, bridged: status)

@ -171,8 +171,13 @@ defmodule Explorer.Chain.Block.Reward do
if payout_key_hash == @empty_address do
mining_key
else
{:ok, payout_key} = Chain.string_to_address_hash(payout_key_hash)
payout_key
case Chain.string_to_address_hash(payout_key_hash) do
{:ok, payout_key} ->
payout_key
_ ->
mining_key
end
end
else
mining_key

@ -35,6 +35,7 @@ defmodule Explorer.Chain.Token do
* `contract_address_hash` - Address hash foreign key
* `holder_count` - the number of `t:Explorer.Chain.Address.t/0` (except the burn address) that have a
`t:Explorer.Chain.CurrentTokenBalance.t/0` `value > 0`. Can be `nil` when data not migrated.
* `bridged` - Flag for bridged tokens from other chain
"""
@type t :: %Token{
name: String.t(),

Loading…
Cancel
Save