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
pull/7636/head
nikitosing 1 year ago committed by GitHub
parent dac2e570b1
commit e81f2ee75a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 2
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
  3. 2
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_flattened_code_controller.ex
  4. 2
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_multi_part_files_controller.ex
  5. 1
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex
  6. 5
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
  7. 3
      apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
  8. 2
      apps/block_scout_web/lib/block_scout_web/notifier.ex
  9. 2
      apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex
  10. 3
      apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
  11. 38
      apps/block_scout_web/lib/block_scout_web/views/api/v2/smart_contract_view.ex
  12. 46
      apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex
  13. 284
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs
  14. 18
      apps/explorer/lib/explorer/chain.ex
  15. 3
      apps/explorer/lib/explorer/smart_contract/helper.ex
  16. 49
      apps/explorer/lib/explorer/smart_contract/reader.ex
  17. 18
      apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
  18. 10
      apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
  19. 8
      apps/explorer/test/explorer/smart_contract/reader_test.exs
  20. 14
      apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs
  21. 9
      config/runtime.exs
  22. 3
      docker-compose/envs/common-blockscout.env
  23. 7
      docker/Makefile

@ -14,8 +14,9 @@
- [#7635](https://github.com/blockscout/blockscout/pull/7635) - Fix single 1155 transfer displaying - [#7635](https://github.com/blockscout/blockscout/pull/7635) - Fix single 1155 transfer displaying
- [#7629](https://github.com/blockscout/blockscout/pull/7629) - Fix NFT fetcher - [#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 - [#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 - [#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 - [#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 - [#7537](https://github.com/blockscout/blockscout/pull/7537), [#7553](https://github.com/blockscout/blockscout/pull/7553) - Withdrawals fixes and improvements

@ -38,7 +38,7 @@ defmodule BlockScoutWeb.AddressContractVerificationController do
render(conn, "new.html", render(conn, "new.html",
changeset: changeset, changeset: changeset,
compiler_versions: compiler_versions, compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions(), evm_versions: CodeCompiler.evm_versions(:solidity),
address_hash: address_hash_string address_hash: address_hash_string
) )
end end

@ -33,7 +33,7 @@ defmodule BlockScoutWeb.AddressContractVerificationViaFlattenedCodeController do
render(conn, "new.html", render(conn, "new.html",
changeset: changeset, changeset: changeset,
compiler_versions: compiler_versions, compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions(), evm_versions: CodeCompiler.evm_versions(:solidity),
address_hash: address_hash_string address_hash: address_hash_string
) )
end end

@ -33,7 +33,7 @@ defmodule BlockScoutWeb.AddressContractVerificationViaMultiPartFilesController d
render(conn, "new.html", render(conn, "new.html",
changeset: changeset, changeset: changeset,
address_hash: address_hash_string, address_hash: address_hash_string,
evm_versions: CodeCompiler.allowed_evm_versions(), evm_versions: CodeCompiler.evm_versions(:solidity),
compiler_versions: compiler_versions compiler_versions: compiler_versions
) )
end end

@ -176,6 +176,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do
contract_type, contract_type,
params["from"], params["from"],
address.smart_contract.abi, address.smart_contract.abi,
true,
@api_true @api_true
) )
end end

@ -16,7 +16,6 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
@api_true [api?: true] @api_true [api?: true]
def config(conn, _params) do def config(conn, _params) do
evm_versions = CodeCompiler.allowed_evm_versions()
solidity_compiler_versions = CompilerVersion.fetch_version_list(:solc) solidity_compiler_versions = CompilerVersion.fetch_version_list(:solc)
vyper_compiler_versions = CompilerVersion.fetch_version_list(:vyper) vyper_compiler_versions = CompilerVersion.fetch_version_list(:vyper)
@ -31,11 +30,11 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
conn conn
|> json(%{ |> json(%{
solidity_evm_versions: evm_versions, solidity_evm_versions: CodeCompiler.evm_versions(:solidity),
solidity_compiler_versions: solidity_compiler_versions, solidity_compiler_versions: solidity_compiler_versions,
vyper_compiler_versions: vyper_compiler_versions, vyper_compiler_versions: vyper_compiler_versions,
verification_options: verification_options, 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?() is_rust_verifier_microservice_enabled: RustVerifierInterface.enabled?()
}) })
end end

