Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1365452
fix: update revert_reason logic to handle transaction errors more acc…
yavrsky Mar 10, 2026
7487924
feat: add helper functions to identify standard revert reasons
yavrsky Mar 10, 2026
a7843d1
feat: add helper functions to identify standard revert reasons
yavrsky Mar 11, 2026
e9d4850
fix: update error handling in fetch_fair_beneficiaries function
yavrsky Mar 11, 2026
1e2e54e
fix: remove unused burn address hash string
yavrsky Mar 11, 2026
5cf9088
feat: add Skale-specific revert message prefix for better error handling
yavrsky Mar 11, 2026
4cfe693
fix: enhance revert reason handling with fallback for generic outputs
yavrsky Mar 12, 2026
0c7334d
fix: improve revert reason saving logic to exclude specific cases
yavrsky Mar 12, 2026
286265e
fix: add helper function to identify generic revert outputs
yavrsky Mar 12, 2026
87a168c
fix: add fallback for generic revert output handling in error parsing
yavrsky Mar 13, 2026
de4ea60
fix: enhance transaction revert reason fetching logic for SKALE messages
yavrsky Mar 13, 2026
4880ddd
fix: add handling for SKALE revert message prefix to return nil
yavrsky Mar 13, 2026
8b0a130
fix: comment out experimental function due to undefined ConstructorAr…
yavrsky Mar 13, 2026
3b6e8e3
fix: remove comment about function selector length in generic revert …
yavrsky Mar 17, 2026
79dc052
fix: remove commented-out code for SKALE's generic revert message check
yavrsky Mar 17, 2026
623a950
fix: uncomment experimental function for constructor arguments verifi…
yavrsky Mar 17, 2026
4bae03e
fix: add burn address hash string to chain module
yavrsky Mar 17, 2026
1107a32
fix: add FetchedBeneficiaries alias to EthereumJSONRPC.Geth module
yavrsky Mar 17, 2026
0251772
fix: update error handling in fetch_beneficiaries function
yavrsky Mar 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,8 @@ defmodule BlockScoutWeb.API.V2.TransactionView do
end
end

defp revert_reason(status, transaction) do
if is_binary(status) && status |> String.downcase() |> String.contains?("reverted") do
defp revert_reason(_status, transaction) do
if transaction.status == :error do
case TransactionView.transaction_revert_reason(transaction, @api_true) do
{:error, _contract_not_verified, candidates} when candidates != [] ->
{:ok, method_id, text, mapping} = Enum.at(candidates, 0)
Expand All @@ -520,16 +520,29 @@ defmodule BlockScoutWeb.API.V2.TransactionView do
{:ok, method_id, text, mapping} ->
render(__MODULE__, "decoded_input.json", method_id: method_id, text: text, mapping: mapping, error?: true)

{:error, :contract_not_verified, _} ->
nil

_ ->
hex = TransactionView.get_pure_transaction_revert_reason(transaction)
render(__MODULE__, "revert_reason.json", raw: hex)
if is_standard_revert_reason?(hex) do
render(__MODULE__, "revert_reason.json", raw: hex)
else
nil
end
end
end
rescue
_ ->
nil
end

defp is_standard_revert_reason?(hex) when is_binary(hex) do
String.starts_with?(hex, "0x08c379a0") || String.starts_with?(hex, "0x4e487b71")
end

defp is_standard_revert_reason?(_), do: false

@doc """
Prepares decoded transaction info
"""
Expand Down
53 changes: 50 additions & 3 deletions apps/explorer/lib/explorer/chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ defmodule Explorer.Chain do
# Geth-like node
@revert_msg_prefix_5 "execution reverted: "
@revert_msg_prefix_6_empty "execution reverted"
@revert_msg_prefix_7_skale "EVM revert instruction without description message"

@burn_address_hash_str "0x0000000000000000000000000000000000000000"
Comment thread
yavrsky marked this conversation as resolved.

@out_of_gas_msg "Out of gas"

@limit_showing_transactions 10_000
Expand Down Expand Up @@ -3004,7 +3006,14 @@ defmodule Explorer.Chain do
def transaction_to_revert_reason(transaction) do
%Transaction{revert_reason: revert_reason} = transaction

if revert_reason == nil do
should_fetch =
revert_reason == nil ||
revert_reason == "" ||
revert_reason == "0x" ||
revert_reason == @revert_msg_prefix_7_skale ||
String.contains?(revert_reason || "", @revert_msg_prefix_7_skale)

if should_fetch do
fetch_transaction_revert_reason(transaction)
else
revert_reason
Expand Down Expand Up @@ -3032,7 +3041,17 @@ defmodule Explorer.Chain do
revert_reason =
case response do
{:ok, first_trace_params} ->
first_trace_params |> Enum.at(0) |> Map.get(:output, %Data{bytes: <<>>}) |> to_string()
output = first_trace_params |> Enum.at(0) |> Map.get(:output, %Data{bytes: <<>>}) |> to_string()

if output in ["", "0x"] or is_generic_revert_output?(output) do
Logger.debug(fn ->
["Trace returned generic revert for transaction: #{hash_string}, falling back to eth_call"]
end)

fetch_transaction_revert_reason_using_call(transaction)
else
output
end

{:error, reason} ->
Logger.error(fn ->
Expand All @@ -3045,7 +3064,13 @@ defmodule Explorer.Chain do
fetch_transaction_revert_reason_using_call(transaction)
end

if !is_nil(revert_reason) do
should_save =
!is_nil(revert_reason) &&
revert_reason != "" &&
revert_reason != "0x" &&
revert_reason != @revert_msg_prefix_7_skale

if should_save do
transaction
|> Changeset.change(%{revert_reason: revert_reason})
|> Repo.update()
Expand All @@ -3054,6 +3079,18 @@ defmodule Explorer.Chain do
revert_reason
end

defp is_generic_revert_output?(output) when is_binary(output) do
case output do
"0x" <> hex_part when byte_size(hex_part) < 8 ->
true

_ ->
String.match?(output, ~r/^[^0-9a-fA-F]/) or output == "Reverted"
end
end

defp is_generic_revert_output?(_), do: true

defp fetch_transaction_revert_reason_using_call(%Transaction{
block_number: block_number,
to_address_hash: to_address_hash,
Expand Down Expand Up @@ -3105,6 +3142,13 @@ defmodule Explorer.Chain do
Returns `nil` if the revert reason cannot be parsed or error format is unknown.
"""
@spec parse_revert_reason_from_error(any()) :: String.t() | nil
def parse_revert_reason_from_error(%{data: data, message: message}) when is_binary(data) and is_binary(message) do
case format_revert_data(data) do
nil -> format_revert_reason_message(message)
formatted_data -> formatted_data
end
end

def parse_revert_reason_from_error(%{data: data}), do: format_revert_data(data)

def parse_revert_reason_from_error(%{message: message}), do: format_revert_reason_message(message)
Expand Down Expand Up @@ -3144,6 +3188,9 @@ defmodule Explorer.Chain do
@revert_msg_prefix_6_empty ->
""

@revert_msg_prefix_7_skale ->
nil

_ ->
nil
end
Expand Down
Loading