From ec87839a2045f0405e59345fb2988f567492d1e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=9F=D0=BE=D0=B7?= =?UTF-8?q?=D0=B4=D0=BD=D1=8F=D0=BA=D0=BE=D0=B2?= Date: Fri, 30 Dec 2022 17:07:17 +0700 Subject: [PATCH] Fix unhandled error; Add regression tests; Add missing existance smart-contracts checks --- .../api/v2/smart_contract_controller.ex | 18 +++++- .../api/v2/smart_contract_controller_test.exs | 57 +++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex index df81741cd8..5696dbd186 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex @@ -5,6 +5,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do alias BlockScoutWeb.{AccessHelpers, AddressView} alias BlockScoutWeb.AddressContractVerificationController, as: VerificationController + alias Ecto.Association.NotLoaded alias Explorer.Chain alias Explorer.Chain.SmartContract alias Explorer.SmartContract.{Reader, Writer} @@ -90,7 +91,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)}, {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params), {:not_found, {:ok, address}} <- - {:not_found, Chain.find_contract_address(address_hash, @smart_contract_address_options)} do + {:not_found, Chain.find_contract_address(address_hash, @smart_contract_address_options)}, + {:not_found, false} <- {:not_found, is_nil(address.smart_contract)} do implementation_address_hash_string = address.smart_contract |> SmartContract.get_implementation_address_hash() @@ -109,7 +111,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)}, {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params), {:not_found, {:ok, address}} <- - {:not_found, Chain.find_contract_address(address_hash, @smart_contract_address_options)} do + {:not_found, Chain.find_contract_address(address_hash, @smart_contract_address_options)}, + {:not_found, false} <- {:not_found, is_nil(address.smart_contract)} do implementation_address_hash_string = address.smart_contract |> SmartContract.get_implementation_address_hash() @@ -133,7 +136,16 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)}, {:ok, false} <- AccessHelpers.restricted_access?(address_hash_string, params), - {:not_found, {:ok, _address}} <- {:not_found, Chain.find_contract_address(address_hash, [])} do + {:not_found, {:ok, address}} <- + {:not_found, + Chain.find_contract_address(address_hash, + necessity_by_association: %{ + :smart_contract => :optional + } + )}, + {:not_found, true} <- + {:not_found, + !is_nil(custom_abi) || (address.smart_contract && !match?(%NotLoaded{}, address.smart_contract))} do %{output: output, names: names} = if custom_abi do Reader.query_function_with_names_custom_abi( diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs index 32df5d2c79..b49e126634 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs @@ -122,6 +122,13 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do assert %{"message" => "Invalid parameter(s)"} = json_response(request, 422) end + test "return 404 on unverified contract", %{conn: conn} do + address = insert(:contract_address) + + request = get(conn, "/api/v2/smart-contracts/#{Address.checksum(address.hash)}/methods-read") + assert %{"message" => "Not found"} = json_response(request, 404) + end + test "get read-methods", %{conn: conn} do abi = [ %{ @@ -206,6 +213,19 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do assert %{"message" => "Invalid parameter(s)"} = json_response(request, 422) end + test "return 404 on unverified contract", %{conn: conn} do + address = insert(:contract_address) + + request = + post(conn, "/api/v2/smart-contracts/#{Address.checksum(address.hash)}/query-read-method", %{ + "contract_type" => "regular", + "args" => ["0xfffffffffffffffffffffffffffffffffffffffe"], + "method_id" => "c683630d" + }) + + assert %{"message" => "Not found"} = json_response(request, 404) + end + test "query-read-method", %{conn: conn} do abi = [ %{ @@ -231,6 +251,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do } ] + blockchain_get_code_mock() + expect( EthereumJSONRPC.Mox, :json_rpc, @@ -295,6 +317,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do } ] + blockchain_get_code_mock() + expect( EthereumJSONRPC.Mox, :json_rpc, @@ -349,6 +373,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do } ] + blockchain_get_code_mock() + expect( EthereumJSONRPC.Mox, :json_rpc, @@ -402,6 +428,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do } ] + blockchain_get_code_mock() + expect( EthereumJSONRPC.Mox, :json_rpc, @@ -447,6 +475,13 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do assert %{"message" => "Invalid parameter(s)"} = json_response(request, 422) end + test "return 404 on unverified contract", %{conn: conn} do + address = insert(:contract_address) + + request = get(conn, "/api/v2/smart-contracts/#{Address.checksum(address.hash)}/methods-write") + assert %{"message" => "Not found"} = json_response(request, 404) + end + test "get write-methods", %{conn: conn} do abi = [ %{ @@ -704,6 +739,13 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do assert %{"message" => "Invalid parameter(s)"} = json_response(request, 422) end + test "return 404 on unverified contract", %{conn: conn} do + address = insert(:contract_address) + + request = get(conn, "/api/v2/smart-contracts/#{Address.checksum(address.hash)}/methods-read-proxy") + assert %{"message" => "Not found"} = json_response(request, 404) + end + test "get read-methods", %{conn: conn} do abi = [ %{ @@ -843,6 +885,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do target_contract = insert(:smart_contract, abi: abi) + blockchain_get_code_mock() + expect(EthereumJSONRPC.Mox, :json_rpc, fn %{ id: 0, method: "eth_getStorageAt", @@ -928,6 +972,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do target_contract = insert(:smart_contract, abi: abi) + blockchain_get_code_mock() + expect(EthereumJSONRPC.Mox, :json_rpc, fn %{ id: 0, method: "eth_getStorageAt", @@ -997,6 +1043,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do target_contract = insert(:smart_contract, abi: abi) + blockchain_get_code_mock() + expect(EthereumJSONRPC.Mox, :json_rpc, fn %{ id: 0, method: "eth_getStorageAt", @@ -1065,6 +1113,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do target_contract = insert(:smart_contract, abi: abi) + blockchain_get_code_mock() + expect(EthereumJSONRPC.Mox, :json_rpc, fn %{ id: 0, method: "eth_getStorageAt", @@ -1123,6 +1173,13 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do assert %{"message" => "Invalid parameter(s)"} = json_response(request, 422) end + test "return 404 on unverified contract", %{conn: conn} do + address = insert(:contract_address) + + request = get(conn, "/api/v2/smart-contracts/#{Address.checksum(address.hash)}/methods-write-proxy") + assert %{"message" => "Not found"} = json_response(request, 404) + end + test "get write-methods", %{conn: conn} do abi = [ %{