@ -196,7 +196,8 @@ defmodule BlockScoutWeb.SmartContractController do
%{method_id: params["method_id"], args: args}, %{method_id: params["method_id"], args: args},
contract_type, contract_type,
params["from"], params["from"],
address.smart_contract && address.smart_contract.abi address.smart_contract && address.smart_contract.abi,
true
) )
end end

@ -80,7 +80,7 @@ defmodule BlockScoutWeb.Notifier do
|> View.render_to_string("new.html", |> View.render_to_string("new.html",
changeset: changeset, changeset: changeset,
compiler_versions: compiler_versions, compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions(), evm_versions: CodeCompiler.evm_versions(:solidity),
address_hash: address_hash, address_hash: address_hash,
conn: conn, conn: conn,
retrying: true retrying: true

@ -145,7 +145,7 @@
</div> </div>
</div> </div>
<% else %> <% else %>
<div class="align-self-center function-output word-break-all <%= if not_last_element?(length, index), do: "mb-1" %>"><%= raw(values_with_type(output["value"], output["type"], [output["name"]], 0, output["components"])) %></div> <div class="align-self-center function-output word-break-all <%= if not_last_element?(length, index), do: "mb-1" %>"><%= raw(values_with_type(output["value"], output["type"], fetch_name(function["names"], index), 0)) %></div>
<% end %> <% end %>
<% end %> <% end %>
<% end %> <% end %>

@ -23,7 +23,8 @@ defmodule BlockScoutWeb.API.V2.SearchView do
"symbol" => search_result.symbol, "symbol" => search_result.symbol,
"address" => search_result.address_hash, "address" => search_result.address_hash,
"token_url" => token_path(Endpoint, :show, 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 end

@ -98,7 +98,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractView do
%{result: %{error: error}, is_error: true} %{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
end end
@ -118,13 +118,13 @@ defmodule BlockScoutWeb.API.V2.SmartContractView do
function function
|> Map.drop(["abi_outputs"]) |> 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) Map.replace(result, "outputs", outputs)
end end
end end
defp prepare_output(%{"type" => type, "value" => value} = output) do 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 end
defp prepare_output(output), do: output defp prepare_output(output), do: output
@ -277,4 +277,36 @@ defmodule BlockScoutWeb.API.V2.SmartContractView do
"solidity" "solidity"
end end
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 end

@ -6,6 +6,8 @@ defmodule BlockScoutWeb.SmartContractView do
alias Explorer.Chain.Hash.Address, as: HashAddress alias Explorer.Chain.Hash.Address, as: HashAddress
alias Explorer.SmartContract.Helper alias Explorer.SmartContract.Helper
require Logger
def queryable?(inputs) when not is_nil(inputs), do: Enum.any?(inputs) def queryable?(inputs) when not is_nil(inputs), do: Enum.any?(inputs)
def queryable?(inputs) when is_nil(inputs), do: false def queryable?(inputs) when is_nil(inputs), do: false
@ -63,7 +65,7 @@ defmodule BlockScoutWeb.SmartContractView do
String.starts_with?(type, "address") -> String.starts_with?(type, "address") ->
values = values =
value 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)) 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), def values_with_type(value, :error, _components),
do: render_type_value("error", Helper.sanitize_input(value), "error") 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(nil, _index), do: nil
defp fetch_name([], _index), do: nil defp fetch_name([], _index), do: nil
@ -137,6 +150,15 @@ defmodule BlockScoutWeb.SmartContractView do
end end
defp tuple_to_array(value, type, names) do 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 = types_string =
type type
|> String.slice(6..-2) |> String.slice(6..-2)
@ -165,16 +187,10 @@ defmodule BlockScoutWeb.SmartContractView do
value value
|> Tuple.to_list() |> Tuple.to_list()
values_types_list = Enum.zip(tuple_types, values_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)
end 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 if count_string_symbols(val)["]"] > count_string_symbols(val)["["] do
updated_arr = update_last_list_item(arr, val) updated_arr = update_last_list_item(arr, val)
{updated_arr, !to_merge} {updated_arr, !to_merge}
@ -184,7 +200,7 @@ defmodule BlockScoutWeb.SmartContractView do
end end
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 if count_string_symbols(val)["["] > count_string_symbols(val)["]"] do
# credo:disable-for-next-line # credo:disable-for-next-line
{arr ++ [val], !to_merge} {arr ++ [val], !to_merge}
@ -214,7 +230,7 @@ defmodule BlockScoutWeb.SmartContractView do
end) end)
end end
defp binary_to_utf_string(item) do def binary_to_utf_string(item) do
case Integer.parse(to_string(item)) do case Integer.parse(to_string(item)) do
{item_integer, ""} -> {item_integer, ""} ->
to_string(item_integer) to_string(item_integer)
@ -229,11 +245,7 @@ defmodule BlockScoutWeb.SmartContractView do
end end
defp add_0x(item) do defp add_0x(item) do
if String.starts_with?(item, "0x") do "0x" <> Base.encode16(item, case: :lower)
item
else
"0x" <> Base.encode16(item, case: :lower)
end
end end
defp render_type_value(type, value, type) do defp render_type_value(type, value, type) do
@ -250,7 +262,7 @@ defmodule BlockScoutWeb.SmartContractView do
render_type_value(type, value_to_display, name) render_type_value(type, value_to_display, name)
end end
defp supplement_type_with_components(type, components) do def supplement_type_with_components(type, components) do
if type == "tuple" && components do if type == "tuple" && components do
types = types =
components components

