diff --git a/CHANGELOG.md b/CHANGELOG.md index fe195ebc8b..b9b0dc5415 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - [#4690](https://github.com/blockscout/blockscout/pull/4690) - Improve pagination: introduce pagination with random access to pages; Integrate it to the Transactions List page ### Fixes +- [#5248](https://github.com/blockscout/blockscout/pull/5248) - Speedup query for getting verified smart-contract bytecode twin - [#5241](https://github.com/blockscout/blockscout/pull/5241) - Fix DB hostname Regex pattern - [#5216](https://github.com/blockscout/blockscout/pull/5216) - Add token-transfers-toggle.js to the `block_transaction/index.html.eex` - [#5212](https://github.com/blockscout/blockscout/pull/5212) - Fix `gas_used` value bug diff --git a/apps/block_scout_web/test/block_scout_web/controllers/address_read_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/address_read_contract_controller_test.exs index e13af34d94..6fa1c616e0 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/address_read_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/address_read_contract_controller_test.exs @@ -50,7 +50,7 @@ defmodule BlockScoutWeb.AddressReadContractControllerTest do block_index: 0 ) - insert(:smart_contract, address_hash: contract_address.hash) + insert(:smart_contract, address_hash: contract_address.hash, contract_code_md5: "123") get_eip1967_implementation() diff --git a/apps/block_scout_web/test/block_scout_web/controllers/address_read_proxy_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/address_read_proxy_controller_test.exs index dd8781f993..8453544e71 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/address_read_proxy_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/address_read_proxy_controller_test.exs @@ -49,7 +49,7 @@ defmodule BlockScoutWeb.AddressReadProxyControllerTest do block_index: 0 ) - insert(:smart_contract, address_hash: contract_address.hash) + insert(:smart_contract, address_hash: contract_address.hash, contract_code_md5: "123") get_eip1967_implementation() diff --git a/apps/block_scout_web/test/block_scout_web/controllers/address_write_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/address_write_contract_controller_test.exs index 06a0c070f1..ed8de0f115 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/address_write_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/address_write_contract_controller_test.exs @@ -51,7 +51,7 @@ defmodule BlockScoutWeb.AddressWriteContractControllerTest do block_index: 0 ) - insert(:smart_contract, address_hash: contract_address.hash) + insert(:smart_contract, address_hash: contract_address.hash, contract_code_md5: "123") get_eip1967_implementation() diff --git a/apps/block_scout_web/test/block_scout_web/controllers/address_write_proxy_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/address_write_proxy_controller_test.exs index 17dfcdd982..f767b098ee 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/address_write_proxy_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/address_write_proxy_controller_test.exs @@ -49,7 +49,7 @@ defmodule BlockScoutWeb.AddressWriteProxyControllerTest do block_index: 0 ) - insert(:smart_contract, address_hash: contract_address.hash) + insert(:smart_contract, address_hash: contract_address.hash, contract_code_md5: "123") get_eip1967_implementation() diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs index 5bfc345c19..aa2a413a00 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs @@ -36,7 +36,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do end test "with a verified smart contract, all contract information is shown", %{conn: conn, params: params} do - contract = insert(:smart_contract) + contract = insert(:smart_contract, contract_code_md5: "123") response = conn @@ -82,7 +82,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do test "filtering for only unverified contracts shows only unverified contracts", %{params: params, conn: conn} do address = insert(:contract_address) - insert(:smart_contract) + insert(:smart_contract, contract_code_md5: "123") response = conn @@ -107,7 +107,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do conn: conn } do address = insert(:contract_address) - insert(:smart_contract) + insert(:smart_contract, contract_code_md5: "123") insert(:contract_address, contract_code: "0x") response = @@ -130,7 +130,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do test "filtering for only verified contracts shows only verified contracts", %{params: params, conn: conn} do insert(:contract_address) - contract = insert(:smart_contract) + contract = insert(:smart_contract, contract_code_md5: "123") response = conn @@ -222,7 +222,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do test "filtering for only not_decompiled (and by extension not verified contracts)", %{params: params, conn: conn} do insert(:decompiled_smart_contract) - insert(:smart_contract) + insert(:smart_contract, contract_code_md5: "123") contract_address = insert(:contract_address) response = @@ -248,7 +248,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do conn: conn } do insert(:decompiled_smart_contract) - insert(:smart_contract) + insert(:smart_contract, contract_code_md5: "123") insert(:contract_address, contract_code: "0x") contract_address = insert(:contract_address) @@ -328,7 +328,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do end test "with a verified contract address", %{conn: conn} do - contract = insert(:smart_contract) + contract = insert(:smart_contract, contract_code_md5: "123") params = %{ "module" => "contract", @@ -424,7 +424,13 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do end test "with a verified contract address", %{conn: conn} do - contract = insert(:smart_contract, optimization: true, optimization_runs: 200, evm_version: "default") + contract = + insert(:smart_contract, + optimization: true, + optimization_runs: 200, + evm_version: "default", + contract_code_md5: "123" + ) params = %{ "module" => "contract", @@ -470,7 +476,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do optimization_runs: 200, evm_version: "default", constructor_arguments: - "00000000000000000000000008e7592ce0d7ebabf42844b62ee6a878d4e1913e000000000000000000000000e1b6037da5f1d756499e184ca15254a981c92546" + "00000000000000000000000008e7592ce0d7ebabf42844b62ee6a878d4e1913e000000000000000000000000e1b6037da5f1d756499e184ca15254a981c92546", + contract_code_md5: "123" ) params = %{ diff --git a/apps/block_scout_web/test/block_scout_web/controllers/chain_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/chain_controller_test.exs index 7aba3e7b8b..f361b8b55d 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/chain_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/chain_controller_test.exs @@ -94,7 +94,7 @@ defmodule BlockScoutWeb.ChainControllerTest do end test "finds verified contract" do - insert(:smart_contract, name: "SuperToken") + insert(:smart_contract, name: "SuperToken", contract_code_md5: "123") conn = build_conn() @@ -104,7 +104,7 @@ defmodule BlockScoutWeb.ChainControllerTest do end test "finds verified contract and token" do - insert(:smart_contract, name: "MagicContract") + insert(:smart_contract, name: "MagicContract", contract_code_md5: "123") insert(:token, name: "magicToken") conn = @@ -115,10 +115,10 @@ defmodule BlockScoutWeb.ChainControllerTest do end test "finds verified contracts and tokens" do - insert(:smart_contract, name: "something") - insert(:smart_contract, name: "MagicContract") + insert(:smart_contract, name: "something", contract_code_md5: "123") + insert(:smart_contract, name: "MagicContract", contract_code_md5: "123") insert(:token, name: "Magic3") - insert(:smart_contract, name: "magicContract2") + insert(:smart_contract, name: "magicContract2", contract_code_md5: "123") insert(:token, name: "magicToken") insert(:token, name: "OneMoreToken") @@ -142,7 +142,7 @@ defmodule BlockScoutWeb.ChainControllerTest do test "find by empty query" do insert(:token, name: "MaGiCt0k3n") - insert(:smart_contract, name: "MagicContract") + insert(:smart_contract, name: "MagicContract", contract_code_md5: "123") conn = build_conn() diff --git a/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs index 07e1124311..57d40dd30a 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs @@ -33,7 +33,7 @@ defmodule BlockScoutWeb.SmartContractControllerTest do end test "only responds to ajax requests", %{conn: conn} do - smart_contract = insert(:smart_contract) + smart_contract = insert(:smart_contract, contract_code_md5: "123") path = smart_contract_path(BlockScoutWeb.Endpoint, :index, hash: smart_contract.address_hash) @@ -45,7 +45,7 @@ defmodule BlockScoutWeb.SmartContractControllerTest do test "lists the smart contract read only functions" do token_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: token_contract_address.hash) + insert(:smart_contract, address_hash: token_contract_address.hash, contract_code_md5: "123") blockchain_get_code_mock() blockchain_get_function_mock() @@ -81,7 +81,8 @@ defmodule BlockScoutWeb.SmartContractControllerTest do "inputs" => [], "constant" => true } - ] + ], + contract_code_md5: "123" ) blockchain_get_code_mock() @@ -117,7 +118,8 @@ defmodule BlockScoutWeb.SmartContractControllerTest do "inputs" => [], "constant" => false } - ] + ], + contract_code_md5: "123" ) blockchain_get_code_mock() @@ -154,7 +156,8 @@ defmodule BlockScoutWeb.SmartContractControllerTest do "inputs" => [], "constant" => false } - ] + ], + contract_code_md5: "123" ) blockchain_get_code_mock() @@ -217,7 +220,7 @@ defmodule BlockScoutWeb.SmartContractControllerTest do end test "only responds to ajax requests", %{conn: conn} do - smart_contract = insert(:smart_contract) + smart_contract = insert(:smart_contract, contract_code_md5: "123") path = smart_contract_path( @@ -235,7 +238,7 @@ defmodule BlockScoutWeb.SmartContractControllerTest do test "fetch the function value from the blockchain" do address = insert(:contract_address) - smart_contract = insert(:smart_contract, address_hash: address.hash) + smart_contract = insert(:smart_contract, address_hash: address.hash, contract_code_md5: "123") blockchain_get_code_mock() blockchain_get_function_mock() diff --git a/apps/block_scout_web/test/block_scout_web/controllers/tokens/read_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/tokens/read_contract_controller_test.exs index efc5e982ce..182be79a97 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/tokens/read_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/tokens/read_contract_controller_test.exs @@ -36,7 +36,7 @@ defmodule BlockScoutWeb.Tokens.ContractControllerTest do test "successfully renders the page when the token is a verified smart contract", %{conn: conn} do token_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: token_contract_address.hash) + insert(:smart_contract, address_hash: token_contract_address.hash, contract_code_md5: "123") token = insert(:token, contract_address: token_contract_address) diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs index 55d2847e35..64adae6fb9 100644 --- a/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs +++ b/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs @@ -58,7 +58,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do test "smart_contract returns all expected fields", %{conn: conn} do address = insert(:address, fetched_coin_balance: 100) - smart_contract = insert(:smart_contract, address_hash: address.hash) + smart_contract = insert(:smart_contract, address_hash: address.hash, contract_code_md5: "123") query = """ query ($hash: AddressHash!) { diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs index 3468e74693..f6145a4afc 100644 --- a/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs +++ b/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs @@ -62,7 +62,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do test "smart_contract returns all expected fields", %{conn: conn} do address = insert(:address, fetched_coin_balance: 100) - smart_contract = insert(:smart_contract, address_hash: address.hash) + smart_contract = insert(:smart_contract, address_hash: address.hash, contract_code_md5: "123") query = """ query ($hashes: [AddressHash!]!) { diff --git a/apps/block_scout_web/test/block_scout_web/views/address_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/address_view_test.exs index 263f6fd635..df8ee5a772 100644 --- a/apps/block_scout_web/test/block_scout_web/views/address_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/address_view_test.exs @@ -235,7 +235,7 @@ defmodule BlockScoutWeb.AddressViewTest do describe "smart_contract_verified?/1" do test "returns true when smart contract is verified" do - smart_contract = insert(:smart_contract) + smart_contract = insert(:smart_contract, contract_code_md5: "123") address = insert(:address, smart_contract: smart_contract) assert AddressView.smart_contract_verified?(address) @@ -263,7 +263,8 @@ defmodule BlockScoutWeb.AddressViewTest do "stateMutability" => "view", "type" => "function" } - ] + ], + contract_code_md5: "123" ) address = insert(:address, smart_contract: smart_contract) @@ -285,7 +286,8 @@ defmodule BlockScoutWeb.AddressViewTest do "stateMutability" => "nonpayable", "type" => "function" } - ] + ], + contract_code_md5: "123" ) address = insert(:address, smart_contract: smart_contract) diff --git a/apps/block_scout_web/test/block_scout_web/views/tokens/overview_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/tokens/overview_view_test.exs index 55095c52b0..9d10d46c54 100644 --- a/apps/block_scout_web/test/block_scout_web/views/tokens/overview_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/tokens/overview_view_test.exs @@ -94,7 +94,8 @@ defmodule BlockScoutWeb.Tokens.OverviewViewTest do "stateMutability" => "view", "type" => "function" } - ] + ], + contract_code_md5: "123" ) address = insert(:address, smart_contract: smart_contract) @@ -118,7 +119,8 @@ defmodule BlockScoutWeb.Tokens.OverviewViewTest do "stateMutability" => "nonpayable", "type" => "function" } - ] + ], + contract_code_md5: "123" ) address = insert(:address, smart_contract: smart_contract) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 53f05fbf9e..8017202632 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -83,7 +83,7 @@ defmodule Explorer.Chain do alias Explorer.Counters.{AddressesCounter, AddressesWithBalanceCounter} alias Explorer.Market.MarketHistoryCache alias Explorer.{PagingOptions, Repo} - alias Explorer.SmartContract.Reader + alias Explorer.SmartContract.{Helper, Reader} alias Explorer.Staking.ContractState alias Dataloader.Ecto, as: DataloaderEcto @@ -3965,6 +3965,10 @@ defmodule Explorer.Chain do def create_smart_contract(attrs \\ %{}, external_libraries \\ [], secondary_sources \\ []) do new_contract = %SmartContract{} + attrs = + attrs + |> Helper.add_contract_code_md5() + smart_contract_changeset = new_contract |> SmartContract.changeset(attrs) @@ -4172,11 +4176,9 @@ defmodule Explorer.Chain do verified_contract_twin_query = from( - address in Address, - inner_join: smart_contract in SmartContract, - on: address.hash == smart_contract.address_hash, - where: fragment("md5(contract_code::text)") == ^contract_code_md5, - where: address.hash != ^target_address_hash, + smart_contract in SmartContract, + where: smart_contract.contract_code_md5 == ^contract_code_md5, + where: smart_contract.address_hash != ^target_address_hash, select: smart_contract, limit: 1 ) diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index 502a7e8088..df24f79fd1 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -198,6 +198,7 @@ defmodule Explorer.Chain.SmartContract do * `file_path` - show the filename or path to the file of the contract source file * `is_changed_bytecode` - boolean flag, determines if contract's bytecode was modified * `bytecode_checked_at` - timestamp of the last check of contract's bytecode matching (DB and BlockChain) + * `contract_code_md5` - md5(`t:Explorer.Chain.Address.t/0` `contract_code`) """ @type t :: %Explorer.Chain.SmartContract{ @@ -214,7 +215,8 @@ defmodule Explorer.Chain.SmartContract do file_path: String.t(), is_vyper_contract: boolean | nil, is_changed_bytecode: boolean, - bytecode_checked_at: DateTime.t() + bytecode_checked_at: DateTime.t(), + contract_code_md5: String.t() } schema "smart_contracts" do @@ -233,6 +235,7 @@ defmodule Explorer.Chain.SmartContract do field(:is_vyper_contract, :boolean) field(:is_changed_bytecode, :boolean, default: false) field(:bytecode_checked_at, :utc_datetime_usec, default: DateTime.add(DateTime.utc_now(), -86400, :second)) + field(:contract_code_md5, :string) has_many( :decompiled_smart_contracts, @@ -272,9 +275,18 @@ defmodule Explorer.Chain.SmartContract do :file_path, :is_vyper_contract, :is_changed_bytecode, - :bytecode_checked_at + :bytecode_checked_at, + :contract_code_md5 + ]) + |> validate_required([ + :name, + :compiler_version, + :optimization, + :contract_source_code, + :abi, + :address_hash, + :contract_code_md5 ]) - |> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash]) |> unique_constraint(:address_hash) |> prepare_changes(&upsert_contract_methods/1) end @@ -302,11 +314,12 @@ defmodule Explorer.Chain.SmartContract do :file_path, :is_vyper_contract, :is_changed_bytecode, - :bytecode_checked_at + :bytecode_checked_at, + :contract_code_md5 ]) |> (&if(json_verification, do: &1, - else: validate_required(&1, [:name, :compiler_version, :optimization, :address_hash]) + else: validate_required(&1, [:name, :compiler_version, :optimization, :address_hash, :contract_code_md5]) )).() field_to_put_message = if json_verification, do: :file, else: :contract_source_code diff --git a/apps/explorer/lib/explorer/smart_contract/helper.ex b/apps/explorer/lib/explorer/smart_contract/helper.ex index 59e7013bfd..609091c065 100644 --- a/apps/explorer/lib/explorer/smart_contract/helper.ex +++ b/apps/explorer/lib/explorer/smart_contract/helper.ex @@ -3,6 +3,8 @@ defmodule Explorer.SmartContract.Helper do SmartContract helper functions """ + alias Explorer.Chain + def queriable_method?(method) do method["constant"] || method["stateMutability"] == "view" || method["stateMutability"] == "pure" end @@ -36,4 +38,37 @@ defmodule Explorer.SmartContract.Helper do false end end + + def add_contract_code_md5(%{address_hash: address_hash_string} = attrs) when is_binary(address_hash_string) do + with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), + {:ok, address} <- Chain.hash_to_address(address_hash) do + contract_code_md5 = + :md5 + |> :crypto.hash(address.contract_code.bytes) + |> Base.encode16(case: :lower) + + attrs + |> Map.put_new(:contract_code_md5, contract_code_md5) + else + _ -> attrs + end + end + + def add_contract_code_md5(%{address_hash: address_hash} = attrs) do + case Chain.hash_to_address(address_hash) do + {:ok, address} -> + contract_code_md5 = + :md5 + |> :crypto.hash(address.contract_code.bytes) + |> Base.encode16(case: :lower) + + attrs + |> Map.put_new(:contract_code_md5, contract_code_md5) + + _ -> + attrs + end + end + + def add_contract_code_md5(attrs), do: attrs end diff --git a/apps/explorer/priv/repo/migrations/20220303083252_smart_contracts_contract_code_md5.exs b/apps/explorer/priv/repo/migrations/20220303083252_smart_contracts_contract_code_md5.exs new file mode 100644 index 0000000000..7c8a66ddf4 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20220303083252_smart_contracts_contract_code_md5.exs @@ -0,0 +1,23 @@ +defmodule Explorer.Repo.Migrations.SmartContractsContractCodeMd5 do + use Ecto.Migration + + def change do + alter table(:smart_contracts) do + add(:contract_code_md5, :string, null: true) + end + + execute(""" + UPDATE smart_contracts + SET contract_code_md5 = md5(a.contract_code) + FROM addresses a + WHERE smart_contracts.address_hash = a.hash; + """) + + alter table(:smart_contracts) do + modify(:contract_code_md5, :string, null: false) + end + + drop_if_exists(index(:addresses, ["md5(contract_code::text)"], name: "addresses_contract_code_index")) + create(index(:smart_contracts, :contract_code_md5)) + end +end diff --git a/apps/explorer/test/explorer/chain/log_test.exs b/apps/explorer/test/explorer/chain/log_test.exs index 880bd0274a..31f6b10f08 100644 --- a/apps/explorer/test/explorer/chain/log_test.exs +++ b/apps/explorer/test/explorer/chain/log_test.exs @@ -75,7 +75,8 @@ defmodule Explorer.Chain.LogTest do "type" => "event" } ], - address_hash: to_address.hash + address_hash: to_address.hash, + contract_code_md5: "123" ) topic1_bytes = ExKeccak.hash_256("WantsPets(string,uint256,bool)") diff --git a/apps/explorer/test/explorer/chain/transaction_test.exs b/apps/explorer/test/explorer/chain/transaction_test.exs index 8332b70659..830caaf321 100644 --- a/apps/explorer/test/explorer/chain/transaction_test.exs +++ b/apps/explorer/test/explorer/chain/transaction_test.exs @@ -305,7 +305,7 @@ defmodule Explorer.Chain.TransactionTest do |> insert() |> Repo.preload(to_address: :smart_contract) - contract = insert(:smart_contract) |> Repo.preload(:address) + contract = insert(:smart_contract, contract_code_md5: "123") |> Repo.preload(:address) input_data = "set(uint)" diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 08ea81b603..1a18b53588 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -4403,7 +4403,7 @@ defmodule Explorer.ChainTest do describe "address_hash_to_smart_contract/1" do test "fetches a smart contract" do - smart_contract = insert(:smart_contract) + smart_contract = insert(:smart_contract, contract_code_md5: "123") assert ^smart_contract = Chain.address_hash_to_smart_contract(smart_contract.address_hash) end @@ -5646,16 +5646,21 @@ defmodule Explorer.ChainTest do test "combine_proxy_implementation_abi/2 returns proxy abi if implementation is not verified" do proxy_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi) + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi, contract_code_md5: "123") assert Chain.combine_proxy_implementation_abi(proxy_contract_address, @proxy_abi) == @proxy_abi end test "combine_proxy_implementation_abi/2 returns proxy + implementation abi if implementation is verified" do proxy_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi) + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi, contract_code_md5: "123") implementation_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: implementation_contract_address.hash, abi: @implementation_abi) + + insert(:smart_contract, + address_hash: implementation_contract_address.hash, + abi: @implementation_abi, + contract_code_md5: "123" + ) implementation_contract_address_hash_string = Base.encode16(implementation_contract_address.hash.bytes, case: :lower) @@ -5728,16 +5733,21 @@ defmodule Explorer.ChainTest do test "get_implementation_abi_from_proxy/2 returns [] if implementation is not verified" do proxy_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi) + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi, contract_code_md5: "123") assert Chain.get_implementation_abi_from_proxy(proxy_contract_address, @proxy_abi) == [] end test "get_implementation_abi_from_proxy/2 returns implementation abi if implementation is verified" do proxy_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi) + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi, contract_code_md5: "123") implementation_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: implementation_contract_address.hash, abi: @implementation_abi) + + insert(:smart_contract, + address_hash: implementation_contract_address.hash, + abi: @implementation_abi, + contract_code_md5: "123" + ) implementation_contract_address_hash_string = Base.encode16(implementation_contract_address.hash.bytes, case: :lower) @@ -5764,10 +5774,15 @@ defmodule Explorer.ChainTest do test "get_implementation_abi_from_proxy/2 returns implementation abi in case of EIP-1967 proxy pattern" do proxy_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: []) + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: [], contract_code_md5: "123") implementation_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: implementation_contract_address.hash, abi: @implementation_abi) + + insert(:smart_contract, + address_hash: implementation_contract_address.hash, + abi: @implementation_abi, + contract_code_md5: "123" + ) implementation_contract_address_hash_string = Base.encode16(implementation_contract_address.hash.bytes, case: :lower) @@ -5809,10 +5824,15 @@ defmodule Explorer.ChainTest do test "get_implementation_abi/1 returns implementation abi if implementation is verified" do proxy_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi) + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi, contract_code_md5: "123") implementation_contract_address = insert(:contract_address) - insert(:smart_contract, address_hash: implementation_contract_address.hash, abi: @implementation_abi) + + insert(:smart_contract, + address_hash: implementation_contract_address.hash, + abi: @implementation_abi, + contract_code_md5: "123" + ) implementation_contract_address_hash_string = Base.encode16(implementation_contract_address.hash.bytes, case: :lower) diff --git a/apps/explorer/test/explorer/smart_contract/reader_test.exs b/apps/explorer/test/explorer/smart_contract/reader_test.exs index 87ba283eb4..3b2e7d1471 100644 --- a/apps/explorer/test/explorer/smart_contract/reader_test.exs +++ b/apps/explorer/test/explorer/smart_contract/reader_test.exs @@ -190,7 +190,8 @@ defmodule Explorer.SmartContract.ReaderTest do "inputs" => [], "constant" => true } - ] + ], + contract_code_md5: "123" ) implementation_contract_address = insert(:contract_address) @@ -216,7 +217,8 @@ defmodule Explorer.SmartContract.ReaderTest do "stateMutability" => "view", "type" => "function" } - ] + ], + contract_code_md5: "123" ) implementation_contract_address_hash_string = @@ -255,7 +257,7 @@ defmodule Explorer.SmartContract.ReaderTest do describe "query_function/3" do test "given the arguments, fetches the function value from the blockchain" do - smart_contract = insert(:smart_contract) + smart_contract = insert(:smart_contract, contract_code_md5: "123") blockchain_get_function_mock() @@ -268,7 +270,7 @@ defmodule Explorer.SmartContract.ReaderTest do end test "nil arguments is treated as []" do - smart_contract = insert(:smart_contract) + smart_contract = insert(:smart_contract, contract_code_md5: "123") blockchain_get_function_mock() diff --git a/apps/explorer/test/explorer/smart_contract/writer_test.exs b/apps/explorer/test/explorer/smart_contract/writer_test.exs index 85d1f69fce..ac95dfa918 100644 --- a/apps/explorer/test/explorer/smart_contract/writer_test.exs +++ b/apps/explorer/test/explorer/smart_contract/writer_test.exs @@ -283,14 +283,16 @@ defmodule Explorer.SmartContract.WriterTest do test "fetches the smart contract proxy write functions" do _proxy_smart_contract = insert(:smart_contract, - abi: @abi + abi: @abi, + contract_code_md5: "123" ) implementation_contract_address = insert(:contract_address) insert(:smart_contract, address_hash: implementation_contract_address.hash, - abi: @implementation_abi + abi: @implementation_abi, + contract_code_md5: "123" ) implementation_contract_address_hash_string = diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index 95e8a2b04a..2777fdf798 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -607,13 +607,19 @@ defmodule Explorer.Factory do def smart_contract_factory do contract_code_info = contract_code_info() + bytecode_md5 = + :md5 + |> :crypto.hash(contract_code_info.bytecode) + |> Base.encode16(case: :lower) + %SmartContract{ address_hash: insert(:address, contract_code: contract_code_info.bytecode, verified: true).hash, compiler_version: contract_code_info.version, name: contract_code_info.name, contract_source_code: contract_code_info.source_code, optimization: contract_code_info.optimized, - abi: contract_code_info.abi + abi: contract_code_info.abi, + contract_code_md5: bytecode_md5 } end