diff --git a/CHANGELOG.md b/CHANGELOG.md
index aefcdea38b..697092388e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
## Current
+### Features
+
+### Fixes
+- [#2425](https://github.com/poanetwork/blockscout/pull/2425) - Force to show address view for checksummed address even if it is not in DB
+
+### Chore
+
+
+## 2.0.2-beta
+
### Features
- [#2412](https://github.com/poanetwork/blockscout/pull/2412) - dark theme
- [#2399](https://github.com/poanetwork/blockscout/pull/2399) - decode verified smart contract's logs
@@ -13,13 +23,15 @@
- [#2324](https://github.com/poanetwork/blockscout/pull/2324) - set timeout for loading message on the main page
### Fixes
-- [#2425](https://github.com/poanetwork/blockscout/pull/2425) - Force to show address view for checksummed address even if it is not in DB
+- [#2421](https://github.com/poanetwork/blockscout/pull/2421) - Fix hiding of loader for txs on the main page
+- [#2420](https://github.com/poanetwork/blockscout/pull/2420) - fetch data from cache in healthy endpoint
- [#2416](https://github.com/poanetwork/blockscout/pull/2416) - Fix "page not found" handling in the router
+- [#2413](https://github.com/poanetwork/blockscout/pull/2413) - remove outer tables for decoded data
- [#2410](https://github.com/poanetwork/blockscout/pull/2410) - preload smart contract for logs decoding
- [#2405](https://github.com/poanetwork/blockscout/pull/2405) - added templates for table loader and tile loader
- [#2398](https://github.com/poanetwork/blockscout/pull/2398) - show only one decoded candidate
-- [#2395](https://github.com/poanetwork/blockscout/pull/2395) - new block loading animation
- [#2389](https://github.com/poanetwork/blockscout/pull/2389) - Reduce Lodash lib size (86% of lib methods are not used)
+- [#2388](https://github.com/poanetwork/blockscout/pull/2388) - add create2 support to geth's js tracer
- [#2387](https://github.com/poanetwork/blockscout/pull/2387) - fix not existing keys in transaction json rpc
- [#2378](https://github.com/poanetwork/blockscout/pull/2378) - Page performance: exclude moment.js localization files except EN, remove unused css
- [#2368](https://github.com/poanetwork/blockscout/pull/2368) - add two columns of smart contract info
@@ -38,6 +50,7 @@
- [#2326](https://github.com/poanetwork/blockscout/pull/2326) - fix nested constructor arguments
### Chore
+- [#2422](https://github.com/poanetwork/blockscout/pull/2422) - check if address_id is binary in token_transfers_csv endpoint
- [#2418](https://github.com/poanetwork/blockscout/pull/2418) - Remove parentheses in market cap percentage
- [#2401](https://github.com/poanetwork/blockscout/pull/2401) - add ENV vars to manage updating period of average block time and market history cache
- [#2363](https://github.com/poanetwork/blockscout/pull/2363) - add parameters example for eth rpc
diff --git a/apps/block_scout_web/assets/css/components/_tile.scss b/apps/block_scout_web/assets/css/components/_tile.scss
index 501533ce05..e621e4fd6d 100644
--- a/apps/block_scout_web/assets/css/components/_tile.scss
+++ b/apps/block_scout_web/assets/css/components/_tile.scss
@@ -340,6 +340,9 @@ $tile-body-a-color: #5959d8 !default;
padding-right: 6px;
}
}
+ .tile-type-block {
+ overflow: hidden;
+ }
.row {
@include media-breakpoint-down(lg) {
margin-left: -6px;
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
index 35dad3662c..47100b972e 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
@@ -131,7 +131,7 @@ defmodule BlockScoutWeb.AddressTransactionController do
end
end
- def token_transfers_csv(conn, %{"address_id" => address_hash_string}) do
+ def token_transfers_csv(conn, %{"address_id" => address_hash_string}) when is_binary(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
address
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
index 957dc797be..1e65fa75ba 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
@@ -4,19 +4,22 @@ defmodule BlockScoutWeb.API.V1.HealthController do
alias Explorer.Chain
def health(conn, _) do
- with {:ok, number, timestamp} <- Chain.last_block_status() do
- send_resp(conn, :ok, result(number, timestamp))
+ with {:ok, number, timestamp} <- Chain.last_db_block_status(),
+ {:ok, cache_number, cache_timestamp} <- Chain.last_cache_block_status() do
+ send_resp(conn, :ok, result(number, timestamp, cache_number, cache_timestamp))
else
status -> send_resp(conn, :internal_server_error, error(status))
end
end
- def result(number, timestamp) do
+ def result(number, timestamp, cache_number, cache_timestamp) do
%{
"healthy" => true,
"data" => %{
"latest_block_number" => to_string(number),
- "latest_block_inserted_at" => to_string(timestamp)
+ "latest_block_inserted_at" => to_string(timestamp),
+ "cache_latest_block_number" => to_string(cache_number),
+ "cache_latest_block_inserted_at" => to_string(cache_timestamp)
}
}
|> Jason.encode!()
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/chain/_block.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/chain/_block.html.eex
index 729df59a3c..706d18ec47 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/chain/_block.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/chain/_block.html.eex
@@ -1,172 +1,5 @@
-
-
-
Block Validated, processing...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<%= link(
@block,
class: "tile-title",
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
index 69d1f8b6ed..53b21cb3fa 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
@@ -117,7 +117,9 @@
<%= gettext "Something went wrong, click to retry." %>
- <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
index f009eeb2b3..9e68d7e1bd 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
@@ -1,4 +1,5 @@
-" class="table thead-light table-bordered table-responsive transaction-info-table">
+
+
" class="table thead-light table-bordered">
<%= gettext "Method Id" %>
0x<%= @method_id %>
@@ -7,49 +8,52 @@
Call
<%= @text %>
-
+
+
<%= unless Enum.empty?(@mapping) do %>
- " class="table thead-light table-bordered table-responsive">
-
-
- <%= gettext "Name" %>
- <%= gettext "Type" %>
- <%= gettext "Data" %>
-
- <%= for {name, type, value} <- @mapping do %>
+
+
" class="table thead-light table-bordered">
+
+
+ <%= gettext "Name" %>
+ <%= gettext "Type" %>
+ <%= gettext "Data" %>
-
- <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
- <% :error -> %>
- <%= nil %>
- <% copy_text -> %>
-
-
-
-
-
- <% end %>
-
- <%= name %>
- <%= type %>
-
- <%= case BlockScoutWeb.ABIEncodedValueView.value_html(type, value) do %>
- <% :error -> %>
-
- <%= gettext "Error rendering value" %>
-
- <% value -> %>
- <%= value %>
+ <%= for {name, type, value} <- @mapping do %>
+
+
+ <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
+ <% :error -> %>
+ <%= nil %>
+ <% copy_text -> %>
+
+
+
+
+
<% end %>
-
-
- <% end %>
-
+
+
<%= name %>
+
<%= type %>
+
+ <%= case BlockScoutWeb.ABIEncodedValueView.value_html(type, value) do %>
+ <% :error -> %>
+
+ <%= gettext "Error rendering value" %>
+
+ <% value -> %>
+ <%= value %>
+ <% end %>
+
+
+ <% end %>
+
+
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
index 5a52821601..ff3e46d42a 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
@@ -39,43 +39,45 @@
<%= text %>
- " class="table thead-light table-bordered table-responsive">
-
-
- <%= gettext "Name" %>
- <%= gettext "Type" %>
- <%= gettext "Indexed?" %>
- <%= gettext "Data" %>
-
- <%= for {name, type, indexed?, value} <- mapping do %>
+
+
" class="table thead-light table-bordered">
-
- <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
- <% :error -> %>
- <%= nil %>
- <% copy_text -> %>
-
-
-
-
-
- <% end %>
-
- <%= name %>
- <%= type %>
- <%= indexed? %>
-
- <%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %>
-
-
- <% end %>
-
+
+
<%= gettext "Name" %>
+
<%= gettext "Type" %>
+
<%= gettext "Indexed?" %>
+
<%= gettext "Data" %>
+
+ <%= for {name, type, indexed?, value} <- mapping do %>
+
+
+ <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
+ <% :error -> %>
+ <%= nil %>
+ <% copy_text -> %>
+
+
+
+
+
+ <% end %>
+
+ <%= name %>
+ <%= type %>
+ <%= indexed? %>
+
+ <%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %>
+
+
+ <% end %>
+
+
<% _ -> %>
<%= nil %>
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex b/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
index fe12f04302..46252f72ce 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
@@ -23,6 +23,7 @@ defmodule BlockScoutWeb.InternalTransactionView do
def type(%InternalTransaction{type: :call, call_type: :delegatecall}), do: gettext("Delegate Call")
def type(%InternalTransaction{type: :call, call_type: :staticcall}), do: gettext("Static Call")
def type(%InternalTransaction{type: :create}), do: gettext("Create")
+ def type(%InternalTransaction{type: :create2}), do: gettext("Create2")
def type(%InternalTransaction{type: :selfdestruct}), do: gettext("Self-Destruct")
def type(%InternalTransaction{type: :reward}), do: gettext("Reward")
end
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot
index d413873e85..e356d87df9 100644
--- a/apps/block_scout_web/priv/gettext/default.pot
+++ b/apps/block_scout_web/priv/gettext/default.pot
@@ -34,7 +34,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:21
-#: lib/block_scout_web/templates/chain/_block.html.eex:178
+#: lib/block_scout_web/templates/chain/_block.html.eex:11
msgid "%{count} Transactions"
msgstr ""
@@ -328,15 +328,6 @@ msgstr ""
msgid "Curl"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
-msgid "Data"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@@ -523,7 +514,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121
-#: lib/block_scout_web/templates/chain/_block.html.eex:182
+#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
@@ -558,8 +549,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Name"
msgstr ""
@@ -827,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
-msgid "Topics"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
@@ -1041,14 +1026,7 @@ msgid "Delegate Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/block/_tile.html.eex:47
-#: lib/block_scout_web/templates/chain/_block.html.eex:190
#: lib/block_scout_web/views/internal_transaction_view.ex:27
-msgid "Reward"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct"
msgstr ""
@@ -1136,20 +1114,7 @@ msgid "Decoded"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
-msgid "Indexed?"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
-msgid "Type"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
msgid "Method Id"
msgstr ""
@@ -1160,12 +1125,8 @@ msgid "To see decoded input data, the contract must be verified."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1
-msgid "Transaction Info"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgid "Transaction Inputs"
msgstr ""
@@ -1189,29 +1150,10 @@ msgid "Failed to decode input data."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
-msgid "Copy Value"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
-msgid "Failed to decode log data."
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
-msgid "Log Data"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
@@ -1809,3 +1751,62 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Constructor Arguments"
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59
+msgid "Copy Value"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/views/internal_transaction_view.ex:26
+msgid "Create2"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115
+msgid "Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
+msgid "Failed to decode log data."
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
+msgid "Indexed?"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43
+msgid "Log Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/block/_tile.html.eex:47
+#: lib/block_scout_web/templates/chain/_block.html.eex:23
+#: lib/block_scout_web/views/internal_transaction_view.ex:28
+msgid "Reward"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85
+msgid "Topics"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
+msgid "Type"
+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 b349db9ecf..58e159d0bb 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
@@ -34,7 +34,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:21
-#: lib/block_scout_web/templates/chain/_block.html.eex:178
+#: lib/block_scout_web/templates/chain/_block.html.eex:11
msgid "%{count} Transactions"
msgstr ""
@@ -328,15 +328,6 @@ msgstr ""
msgid "Curl"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
-msgid "Data"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@@ -523,7 +514,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121
-#: lib/block_scout_web/templates/chain/_block.html.eex:182
+#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
@@ -558,8 +549,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Name"
msgstr ""
@@ -827,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
-msgid "Topics"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
@@ -1041,14 +1026,7 @@ msgid "Delegate Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/block/_tile.html.eex:47
-#: lib/block_scout_web/templates/chain/_block.html.eex:190
#: lib/block_scout_web/views/internal_transaction_view.ex:27
-msgid "Reward"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct"
msgstr ""
@@ -1136,20 +1114,7 @@ msgid "Decoded"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
-msgid "Indexed?"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
-msgid "Type"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
msgid "Method Id"
msgstr ""
@@ -1160,12 +1125,8 @@ msgid "To see decoded input data, the contract must be verified."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1
-msgid "Transaction Info"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgid "Transaction Inputs"
msgstr ""
@@ -1189,28 +1150,10 @@ msgid "Failed to decode input data."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value"
msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
-msgid "Copy Value"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
-msgid "Failed to decode log data."
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
-msgid "Log Data"
-msgstr ""
+""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
@@ -1809,3 +1752,62 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Constructor Arguments"
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59
+msgid "Copy Value"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/views/internal_transaction_view.ex:26
+msgid "Create2"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115
+msgid "Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
+msgid "Failed to decode log data."
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
+msgid "Indexed?"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43
+msgid "Log Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/block/_tile.html.eex:47
+#: lib/block_scout_web/templates/chain/_block.html.eex:23
+#: lib/block_scout_web/views/internal_transaction_view.ex:28
+msgid "Reward"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85
+msgid "Topics"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
+msgid "Type"
+msgstr ""
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
index 41735f685a..19631ff746 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
@@ -1,6 +1,15 @@
defmodule BlockScoutWeb.API.V1.HealthControllerTest do
use BlockScoutWeb.ConnCase
+ alias Explorer.{Chain, PagingOptions}
+
+ setup do
+ Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
+ Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
+
+ :ok
+ end
+
describe "GET last_block_status/0" do
test "returns error when there are no blocks in db", %{conn: conn} do
request = get(conn, api_v1_health_path(conn, :health))
@@ -32,19 +41,50 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do
end
test "returns ok when last block is not stale", %{conn: conn} do
- insert(:block, consensus: true, timestamp: DateTime.utc_now())
+ block1 = insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 2)
+ insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
request = get(conn, api_v1_health_path(conn, :health))
assert request.status == 200
+ result = Poison.decode!(request.resp_body)
+
+ assert result["healthy"] == true
+
assert %{
- "healthy" => true,
- "data" => %{
- "latest_block_number" => _,
- "latest_block_inserted_at" => _
- }
- } = Poison.decode!(request.resp_body)
+ "latest_block_number" => to_string(block1.number),
+ "latest_block_inserted_at" => to_string(block1.timestamp),
+ "cache_latest_block_number" => to_string(block1.number),
+ "cache_latest_block_inserted_at" => to_string(block1.timestamp)
+ } == result["data"]
end
end
+
+ test "return error when cache is stale", %{conn: conn} do
+ stale_block = insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50), number: 3)
+ state_block_hash = stale_block.hash
+
+ assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
+
+ insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
+
+ assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
+
+ request = get(conn, api_v1_health_path(conn, :health))
+
+ assert request.status == 500
+
+ assert %{
+ "healthy" => false,
+ "error_code" => 5001,
+ "error_title" => "blocks fetching is stuck",
+ "error_description" =>
+ "There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance",
+ "data" => %{
+ "latest_block_number" => _,
+ "latest_block_inserted_at" => _
+ }
+ } = Poison.decode!(request.resp_body)
+ end
end
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
index 1555ea6c8f..c83b157324 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
@@ -426,13 +426,14 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash,
"index" => index,
"traceAddress" => trace_address,
- "type" => "create" = type,
+ "type" => type,
"from" => from_address_hash,
"error" => error,
"gas" => gas,
"init" => init,
"value" => value
- }) do
+ })
+ when type in ~w(create create2) do
%{
block_number: block_number,
transaction_index: transaction_index,
@@ -454,7 +455,7 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash,
"index" => index,
"traceAddress" => trace_address,
- "type" => "create",
+ "type" => type,
"from" => from_address_hash,
"createdContractAddressHash" => created_contract_address_hash,
"gas" => gas,
@@ -462,14 +463,15 @@ defmodule EthereumJSONRPC.Geth.Call do
"init" => init,
"createdContractCode" => created_contract_code,
"value" => value
- }) do
+ })
+ when type in ~w(create create2) do
%{
block_number: block_number,
transaction_index: transaction_index,
transaction_hash: transaction_hash,
index: index,
trace_address: trace_address,
- type: "create",
+ type: type,
from_address_hash: from_address_hash,
gas: gas,
gas_used: gas_used,
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
index 6545250b4a..cbc43fa71d 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
@@ -113,6 +113,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
end
defp op(%{"op" => "CREATE"} = log, ctx), do: create_op(log, ctx)
+ defp op(%{"op" => "CREATE2"} = log, ctx), do: create_op(log, ctx, "create2")
defp op(%{"op" => "SELFDESTRUCT"} = log, ctx), do: self_destruct_op(log, ctx)
defp op(%{"op" => "CALL"} = log, ctx), do: call_op(log, "call", ctx)
defp op(%{"op" => "CALLCODE"} = log, ctx), do: call_op(log, "callcode", ctx)
@@ -155,7 +156,8 @@ defmodule EthereumJSONRPC.Geth.Tracer do
defp create_op(
%{"stack" => log_stack, "memory" => log_memory},
- %{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx
+ %{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx,
+ type \\ "create"
) do
[value, input_offset, input_length | _] = Enum.reverse(log_stack)
@@ -165,7 +167,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
|> String.slice(quantity_to_integer("0x" <> input_offset) * 2, quantity_to_integer("0x" <> input_length) * 2)
call = %{
- "type" => "create",
+ "type" => type,
"from" => nil,
"traceAddress" => Enum.reverse(trace_address),
"init" => "0x" <> init,
diff --git a/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js b/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
index 15db7d8ff9..5c3c98f871 100644
--- a/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
+++ b/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
@@ -91,6 +91,9 @@
case 'CREATE':
this.createOp(log);
break;
+ case 'CREATE2':
+ this.create2Op(log);
+ break;
case 'SELFDESTRUCT':
this.selfDestructOp(log, db);
break;
@@ -127,7 +130,7 @@
const ret = log.stack.peek(0);
if (!ret.equals(0)) {
- if (call.type === 'create') {
+ if (call.type === 'create' || call.type === 'create2') {
call.createdContractAddressHash = toHex(toAddress(ret.toString(16)));
call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16))));
} else {
@@ -162,6 +165,21 @@
this.callStack.push(call);
},
+ create2Op(log) {
+ const inputOffset = log.stack.peek(1).valueOf();
+ const inputLength = log.stack.peek(2).valueOf();
+ const inputEnd = inputOffset + inputLength;
+ const stackValue = log.stack.peek(0);
+
+ const call = {
+ type: 'create2',
+ from: toHex(log.contract.getAddress()),
+ init: toHex(log.memory.slice(inputOffset, inputEnd)),
+ valueBigInt: bigInt(stackValue.toString(10))
+ };
+ this.callStack.push(call);
+ },
+
selfDestructOp(log, db) {
const contractAddress = log.contract.getAddress();
@@ -243,6 +261,9 @@
case 'CREATE':
result = this.ctxToCreate(ctx, db);
break;
+ case 'CREATE2':
+ result = this.ctxToCreate2(ctx, db);
+ break;
}
return result;
@@ -292,6 +313,22 @@
return result;
},
+ ctxToCreate2(ctx, db) {
+ const result = {
+ type: 'create2',
+ from: toHex(ctx.from),
+ init: toHex(ctx.input),
+ valueBigInt: bigInt(ctx.value.toString(10)),
+ gasBigInt: bigInt(ctx.gas),
+ gasUsedBigInt: bigInt(ctx.gasUsed)
+ };
+
+ this.putBottomChildCalls(result);
+ this.putErrorOrCreatedContract(result, ctx, db);
+
+ return result;
+ },
+
putBottomChildCalls(result) {
const bottomCall = this.bottomCall();
const bottomChildCalls = bottomCall.calls;
@@ -422,4 +459,3 @@
call.gasUsed = '0x' + gasUsedBigInt.toString(16);
}
}
-
diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex
index 46eda15b62..c2e480957d 100644
--- a/apps/explorer/lib/explorer/chain.ex
+++ b/apps/explorer/lib/explorer/chain.ex
@@ -1818,7 +1818,7 @@ defmodule Explorer.Chain do
Repo.one!(query)
end
- def last_block_status do
+ def last_db_block_status do
query =
from(block in Block,
select: {block.number, block.timestamp},
@@ -1827,22 +1827,39 @@ defmodule Explorer.Chain do
limit: 1
)
- case Repo.one(query) do
- nil ->
- {:error, :no_blocks}
+ query
+ |> Repo.one()
+ |> block_status()
+ end
- {number, timestamp} ->
- now = DateTime.utc_now()
- last_block_period = DateTime.diff(now, timestamp, :millisecond)
+ def last_cache_block_status do
+ [
+ paging_options: %PagingOptions{page_size: 1}
+ ]
+ |> list_blocks()
+ |> List.last()
+ |> case do
+ %{timestamp: timestamp, number: number} ->
+ block_status({number, timestamp})
- if last_block_period > Application.get_env(:explorer, :healthy_blocks_period) do
- {:error, number, timestamp}
- else
- {:ok, number, timestamp}
- end
+ _ ->
+ block_status(nil)
end
end
+ defp block_status({number, timestamp}) do
+ now = DateTime.utc_now()
+ last_block_period = DateTime.diff(now, timestamp, :millisecond)
+
+ if last_block_period > Application.get_env(:explorer, :healthy_blocks_period) do
+ {:error, number, timestamp}
+ else
+ {:ok, number, timestamp}
+ end
+ end
+
+ defp block_status(nil), do: {:error, :no_blocks}
+
@doc """
Calculates the ranges of missing consensus blocks in `range`.
diff --git a/apps/explorer/lib/explorer/chain/internal_transaction.ex b/apps/explorer/lib/explorer/chain/internal_transaction.ex
index 1231677a57..77f7d15da2 100644
--- a/apps/explorer/lib/explorer/chain/internal_transaction.ex
+++ b/apps/explorer/lib/explorer/chain/internal_transaction.ex
@@ -392,7 +392,7 @@ defmodule Explorer.Chain.InternalTransaction do
@create_required_fields ~w(from_address_hash gas index init trace_address transaction_hash value)a
@create_allowed_fields @create_optional_fields ++ @create_required_fields
- defp type_changeset(changeset, attrs, :create) do
+ defp type_changeset(changeset, attrs, type) when type in [:create, :create2] do
changeset
|> cast(attrs, @create_allowed_fields)
|> validate_required(@create_required_fields)
@@ -537,7 +537,7 @@ defmodule Explorer.Chain.InternalTransaction do
|> put_raw_call_error_or_result(transaction)
end
- defp internal_transaction_to_raw(%{type: :create} = transaction) do
+ defp internal_transaction_to_raw(%{type: type} = transaction) when type in [:create, :create2] do
%{
from_address_hash: from_address_hash,
gas: gas,
@@ -549,7 +549,7 @@ defmodule Explorer.Chain.InternalTransaction do
action = %{"from" => from_address_hash, "gas" => gas, "init" => init, "value" => value}
%{
- "type" => "create",
+ "type" => Atom.to_string(type),
"action" => Action.to_raw(action),
"traceAddress" => trace_address
}
diff --git a/apps/explorer/lib/explorer/chain/internal_transaction/type.ex b/apps/explorer/lib/explorer/chain/internal_transaction/type.ex
index 4133dcf45f..0a13587afe 100644
--- a/apps/explorer/lib/explorer/chain/internal_transaction/type.ex
+++ b/apps/explorer/lib/explorer/chain/internal_transaction/type.ex
@@ -11,7 +11,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
* `:reward`
* `:selfdestruct`
"""
- @type t :: :call | :create | :reward | :selfdestruct
+ @type t :: :call | :create | :create2 | :reward | :selfdestruct
@doc """
Casts `term` to `t:t/0`
@@ -22,6 +22,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast(:create)
{:ok, :create}
+ iex> Explorer.Chain.InternalTransaction.Type.cast(:create2)
+ {:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast(:reward)
{:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast(:selfdestruct)
@@ -33,6 +35,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast("create")
{:ok, :create}
+ iex> Explorer.Chain.InternalTransaction.Type.cast("create2")
+ {:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast("reward")
{:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast("selfdestruct")
@@ -53,9 +57,10 @@ defmodule Explorer.Chain.InternalTransaction.Type do
"""
@impl Ecto.Type
@spec cast(term()) :: {:ok, t()} | :error
- def cast(t) when t in ~w(call create selfdestruct reward)a, do: {:ok, t}
+ def cast(t) when t in ~w(call create create2 selfdestruct reward)a, do: {:ok, t}
def cast("call"), do: {:ok, :call}
def cast("create"), do: {:ok, :create}
+ def cast("create2"), do: {:ok, :create2}
def cast("reward"), do: {:ok, :reward}
def cast("selfdestruct"), do: {:ok, :selfdestruct}
def cast(_), do: :error
@@ -67,6 +72,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, "call"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:create)
{:ok, "create"}
+ iex> Explorer.Chain.InternalTransaction.Type.dump(:create2)
+ {:ok, "create2"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:reward)
{:ok, "reward"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:selfdestruct)
@@ -87,6 +94,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec dump(term()) :: {:ok, String.t()} | :error
def dump(:call), do: {:ok, "call"}
def dump(:create), do: {:ok, "create"}
+ def dump(:create2), do: {:ok, "create2"}
def dump(:reward), do: {:ok, "reward"}
def dump(:selfdestruct), do: {:ok, "selfdestruct"}
def dump(_), do: :error
@@ -98,6 +106,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.load("create")
{:ok, :create}
+ iex> Explorer.Chain.InternalTransaction.Type.load("create2")
+ {:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.load("reward")
{:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.load("selfdestruct")
@@ -118,6 +128,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec load(term()) :: {:ok, t()} | :error
def load("call"), do: {:ok, :call}
def load("create"), do: {:ok, :create}
+ def load("create2"), do: {:ok, :create2}
def load("reward"), do: {:ok, :reward}
def load("selfdestruct"), do: {:ok, :selfdestruct}
# deprecated
diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs
index 5ee506982b..234252dbe4 100644
--- a/apps/explorer/test/explorer/chain_test.exs
+++ b/apps/explorer/test/explorer/chain_test.exs
@@ -50,21 +50,35 @@ defmodule Explorer.ChainTest do
end
end
- describe "last_block_status/0" do
+ describe "last_db_block_status/0" do
test "return no_blocks errors if db is empty" do
- assert {:error, :no_blocks} = Chain.last_block_status()
+ assert {:error, :no_blocks} = Chain.last_db_block_status()
end
test "returns {:ok, last_block_period} if block is in healthy period" do
insert(:block, consensus: true)
- assert {:ok, _, _} = Chain.last_block_status()
+ assert {:ok, _, _} = Chain.last_db_block_status()
end
test "return {:ok, last_block_period} if block is not in healthy period" do
insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
- assert {:error, _, _} = Chain.last_block_status()
+ assert {:error, _, _} = Chain.last_db_block_status()
+ end
+ end
+
+ describe "last_cache_block_status/0" do
+ test "returns success if cache is not stale" do
+ insert(:block, consensus: true)
+
+ assert {:ok, _, _} = Chain.last_cache_block_status()
+ end
+
+ test "return error if cache is stale" do
+ insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
+
+ assert {:error, _, _} = Chain.last_cache_block_status()
end
end