@ -462,24 +462,83 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"name" => "disableWhitelist", "name" => "disableWhitelist",
"inputs" => [%{"type" => "bool", "name" => "disable", "internalType" => "bool"}] "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) target_contract = insert(:smart_contract, abi: abi)
blockchain_eth_call_mock() 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 response = json_response(request, 200)
assert %{ assert %{
"type" => "function", "type" => "function",
"stateMutability" => "view", "stateMutability" => "view",
"names" => ["address"],
"outputs" => [ "outputs" => [
%{ %{
"type" => "address", "type" => "address",
"name" => "",
"internalType" => "address",
"value" => "0xfffffffffffffffffffffffffffffffffffffffe" "value" => "0xfffffffffffffffffffffffffffffffffffffffe"
} }
], ],
@ -497,6 +556,75 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"method_id" => "c683630d" "method_id" => "c683630d"
} in response } 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 refute %{"type" => "fallback"} in response
end end
@ -544,10 +672,10 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"type" => "function", "type" => "function",
"stateMutability" => "view", "stateMutability" => "view",
"payable" => false, "payable" => false,
"names" => [nil],
"outputs" => [ "outputs" => [
%{ %{
"type" => "address[]", "type" => "address[]",
"name" => "",
"value" => [ "value" => [
"0x64631b5d259ead889e8b06d12c8b74742804e5f1", "0x64631b5d259ead889e8b06d12c8b74742804e5f1",
"0x234fe7224ce480ca97d01897311b8c3d35162f86", "0x234fe7224ce480ca97d01897311b8c3d35162f86",
@ -666,6 +794,146 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
} == response } == response
end 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 test "query-read-method with nonexistent method_id", %{conn: conn} do
abi = [ abi = [
%{ %{
@ -1041,11 +1309,10 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
assert %{ assert %{
"type" => "function", "type" => "function",
"stateMutability" => "view", "stateMutability" => "view",
"names" => ["address"],
"outputs" => [ "outputs" => [
%{ %{
"type" => "address", "type" => "address",
"name" => "",
"internalType" => "address",
"value" => "0xfffffffffffffffffffffffffffffffffffffffe" "value" => "0xfffffffffffffffffffffffffffffffffffffffe"
} }
], ],
@ -1220,11 +1487,10 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
assert %{ assert %{
"type" => "function", "type" => "function",
"stateMutability" => "view", "stateMutability" => "view",
"names" => ["address"],
"outputs" => [ "outputs" => [
%{ %{
"type" => "address", "type" => "address",
"name" => "",
"internalType" => "address",
"value" => "0xfffffffffffffffffffffffffffffffffffffffe" "value" => "0xfffffffffffffffffffffffffffffffffffffffe"
} }
], ],

@ -1512,7 +1512,8 @@ defmodule Explorer.Chain do
symbol: token.symbol, symbol: token.symbol,
holder_count: token.holder_count, holder_count: token.holder_count,
inserted_at: token.inserted_at, inserted_at: token.inserted_at,
block_number: 0 block_number: 0,
icon_url: token.icon_url
} }
) )
end end
@ -1531,7 +1532,8 @@ defmodule Explorer.Chain do
symbol: ^nil, symbol: ^nil,
holder_count: ^nil, holder_count: ^nil,
inserted_at: address.inserted_at, inserted_at: address.inserted_at,
block_number: 0 block_number: 0,
icon_url: nil
} }
) )
end end
@ -1559,7 +1561,8 @@ defmodule Explorer.Chain do
symbol: ^nil, symbol: ^nil,
holder_count: ^nil, holder_count: ^nil,
inserted_at: address.inserted_at, inserted_at: address.inserted_at,
block_number: 0 block_number: 0,
icon_url: nil
} }
) )
@ -1582,7 +1585,8 @@ defmodule Explorer.Chain do
symbol: ^nil, symbol: ^nil,
holder_count: ^nil, holder_count: ^nil,
inserted_at: transaction.inserted_at, inserted_at: transaction.inserted_at,
block_number: 0 block_number: 0,
icon_url: nil
} }
) )
@ -1605,7 +1609,8 @@ defmodule Explorer.Chain do
symbol: ^nil, symbol: ^nil,
holder_count: ^nil, holder_count: ^nil,
inserted_at: block.inserted_at, 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, symbol: ^nil,
holder_count: ^nil, holder_count: ^nil,
inserted_at: block.inserted_at, inserted_at: block.inserted_at,
block_number: block.number block_number: block.number,
icon_url: nil
} }
) )

