fix: Fix contract codes fetching for zksync chain type (#11055)
* fix: Fix contract codes fetching for zksync chain type * Process review comments * Fix tests * Fix tests * Fix testspull/11082/head
parent
940a95f0e0
commit
0423c18d3a
@ -0,0 +1,80 @@ |
|||||||
|
defmodule Explorer.Migrator.RefetchContractCodes do |
||||||
|
@moduledoc """ |
||||||
|
Refetch contract_code for. Migration created for running on zksync chain type. |
||||||
|
It has an issue with created contract code derived from internal transactions. Such codes are not correct. |
||||||
|
So, this migration fetches for all current smart contracts actual bytecode from the JSON RPC node. |
||||||
|
""" |
||||||
|
|
||||||
|
use Explorer.Migrator.FillingMigration |
||||||
|
|
||||||
|
import Ecto.Query |
||||||
|
|
||||||
|
alias Explorer.Chain.{Address, Data, Import} |
||||||
|
alias Explorer.Chain.Hash.Address, as: AddressHash |
||||||
|
alias Explorer.Chain.Import.Runner.Addresses |
||||||
|
alias Explorer.Migrator.FillingMigration |
||||||
|
alias Explorer.Repo |
||||||
|
|
||||||
|
require Logger |
||||||
|
|
||||||
|
@migration_name "refetch_contract_codes" |
||||||
|
|
||||||
|
@impl FillingMigration |
||||||
|
def migration_name, do: @migration_name |
||||||
|
|
||||||
|
@impl FillingMigration |
||||||
|
def last_unprocessed_identifiers(state) do |
||||||
|
limit = batch_size() * concurrency() |
||||||
|
|
||||||
|
ids = |
||||||
|
unprocessed_data_query() |
||||||
|
|> select([address], address.hash) |
||||||
|
|> limit(^limit) |
||||||
|
|> Repo.all(timeout: :infinity) |
||||||
|
|
||||||
|
{ids, state} |
||||||
|
end |
||||||
|
|
||||||
|
@impl FillingMigration |
||||||
|
def unprocessed_data_query do |
||||||
|
Address |
||||||
|
|> where([address], not is_nil(address.contract_code) and not address.contract_code_refetched) |
||||||
|
end |
||||||
|
|
||||||
|
@impl FillingMigration |
||||||
|
def update_batch(address_hashes) do |
||||||
|
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments) |
||||||
|
|
||||||
|
address_hashes |
||||||
|
|> Enum.map(&address_to_fetch_code_params/1) |
||||||
|
|> EthereumJSONRPC.fetch_codes(json_rpc_named_arguments) |
||||||
|
|> case do |
||||||
|
{:ok, create_address_codes} -> |
||||||
|
addresses_params = create_address_codes.params_list |> Enum.map(¶m_to_address/1) |> Enum.sort_by(& &1.hash) |
||||||
|
|
||||||
|
Addresses.insert(Repo, addresses_params, %{ |
||||||
|
timeout: :infinity, |
||||||
|
on_conflict: {:replace, [:contract_code, :contract_code_refetched, :updated_at]}, |
||||||
|
timestamps: Import.timestamps() |
||||||
|
}) |
||||||
|
|
||||||
|
{:error, reason} -> |
||||||
|
Logger.error(fn -> ["failed to fetch contract codes: ", inspect(reason)] end, |
||||||
|
error_count: Enum.count(address_hashes) |
||||||
|
) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
@impl FillingMigration |
||||||
|
def update_cache, do: :ok |
||||||
|
|
||||||
|
defp address_to_fetch_code_params(address_hash) do |
||||||
|
%{block_quantity: "latest", address: to_string(address_hash)} |
||||||
|
end |
||||||
|
|
||||||
|
defp param_to_address(%{code: bytecode, address: address_hash}) do |
||||||
|
{:ok, address_hash} = AddressHash.cast(address_hash) |
||||||
|
{:ok, bytecode} = Data.cast(bytecode) |
||||||
|
%{hash: address_hash, contract_code: bytecode, contract_code_refetched: true} |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,13 @@ |
|||||||
|
defmodule Explorer.Repo.ZkSync.Migrations.AddContractCodeRefetched do |
||||||
|
use Ecto.Migration |
||||||
|
|
||||||
|
def change do |
||||||
|
alter table(:addresses) do |
||||||
|
add(:contract_code_refetched, :boolean, default: false) |
||||||
|
end |
||||||
|
|
||||||
|
execute(""" |
||||||
|
ALTER TABLE addresses ALTER COLUMN contract_code_refetched SET DEFAULT true; |
||||||
|
""") |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue