From e81f2ee75a917a1dedc8881c8f51da0d743950b2 Mon Sep 17 00:00:00 2001
From: nikitosing <32202610+nikitosing@users.noreply.github.com>
Date: Mon, 5 Jun 2023 23:30:51 +0300
Subject: [PATCH] API and smart-contracts fixes (#7614)
* Add icon url to search results
* Move vyper evm versions to envs
* Fix smart contracts reading
* Fix review comments
---
CHANGELOG.md | 3 +-
...ddress_contract_verification_controller.ex | 2 +-
...ification_via_flattened_code_controller.ex | 2 +-
...ication_via_multi_part_files_controller.ex | 2 +-
.../api/v2/smart_contract_controller.ex | 1 +
.../api/v2/verification_controller.ex | 5 +-
.../controllers/smart_contract_controller.ex | 3 +-
.../lib/block_scout_web/notifier.ex | 2 +-
.../smart_contract/_functions.html.eex | 2 +-
.../views/api/v2/search_view.ex | 3 +-
.../views/api/v2/smart_contract_view.ex | 38 ++-
.../views/smart_contract_view.ex | 46 +--
.../api/v2/smart_contract_controller_test.exs | 284 +++++++++++++++++-
apps/explorer/lib/explorer/chain.ex | 18 +-
.../lib/explorer/smart_contract/helper.ex | 3 +-
.../lib/explorer/smart_contract/reader.ex | 49 ++-
.../smart_contract/solidity/code_compiler.ex | 18 +-
.../smart_contract/solidity/verifier.ex | 10 +-
.../explorer/smart_contract/reader_test.exs | 8 +-
.../solidity/code_compiler_test.exs | 14 +-
config/runtime.exs | 9 +-
docker-compose/envs/common-blockscout.env | 3 +-
docker/Makefile | 7 +-
23 files changed, 446 insertions(+), 86 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 29ca633f87..4db918c760 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,8 +14,9 @@
- [#7635](https://github.com/blockscout/blockscout/pull/7635) - Fix single 1155 transfer displaying
- [#7629](https://github.com/blockscout/blockscout/pull/7629) - Fix NFT fetcher
+- [#7614](https://github.com/blockscout/blockscout/pull/7614) - API and smart-contracts fixes and improvements
- [#7611](https://github.com/blockscout/blockscout/pull/7611) - Fix tokens pagination
-- [#7566](https://github.com/blockscout/blockscout/pull/7566) - Account: check composed email beofre sending
+- [#7566](https://github.com/blockscout/blockscout/pull/7566) - Account: check composed email before sending
- [#7564](https://github.com/blockscout/blockscout/pull/7564) - Return contract type in address view
- [#7562](https://github.com/blockscout/blockscout/pull/7562) - Remove fallback from Read methods
- [#7537](https://github.com/blockscout/blockscout/pull/7537), [#7553](https://github.com/blockscout/blockscout/pull/7553) - Withdrawals fixes and improvements
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
index 9f2d689093..5a00556fac 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
@@ -38,7 +38,7 @@ defmodule BlockScoutWeb.AddressContractVerificationController do
render(conn, "new.html",
changeset: changeset,
compiler_versions: compiler_versions,
- evm_versions: CodeCompiler.allowed_evm_versions(),
+ evm_versions: CodeCompiler.evm_versions(:solidity),
address_hash: address_hash_string
)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_flattened_code_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_flattened_code_controller.ex
index 99017a86ee..fab2192cfa 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_flattened_code_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_flattened_code_controller.ex
@@ -33,7 +33,7 @@ defmodule BlockScoutWeb.AddressContractVerificationViaFlattenedCodeController do
render(conn, "new.html",
changeset: changeset,
compiler_versions: compiler_versions,
- evm_versions: CodeCompiler.allowed_evm_versions(),
+ evm_versions: CodeCompiler.evm_versions(:solidity),
address_hash: address_hash_string
)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_multi_part_files_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_multi_part_files_controller.ex
index cdc6d44b32..7d0f819e96 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_multi_part_files_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_multi_part_files_controller.ex
@@ -33,7 +33,7 @@ defmodule BlockScoutWeb.AddressContractVerificationViaMultiPartFilesController d
render(conn, "new.html",
changeset: changeset,
address_hash: address_hash_string,
- evm_versions: CodeCompiler.allowed_evm_versions(),
+ evm_versions: CodeCompiler.evm_versions(:solidity),
compiler_versions: compiler_versions
)
end
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 dc294bed73..8d016c4047 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
@@ -176,6 +176,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do
contract_type,
params["from"],
address.smart_contract.abi,
+ true,
@api_true
)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
index 60ee9fbc13..2463d5792d 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
@@ -16,7 +16,6 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
@api_true [api?: true]
def config(conn, _params) do
- evm_versions = CodeCompiler.allowed_evm_versions()
solidity_compiler_versions = CompilerVersion.fetch_version_list(:solc)
vyper_compiler_versions = CompilerVersion.fetch_version_list(:vyper)
@@ -31,11 +30,11 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
conn
|> json(%{
- solidity_evm_versions: evm_versions,
+ solidity_evm_versions: CodeCompiler.evm_versions(:solidity),
solidity_compiler_versions: solidity_compiler_versions,
vyper_compiler_versions: vyper_compiler_versions,
verification_options: verification_options,
- vyper_evm_versions: ["byzantium", "constantinople", "petersburg", "istanbul"],
+ vyper_evm_versions: CodeCompiler.evm_versions(:vyper),
is_rust_verifier_microservice_enabled: RustVerifierInterface.enabled?()
})
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
index 0ba2f294ad..b403e0e7d5 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
@@ -196,7 +196,8 @@ defmodule BlockScoutWeb.SmartContractController do
%{method_id: params["method_id"], args: args},
contract_type,
params["from"],
- address.smart_contract && address.smart_contract.abi
+ address.smart_contract && address.smart_contract.abi,
+ true
)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/notifier.ex b/apps/block_scout_web/lib/block_scout_web/notifier.ex
index e70ff42029..7ca4a892a8 100644
--- a/apps/block_scout_web/lib/block_scout_web/notifier.ex
+++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex
@@ -80,7 +80,7 @@ defmodule BlockScoutWeb.Notifier do
|> View.render_to_string("new.html",
changeset: changeset,
compiler_versions: compiler_versions,
- evm_versions: CodeCompiler.allowed_evm_versions(),
+ evm_versions: CodeCompiler.evm_versions(:solidity),
address_hash: address_hash,
conn: conn,
retrying: true
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex
index ced64b2c06..af6885a211 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex
@@ -145,7 +145,7 @@
<% else %>
-
"><%= raw(values_with_type(output["value"], output["type"], [output["name"]], 0, output["components"])) %>
+ "><%= raw(values_with_type(output["value"], output["type"], fetch_name(function["names"], index), 0)) %>
<% end %>
<% end %>
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
index bddd3b60d9..a8ac5cc644 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
@@ -23,7 +23,8 @@ defmodule BlockScoutWeb.API.V2.SearchView do
"symbol" => search_result.symbol,
"address" => search_result.address_hash,
"token_url" => token_path(Endpoint, :show, search_result.address_hash),
- "address_url" => address_path(Endpoint, :show, search_result.address_hash)
+ "address_url" => address_path(Endpoint, :show, search_result.address_hash),
+ "icon_url" => search_result.icon_url
}
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/v2/smart_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/v2/smart_contract_view.ex
index bfe8f1d09d..4fc3b77994 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api/v2/smart_contract_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api/v2/smart_contract_view.ex
@@ -98,7 +98,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractView do
%{result: %{error: error}, is_error: true}
_ ->
- %{result: %{output: outputs, names: names}, is_error: false}
+ %{result: %{output: Enum.map(outputs, &render_json/1), names: names}, is_error: false}
end
end
@@ -118,13 +118,13 @@ defmodule BlockScoutWeb.API.V2.SmartContractView do
function
|> Map.drop(["abi_outputs"])
- outputs = Enum.map(result["outputs"], &prepare_output/1)
+ outputs = result["outputs"] |> Enum.map(&prepare_output/1)
Map.replace(result, "outputs", outputs)
end
end
defp prepare_output(%{"type" => type, "value" => value} = output) do
- Map.replace(output, "value", ABIEncodedValueView.value_json(type, value))
+ Map.replace(output, "value", render_json(value, type))
end
defp prepare_output(output), do: output
@@ -277,4 +277,36 @@ defmodule BlockScoutWeb.API.V2.SmartContractView do
"solidity"
end
end
+
+ def render_json(%{"type" => type, "value" => value}) do
+ %{"type" => type, "value" => render_json(value, type)}
+ end
+
+ def render_json(value, type) when type in [:address, "address", "address payable"] do
+ SmartContractView.cast_address(value)
+ end
+
+ def render_json(value, type) when type in [:string, "string"] do
+ to_string(value)
+ end
+
+ def render_json(value, type) when is_tuple(value) do
+ value
+ |> SmartContractView.zip_tuple_values_with_types(type)
+ |> Enum.map(fn {type, value} ->
+ render_json(value, type)
+ end)
+ end
+
+ def render_json(value, type) when is_list(value) do
+ value |> Enum.map(&render_json(&1, type))
+ end
+
+ def render_json(value, _type) when is_binary(value) do
+ SmartContractView.binary_to_utf_string(value)
+ end
+
+ def render_json(value, _type) do
+ value
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex
index 39297f2956..4a96a93adb 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex
@@ -6,6 +6,8 @@ defmodule BlockScoutWeb.SmartContractView do
alias Explorer.Chain.Hash.Address, as: HashAddress
alias Explorer.SmartContract.Helper
+ require Logger
+
def queryable?(inputs) when not is_nil(inputs), do: Enum.any?(inputs)
def queryable?(inputs) when is_nil(inputs), do: false
@@ -63,7 +65,7 @@ defmodule BlockScoutWeb.SmartContractView do
String.starts_with?(type, "address") ->
values =
value
- |> Enum.map_join(", ", &binary_to_utf_string(&1))
+ |> Enum.map_join(", ", &cast_address(&1))
render_array_type_value(type, values, fetch_name(names, index))
@@ -117,6 +119,17 @@ defmodule BlockScoutWeb.SmartContractView do
def values_with_type(value, :error, _components),
do: render_type_value("error", Helper.sanitize_input(value), "error")
+ def cast_address(value) do
+ case HashAddress.cast(value) do
+ {:ok, address} ->
+ to_string(address)
+
+ _ ->
+ Logger.warn(fn -> ["Error decoding address value: #{inspect(value)}"] end)
+ "(decoding error)"
+ end
+ end
+
defp fetch_name(nil, _index), do: nil
defp fetch_name([], _index), do: nil
@@ -137,6 +150,15 @@ defmodule BlockScoutWeb.SmartContractView do
end
defp tuple_to_array(value, type, names) do
+ value
+ |> zip_tuple_values_with_types(type)
+ |> Enum.with_index()
+ |> Enum.map(fn {{type, value}, index} ->
+ values_with_type(value, type, fetch_name(names, index), 0)
+ end)
+ end
+
+ def zip_tuple_values_with_types(value, type) do
types_string =
type
|> String.slice(6..-2)
@@ -165,16 +187,10 @@ defmodule BlockScoutWeb.SmartContractView do
value
|> Tuple.to_list()
- values_types_list = Enum.zip(tuple_types, values_list)
-
- values_types_list
- |> Enum.with_index()
- |> Enum.map(fn {{type, value}, index} ->
- values_with_type(value, type, fetch_name(names, index), 0)
- end)
+ Enum.zip(tuple_types, values_list)
end
- defp compose_array_if_to_merge(arr, val, to_merge) do
+ def compose_array_if_to_merge(arr, val, to_merge) do
if count_string_symbols(val)["]"] > count_string_symbols(val)["["] do
updated_arr = update_last_list_item(arr, val)
{updated_arr, !to_merge}
@@ -184,7 +200,7 @@ defmodule BlockScoutWeb.SmartContractView do
end
end
- defp compose_array_else(arr, val, to_merge) do
+ def compose_array_else(arr, val, to_merge) do
if count_string_symbols(val)["["] > count_string_symbols(val)["]"] do
# credo:disable-for-next-line
{arr ++ [val], !to_merge}
@@ -214,7 +230,7 @@ defmodule BlockScoutWeb.SmartContractView do
end)
end
- defp binary_to_utf_string(item) do
+ def binary_to_utf_string(item) do
case Integer.parse(to_string(item)) do
{item_integer, ""} ->
to_string(item_integer)
@@ -229,11 +245,7 @@ defmodule BlockScoutWeb.SmartContractView do
end
defp add_0x(item) do
- if String.starts_with?(item, "0x") do
- item
- else
- "0x" <> Base.encode16(item, case: :lower)
- end
+ "0x" <> Base.encode16(item, case: :lower)
end
defp render_type_value(type, value, type) do
@@ -250,7 +262,7 @@ defmodule BlockScoutWeb.SmartContractView do
render_type_value(type, value_to_display, name)
end
- defp supplement_type_with_components(type, components) do
+ def supplement_type_with_components(type, components) do
if type == "tuple" && components do
types =
components
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 7525beafd3..d404d3655c 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
@@ -462,24 +462,83 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"name" => "disableWhitelist",
"inputs" => [%{"type" => "bool", "name" => "disable", "internalType" => "bool"}]
},
- %{"type" => "fallback"}
+ %{"type" => "fallback"},
+ %{
+ "type" => "function",
+ "stateMutability" => "view",
+ "outputs" => [
+ %{
+ "type" => "tuple",
+ "name" => "",
+ "internalType" => "struct Storage.TransactionReceipt",
+ "components" => [
+ %{"type" => "bytes32", "name" => "txHash", "internalType" => "bytes32"},
+ %{"type" => "uint256", "name" => "blockNumber", "internalType" => "uint256"},
+ %{"type" => "bytes32", "name" => "blockHash", "internalType" => "bytes32"},
+ %{"type" => "uint256", "name" => "transactionIndex", "internalType" => "uint256"},
+ %{"type" => "address", "name" => "from", "internalType" => "address"},
+ %{"type" => "address", "name" => "to", "internalType" => "address"},
+ %{"type" => "uint256", "name" => "gasUsed", "internalType" => "uint256"},
+ %{"type" => "bool", "name" => "status", "internalType" => "bool"},
+ %{
+ "type" => "tuple[]",
+ "name" => "logs",
+ "internalType" => "struct Storage.Log[]",
+ "components" => [
+ %{"type" => "address", "name" => "from", "internalType" => "address"},
+ %{"type" => "bytes32[]", "name" => "topics", "internalType" => "bytes32[]"},
+ %{"type" => "bytes", "name" => "data", "internalType" => "bytes"}
+ ]
+ }
+ ]
+ }
+ ],
+ "name" => "retrieve",
+ "inputs" => []
+ }
]
target_contract = insert(:smart_contract, abi: abi)
blockchain_eth_call_mock()
- request = get(conn, "/api/v2/smart-contracts/#{target_contract.address_hash}/methods-read")
+ expect(
+ EthereumJSONRPC.Mox,
+ :json_rpc,
+ fn [
+ %{
+ id: id,
+ method: "eth_call",
+ params: [%{to: _address_hash, from: "0xBb36c792B9B45Aaf8b848A1392B0d6559202729E"}, _]
+ }
+ ],
+ _opts ->
+ {:ok,
+ [
+ %{
+ id: id,
+ jsonrpc: "2.0",
+ result:
+ "0x0000000000000000000000000000000000000000000000000000000000000020fe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab200000000000000000000000000000000000000000000000000000000000003e8fe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab2000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000001e0f30000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003307830000000000000000000000000000000000000000000000000000000000030783030313132323333000000000000000000000000000000000000000000003078303031313232333331323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3078303030303132333132330000000000000000000000000000000000000000000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003307830000000000000000000000000000000000000000000000000000000000030783030313132323333000000000000000000000000000000000000000000003078303031313232333331323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3078303030303132333132330000000000000000000000000000000000000000000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003307830000000000000000000000000000000000000000000000000000000000030783030313132323333000000000000000000000000000000000000000000003078303031313232333331323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3078303030303132333132330000000000000000000000000000000000000000"
+ }
+ ]}
+ end
+ )
+
+ request =
+ get(conn, "/api/v2/smart-contracts/#{target_contract.address_hash}/methods-read", %{
+ "from" => "0xBb36c792B9B45Aaf8b848A1392B0d6559202729E"
+ })
+
assert response = json_response(request, 200)
assert %{
"type" => "function",
"stateMutability" => "view",
+ "names" => ["address"],
"outputs" => [
%{
"type" => "address",
- "name" => "",
- "internalType" => "address",
"value" => "0xfffffffffffffffffffffffffffffffffffffffe"
}
],
@@ -497,6 +556,75 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"method_id" => "c683630d"
} in response
+ assert %{
+ "inputs" => [],
+ "method_id" => "2e64cec1",
+ "name" => "retrieve",
+ "names" => [
+ [
+ "struct Storage.TransactionReceipt",
+ [
+ "txHash",
+ "blockNumber",
+ "blockHash",
+ "transactionIndex",
+ "from",
+ "to",
+ "gasUsed",
+ "status",
+ ["logs", ["from", "topics", "data"]]
+ ]
+ ]
+ ],
+ "outputs" => [
+ %{
+ "type" =>
+ "tuple[bytes32,uint256,bytes32,uint256,address,address,uint256,bool,tuple[address,bytes32[],bytes][]]",
+ "value" => [
+ "0xfe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab2",
+ 1000,
+ "0xfe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab2",
+ 10,
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ 123_123,
+ true,
+ [
+ [
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ [
+ "0x3078300000000000000000000000000000000000000000000000000000000000",
+ "0x3078303031313232333300000000000000000000000000000000000000000000",
+ "0x3078303031313232333331323300000000000000000000000000000000000000"
+ ],
+ "0x307830303030313233313233"
+ ],
+ [
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ [
+ "0x3078300000000000000000000000000000000000000000000000000000000000",
+ "0x3078303031313232333300000000000000000000000000000000000000000000",
+ "0x3078303031313232333331323300000000000000000000000000000000000000"
+ ],
+ "0x307830303030313233313233"
+ ],
+ [
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ [
+ "0x3078300000000000000000000000000000000000000000000000000000000000",
+ "0x3078303031313232333300000000000000000000000000000000000000000000",
+ "0x3078303031313232333331323300000000000000000000000000000000000000"
+ ],
+ "0x307830303030313233313233"
+ ]
+ ]
+ ]
+ }
+ ],
+ "stateMutability" => "view",
+ "type" => "function"
+ } in response
+
refute %{"type" => "fallback"} in response
end
@@ -544,10 +672,10 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"type" => "function",
"stateMutability" => "view",
"payable" => false,
+ "names" => [nil],
"outputs" => [
%{
"type" => "address[]",
- "name" => "",
"value" => [
"0x64631b5d259ead889e8b06d12c8b74742804e5f1",
"0x234fe7224ce480ca97d01897311b8c3d35162f86",
@@ -666,6 +794,146 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
} == response
end
+ test "query complex response", %{conn: conn} do
+ abi = [
+ %{
+ "type" => "function",
+ "stateMutability" => "view",
+ "outputs" => [
+ %{
+ "type" => "tuple",
+ "name" => "",
+ "internalType" => "struct Storage.TransactionReceipt",
+ "components" => [
+ %{"type" => "bytes32", "name" => "txHash", "internalType" => "bytes32"},
+ %{"type" => "uint256", "name" => "blockNumber", "internalType" => "uint256"},
+ %{"type" => "bytes32", "name" => "blockHash", "internalType" => "bytes32"},
+ %{"type" => "uint256", "name" => "transactionIndex", "internalType" => "uint256"},
+ %{"type" => "address", "name" => "from", "internalType" => "address"},
+ %{"type" => "address", "name" => "to", "internalType" => "address"},
+ %{"type" => "uint256", "name" => "gasUsed", "internalType" => "uint256"},
+ %{"type" => "bool", "name" => "status", "internalType" => "bool"},
+ %{
+ "type" => "tuple[]",
+ "name" => "logs",
+ "internalType" => "struct Storage.Log[]",
+ "components" => [
+ %{"type" => "address", "name" => "from", "internalType" => "address"},
+ %{"type" => "bytes32[]", "name" => "topics", "internalType" => "bytes32[]"},
+ %{"type" => "bytes", "name" => "data", "internalType" => "bytes"}
+ ]
+ }
+ ]
+ }
+ ],
+ "name" => "retrieve",
+ "inputs" => []
+ }
+ ]
+
+ target_contract = insert(:smart_contract, abi: abi)
+
+ expect(
+ EthereumJSONRPC.Mox,
+ :json_rpc,
+ fn [
+ %{
+ id: id,
+ method: "eth_call",
+ params: [%{to: _address_hash, from: "0xBb36c792B9B45Aaf8b848A1392B0d6559202729E"}, _]
+ }
+ ],
+ _opts ->
+ {:ok,
+ [
+ %{
+ id: id,
+ jsonrpc: "2.0",
+ result:
+ "0x0000000000000000000000000000000000000000000000000000000000000020fe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab200000000000000000000000000000000000000000000000000000000000003e8fe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab2000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000001e0f30000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003307830000000000000000000000000000000000000000000000000000000000030783030313132323333000000000000000000000000000000000000000000003078303031313232333331323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3078303030303132333132330000000000000000000000000000000000000000000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003307830000000000000000000000000000000000000000000000000000000000030783030313132323333000000000000000000000000000000000000000000003078303031313232333331323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3078303030303132333132330000000000000000000000000000000000000000000000000000000000000000bb36c792b9b45aaf8b848a1392b0d6559202729e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003307830000000000000000000000000000000000000000000000000000000000030783030313132323333000000000000000000000000000000000000000000003078303031313232333331323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3078303030303132333132330000000000000000000000000000000000000000"
+ }
+ ]}
+ end
+ )
+
+ request =
+ post(conn, "/api/v2/smart-contracts/#{target_contract.address_hash}/query-read-method", %{
+ "contract_type" => "regular",
+ "args" => [],
+ "method_id" => "2e64cec1",
+ "from" => "0xBb36c792B9B45Aaf8b848A1392B0d6559202729E"
+ })
+
+ assert response = json_response(request, 200)
+
+ assert %{
+ "is_error" => false,
+ "result" => %{
+ "names" => [
+ [
+ "struct Storage.TransactionReceipt",
+ [
+ "txHash",
+ "blockNumber",
+ "blockHash",
+ "transactionIndex",
+ "from",
+ "to",
+ "gasUsed",
+ "status",
+ ["logs", ["from", "topics", "data"]]
+ ]
+ ]
+ ],
+ "output" => [
+ %{
+ "type" =>
+ "tuple[bytes32,uint256,bytes32,uint256,address,address,uint256,bool,tuple[address,bytes32[],bytes][]]",
+ "value" => [
+ "0xfe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab2",
+ 1000,
+ "0xfe6a43fa23a0269092cbf97cb908e1d5a49a18fd6942baf2467fb5b221e39ab2",
+ 10,
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ 123_123,
+ true,
+ [
+ [
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ [
+ "0x3078300000000000000000000000000000000000000000000000000000000000",
+ "0x3078303031313232333300000000000000000000000000000000000000000000",
+ "0x3078303031313232333331323300000000000000000000000000000000000000"
+ ],
+ "0x307830303030313233313233"
+ ],
+ [
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ [
+ "0x3078300000000000000000000000000000000000000000000000000000000000",
+ "0x3078303031313232333300000000000000000000000000000000000000000000",
+ "0x3078303031313232333331323300000000000000000000000000000000000000"
+ ],
+ "0x307830303030313233313233"
+ ],
+ [
+ "0xbb36c792b9b45aaf8b848a1392b0d6559202729e",
+ [
+ "0x3078300000000000000000000000000000000000000000000000000000000000",
+ "0x3078303031313232333300000000000000000000000000000000000000000000",
+ "0x3078303031313232333331323300000000000000000000000000000000000000"
+ ],
+ "0x307830303030313233313233"
+ ]
+ ]
+ ]
+ }
+ ]
+ }
+ } == response
+ end
+
test "query-read-method with nonexistent method_id", %{conn: conn} do
abi = [
%{
@@ -1041,11 +1309,10 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
assert %{
"type" => "function",
"stateMutability" => "view",
+ "names" => ["address"],
"outputs" => [
%{
"type" => "address",
- "name" => "",
- "internalType" => "address",
"value" => "0xfffffffffffffffffffffffffffffffffffffffe"
}
],
@@ -1220,11 +1487,10 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
assert %{
"type" => "function",
"stateMutability" => "view",
+ "names" => ["address"],
"outputs" => [
%{
"type" => "address",
- "name" => "",
- "internalType" => "address",
"value" => "0xfffffffffffffffffffffffffffffffffffffffe"
}
],
diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex
index cbf78ee991..b43d383ce4 100644
--- a/apps/explorer/lib/explorer/chain.ex
+++ b/apps/explorer/lib/explorer/chain.ex
@@ -1512,7 +1512,8 @@ defmodule Explorer.Chain do
symbol: token.symbol,
holder_count: token.holder_count,
inserted_at: token.inserted_at,
- block_number: 0
+ block_number: 0,
+ icon_url: token.icon_url
}
)
end
@@ -1531,7 +1532,8 @@ defmodule Explorer.Chain do
symbol: ^nil,
holder_count: ^nil,
inserted_at: address.inserted_at,
- block_number: 0
+ block_number: 0,
+ icon_url: nil
}
)
end
@@ -1559,7 +1561,8 @@ defmodule Explorer.Chain do
symbol: ^nil,
holder_count: ^nil,
inserted_at: address.inserted_at,
- block_number: 0
+ block_number: 0,
+ icon_url: nil
}
)
@@ -1582,7 +1585,8 @@ defmodule Explorer.Chain do
symbol: ^nil,
holder_count: ^nil,
inserted_at: transaction.inserted_at,
- block_number: 0
+ block_number: 0,
+ icon_url: nil
}
)
@@ -1605,7 +1609,8 @@ defmodule Explorer.Chain do
symbol: ^nil,
holder_count: ^nil,
inserted_at: block.inserted_at,
- block_number: block.number
+ block_number: block.number,
+ icon_url: nil
}
)
@@ -1623,7 +1628,8 @@ defmodule Explorer.Chain do
symbol: ^nil,
holder_count: ^nil,
inserted_at: block.inserted_at,
- block_number: block.number
+ block_number: block.number,
+ icon_url: nil
}
)
diff --git a/apps/explorer/lib/explorer/smart_contract/helper.ex b/apps/explorer/lib/explorer/smart_contract/helper.ex
index c2476ee713..cffc145b35 100644
--- a/apps/explorer/lib/explorer/smart_contract/helper.ex
+++ b/apps/explorer/lib/explorer/smart_contract/helper.ex
@@ -24,7 +24,8 @@ defmodule Explorer.SmartContract.Helper do
@spec read_with_wallet_method?(%{}) :: true | false
def read_with_wallet_method?(function),
do:
- !error?(function) && !event?(function) && !constructor?(function) && !fallback?(function) && nonpayable?(function) &&
+ !error?(function) && !event?(function) && !constructor?(function) && !fallback?(function) &&
+ nonpayable?(function) &&
!empty_outputs?(function)
def empty_inputs?(function), do: function["inputs"] == []
diff --git a/apps/explorer/lib/explorer/smart_contract/reader.ex b/apps/explorer/lib/explorer/smart_contract/reader.ex
index 6f0d3fa938..4fa3e8dadf 100644
--- a/apps/explorer/lib/explorer/smart_contract/reader.ex
+++ b/apps/explorer/lib/explorer/smart_contract/reader.ex
@@ -270,7 +270,7 @@ defmodule Explorer.SmartContract.Reader do
abi_with_method_id
|> Enum.filter(&Helper.queriable_method?(&1))
- |> Enum.map(&fetch_current_value_from_blockchain(&1, abi_with_method_id, contract_address_hash, false, from))
+ |> Enum.map(&fetch_current_value_from_blockchain(&1, abi_with_method_id, contract_address_hash, false, [], from))
end
def read_only_functions_from_abi_with_sender(_, _, _), do: []
@@ -332,21 +332,34 @@ defmodule Explorer.SmartContract.Reader do
"tuple[#{tuple_types}]"
end
- def fetch_current_value_from_blockchain(function, abi, contract_address_hash, leave_error_as_map, from \\ nil) do
+ def fetch_current_value_from_blockchain(
+ function,
+ abi,
+ contract_address_hash,
+ leave_error_as_map,
+ options,
+ from \\ nil
+ ) do
case function do
%{"inputs" => []} ->
method_id = function["method_id"]
args = function["inputs"]
- outputs = function["outputs"]
- values =
- contract_address_hash
- |> query_verified_contract(%{method_id => normalize_args(args)}, from, leave_error_as_map, abi)
- |> link_outputs_and_values(outputs, method_id)
+ %{output: outputs, names: names} =
+ query_function_with_names(
+ contract_address_hash,
+ %{method_id: method_id, args: args},
+ :regular,
+ from,
+ abi,
+ leave_error_as_map,
+ options
+ )
function
- |> Map.replace!("outputs", values)
+ |> Map.replace!("outputs", outputs)
|> Map.put("abi_outputs", Map.get(function, "outputs", []))
+ |> Map.put("names", names)
_ ->
function
@@ -364,9 +377,10 @@ defmodule Explorer.SmartContract.Reader do
%{method_id: String.t(), args: [term()] | nil},
:regular | :proxy,
String.t() | nil,
- [api?]
+ [],
+ boolean()
) :: %{:names => [any()], :output => [%{}]}
- def query_function_with_names(contract_address_hash, params, type, from, abi, options \\ [])
+ def query_function_with_names(contract_address_hash, params, type, from, abi, leave_error_as_map, options \\ [])
def query_function_with_names(
contract_address_hash,
@@ -374,6 +388,7 @@ defmodule Explorer.SmartContract.Reader do
:regular,
from,
abi,
+ leave_error_as_map,
_options
) do
outputs =
@@ -382,7 +397,7 @@ defmodule Explorer.SmartContract.Reader do
method_id,
args || [],
from,
- true,
+ leave_error_as_map,
abi
)
@@ -390,7 +405,15 @@ defmodule Explorer.SmartContract.Reader do
%{output: outputs, names: names}
end
- def query_function_with_names(contract_address_hash, %{method_id: method_id, args: args}, :proxy, from, _abi, options) do
+ def query_function_with_names(
+ contract_address_hash,
+ %{method_id: method_id, args: args},
+ :proxy,
+ from,
+ _abi,
+ leave_error_as_map,
+ options
+ ) do
abi = get_abi(contract_address_hash, :proxy, options)
outputs =
@@ -399,7 +422,7 @@ defmodule Explorer.SmartContract.Reader do
method_id,
args || [],
from,
- true,
+ leave_error_as_map,
abi
)
diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
index b08e64c970..b63d01c57e 100644
--- a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
+++ b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
@@ -76,14 +76,14 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
code = Keyword.fetch!(params, :code)
optimize = Keyword.fetch!(params, :optimize)
optimization_runs = optimization_runs(params)
- evm_version = Keyword.get(params, :evm_version, List.last(allowed_evm_versions()))
+ evm_version = Keyword.get(params, :evm_version, List.last(evm_versions(:solidity)))
bytecode_hash = Keyword.get(params, :bytecode_hash, "default")
external_libs = Keyword.get(params, :external_libs, %{})
external_libs_string = Jason.encode!(external_libs)
checked_evm_version =
- if evm_version in allowed_evm_versions() do
+ if evm_version in evm_versions(:solidity) do
evm_version
else
"byzantium"
@@ -262,9 +262,19 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
end
end
- def allowed_evm_versions do
+ def evm_versions(compiler_type) do
+ case compiler_type do
+ :vyper ->
+ allowed_evm_versions(:allowed_vyper_evm_versions)
+
+ :solidity ->
+ allowed_evm_versions(:allowed_solidity_evm_versions)
+ end
+ end
+
+ defp allowed_evm_versions(env_name) do
:explorer
- |> Application.get_env(:allowed_evm_versions)
+ |> Application.get_env(env_name)
|> String.split(",")
|> Enum.map(fn version -> String.trim(version) end)
end
diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex b/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
index a41847ad3c..57c11709ab 100644
--- a/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
+++ b/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
@@ -59,7 +59,7 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
if is_nil(params["name"]) or params["name"] == "" do
{:error, :name}
else
- latest_evm_version = List.last(CodeCompiler.allowed_evm_versions())
+ latest_evm_version = List.last(CodeCompiler.evm_versions(:solidity))
evm_version = Map.get(params, "evm_version", latest_evm_version)
all_versions = [evm_version | previous_evm_versions(evm_version)]
@@ -505,19 +505,19 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
end
def previous_evm_versions(current_evm_version) do
- index = Enum.find_index(CodeCompiler.allowed_evm_versions(), fn el -> el == current_evm_version end)
+ index = Enum.find_index(CodeCompiler.evm_versions(:solidity), fn el -> el == current_evm_version end)
cond do
index == 0 ->
[]
index == 1 ->
- [List.first(CodeCompiler.allowed_evm_versions())]
+ [List.first(CodeCompiler.evm_versions(:solidity))]
true ->
[
- Enum.at(CodeCompiler.allowed_evm_versions(), index - 1),
- Enum.at(CodeCompiler.allowed_evm_versions(), index - 2)
+ Enum.at(CodeCompiler.evm_versions(:solidity), index - 1),
+ Enum.at(CodeCompiler.evm_versions(:solidity), index - 2)
]
end
end
diff --git a/apps/explorer/test/explorer/smart_contract/reader_test.exs b/apps/explorer/test/explorer/smart_contract/reader_test.exs
index df6ed4727b..8eb6e1a2ec 100644
--- a/apps/explorer/test/explorer/smart_contract/reader_test.exs
+++ b/apps/explorer/test/explorer/smart_contract/reader_test.exs
@@ -153,7 +153,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true,
"inputs" => [],
"name" => "get",
- "outputs" => [%{"name" => "", "type" => "uint256", "value" => 0}],
+ "outputs" => [%{"type" => "uint256", "value" => 0}],
"payable" => _,
"stateMutability" => _,
"type" => _
@@ -162,7 +162,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true,
"inputs" => [%{"name" => "x", "type" => "uint256"}],
"name" => "with_arguments",
- "outputs" => [%{"name" => "", "type" => "bool"}],
+ "outputs" => [%{"type" => "bool"}],
"payable" => _,
"stateMutability" => _,
"type" => _
@@ -238,7 +238,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true,
"inputs" => [],
"name" => "get",
- "outputs" => [%{"name" => "", "type" => "uint256", "value" => 0}],
+ "outputs" => [%{"type" => "uint256", "value" => 0}],
"payable" => _,
"stateMutability" => _,
"type" => _
@@ -247,7 +247,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true,
"inputs" => [%{"name" => "x", "type" => "uint256"}],
"name" => "with_arguments",
- "outputs" => [%{"name" => "", "type" => "bool"}],
+ "outputs" => [%{"type" => "bool"}],
"payable" => _,
"stateMutability" => _,
"type" => _
diff --git a/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs b/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs
index 952c320ebf..ed80cb1219 100644
--- a/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs
+++ b/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs
@@ -353,17 +353,17 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
end
end
- # describe "allowed_evm_versions/0" do
+ # describe "allowed_solidity_evm_versions/0" do
# test "returns allowed evm versions defined by ALLOWED_EVM_VERSIONS env var" do
- # Application.put_env(:explorer, :allowed_evm_versions, "CustomEVM1,CustomEVM2,CustomEVM3")
- # response = CodeCompiler.allowed_evm_versions()
+ # Application.put_env(:explorer, :allowed_solidity_evm_versions, "CustomEVM1,CustomEVM2,CustomEVM3")
+ # response = CodeCompiler.evm_versions(:solidity)
# assert ["CustomEVM1", "CustomEVM2", "CustomEVM3"] = response
# end
# test "returns allowed evm versions defined by not trimmed ALLOWED_EVM_VERSIONS env var" do
- # Application.put_env(:explorer, :allowed_evm_versions, "CustomEVM1, CustomEVM2, CustomEVM3")
- # response = CodeCompiler.allowed_evm_versions()
+ # Application.put_env(:explorer, :allowed_solidity_evm_versions, "CustomEVM1, CustomEVM2, CustomEVM3")
+ # response = CodeCompiler.evm_versions(:solidity)
# assert ["CustomEVM1", "CustomEVM2", "CustomEVM3"] = response
# end
@@ -371,11 +371,11 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
# test "returns default_allowed_evm_versions" do
# Application.put_env(
# :explorer,
- # :allowed_evm_versions,
+ # :allowed_solidity_evm_versions,
# "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg"
# )
- # response = CodeCompiler.allowed_evm_versions()
+ # response = CodeCompiler.evm_versions(:solidity)
# assert ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"] = response
# end
diff --git a/config/runtime.exs b/config/runtime.exs
index dd7e25d532..5f5de06c14 100644
--- a/config/runtime.exs
+++ b/config/runtime.exs
@@ -170,9 +170,12 @@ exchange_rates_coin = System.get_env("EXCHANGE_RATES_COIN")
config :explorer,
coin: System.get_env("COIN") || exchange_rates_coin || "ETH",
coin_name: System.get_env("COIN_NAME") || exchange_rates_coin || "ETH",
- allowed_evm_versions:
- System.get_env("CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS") ||
- "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg,istanbul,berlin,london,paris,default",
+ allowed_solidity_evm_versions:
+ System.get_env("CONTRACT_VERIFICATION_ALLOWED_SOLIDITY_EVM_VERSIONS") ||
+ "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg,istanbul,berlin,london,paris,shanghai,default",
+ allowed_vyper_evm_versions:
+ System.get_env("CONTRACT_VERIFICATION_ALLOWED_VYPER_EVM_VERSIONS") ||
+ "byzantium,constantinople,petersburg,istanbul,berlin,paris,shanghai,default",
include_uncles_in_average_block_time: ConfigHelper.parse_bool_env_var("UNCLES_IN_AVERAGE_BLOCK_TIME"),
healthy_blocks_period: ConfigHelper.parse_time_env_var("HEALTHY_BLOCKS_PERIOD", "5m"),
realtime_events_sender:
diff --git a/docker-compose/envs/common-blockscout.env b/docker-compose/envs/common-blockscout.env
index 5f67ecace9..b5717e3b73 100644
--- a/docker-compose/envs/common-blockscout.env
+++ b/docker-compose/envs/common-blockscout.env
@@ -81,7 +81,8 @@ CACHE_ADDRESS_TRANSACTIONS_COUNTER_PERIOD=1800
CACHE_ADDRESS_TOKENS_USD_SUM_PERIOD=3600
CACHE_ADDRESS_TOKEN_TRANSFERS_COUNTER_PERIOD=1800
TOKEN_METADATA_UPDATE_INTERVAL=172800
-CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS=homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg,istanbul,berlin,london,paris,default
+CONTRACT_VERIFICATION_ALLOWED_SOLIDITY_EVM_VERSIONS=homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg,istanbul,berlin,london,paris,shanghai,default
+CONTRACT_VERIFICATION_ALLOWED_VYPER_EVM_VERSIONS=byzantium,constantinople,petersburg,istanbul,berlin,paris,shanghai,default
# CONTRACT_VERIFICATION_MAX_LIBRARIES=10
CONTRACT_MAX_STRING_LENGTH_WITHOUT_TRIMMING=2040
# CONTRACT_DISABLE_INTERACTION=
diff --git a/docker/Makefile b/docker/Makefile
index fff407f212..ce4806af8c 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -690,8 +690,11 @@ endif
ifdef DECODE_NOT_A_CONTRACT_CALLS
BLOCKSCOUT_CONTAINER_PARAMS += -e 'DECODE_NOT_A_CONTRACT_CALLS=$(DECODE_NOT_A_CONTRACT_CALLS)'
endif
-ifdef CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS
- BLOCKSCOUT_CONTAINER_PARAMS += -e 'CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS=$(CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS)'
+ifdef CONTRACT_VERIFICATION_ALLOWED_SOLIDITY_EVM_VERSIONS
+ BLOCKSCOUT_CONTAINER_PARAMS += -e 'CONTRACT_VERIFICATION_ALLOWED_SOLIDITY_EVM_VERSIONS=$(CONTRACT_VERIFICATION_ALLOWED_SOLIDITY_EVM_VERSIONS)'
+endif
+ifdef CONTRACT_VERIFICATION_ALLOWED_VYPER_EVM_VERSIONS
+ BLOCKSCOUT_CONTAINER_PARAMS += -e 'CONTRACT_VERIFICATION_ALLOWED_VYPER_EVM_VERSIONS=$(CONTRACT_VERIFICATION_ALLOWED_VYPER_EVM_VERSIONS)'
endif
ifdef CONTRACT_VERIFICATION_MAX_LIBRARIES
BLOCKSCOUT_CONTAINER_PARAMS += -e 'CONTRACT_VERIFICATION_MAX_LIBRARIES=$(CONTRACT_VERIFICATION_MAX_LIBRARIES)'