@ -24,7 +24,8 @@ defmodule Explorer.SmartContract.Helper do
@spec read_with_wallet_method?(%{}) :: true | false @spec read_with_wallet_method?(%{}) :: true | false
def read_with_wallet_method?(function), def read_with_wallet_method?(function),
do: do:
!error?(function) && !event?(function) && !constructor?(function) && !fallback?(function) && nonpayable?(function) && !error?(function) && !event?(function) && !constructor?(function) && !fallback?(function) &&
nonpayable?(function) &&
!empty_outputs?(function) !empty_outputs?(function)
def empty_inputs?(function), do: function["inputs"] == [] def empty_inputs?(function), do: function["inputs"] == []

@ -270,7 +270,7 @@ defmodule Explorer.SmartContract.Reader do
abi_with_method_id abi_with_method_id
|> Enum.filter(&Helper.queriable_method?(&1)) |> 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 end
def read_only_functions_from_abi_with_sender(_, _, _), do: [] def read_only_functions_from_abi_with_sender(_, _, _), do: []
@ -332,21 +332,34 @@ defmodule Explorer.SmartContract.Reader do
"tuple[#{tuple_types}]" "tuple[#{tuple_types}]"
end 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 case function do
%{"inputs" => []} -> %{"inputs" => []} ->
method_id = function["method_id"] method_id = function["method_id"]
args = function["inputs"] args = function["inputs"]
outputs = function["outputs"]
values = %{output: outputs, names: names} =
contract_address_hash query_function_with_names(
|> query_verified_contract(%{method_id => normalize_args(args)}, from, leave_error_as_map, abi) contract_address_hash,
|> link_outputs_and_values(outputs, method_id) %{method_id: method_id, args: args},
:regular,
from,
abi,
leave_error_as_map,
options
)
function function
|> Map.replace!("outputs", values) |> Map.replace!("outputs", outputs)
|> Map.put("abi_outputs", Map.get(function, "outputs", [])) |> Map.put("abi_outputs", Map.get(function, "outputs", []))
|> Map.put("names", names)
_ -> _ ->
function function
@ -364,9 +377,10 @@ defmodule Explorer.SmartContract.Reader do
%{method_id: String.t(), args: [term()] | nil}, %{method_id: String.t(), args: [term()] | nil},
:regular | :proxy, :regular | :proxy,
String.t() | nil, String.t() | nil,
[api?] [],
boolean()
) :: %{:names => [any()], :output => [%{}]} ) :: %{: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( def query_function_with_names(
contract_address_hash, contract_address_hash,
@ -374,6 +388,7 @@ defmodule Explorer.SmartContract.Reader do
:regular, :regular,
from, from,
abi, abi,
leave_error_as_map,
_options _options
) do ) do
outputs = outputs =
@ -382,7 +397,7 @@ defmodule Explorer.SmartContract.Reader do
method_id, method_id,
args || [], args || [],
from, from,
true, leave_error_as_map,
abi abi
) )
@ -390,7 +405,15 @@ defmodule Explorer.SmartContract.Reader do
%{output: outputs, names: names} %{output: outputs, names: names}
end 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) abi = get_abi(contract_address_hash, :proxy, options)
outputs = outputs =
@ -399,7 +422,7 @@ defmodule Explorer.SmartContract.Reader do
method_id, method_id,
args || [], args || [],
from, from,
true, leave_error_as_map,
abi abi
) )

