diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3d0968625..60c0d36f9e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
- [#4931](https://github.com/blockscout/blockscout/pull/4931) - Web3 modal with Wallet Connect for Write contract page and Staking Dapp
### Fixes
+- [#4979](https://github.com/blockscout/blockscout/pull/4979) - Store total gas_used in addresses table
- [#4977](https://github.com/blockscout/blockscout/pull/4977) - Export token transfers on address: include transfers on contract itself
- [#4976](https://github.com/blockscout/blockscout/pull/4976) - Handle :econnrefused in pending transactions fetcher
- [#4965](https://github.com/blockscout/blockscout/pull/4965) - Fix search field appearance on medium size screens
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
index 7d917be3b1..7e7b146c01 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
@@ -84,15 +84,14 @@ defmodule BlockScoutWeb.AddressController do
def address_counters(conn, %{"id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
- {transaction_count, token_transfer_count, gas_usage_count, validation_count, crc_total_worth} =
- address_counters(address)
+ {transaction_count, token_transfer_count, validation_count, crc_total_worth} = address_counters(address)
- gas_usage_count_formatted = if gas_usage_count, do: gas_usage_count, else: 0
+ address_gas_usage_from_db = address.gas_used || 0
json(conn, %{
transaction_count: transaction_count,
token_transfer_count: token_transfer_count,
- gas_usage_count: gas_usage_count_formatted,
+ gas_usage_count: address_gas_usage_from_db,
validation_count: validation_count,
crc_total_worth: crc_total_worth
})
@@ -119,11 +118,6 @@ defmodule BlockScoutWeb.AddressController do
token_transfers_count(address)
end)
- gas_usage_count_task =
- Task.async(fn ->
- gas_usage_count(address)
- end)
-
validation_count_task =
Task.async(fn ->
validation_count(address)
@@ -134,14 +128,17 @@ defmodule BlockScoutWeb.AddressController do
crc_total_worth(address)
end)
+ Task.start_link(fn ->
+ gas_usage_count(address)
+ end)
+
[
transaction_count_task,
token_transfer_count_task,
- gas_usage_count_task,
validation_count_task,
crc_total_worth_task
]
- |> Task.yield_many(:timer.seconds(60))
+ |> Task.yield_many(:infinity)
|> Enum.map(fn {_task, res} ->
case res do
{:ok, result} ->
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
index 84e4f6a784..0449eb1707 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
@@ -242,7 +242,11 @@
- <%= render BlockScoutWeb.CommonComponentsView, "_loading_spinner.html", loading_text: gettext("Fetching gas used...") %>
+ <%= if @address.gas_used do %>
+ <%= Number.Delimit.number_to_delimited(@address.gas_used, precision: 0) %>
+ <% else %>
+ <%= render BlockScoutWeb.CommonComponentsView, "_loading_spinner.html", loading_text: gettext("Fetching gas used...") %>
+ <% end %>
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot
index 9478570c66..39d8402344 100644
--- a/apps/block_scout_web/priv/gettext/default.pot
+++ b/apps/block_scout_web/priv/gettext/default.pot
@@ -398,7 +398,7 @@ msgid "Block number containing the transaction."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:254
+#: lib/block_scout_web/templates/address/overview.html.eex:258
msgid "Block number in which the address was updated."
msgstr ""
@@ -420,7 +420,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:48
-#: lib/block_scout_web/templates/address/overview.html.eex:271 lib/block_scout_web/templates/address_validation/index.html.eex:15
+#: lib/block_scout_web/templates/address/overview.html.eex:275 lib/block_scout_web/templates/address_validation/index.html.eex:15
#: lib/block_scout_web/views/address_view.ex:356
msgid "Blocks Validated"
msgstr ""
@@ -1151,7 +1151,7 @@ msgid "Favorites"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:245
+#: lib/block_scout_web/templates/address/overview.html.eex:248
msgid "Fetching gas used..."
msgstr ""
@@ -1220,7 +1220,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:240
-#: lib/block_scout_web/templates/address/overview.html.eex:270
+#: lib/block_scout_web/templates/address/overview.html.eex:274
msgid "Gas used by the address."
msgstr ""
@@ -1377,7 +1377,7 @@ msgid "JSON RPC error"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:255
+#: lib/block_scout_web/templates/address/overview.html.eex:259
msgid "Last Balance Update"
msgstr ""
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 9478570c66..39d8402344 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
@@ -398,7 +398,7 @@ msgid "Block number containing the transaction."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:254
+#: lib/block_scout_web/templates/address/overview.html.eex:258
msgid "Block number in which the address was updated."
msgstr ""
@@ -420,7 +420,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:48
-#: lib/block_scout_web/templates/address/overview.html.eex:271 lib/block_scout_web/templates/address_validation/index.html.eex:15
+#: lib/block_scout_web/templates/address/overview.html.eex:275 lib/block_scout_web/templates/address_validation/index.html.eex:15
#: lib/block_scout_web/views/address_view.ex:356
msgid "Blocks Validated"
msgstr ""
@@ -1151,7 +1151,7 @@ msgid "Favorites"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:245
+#: lib/block_scout_web/templates/address/overview.html.eex:248
msgid "Fetching gas used..."
msgstr ""
@@ -1220,7 +1220,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:240
-#: lib/block_scout_web/templates/address/overview.html.eex:270
+#: lib/block_scout_web/templates/address/overview.html.eex:274
msgid "Gas used by the address."
msgstr ""
@@ -1377,7 +1377,7 @@ msgid "JSON RPC error"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:255
+#: lib/block_scout_web/templates/address/overview.html.eex:259
msgid "Last Balance Update"
msgstr ""
diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex
index 5a621035c1..e4e0040753 100644
--- a/apps/explorer/lib/explorer/chain.ex
+++ b/apps/explorer/lib/explorer/chain.ex
@@ -867,7 +867,7 @@ defmodule Explorer.Chain do
Repo.aggregate(to_address_query, :count, :hash, timeout: :infinity)
end
- @spec address_to_incoming_transaction_gas_usage(Hash.Address.t()) :: non_neg_integer()
+ @spec address_to_incoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil
def address_to_incoming_transaction_gas_usage(address_hash) do
to_address_query =
from(
@@ -878,7 +878,7 @@ defmodule Explorer.Chain do
Repo.aggregate(to_address_query, :sum, :gas_used, timeout: :infinity)
end
- @spec address_to_outcoming_transaction_gas_usage(Hash.Address.t()) :: non_neg_integer()
+ @spec address_to_outcoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil
def address_to_outcoming_transaction_gas_usage(address_hash) do
to_address_query =
from(
@@ -2527,12 +2527,12 @@ defmodule Explorer.Chain do
Repo.aggregate(query, :count, timeout: :infinity)
end
- @spec address_to_gas_usage_count(Address.t()) :: non_neg_integer()
+ @spec address_to_gas_usage_count(Address.t()) :: Decimal.t() | nil
def address_to_gas_usage_count(address) do
if contract?(address) do
incoming_transaction_gas_usage = address_to_incoming_transaction_gas_usage(address.hash)
- if incoming_transaction_gas_usage == 0 do
+ if Decimal.cmp(incoming_transaction_gas_usage, 0) == :eq do
address_to_outcoming_transaction_gas_usage(address.hash)
else
incoming_transaction_gas_usage
diff --git a/apps/explorer/lib/explorer/chain/address.ex b/apps/explorer/lib/explorer/chain/address.ex
index c310600789..7382cb7d07 100644
--- a/apps/explorer/lib/explorer/chain/address.ex
+++ b/apps/explorer/lib/explorer/chain/address.ex
@@ -25,7 +25,7 @@ defmodule Explorer.Chain.Address do
alias Explorer.Chain.Cache.NetVersion
- @optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce decompiled verified)a
+ @optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce decompiled verified gas_used)a
@required_attrs ~w(hash)a
@allowed_attrs @optional_attrs ++ @required_attrs
@@ -58,7 +58,8 @@ defmodule Explorer.Chain.Address do
contracts_creation_transaction: %Ecto.Association.NotLoaded{} | Transaction.t(),
inserted_at: DateTime.t(),
updated_at: DateTime.t(),
- nonce: non_neg_integer() | nil
+ nonce: non_neg_integer() | nil,
+ gas_used: non_neg_integer() | nil
}
@derive {Poison.Encoder,
@@ -95,6 +96,7 @@ defmodule Explorer.Chain.Address do
field(:verified, :boolean, default: false)
field(:has_decompiled_code?, :boolean, virtual: true)
field(:stale?, :boolean, virtual: true)
+ field(:gas_used, :integer)
has_one(:smart_contract, SmartContract)
has_one(:token, Token, foreign_key: :contract_address_hash)
diff --git a/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex b/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex
index fbffbe1ccf..5dd1a825b1 100644
--- a/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex
+++ b/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex
@@ -4,7 +4,8 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
"""
use GenServer
- alias Explorer.Chain
+ alias Ecto.Changeset
+ alias Explorer.{Chain, Repo}
@cache_name :address_transactions_gas_usage_counter
@last_update_key "last_update"
@@ -16,7 +17,7 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
read_concurrency: true
]
- config = Application.get_env(:explorer, Explorer.Counters.AddressTransactionsGasUsageCounter)
+ config = Application.get_env(:explorer, __MODULE__)
@enable_consolidation Keyword.get(config, :enable_consolidation)
@spec start_link(term()) :: GenServer.on_start()
@@ -51,7 +52,7 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
update_cache(address)
end
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
fetch_from_cache("hash_#{address_hash_string}")
end
@@ -59,7 +60,7 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
defp cache_expired?(address) do
cache_period = address_transactions_gas_usage_counter_cache_period()
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}")
cond do
@@ -70,10 +71,11 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
end
defp update_cache(address) do
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time())
new_data = Chain.address_to_gas_usage_count(address)
put_into_cache("hash_#{address_hash_string}", new_data)
+ put_into_db(address, new_data)
end
defp fetch_from_cache(key) do
@@ -90,8 +92,12 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
:ets.insert(@cache_name, {key, value})
end
- defp get_address_hash_string(address) do
- Base.encode16(address.hash.bytes, case: :lower)
+ defp put_into_db(_address, value) when is_nil(value), do: :ignore
+
+ defp put_into_db(address, value) do
+ address
+ |> Changeset.change(%{gas_used: Decimal.to_integer(value)})
+ |> Repo.update()
end
defp current_time do
diff --git a/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex b/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex
index c5488afd99..9df1ea7ebd 100644
--- a/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex
+++ b/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex
@@ -51,7 +51,7 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do
update_cache(address)
end
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
fetch_from_cache("hash_#{address_hash_string}")
end
@@ -59,7 +59,7 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do
defp cache_expired?(address) do
cache_period = address_token_transfers_counter_cache_period()
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}")
cond do
@@ -70,7 +70,7 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do
end
defp update_cache(address) do
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time())
new_data = Chain.address_to_token_transfer_count(address)
put_into_cache("hash_#{address_hash_string}", new_data)
@@ -90,10 +90,6 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do
:ets.insert(@cache_name, {key, value})
end
- defp get_address_hash_string(address) do
- Base.encode16(address.hash.bytes, case: :lower)
- end
-
defp current_time do
utc_now = DateTime.utc_now()
diff --git a/apps/explorer/lib/explorer/counters/address_transactions_counter.ex b/apps/explorer/lib/explorer/counters/address_transactions_counter.ex
index ac73176e45..487f04e7eb 100644
--- a/apps/explorer/lib/explorer/counters/address_transactions_counter.ex
+++ b/apps/explorer/lib/explorer/counters/address_transactions_counter.ex
@@ -51,7 +51,7 @@ defmodule Explorer.Counters.AddressTransactionsCounter do
update_cache(address)
end
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
fetch_from_cache("hash_#{address_hash_string}")
end
@@ -59,7 +59,7 @@ defmodule Explorer.Counters.AddressTransactionsCounter do
defp cache_expired?(address) do
cache_period = address_transactions_counter_cache_period()
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}")
cond do
@@ -70,7 +70,7 @@ defmodule Explorer.Counters.AddressTransactionsCounter do
end
defp update_cache(address) do
- address_hash_string = get_address_hash_string(address)
+ address_hash_string = to_string(address.hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time())
new_data = Chain.address_to_transaction_count(address)
put_into_cache("hash_#{address_hash_string}", new_data)
@@ -90,10 +90,6 @@ defmodule Explorer.Counters.AddressTransactionsCounter do
:ets.insert(@cache_name, {key, value})
end
- defp get_address_hash_string(address) do
- Base.encode16(address.hash.bytes, case: :lower)
- end
-
defp current_time do
utc_now = DateTime.utc_now()
diff --git a/apps/explorer/lib/explorer/counters/token_holders_counter.ex b/apps/explorer/lib/explorer/counters/token_holders_counter.ex
index 00681b985f..3b3380eea5 100644
--- a/apps/explorer/lib/explorer/counters/token_holders_counter.ex
+++ b/apps/explorer/lib/explorer/counters/token_holders_counter.ex
@@ -53,7 +53,7 @@ defmodule Explorer.Counters.TokenHoldersCounter do
end)
end
- address_hash_string = get_address_hash_string(address_hash)
+ address_hash_string = to_string(address_hash)
fetch_from_cache("hash_#{address_hash_string}")
end
@@ -61,7 +61,7 @@ defmodule Explorer.Counters.TokenHoldersCounter do
defp cache_expired?(address_hash) do
cache_period = token_holders_counter_cache_period()
- address_hash_string = get_address_hash_string(address_hash)
+ address_hash_string = to_string(address_hash)
updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}")
cond do
@@ -72,7 +72,7 @@ defmodule Explorer.Counters.TokenHoldersCounter do
end
defp update_cache(address_hash) do
- address_hash_string = get_address_hash_string(address_hash)
+ address_hash_string = to_string(address_hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time())
new_data = Chain.count_token_holders_from_token_hash(address_hash)
put_into_cache("hash_#{address_hash_string}", new_data)
@@ -92,10 +92,6 @@ defmodule Explorer.Counters.TokenHoldersCounter do
:ets.insert(@cache_name, {key, value})
end
- defp get_address_hash_string(address_hash) do
- Base.encode16(address_hash.bytes, case: :lower)
- end
-
defp current_time do
utc_now = DateTime.utc_now()
diff --git a/apps/explorer/lib/explorer/counters/token_transfers_counter.ex b/apps/explorer/lib/explorer/counters/token_transfers_counter.ex
index 2026be6519..ce8eb7f854 100644
--- a/apps/explorer/lib/explorer/counters/token_transfers_counter.ex
+++ b/apps/explorer/lib/explorer/counters/token_transfers_counter.ex
@@ -53,7 +53,7 @@ defmodule Explorer.Counters.TokenTransfersCounter do
end)
end
- address_hash_string = get_address_hash_string(address_hash)
+ address_hash_string = to_string(address_hash)
fetch_from_cache("hash_#{address_hash_string}")
end
@@ -61,7 +61,7 @@ defmodule Explorer.Counters.TokenTransfersCounter do
defp cache_expired?(address_hash) do
cache_period = token_transfers_counter_cache_period()
- address_hash_string = get_address_hash_string(address_hash)
+ address_hash_string = to_string(address_hash)
updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}")
cond do
@@ -72,7 +72,7 @@ defmodule Explorer.Counters.TokenTransfersCounter do
end
defp update_cache(address_hash) do
- address_hash_string = get_address_hash_string(address_hash)
+ address_hash_string = to_string(address_hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time())
new_data = Chain.count_token_transfers_from_token_hash(address_hash)
put_into_cache("hash_#{address_hash_string}", new_data)
@@ -92,10 +92,6 @@ defmodule Explorer.Counters.TokenTransfersCounter do
:ets.insert(@cache_name, {key, value})
end
- defp get_address_hash_string(address_hash) do
- Base.encode16(address_hash.bytes, case: :lower)
- end
-
defp current_time do
utc_now = DateTime.utc_now()
diff --git a/apps/explorer/priv/repo/migrations/20211204184037_address_add_gas_used.exs b/apps/explorer/priv/repo/migrations/20211204184037_address_add_gas_used.exs
new file mode 100644
index 0000000000..0494e0a9e6
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20211204184037_address_add_gas_used.exs
@@ -0,0 +1,9 @@
+defmodule Explorer.Repo.Migrations.AddressAddGasUsed do
+ use Ecto.Migration
+
+ def change do
+ alter table(:addresses) do
+ add(:gas_used, :integer, null: true)
+ end
+ end
+end
diff --git a/apps/explorer/priv/repo/migrations/20211206071033_modify_address_gas_used_bigint.exs b/apps/explorer/priv/repo/migrations/20211206071033_modify_address_gas_used_bigint.exs
new file mode 100644
index 0000000000..5fecbe5c32
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20211206071033_modify_address_gas_used_bigint.exs
@@ -0,0 +1,15 @@
+defmodule Explorer.Repo.Migrations.ModifyAddressGasUsedBignit do
+ use Ecto.Migration
+
+ def up do
+ alter table(:addresses) do
+ modify(:gas_used, :bigint)
+ end
+ end
+
+ def down do
+ alter table(:addresses) do
+ modify(:gas_used, :integer)
+ end
+ end
+end