diff --git a/CHANGELOG.md b/CHANGELOG.md index a38c6f8559..c8c590632b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,9 +22,11 @@ - [#1920](https://github.com/poanetwork/blockscout/pull/1920) - fix: remove source code fields from list endpoint - [#1876](https://github.com/poanetwork/blockscout/pull/1876) - async calculate a count of blocks - [#1941](https://github.com/poanetwork/blockscout/pull/1941) - feat: add on demand fetching and stale attr to rpc +- [#1957](https://github.com/poanetwork/blockscout/pull/1957) - Calculate stakes ratio before insert pools - [#1956](https://github.com/poanetwork/blockscout/pull/1956) - add logs tab to address - [#1933](https://github.com/poanetwork/blockscout/pull/1933) - add eth_BlockNumber json rpc method - [#1952](https://github.com/poanetwork/blockscout/pull/1952) - feat: exclude empty contracts by default +- [#1954](https://github.com/poanetwork/blockscout/pull/1954) - feat: use creation init on self destruct ### Fixes diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex index 560440fb4e..b7b2282682 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex @@ -1,18 +1,25 @@ +<% contract_creation_code = contract_creation_code(@address) %> +
<%= render BlockScoutWeb.AddressView, "overview.html", assigns %>
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
- <%= if !BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %> - <%= link( - gettext("Verify & Publish"), - to: address_verify_contract_path(@conn, :new, @address.hash), - class: "button button-primary button-sm float-right ml-3", - "data-test": "verify_and_publish" - ) %> + <%= if match?({:selfdestructed, _}, contract_creation_code) do %> +
+ <%= gettext("Verify & Publish") %> +
+ <% else %> + <%= if !BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %> + <%= link( + gettext("Verify & Publish"), + to: address_verify_contract_path(@conn, :new, @address.hash), + class: "button button-primary button-sm float-right ml-3", + "data-test": "verify_and_publish" + ) %> + <% end %> <% end %> - <%= if BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %>
@@ -56,15 +63,32 @@ <% end %>
-
-

<%= gettext "Contract creation code" %>

- -
-
-
<%= @address.contract_code %>
-
+ <%= case contract_creation_code do %> + <% {:selfdestructed, transaction_init} -> %> +
+

<%= gettext "Contract Creation Code" %>

+ +
+
+

<%= gettext "Contracts that self destruct in their constructors have no contract code published and cannot be verified." %>

+

<%= gettext "Displaying the init data provided of the creating transaction." %>

+
+
+
<%= transaction_init %>
+
+ <% {:ok, contract_code} -> %> +
+

<%= gettext "Contract Byte Code" %>

+ +
+
+
<%= contract_code %>
+
+ <% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex index 27dbd1b559..4dc99a2a68 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex @@ -1,6 +1,8 @@ defmodule BlockScoutWeb.AddressContractView do use BlockScoutWeb, :view + alias Explorer.Chain.{Address, Data, InternalTransaction} + def render("scripts.html", %{conn: conn}) do render_scripts(conn, "address_contract/code_highlighting.js") end @@ -34,4 +36,15 @@ defmodule BlockScoutWeb.AddressContractView do {value, String.pad_leading(to_string(line), max_digits, " ")} end) end + + def contract_creation_code(%Address{ + contract_code: %Data{bytes: <<>>}, + contracts_creation_internal_transaction: %InternalTransaction{init: init} + }) do + {:selfdestructed, init} + end + + def contract_creation_code(%Address{contract_code: contract_code}) do + {:ok, contract_code} + end end diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 4917896dd7..96e75e5c6f 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -228,7 +228,7 @@ msgid "Compiler" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:23 +#: lib/block_scout_web/templates/address_contract/index.html.eex:30 msgid "Compiler version" msgstr "" @@ -256,7 +256,7 @@ msgid "Connection Lost, click to load newer validations" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:46 +#: lib/block_scout_web/templates/address_contract/index.html.eex:53 msgid "Contract ABI" msgstr "" @@ -289,17 +289,12 @@ msgid "Contract Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:60 -msgid "Contract creation code" -msgstr "" - -#, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:19 +#: lib/block_scout_web/templates/address_contract/index.html.eex:26 msgid "Contract name:" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:34 +#: lib/block_scout_web/templates/address_contract/index.html.eex:41 msgid "Contract source code" msgstr "" @@ -625,7 +620,7 @@ msgid "Older" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:27 +#: lib/block_scout_web/templates/address_contract/index.html.eex:34 msgid "Optimization enabled" msgstr "" @@ -988,7 +983,8 @@ msgid "Value" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:9 +#: lib/block_scout_web/templates/address_contract/index.html.eex:11 +#: lib/block_scout_web/templates/address_contract/index.html.eex:16 msgid "Verify & Publish" msgstr "" @@ -1053,7 +1049,7 @@ msgid "at" msgstr "" #, elixir-format -#: lib/block_scout_web/views/address_contract_view.ex:20 +#: lib/block_scout_web/views/address_contract_view.ex:22 msgid "false" msgstr "" @@ -1071,7 +1067,7 @@ msgid "string" msgstr "" #, elixir-format -#: lib/block_scout_web/views/address_contract_view.ex:19 +#: lib/block_scout_web/views/address_contract_view.ex:21 msgid "true" msgstr "" @@ -1515,17 +1511,17 @@ msgid "Support" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:48 +#: lib/block_scout_web/templates/address_contract/index.html.eex:55 msgid "Copy ABI" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:62 +#: lib/block_scout_web/templates/address_contract/index.html.eex:71 msgid "Copy Contract Creation Code" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:36 +#: lib/block_scout_web/templates/address_contract/index.html.eex:43 msgid "Copy Source Code" msgstr "" @@ -1752,6 +1748,31 @@ msgstr "" msgid "of" msgstr "" +#, elixir-format +#: lib/block_scout_web/templates/address_contract/index.html.eex:83 +msgid "Contract Byte Code" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract/index.html.eex:69 +msgid "Contract Creation Code" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract/index.html.eex:75 +msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified." +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract/index.html.eex:85 +msgid "Copy Contract Byte Code" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract/index.html.eex:76 +msgid "Displaying the init data provided of the creating transaction." +msgstr "" + #, elixir-format #: lib/block_scout_web/templates/address_logs/index.html.eex:77 msgid "There are no logs for this address." diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 6fc4e2ddec..1dd2465781 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -228,7 +228,7 @@ msgid "Compiler" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:23 +#: lib/block_scout_web/templates/address_contract/index.html.eex:30 msgid "Compiler version" msgstr "" @@ -256,7 +256,7 @@ msgid "Connection Lost, click to load newer validations" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:46 +#: lib/block_scout_web/templates/address_contract/index.html.eex:53 msgid "Contract ABI" msgstr "" @@ -289,17 +289,12 @@ msgid "Contract Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:60 -msgid "Contract creation code" -msgstr "" - -#, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:19 +#: lib/block_scout_web/templates/address_contract/index.html.eex:26 msgid "Contract name:" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:34 +#: lib/block_scout_web/templates/address_contract/index.html.eex:41 msgid "Contract source code" msgstr "" @@ -625,7 +620,7 @@ msgid "Older" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:27 +#: lib/block_scout_web/templates/address_contract/index.html.eex:34 msgid "Optimization enabled" msgstr "" @@ -988,7 +983,8 @@ msgid "Value" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:9 +#: lib/block_scout_web/templates/address_contract/index.html.eex:11 +#: lib/block_scout_web/templates/address_contract/index.html.eex:16 msgid "Verify & Publish" msgstr "" @@ -1053,7 +1049,7 @@ msgid "at" msgstr "" #, elixir-format -#: lib/block_scout_web/views/address_contract_view.ex:20 +#: lib/block_scout_web/views/address_contract_view.ex:22 msgid "false" msgstr "" @@ -1071,7 +1067,7 @@ msgid "string" msgstr "" #, elixir-format -#: lib/block_scout_web/views/address_contract_view.ex:19 +#: lib/block_scout_web/views/address_contract_view.ex:21 msgid "true" msgstr "" @@ -1515,17 +1511,17 @@ msgid "Support" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:48 +#: lib/block_scout_web/templates/address_contract/index.html.eex:55 msgid "Copy ABI" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:62 +#: lib/block_scout_web/templates/address_contract/index.html.eex:71 msgid "Copy Contract Creation Code" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract/index.html.eex:36 +#: lib/block_scout_web/templates/address_contract/index.html.eex:43 msgid "Copy Source Code" msgstr "" @@ -1752,6 +1748,31 @@ msgstr "" msgid "of" msgstr "" +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address_contract/index.html.eex:83 +msgid "Contract Byte Code" +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address_contract/index.html.eex:69 +msgid "Contract Creation Code" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract/index.html.eex:75 +msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified." +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address_contract/index.html.eex:85 +msgid "Copy Contract Byte Code" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract/index.html.eex:76 +msgid "Displaying the init data provided of the creating transaction." +msgstr "" + #, elixir-format, fuzzy #: lib/block_scout_web/templates/address_logs/index.html.eex:77 msgid "There are no logs for this address." diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index c7736efad9..b21c0c4441 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -91,7 +91,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do {:ok, _} = Import.insert_changes_list( repo, - changes_list, + stakes_ratio(changes_list), conflict_target: {:unsafe_fragment, "(address_hash) where \"primary\" = true"}, on_conflict: on_conflict, for: Address.Name, @@ -114,4 +114,20 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do ] ) end + + # Calculates staked ratio for each pool + defp stakes_ratio(pools) do + active_pools = Enum.filter(pools, & &1.metadata[:is_active]) + + stakes_total = + Enum.reduce(pools, 0, fn pool, acc -> + acc + pool.metadata[:staked_amount] + end) + + Enum.map(active_pools, fn pool -> + staked_ratio = if stakes_total > 0, do: pool.metadata[:staked_amount] / stakes_total, else: 0 + + put_in(pool, [:metadata, :staked_ratio], staked_ratio) + end) + end end diff --git a/apps/explorer/lib/explorer/chain/internal_transaction/result.ex b/apps/explorer/lib/explorer/chain/internal_transaction/result.ex index 5b4e3102fc..c4c680e7d4 100644 --- a/apps/explorer/lib/explorer/chain/internal_transaction/result.ex +++ b/apps/explorer/lib/explorer/chain/internal_transaction/result.ex @@ -19,7 +19,7 @@ defmodule Explorer.Chain.InternalTransaction.Result do {key, to_string(hash)} end - defp entry_to_raw({"code", _} = entry), do: entry + defp entry_to_raw({"code", code}), do: {"code", Data.to_string(code)} defp entry_to_raw({key, decimal}) when key in ~w(gasUsed) do integer = diff --git a/apps/explorer/test/explorer/chain/import/runner/staking_pools_test.exs b/apps/explorer/test/explorer/chain/import/runner/staking_pools_test.exs index d5bc6ecfca..af25368679 100644 --- a/apps/explorer/test/explorer/chain/import/runner/staking_pools_test.exs +++ b/apps/explorer/test/explorer/chain/import/runner/staking_pools_test.exs @@ -1,85 +1,29 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsTest do use Explorer.DataCase + import Explorer.Factory + alias Ecto.Multi alias Explorer.Chain.Import.Runner.StakingPools describe "run/1" do test "insert new pools list" do - pools = [ - %{ - address_hash: %Explorer.Chain.Hash{ - byte_count: 20, - bytes: <<11, 47, 94, 47, 60, 189, 134, 78, 170, 44, 100, 46, 55, 105, 193, 88, 35, 97, 202, 246>> - }, - metadata: %{ - banned_unitil: 0, - delegators_count: 0, - is_active: true, - is_banned: false, - is_validator: true, - mining_address: %Explorer.Chain.Hash{ - byte_count: 20, - bytes: <<187, 202, 168, 212, 130, 137, 187, 31, 252, 249, 128, 141, 154, 164, 177, 210, 21, 5, 76, 120>> - }, - retries_count: 1, - staked_amount: 0, - was_banned_count: 0, - was_validator_count: 1 - }, - name: "anonymous", - primary: true - }, - %{ - address_hash: %Explorer.Chain.Hash{ - byte_count: 20, - bytes: <<170, 148, 182, 135, 211, 249, 85, 42, 69, 59, 129, 178, 131, 76, 165, 55, 120, 152, 13, 192>> - }, - metadata: %{ - banned_unitil: 0, - delegators_count: 0, - is_active: true, - is_banned: false, - is_validator: true, - mining_address: %Explorer.Chain.Hash{ - byte_count: 20, - bytes: <<117, 223, 66, 56, 58, 254, 107, 245, 25, 74, 168, 250, 14, 155, 61, 95, 158, 134, 148, 65>> - }, - retries_count: 1, - staked_amount: 0, - was_banned_count: 0, - was_validator_count: 1 - }, - name: "anonymous", - primary: true - }, - %{ - address_hash: %Explorer.Chain.Hash{ - byte_count: 20, - bytes: <<49, 44, 35, 14, 125, 109, 176, 82, 36, 246, 2, 8, 166, 86, 227, 84, 28, 92, 66, 186>> - }, - metadata: %{ - banned_unitil: 0, - delegators_count: 0, - is_active: true, - is_banned: false, - is_validator: true, - mining_address: %Explorer.Chain.Hash{ - byte_count: 20, - bytes: <<82, 45, 243, 150, 174, 112, 160, 88, 189, 105, 119, 132, 8, 99, 15, 219, 2, 51, 137, 178>> - }, - retries_count: 1, - staked_amount: 0, - was_banned_count: 0, - was_validator_count: 1 - }, - name: "anonymous", - primary: true - } - ] + pools = [pool1, pool2, pool3, pool4] = build_list(4, :staking_pool) assert {:ok, %{insert_staking_pools: list}} = run_changes(pools) assert Enum.count(list) == Enum.count(pools) + + saved_list = + Explorer.Chain.Address.Name + |> Repo.all() + |> Enum.reduce(%{}, fn pool, acc -> + Map.put(acc, pool.address_hash, pool) + end) + + assert saved_list[pool1.address_hash].metadata["staked_ratio"] == 0.25 + assert saved_list[pool2.address_hash].metadata["staked_ratio"] == 0.25 + assert saved_list[pool3.address_hash].metadata["staked_ratio"] == 0.25 + assert saved_list[pool4.address_hash].metadata["staked_ratio"] == 0.25 end end diff --git a/apps/explorer/test/explorer/chain/internal_transaction_test.exs b/apps/explorer/test/explorer/chain/internal_transaction_test.exs index 54ace519bd..fc3977a998 100644 --- a/apps/explorer/test/explorer/chain/internal_transaction_test.exs +++ b/apps/explorer/test/explorer/chain/internal_transaction_test.exs @@ -1,7 +1,7 @@ defmodule Explorer.Chain.InternalTransactionTest do use Explorer.DataCase - alias Explorer.Chain.{InternalTransaction, Wei} + alias Explorer.Chain.{Data, InternalTransaction, Wei} alias Explorer.Factory import EthereumJSONRPC, only: [integer_to_quantity: 1] @@ -173,7 +173,7 @@ defmodule Explorer.Chain.InternalTransactionTest do end test "it correctly formats a create" do - contract_code = Factory.contract_code_info().bytecode + {:ok, contract_code} = Data.cast(Factory.contract_code_info().bytecode) contract_address = Factory.address_hash() from = Factory.address_hash() gas = 50_000 diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index 4c030a4db1..115b07e066 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -609,4 +609,24 @@ defmodule Explorer.Factory do user: build(:user) } end + + def staking_pool_factory do + %{ + address_hash: address_hash(), + metadata: %{ + banned_unitil: 0, + delegators_count: 0, + is_active: true, + is_banned: false, + is_validator: true, + mining_address: address_hash(), + retries_count: 1, + staked_amount: 25, + was_banned_count: 0, + was_validator_count: 1 + }, + name: "anonymous", + primary: true + } + end end