@ -76,14 +76,14 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
code = Keyword.fetch!(params, :code) code = Keyword.fetch!(params, :code)
optimize = Keyword.fetch!(params, :optimize) optimize = Keyword.fetch!(params, :optimize)
optimization_runs = optimization_runs(params) 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") bytecode_hash = Keyword.get(params, :bytecode_hash, "default")
external_libs = Keyword.get(params, :external_libs, %{}) external_libs = Keyword.get(params, :external_libs, %{})
external_libs_string = Jason.encode!(external_libs) external_libs_string = Jason.encode!(external_libs)
checked_evm_version = checked_evm_version =
if evm_version in allowed_evm_versions() do if evm_version in evm_versions(:solidity) do
evm_version evm_version
else else
"byzantium" "byzantium"
@ -262,9 +262,19 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
end end
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 :explorer
|> Application.get_env(:allowed_evm_versions) |> Application.get_env(env_name)
|> String.split(",") |> String.split(",")
|> Enum.map(fn version -> String.trim(version) end) |> Enum.map(fn version -> String.trim(version) end)
end end

@ -59,7 +59,7 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
if is_nil(params["name"]) or params["name"] == "" do if is_nil(params["name"]) or params["name"] == "" do
{:error, :name} {:error, :name}
else 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) evm_version = Map.get(params, "evm_version", latest_evm_version)
all_versions = [evm_version | previous_evm_versions(evm_version)] all_versions = [evm_version | previous_evm_versions(evm_version)]
@ -505,19 +505,19 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
end end
def previous_evm_versions(current_evm_version) do 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 cond do
index == 0 -> index == 0 ->
[] []
index == 1 -> index == 1 ->
[List.first(CodeCompiler.allowed_evm_versions())] [List.first(CodeCompiler.evm_versions(:solidity))]
true -> true ->
[ [
Enum.at(CodeCompiler.allowed_evm_versions(), index - 1), Enum.at(CodeCompiler.evm_versions(:solidity), index - 1),
Enum.at(CodeCompiler.allowed_evm_versions(), index - 2) Enum.at(CodeCompiler.evm_versions(:solidity), index - 2)
] ]
end end
end end

@ -153,7 +153,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true, "constant" => true,
"inputs" => [], "inputs" => [],
"name" => "get", "name" => "get",
"outputs" => [%{"name" => "", "type" => "uint256", "value" => 0}], "outputs" => [%{"type" => "uint256", "value" => 0}],
"payable" => _, "payable" => _,
"stateMutability" => _, "stateMutability" => _,
"type" => _ "type" => _
@ -162,7 +162,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true, "constant" => true,
"inputs" => [%{"name" => "x", "type" => "uint256"}], "inputs" => [%{"name" => "x", "type" => "uint256"}],
"name" => "with_arguments", "name" => "with_arguments",
"outputs" => [%{"name" => "", "type" => "bool"}], "outputs" => [%{"type" => "bool"}],
"payable" => _, "payable" => _,
"stateMutability" => _, "stateMutability" => _,
"type" => _ "type" => _
@ -238,7 +238,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true, "constant" => true,
"inputs" => [], "inputs" => [],
"name" => "get", "name" => "get",
"outputs" => [%{"name" => "", "type" => "uint256", "value" => 0}], "outputs" => [%{"type" => "uint256", "value" => 0}],
"payable" => _, "payable" => _,
"stateMutability" => _, "stateMutability" => _,
"type" => _ "type" => _
@ -247,7 +247,7 @@ defmodule Explorer.SmartContract.ReaderTest do
"constant" => true, "constant" => true,
"inputs" => [%{"name" => "x", "type" => "uint256"}], "inputs" => [%{"name" => "x", "type" => "uint256"}],
"name" => "with_arguments", "name" => "with_arguments",
"outputs" => [%{"name" => "", "type" => "bool"}], "outputs" => [%{"type" => "bool"}],
"payable" => _, "payable" => _,
"stateMutability" => _, "stateMutability" => _,
"type" => _ "type" => _

