Show compilation error at conntract verification

pull/3199/head
Victor Baranov 4 years ago
parent 880e17289e
commit 0a0bd31abc
  1. 1
      .dialyzer-ignore
  2. 1
      CHANGELOG.md
  3. 35
      apps/explorer/lib/explorer/chain/smart_contract.ex
  4. 10
      apps/explorer/lib/explorer/smart_contract/publisher.ex
  5. 4
      apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
  6. 10
      apps/explorer/lib/explorer/smart_contract/verifier.ex

@ -6,6 +6,7 @@ apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex:400: Function timestamp_to_datetim
lib/explorer/repo/prometheus_logger.ex:8
lib/block_scout_web/views/layout_view.ex:175
lib/explorer/smart_contract/publisher_worker.ex:6
lib/explorer/smart_contract/verifier.ex:82
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: Function microseconds_time/1 has no local return
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: The call 'Elixir.System':convert_time_unit(__@1::any(),'native','microseconds') breaks the contract (integer(),time_unit() | 'native',time_unit() | 'native') -> integer()
lib/block_scout_web/views/layout_view.ex:172: The call 'Elixir.Poison.Parser':'parse!'(any(),#{'keys':='atoms!'}) will never return since the success typing is (binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | []),[{atom(),_}]) -> 'false' | 'nil' | 'true' | binary() | ['false' | 'nil' | 'true' | binary() | [any()] | number() | map()] | number() | map() and the contract is (iodata(),'Elixir.Keyword':t()) -> t()

@ -1,6 +1,7 @@
## Current
### Features
- [#3199](https://github.com/poanetwork/blockscout/pull/3199) - Show compilation error at contract verification
- [#3193](https://github.com/poanetwork/blockscout/pull/3193) - Raw trace copy button
- [#3184](https://github.com/poanetwork/blockscout/pull/3184) - Apps navbar menu item
- [#3145](https://github.com/poanetwork/blockscout/pull/3145) - Pending txs per address API endpoint

@ -255,20 +255,26 @@ defmodule Explorer.Chain.SmartContract do
|> prepare_changes(&upsert_contract_methods/1)
end
def invalid_contract_changeset(%__MODULE__{} = smart_contract, attrs, error) do
smart_contract
|> cast(attrs, [
:name,
:compiler_version,
:optimization,
:contract_source_code,
:address_hash,
:evm_version,
:optimization_runs,
:constructor_arguments
])
|> validate_required([:name, :compiler_version, :optimization, :address_hash])
|> add_error(:contract_source_code, error_message(error))
def invalid_contract_changeset(%__MODULE__{} = smart_contract, attrs, error, error_message) do
validated =
smart_contract
|> cast(attrs, [
:name,
:compiler_version,
:optimization,
:contract_source_code,
:address_hash,
:evm_version,
:optimization_runs,
:constructor_arguments
])
|> validate_required([:name, :compiler_version, :optimization, :address_hash])
if error_message do
add_error(validated, :contract_source_code, error_message(error, error_message))
else
add_error(validated, :contract_source_code, error_message(error))
end
end
def add_submitted_comment(code, inserted_at) when is_binary(code) do
@ -331,4 +337,5 @@ defmodule Explorer.Chain.SmartContract do
defp error_message(:constructor_arguments), do: "Constructor arguments do not match, please try again."
defp error_message(:name), do: "Wrong contract name, please try again."
defp error_message(_), do: "There was an error validating your contract, please try again."
defp error_message(:compilation, error_message), do: "There was an error compiling your contract: #{error_message}"
end

@ -37,7 +37,10 @@ defmodule Explorer.SmartContract.Publisher do
publish_smart_contract(address_hash, params_with_external_libaries, abi)
{:error, error} ->
{:error, unverified_smart_contract(address_hash, params_with_external_libaries, error)}
{:error, unverified_smart_contract(address_hash, params_with_external_libaries, error, nil)}
{:error, error, error_message} ->
{:error, unverified_smart_contract(address_hash, params_with_external_libaries, error, error_message)}
end
end
@ -47,14 +50,15 @@ defmodule Explorer.SmartContract.Publisher do
Chain.create_smart_contract(attrs, attrs.external_libraries)
end
defp unverified_smart_contract(address_hash, params, error) do
defp unverified_smart_contract(address_hash, params, error, error_message) do
attrs = attributes(address_hash, params)
changeset =
SmartContract.invalid_contract_changeset(
%SmartContract{address_hash: address_hash},
attrs,
error
error,
error_message
)
%{changeset | action: :insert}

@ -116,7 +116,9 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
error ->
error = parse_error(error)
Logger.warn(["There was an error compiling a provided contract: ", inspect(error)])
{:error, :compilation}
{:error, [first_error | _]} = error
%{"message" => error_message} = first_error
{:error, :compilation, error_message}
end
else
{:error, :compilation}

@ -28,7 +28,11 @@ defmodule Explorer.SmartContract.Verifier do
latest_evm_version = List.last(CodeCompiler.allowed_evm_versions())
evm_version = Map.get(params, "evm_version", latest_evm_version)
Enum.reduce([evm_version | previous_evm_versions(evm_version)], false, fn version, acc ->
all_versions = [evm_version | previous_evm_versions(evm_version)]
all_versions_extra = all_versions ++ [evm_version]
Enum.reduce(all_versions_extra, false, fn version, acc ->
case acc do
{:ok, _} = result ->
result
@ -75,6 +79,10 @@ defmodule Explorer.SmartContract.Verifier do
defp compare_bytecodes({:error, :name}, _, _, _, _, _), do: {:error, :name}
defp compare_bytecodes({:error, _}, _, _, _, _, _), do: {:error, :compilation}
defp compare_bytecodes({:error, _, error_message}, _, _, _, _, _) do
{:error, :compilation, error_message}
end
# credo:disable-for-next-line /Complexity/
defp compare_bytecodes(
{:ok, %{"abi" => abi, "bytecode" => bytecode}},

Loading…
Cancel
Save