Merge branch 'master' into ab-use-postgres-stats-as-fallback

pull/1671/head
Ayrat Badykov 6 years ago committed by GitHub
commit b0ce29ba3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      CHANGELOG.md
  2. 30
      apps/block_scout_web/lib/block_scout_web/controllers/address_decompiled_contract_controller.ex
  3. 7
      apps/block_scout_web/lib/block_scout_web/router.ex
  4. 18
      apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex
  5. 1
      apps/block_scout_web/lib/block_scout_web/templates/address_decompiled_contract/_metatags.html.eex
  6. 30
      apps/block_scout_web/lib/block_scout_web/templates/address_decompiled_contract/index.html.eex
  7. 3
      apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex
  8. 7
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  9. 66
      apps/block_scout_web/priv/gettext/default.pot
  10. 78
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  11. 53
      apps/explorer/lib/explorer/chain.ex
  12. 2
      apps/explorer/lib/explorer/chain/address.ex
  13. 33
      apps/explorer/lib/explorer/smart_contract/verifier.ex
  14. 38
      apps/explorer/test/explorer/chain_test.exs
  15. 35
      apps/explorer/test/explorer/smart_contract/verifier_test.exs

@ -2,8 +2,13 @@
### Features
- [1654](https://github.com/poanetwork/blockscout/pull/1654) - add decompiled code tab
- [1661](https://github.com/poanetwork/blockscout/pull/1661) - try to compile smart contract with the latest evm version
### Fixes
- [#1669](https://github.com/poanetwork/blockscout/pull/1669) - do not fail if multiple matching tokens are found
### Chore
@ -15,7 +20,6 @@
- [#1596](https://github.com/poanetwork/blockscout/pull/1596) - add endpoint to create decompiled contracts
- [#1634](https://github.com/poanetwork/blockscout/pull/1634) - add transaction count cache
### Fixes
- [#1630](https://github.com/poanetwork/blockscout/pull/1630) - (Fix) colour for release link in the footer

@ -0,0 +1,30 @@
defmodule BlockScoutWeb.AddressDecompiledContractController do
use BlockScoutWeb, :controller
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1]
alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token
alias Indexer.CoinBalance.OnDemandFetcher
def index(conn, %{"address_id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.find_decompiled_contract_address(address_hash) do
render(
conn,
"index.html",
address: address,
coin_balance_status: OnDemandFetcher.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address)
)
else
:error ->
not_found(conn)
{:error, :not_found} ->
not_found(conn)
end
end
end

@ -129,6 +129,13 @@ defmodule BlockScoutWeb.Router do
as: :contract
)
resources(
"/decompiled_contracts",
AddressDecompiledContractController,
only: [:index],
as: :decompiled_contract
)
resources(
"/contract_verifications",
AddressContractVerificationController,

@ -59,6 +59,16 @@
</li>
<% end %>
<%= if has_decompiled_code?(@address) do %>
<li class="nav-item">
<%= link(
to: address_decompiled_contract_path(@conn, :index, @address.hash),
class: "nav-link #{tab_status("decompiled_contracts", @conn.request_path)}") do %>
<%= gettext("Decompiled code") %>
<% end %>
</li>
<% end %>
<%= if smart_contract_with_read_only_functions?(@address) do %>
<li class="nav-item">
<%= link(
@ -115,6 +125,14 @@
<%= if smart_contract_verified?(@address) do %>
<i class="far fa-check-circle"></i>
<% end %>
<%= if has_decompiled_code?(@address) do %>
<%= link(
to: address_decompiled_contract_path(@conn, :index, @address.hash),
class: "dropdown-item #{tab_status("contracts", @conn.request_path)}") do %>
<%= gettext("Decompiled code") %>
<% end %>
<% end %>
<% end %>
<% end %>
<%= if smart_contract_with_read_only_functions?(@address) do %>

@ -0,0 +1 @@
<%= render BlockScoutWeb.AddressView, "_metatags.html", conn: @conn, address: @address %>

@ -0,0 +1,30 @@
<section class="container">
<%= render BlockScoutWeb.AddressView, "overview.html", assigns %>
<div class="card">
<div class="card-header">
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
</div>
<%= for {contract, _i} <- Enum.with_index(@address.decompiled_smart_contracts) do %>
<div class="card-body">
<h3><%= gettext "Decompiler version" %></h3>
<div class="tile tile-muted">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= contract.decompiler_version %></code></pre>
</div>
<br>
<section>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Decompiled contract code" %></h3>
<button type="button" class="button button-secondary button-sm" id="button" data-clipboard-text="<%= contract.decompiled_source_code %>" aria-label="copy decompiled contract code">
<%= gettext "Copy Decompiled Contract Code" %>
</button>
</div>
<div class="tile tile-muted">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= contract.decompiled_source_code %></code></pre>
</div>
</section>
</div>
<% end %>
</div>
</section>

@ -0,0 +1,3 @@
defmodule BlockScoutWeb.AddressDecompiledContractView do
use BlockScoutWeb, :view
end

@ -16,6 +16,7 @@ defmodule BlockScoutWeb.AddressView do
@tabs [
"coin_balances",
"contracts",
"decompiled_contracts",
"internal_transactions",
"read_contract",
"tokens",
@ -205,6 +206,11 @@ defmodule BlockScoutWeb.AddressView do
def smart_contract_with_read_only_functions?(%Address{smart_contract: nil}), do: false
def has_decompiled_code?(address) do
address.has_decompiled_code? ||
(Ecto.assoc_loaded?(address.decompiled_smart_contracts) && Enum.count(address.decompiled_smart_contracts) > 0)
end
def token_title(%Token{name: nil, contract_address_hash: contract_address_hash}) do
contract_address_hash
|> to_string
@ -288,6 +294,7 @@ defmodule BlockScoutWeb.AddressView do
defp tab_name(["transactions"]), do: gettext("Transactions")
defp tab_name(["internal_transactions"]), do: gettext("Internal Transactions")
defp tab_name(["contracts"]), do: gettext("Code")
defp tab_name(["decompiled_contracts"]), do: gettext("Decompiled Code")
defp tab_name(["read_contract"]), do: gettext("Read Contract")
defp tab_name(["coin_balances"]), do: gettext("Coin Balance History")
defp tab_name(["validations"]), do: gettext("Blocks Validated")

@ -99,7 +99,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:15
#: lib/block_scout_web/views/address_view.ex:100
#: lib/block_scout_web/views/address_view.ex:101
msgid "Address"
msgstr ""
@ -188,11 +188,11 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:40
#: lib/block_scout_web/templates/address/_tabs.html.eex:103
#: lib/block_scout_web/templates/address/_tabs.html.eex:113
#: lib/block_scout_web/templates/address/overview.html.eex:59
#: lib/block_scout_web/templates/address_validation/index.html.eex:30
#: lib/block_scout_web/templates/address_validation/index.html.eex:57
#: lib/block_scout_web/views/address_view.ex:293
#: lib/block_scout_web/views/address_view.ex:300
msgid "Blocks Validated"
msgstr ""
@ -218,11 +218,11 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:53
#: lib/block_scout_web/templates/address/_tabs.html.eex:113
#: lib/block_scout_web/templates/address/_tabs.html.eex:123
#: lib/block_scout_web/templates/address_validation/index.html.eex:39
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:119
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:141
#: lib/block_scout_web/views/address_view.ex:290
#: lib/block_scout_web/views/address_view.ex:296
msgid "Code"
msgstr ""
@ -266,14 +266,14 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:13
#: lib/block_scout_web/views/address_view.ex:98
#: lib/block_scout_web/views/address_view.ex:99
msgid "Contract Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:16
#: lib/block_scout_web/views/address_view.ex:38
#: lib/block_scout_web/views/address_view.ex:72
#: lib/block_scout_web/views/address_view.ex:39
#: lib/block_scout_web/views/address_view.ex:73
msgid "Contract Address Pending"
msgstr ""
@ -488,13 +488,13 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:21
#: lib/block_scout_web/templates/address/_tabs.html.eex:90
#: lib/block_scout_web/templates/address/_tabs.html.eex:100
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:58
#: lib/block_scout_web/templates/address_validation/index.html.eex:24
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:14
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:43
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:289
#: lib/block_scout_web/views/address_view.ex:295
#: lib/block_scout_web/views/transaction_view.ex:258
msgid "Internal Transactions"
msgstr ""
@ -528,7 +528,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:28
#: lib/block_scout_web/templates/layout/app.html.eex:49
#: lib/block_scout_web/views/address_view.ex:120
#: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap"
msgstr ""
@ -698,11 +698,11 @@ msgid "Query"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:65
#: lib/block_scout_web/templates/address/_tabs.html.eex:122
#: lib/block_scout_web/templates/address/_tabs.html.eex:75
#: lib/block_scout_web/templates/address/_tabs.html.eex:140
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:33
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:75
#: lib/block_scout_web/views/address_view.ex:291
#: lib/block_scout_web/views/address_view.ex:298
#: lib/block_scout_web/views/tokens/overview_view.ex:37
msgid "Read Contract"
msgstr ""
@ -891,12 +891,12 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:13
#: lib/block_scout_web/templates/address/_tabs.html.eex:85
#: lib/block_scout_web/templates/address/_tabs.html.eex:95
#: lib/block_scout_web/templates/address_token/index.html.eex:11
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:12
#: lib/block_scout_web/templates/address_validation/index.html.eex:11
#: lib/block_scout_web/templates/address_validation/index.html.eex:19
#: lib/block_scout_web/views/address_view.ex:287
#: lib/block_scout_web/views/address_view.ex:293
msgid "Tokens"
msgstr ""
@ -948,7 +948,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:5
#: lib/block_scout_web/templates/address/_tabs.html.eex:80
#: lib/block_scout_web/templates/address/_tabs.html.eex:90
#: lib/block_scout_web/templates/address_transaction/index.html.eex:53
#: lib/block_scout_web/templates/address_validation/index.html.eex:14
#: lib/block_scout_web/templates/block_transaction/index.html.eex:13
@ -957,7 +957,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35
#: lib/block_scout_web/templates/chain/show.html.eex:93
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:288
#: lib/block_scout_web/views/address_view.ex:294
msgid "Transactions"
msgstr ""
@ -1399,8 +1399,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:30
#: lib/block_scout_web/templates/address/_tabs.html.eex:96
#: lib/block_scout_web/views/address_view.ex:292
#: lib/block_scout_web/templates/address/_tabs.html.eex:106
#: lib/block_scout_web/views/address_view.ex:299
msgid "Coin Balance History"
msgstr ""
@ -1701,3 +1701,29 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:58
msgid "Enter constructor arguments if the contract had any"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:67
#: lib/block_scout_web/templates/address/_tabs.html.eex:133
msgid "Decompiled code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:20
msgid "Copy Decompiled Contract Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/address_view.ex:297
msgid "Decompiled Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:18
msgid "Decompiled contract code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:11
msgid "Decompiler version"
msgstr ""

@ -99,7 +99,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:15
#: lib/block_scout_web/views/address_view.ex:100
#: lib/block_scout_web/views/address_view.ex:101
msgid "Address"
msgstr ""
@ -188,11 +188,11 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:40
#: lib/block_scout_web/templates/address/_tabs.html.eex:103
#: lib/block_scout_web/templates/address/_tabs.html.eex:113
#: lib/block_scout_web/templates/address/overview.html.eex:59
#: lib/block_scout_web/templates/address_validation/index.html.eex:30
#: lib/block_scout_web/templates/address_validation/index.html.eex:57
#: lib/block_scout_web/views/address_view.ex:293
#: lib/block_scout_web/views/address_view.ex:300
msgid "Blocks Validated"
msgstr ""
@ -218,11 +218,11 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:53
#: lib/block_scout_web/templates/address/_tabs.html.eex:113
#: lib/block_scout_web/templates/address/_tabs.html.eex:123
#: lib/block_scout_web/templates/address_validation/index.html.eex:39
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:119
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:141
#: lib/block_scout_web/views/address_view.ex:290
#: lib/block_scout_web/views/address_view.ex:296
msgid "Code"
msgstr ""
@ -266,14 +266,14 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:13
#: lib/block_scout_web/views/address_view.ex:98
#: lib/block_scout_web/views/address_view.ex:99
msgid "Contract Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:16
#: lib/block_scout_web/views/address_view.ex:38
#: lib/block_scout_web/views/address_view.ex:72
#: lib/block_scout_web/views/address_view.ex:39
#: lib/block_scout_web/views/address_view.ex:73
msgid "Contract Address Pending"
msgstr ""
@ -488,13 +488,13 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:21
#: lib/block_scout_web/templates/address/_tabs.html.eex:90
#: lib/block_scout_web/templates/address/_tabs.html.eex:100
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:58
#: lib/block_scout_web/templates/address_validation/index.html.eex:24
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:14
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:43
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:289
#: lib/block_scout_web/views/address_view.ex:295
#: lib/block_scout_web/views/transaction_view.ex:258
msgid "Internal Transactions"
msgstr ""
@ -528,7 +528,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:28
#: lib/block_scout_web/templates/layout/app.html.eex:49
#: lib/block_scout_web/views/address_view.ex:120
#: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap"
msgstr ""
@ -698,11 +698,11 @@ msgid "Query"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:65
#: lib/block_scout_web/templates/address/_tabs.html.eex:122
#: lib/block_scout_web/templates/address/_tabs.html.eex:75
#: lib/block_scout_web/templates/address/_tabs.html.eex:140
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:33
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:75
#: lib/block_scout_web/views/address_view.ex:291
#: lib/block_scout_web/views/address_view.ex:298
#: lib/block_scout_web/views/tokens/overview_view.ex:37
msgid "Read Contract"
msgstr ""
@ -891,12 +891,12 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:13
#: lib/block_scout_web/templates/address/_tabs.html.eex:85
#: lib/block_scout_web/templates/address/_tabs.html.eex:95
#: lib/block_scout_web/templates/address_token/index.html.eex:11
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:12
#: lib/block_scout_web/templates/address_validation/index.html.eex:11
#: lib/block_scout_web/templates/address_validation/index.html.eex:19
#: lib/block_scout_web/views/address_view.ex:287
#: lib/block_scout_web/views/address_view.ex:293
msgid "Tokens"
msgstr ""
@ -948,7 +948,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:5
#: lib/block_scout_web/templates/address/_tabs.html.eex:80
#: lib/block_scout_web/templates/address/_tabs.html.eex:90
#: lib/block_scout_web/templates/address_transaction/index.html.eex:53
#: lib/block_scout_web/templates/address_validation/index.html.eex:14
#: lib/block_scout_web/templates/block_transaction/index.html.eex:13
@ -957,7 +957,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35
#: lib/block_scout_web/templates/chain/show.html.eex:93
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:288
#: lib/block_scout_web/views/address_view.ex:294
msgid "Transactions"
msgstr ""
@ -1399,8 +1399,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:30
#: lib/block_scout_web/templates/address/_tabs.html.eex:96
#: lib/block_scout_web/views/address_view.ex:292
#: lib/block_scout_web/templates/address/_tabs.html.eex:106
#: lib/block_scout_web/views/address_view.ex:299
msgid "Coin Balance History"
msgstr ""
@ -1636,11 +1636,6 @@ msgstr ""
msgid "Contract Libraries"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:58
msgid "Enter contructor arguments if the contract had any"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:52
msgid "Last Balance Update: Block #"
@ -1697,7 +1692,38 @@ msgstr ""
msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr ""
#, elixir-format, fuzzy
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:31
msgid "EVM Version"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:58
msgid "Enter constructor arguments if the contract had any"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:67
#: lib/block_scout_web/templates/address/_tabs.html.eex:133
msgid "Decompiled code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:20
msgid "Copy Decompiled Contract Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/address_view.ex:297
msgid "Decompiled Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:18
msgid "Decompiled contract code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:11
msgid "Decompiler version"
msgstr ""

@ -661,7 +661,9 @@ defmodule Explorer.Chain do
where: address.hash == ^hash
)
query
query_with_decompiled_flag = with_decompiled_code_flag(query, hash)
query_with_decompiled_flag
|> Repo.one()
|> case do
nil -> {:error, :not_found}
@ -692,10 +694,10 @@ defmodule Explorer.Chain do
)
query
|> Repo.one()
|> Repo.all()
|> case do
nil -> {:error, :not_found}
hash -> {:ok, hash}
[] -> {:error, :not_found}
hashes -> {:ok, List.first(hashes)}
end
end
@ -764,6 +766,7 @@ defmodule Explorer.Chain do
Repo.all(query)
end
@spec find_contract_address(Hash.t()) :: {:ok, Address.t()} | {:error, :not_found}
def find_contract_address(%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash) do
query =
from(
@ -778,6 +781,33 @@ defmodule Explorer.Chain do
where: address.hash == ^hash and not is_nil(address.contract_code)
)
query_with_decompiled_flag = with_decompiled_code_flag(query, hash)
address = Repo.one(query_with_decompiled_flag)
if address do
{:ok, address}
else
{:error, :not_found}
end
end
@spec find_decompiled_contract_address(Hash.t()) :: {:ok, Address.t()} | {:error, :not_found}
def find_decompiled_contract_address(%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash) do
query =
from(
address in Address,
preload: [
:contracts_creation_internal_transaction,
:names,
:smart_contract,
:token,
:contracts_creation_transaction,
:decompiled_smart_contracts
],
where: address.hash == ^hash
)
address = Repo.one(query)
if address do
@ -2737,4 +2767,19 @@ defmodule Explorer.Chain do
value
end
defp with_decompiled_code_flag(query, hash) do
has_decompiled_code_query =
from(decompiled_contract in DecompiledSmartContract,
where: decompiled_contract.address_hash == ^hash,
limit: 1,
select: %{has_decompiled_code?: not is_nil(decompiled_contract.address_hash)}
)
from(
address in query,
left_join: decompiled_code in subquery(has_decompiled_code_query),
select_merge: %{has_decompiled_code?: decompiled_code.has_decompiled_code?}
)
end
end

@ -74,6 +74,7 @@ defmodule Explorer.Chain.Address do
field(:fetched_coin_balance_block_number, :integer)
field(:contract_code, Data)
field(:nonce, :integer)
field(:has_decompiled_code?, :boolean, virtual: true)
has_one(:smart_contract, SmartContract)
has_one(:decompiled_smart_contract, DecompiledSmartContract)
@ -92,6 +93,7 @@ defmodule Explorer.Chain.Address do
)
has_many(:names, Address.Name, foreign_key: :address_hash)
has_many(:decompiled_smart_contracts, DecompiledSmartContract, foreign_key: :address_hash)
timestamps()
end

@ -28,7 +28,25 @@ defmodule Explorer.SmartContract.Verifier do
solc_output =
CodeCompiler.run(name, compiler_version, contract_source_code, optimization, evm_version, external_libraries)
compare_bytecodes(solc_output, address_hash, constructor_arguments)
case compare_bytecodes(solc_output, address_hash, constructor_arguments) do
{:error, :generated_bytecode} ->
next_evm_version = next_evm_version(evm_version)
second_solc_output =
CodeCompiler.run(
name,
compiler_version,
contract_source_code,
optimization,
next_evm_version,
external_libraries
)
compare_bytecodes(second_solc_output, address_hash, constructor_arguments)
result ->
result
end
end
defp compare_bytecodes({:error, :name}, _, _), do: {:error, :name}
@ -71,4 +89,17 @@ defmodule Explorer.SmartContract.Verifier do
bytecode
end
def next_evm_version(current_evm_version) do
[prev_version, last_version] =
CodeCompiler.allowed_evm_versions()
|> Enum.reverse()
|> Enum.take(2)
if current_evm_version != last_version do
last_version
else
prev_version
end
end
end

@ -854,6 +854,23 @@ defmodule Explorer.ChainTest do
assert {:ok, address} = Chain.hash_to_address(address.hash)
end
test "has_decompiled_code? is true if there are decompiled contracts" do
address = insert(:address)
insert(:decompiled_smart_contract, address_hash: address.hash)
{:ok, found_address} = Chain.hash_to_address(address.hash)
assert found_address.has_decompiled_code?
end
test "has_decompiled_code? is false if there are no decompiled contracts" do
address = insert(:address)
{:ok, found_address} = Chain.hash_to_address(address.hash)
refute found_address.has_decompiled_code?
end
end
describe "token_contract_address_from_token_name/1" do
@ -869,6 +886,15 @@ defmodule Explorer.ChainTest do
assert {:ok, _} = Chain.token_contract_address_from_token_name(name)
end
test "return only one result if multiple records are found" do
name = "TOKEN"
insert(:token, symbol: name)
insert(:token, symbol: name)
assert {:ok, _} = Chain.token_contract_address_from_token_name(name)
end
end
describe "find_or_insert_address_from_hash/1" do
@ -2321,6 +2347,18 @@ defmodule Explorer.ChainTest do
end
end
describe "find_decompiled_contract_address/1" do
test "returns contract with decompiled contracts" do
address = insert(:address)
insert(:decompiled_smart_contract, address_hash: address.hash)
insert(:decompiled_smart_contract, address_hash: address.hash, decompiler_version: "2")
{:ok, address} = Chain.find_decompiled_contract_address(address.hash)
assert Enum.count(address.decompiled_smart_contracts) == 2
end
end
describe "block_reward/1" do
setup do
%{block_range: range} = emission_reward = insert(:emission_reward)

@ -82,6 +82,41 @@ defmodule Explorer.SmartContract.VerifierTest do
assert abi != nil
end
test "tries to compile with the latest evm version if wrong evm version was provided" do
bytecode =
"0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063256fec88146100545780633fa4f245146100a9578063812600df146100d2575b600080fd5b341561005f57600080fd5b6100676100f5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100b457600080fd5b6100bc61011b565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b6100f36004808035906020019091905050610121565b005b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b806000540160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505600a165627a7a72305820b81379d1ae9d8e0fde05ee02b8bd170f43f8bd3d54da8b7ec203434a23a298980029"
contract_address = insert(:contract_address, contract_code: bytecode)
code = """
pragma solidity ^0.4.15;
contract Incrementer {
event Incremented(address indexed sender, uint256 newValue);
uint256 public value;
address public lastSender;
function Incrementer(uint256 initialValue) {
value = initialValue;
lastSender = msg.sender;
}
function inc(uint256 delta) {
value = value + delta;
lastSender = msg.sender;
}
}
"""
params = %{
"contract_source_code" => code,
"compiler_version" => "v0.4.15+commit.bbb8e64f",
"evm_version" => "homestead",
"name" => "Incrementer",
"optimization" => false
}
assert {:ok, %{abi: abi}} = Verifier.evaluate_authenticity(contract_address.hash, params)
assert abi != nil
end
test "returns error when constructor arguments do not match", %{
contract_code_info: contract_code_info
} do

Loading…
Cancel
Save