@ -353,17 +353,17 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
end end
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 # test "returns allowed evm versions defined by ALLOWED_EVM_VERSIONS env var" do
# Application.put_env(:explorer, :allowed_evm_versions, "CustomEVM1,CustomEVM2,CustomEVM3") # Application.put_env(:explorer, :allowed_solidity_evm_versions, "CustomEVM1,CustomEVM2,CustomEVM3")
# response = CodeCompiler.allowed_evm_versions() # response = CodeCompiler.evm_versions(:solidity)
# assert ["CustomEVM1", "CustomEVM2", "CustomEVM3"] = response # assert ["CustomEVM1", "CustomEVM2", "CustomEVM3"] = response
# end # end
# test "returns allowed evm versions defined by not trimmed ALLOWED_EVM_VERSIONS env var" do # 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") # Application.put_env(:explorer, :allowed_solidity_evm_versions, "CustomEVM1, CustomEVM2, CustomEVM3")
# response = CodeCompiler.allowed_evm_versions() # response = CodeCompiler.evm_versions(:solidity)
# assert ["CustomEVM1", "CustomEVM2", "CustomEVM3"] = response # assert ["CustomEVM1", "CustomEVM2", "CustomEVM3"] = response
# end # end
@ -371,11 +371,11 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
# test "returns default_allowed_evm_versions" do # test "returns default_allowed_evm_versions" do
# Application.put_env( # Application.put_env(
# :explorer, # :explorer,
# :allowed_evm_versions, # :allowed_solidity_evm_versions,
# "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg" # "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg"
# ) # )
# response = CodeCompiler.allowed_evm_versions() # response = CodeCompiler.evm_versions(:solidity)
# assert ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"] = response # assert ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"] = response
# end # end

@ -170,9 +170,12 @@ exchange_rates_coin = System.get_env("EXCHANGE_RATES_COIN")
config :explorer, config :explorer,
coin: System.get_env("COIN") || exchange_rates_coin || "ETH", coin: System.get_env("COIN") || exchange_rates_coin || "ETH",
coin_name: System.get_env("COIN_NAME") || exchange_rates_coin || "ETH", coin_name: System.get_env("COIN_NAME") || exchange_rates_coin || "ETH",
allowed_evm_versions: allowed_solidity_evm_versions:
System.get_env("CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS") || System.get_env("CONTRACT_VERIFICATION_ALLOWED_SOLIDITY_EVM_VERSIONS") ||
"homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg,istanbul,berlin,london,paris,default", "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"), 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"), healthy_blocks_period: ConfigHelper.parse_time_env_var("HEALTHY_BLOCKS_PERIOD", "5m"),
realtime_events_sender: realtime_events_sender:

@ -81,7 +81,8 @@ CACHE_ADDRESS_TRANSACTIONS_COUNTER_PERIOD=1800
CACHE_ADDRESS_TOKENS_USD_SUM_PERIOD=3600 CACHE_ADDRESS_TOKENS_USD_SUM_PERIOD=3600
CACHE_ADDRESS_TOKEN_TRANSFERS_COUNTER_PERIOD=1800 CACHE_ADDRESS_TOKEN_TRANSFERS_COUNTER_PERIOD=1800
TOKEN_METADATA_UPDATE_INTERVAL=172800 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_VERIFICATION_MAX_LIBRARIES=10
CONTRACT_MAX_STRING_LENGTH_WITHOUT_TRIMMING=2040 CONTRACT_MAX_STRING_LENGTH_WITHOUT_TRIMMING=2040
# CONTRACT_DISABLE_INTERACTION= # CONTRACT_DISABLE_INTERACTION=

@ -690,8 +690,11 @@ endif
ifdef DECODE_NOT_A_CONTRACT_CALLS ifdef DECODE_NOT_A_CONTRACT_CALLS
BLOCKSCOUT_CONTAINER_PARAMS += -e 'DECODE_NOT_A_CONTRACT_CALLS=$(DECODE_NOT_A_CONTRACT_CALLS)' BLOCKSCOUT_CONTAINER_PARAMS += -e 'DECODE_NOT_A_CONTRACT_CALLS=$(DECODE_NOT_A_CONTRACT_CALLS)'
endif endif
ifdef CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS ifdef CONTRACT_VERIFICATION_ALLOWED_SOLIDITY_EVM_VERSIONS
BLOCKSCOUT_CONTAINER_PARAMS += -e 'CONTRACT_VERIFICATION_ALLOWED_EVM_VERSIONS=$(CONTRACT_VERIFICATION_ALLOWED_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 endif
ifdef CONTRACT_VERIFICATION_MAX_LIBRARIES ifdef CONTRACT_VERIFICATION_MAX_LIBRARIES
BLOCKSCOUT_CONTAINER_PARAMS += -e 'CONTRACT_VERIFICATION_MAX_LIBRARIES=$(CONTRACT_VERIFICATION_MAX_LIBRARIES)' BLOCKSCOUT_CONTAINER_PARAMS += -e 'CONTRACT_VERIFICATION_MAX_LIBRARIES=$(CONTRACT_VERIFICATION_MAX_LIBRARIES)'

Loading…
Cancel
Save