Merge pull request #3149 from poanetwork/vb-error-reason

Display and store revert reason of tx on demand
pull/3152/head
Victor Baranov 5 years ago committed by GitHub
commit c69e26b092
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .dialyzer-ignore
  2. 1
      CHANGELOG.md
  3. 18
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex
  4. 12
      apps/block_scout_web/lib/block_scout_web/etherscan.ex
  5. 8
      apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex
  6. 1
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/transaction_view.ex
  7. 4
      apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
  8. 79
      apps/block_scout_web/priv/gettext/default.pot
  9. 79
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  10. 183
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/transaction_controller_test.exs
  11. 16
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex
  12. 64
      apps/explorer/lib/explorer/chain.ex
  13. 8
      apps/explorer/lib/explorer/chain/transaction.ex
  14. 1
      apps/explorer/lib/explorer/etherscan.ex
  15. 9
      apps/explorer/priv/repo/migrations/20200608075122_alter_transactions_add_error_reason.exs
  16. 28
      apps/explorer/test/explorer/chain_test.exs
  17. 8
      apps/indexer/test/indexer/fetcher/coin_balance_test.exs

@ -12,4 +12,6 @@ apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The pattern 'fa
apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The test 5 == 'infinity' can never evaluate to 'true'
lib/block_scout_web/router.ex:1
lib/phoenix/router.ex:324
lib/block_scout_web/views/layout_view.ex:143
lib/block_scout_web/views/layout_view.ex:143
lib/block_scout_web/controllers/api/rpc/transaction_controller.ex:21
lib/block_scout_web/controllers/api/rpc/transaction_controller.ex:22

@ -1,6 +1,7 @@
## Current
### Features
- [#3149](https://github.com/poanetwork/blockscout/pull/3149) - Display and store revert reason of tx on demand at transaction details page and at gettxinfo API endpoint.
### Fixes

@ -5,16 +5,30 @@ defmodule BlockScoutWeb.API.RPC.TransactionController do
alias Explorer.Chain
alias Explorer.Chain.Transaction
def gettxinfo(conn, params) do
with {:txhash_param, {:ok, txhash_param}} <- fetch_txhash(params),
{:format, {:ok, transaction_hash}} <- to_transaction_hash(txhash_param),
{:transaction, {:ok, transaction}} <- transaction_from_hash(transaction_hash),
{:transaction, {:ok, %Transaction{revert_reason: revert_reason, error: error} = transaction}} <-
transaction_from_hash(transaction_hash),
paging_options <- paging_options(params) do
logs = Chain.transaction_to_logs(transaction_hash, paging_options)
{logs, next_page} = split_list_by_page(logs)
transaction_updated =
if error == "Reverted" do
if revert_reason == nil do
%Transaction{transaction | revert_reason: Chain.fetch_tx_revert_reason(transaction)}
else
transaction
end
else
transaction
end
render(conn, :gettxinfo, %{
transaction: transaction,
transaction: transaction_updated,
block_height: Chain.block_height(),
logs: logs,
next_page_params: next_page_params(next_page, logs, params)

@ -470,7 +470,8 @@ defmodule BlockScoutWeb.Etherscan do
"success" => true,
"timeStamp" => "1541018182",
"to" => "0x000000000000000000000000000000000000000d",
"value" => "67612"
"value" => "67612",
revertReason: "No credit of that type"
}
}
@ -609,6 +610,12 @@ defmodule BlockScoutWeb.Etherscan do
example: ~s("18")
}
@revert_reason_type %{
type: "revert_reason",
definition: "Revert reason of transaction.",
example: ~s("No credit of that type")
}
@logs_details %{
name: "Log Detail",
fields: %{
@ -1010,7 +1017,8 @@ defmodule BlockScoutWeb.Etherscan do
logs: %{
type: "array",
array_type: @logs_details
}
},
revertReason: @revert_reason_type
}
}

@ -53,6 +53,14 @@
<!-- Verify in other explorers -->
<!-- <%= render BlockScoutWeb.AddressView, "_verify_other_explorers.html", hash: hash(@transaction), type: "tx" %> -->
<hr>
<%= if status == {:error, "Reverted"} do %>
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Revert reason" %> </dt>
<dd class="col-sm-9" data-selector="block-number">
<%= BlockScoutWeb.TransactionView.transaction_revert_reason(@transaction) %>
</dd>
</dl>
<% end %>
<!-- Block Hash -->
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Block Number" %> </dt>

@ -70,6 +70,7 @@ defmodule BlockScoutWeb.API.RPC.TransactionView do
"gasUsed" => "#{transaction.gas_used}",
"gasPrice" => "#{transaction.gas_price.value}",
"logs" => Enum.map(logs, &prepare_log/1),
"revertReason" => "#{transaction.revert_reason}",
"next_page_params" => next_page_params
}
end

@ -237,6 +237,10 @@ defmodule BlockScoutWeb.TransactionView do
Chain.transaction_to_status(transaction)
end
def transaction_revert_reason(transaction) do
Chain.transaction_to_revert_reason(transaction)
end
def empty_exchange_rate?(exchange_rate) do
Token.null?(exchange_rate)
end

@ -13,7 +13,7 @@ msgstr[0] ""
msgstr[1] ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:196
#: lib/block_scout_web/templates/transaction/overview.html.eex:204
msgid " Token Transfer"
msgstr ""
@ -59,7 +59,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:247
#: lib/block_scout_web/views/transaction_view.ex:251
msgid "(Awaiting internal transactions for status)"
msgstr ""
@ -193,7 +193,7 @@ msgid "Block %{block_number} - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:72
#: lib/block_scout_web/templates/transaction/overview.html.eex:80
msgid "Block Confirmations"
msgstr ""
@ -213,7 +213,7 @@ msgid "Block Mined, awaiting import..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:58
#: lib/block_scout_web/templates/transaction/overview.html.eex:66
msgid "Block Number"
msgstr ""
@ -355,12 +355,12 @@ msgid "Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:336
#: lib/block_scout_web/views/transaction_view.ex:340
msgid "Contract Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:333
#: lib/block_scout_web/views/transaction_view.ex:337
msgid "Contract Creation"
msgstr ""
@ -621,12 +621,12 @@ msgid "Error trying to fetch balances."
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:251
#: lib/block_scout_web/views/transaction_view.ex:255
msgid "Error: %{reason}"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:249
#: lib/block_scout_web/views/transaction_view.ex:253
msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
@ -646,8 +646,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/app.html.eex:32
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:29
#: lib/block_scout_web/templates/transaction/overview.html.eex:181
#: lib/block_scout_web/templates/transaction/overview.html.eex:255
#: lib/block_scout_web/templates/transaction/overview.html.eex:189
#: lib/block_scout_web/templates/transaction/overview.html.eex:263
#: lib/block_scout_web/views/wei_helpers.ex:78
msgid "Ether"
msgstr ""
@ -666,7 +666,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:73
#: lib/block_scout_web/templates/transaction/overview.html.eex:79
#: lib/block_scout_web/templates/transaction/overview.html.eex:87
msgid "Nonce"
msgstr ""
@ -753,8 +753,8 @@ msgid "Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:115
#: lib/block_scout_web/templates/transaction/overview.html.eex:119
#: lib/block_scout_web/templates/transaction/overview.html.eex:123
#: lib/block_scout_web/templates/transaction/overview.html.eex:127
msgid "Hex (Default)"
msgstr ""
@ -776,7 +776,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:248
#: lib/block_scout_web/views/transaction_view.ex:252
msgid "Success"
msgstr ""
@ -789,7 +789,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:21
#: lib/block_scout_web/templates/transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/overview.html.eex:84
#: lib/block_scout_web/templates/transaction/overview.html.eex:92
msgid "TX Fee"
msgstr ""
@ -891,7 +891,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:12
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:10
#: lib/block_scout_web/views/transaction_view.ex:329
#: lib/block_scout_web/views/transaction_view.ex:333
msgid "Token Transfer"
msgstr ""
@ -906,7 +906,7 @@ msgstr ""
#: lib/block_scout_web/views/address_view.ex:325
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:98
#: lib/block_scout_web/views/tokens/overview_view.ex:35
#: lib/block_scout_web/views/transaction_view.ex:390
#: lib/block_scout_web/views/transaction_view.ex:394
msgid "Token Transfers"
msgstr ""
@ -922,7 +922,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18
#: lib/block_scout_web/views/transaction_view.ex:339
#: lib/block_scout_web/views/transaction_view.ex:343
msgid "Transaction"
msgstr ""
@ -1005,7 +1005,7 @@ msgid "License ID"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:283
#: lib/block_scout_web/templates/transaction/overview.html.eex:291
msgid "Limit"
msgstr ""
@ -1159,8 +1159,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:59
#: lib/block_scout_web/views/transaction_view.ex:246
#: lib/block_scout_web/views/transaction_view.ex:280
#: lib/block_scout_web/views/transaction_view.ex:250
#: lib/block_scout_web/views/transaction_view.ex:284
msgid "Pending"
msgstr ""
@ -1201,14 +1201,14 @@ msgid "RPC"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:109
#: lib/block_scout_web/templates/transaction/overview.html.eex:117
msgid "Raw Input"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:7
#: lib/block_scout_web/views/transaction_view.ex:393
#: lib/block_scout_web/views/transaction_view.ex:397
msgid "Raw Trace"
msgstr ""
@ -1488,7 +1488,7 @@ msgid "Transaction Inputs"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:101
#: lib/block_scout_web/templates/transaction/overview.html.eex:109
msgid "Transaction Speed"
msgstr ""
@ -1518,7 +1518,7 @@ msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:122
#: lib/block_scout_web/templates/transaction/overview.html.eex:130
msgid "UTF-8"
msgstr ""
@ -1544,7 +1544,7 @@ msgid "Use the search box to find a hosted network, or select from the list of a
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:277
#: lib/block_scout_web/templates/transaction/overview.html.eex:285
msgid "Used"
msgstr ""
@ -1574,8 +1574,8 @@ msgid "Validator Info"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:181
#: lib/block_scout_web/templates/transaction/overview.html.eex:255
#: lib/block_scout_web/templates/transaction/overview.html.eex:189
#: lib/block_scout_web/templates/transaction/overview.html.eex:263
msgid "Value"
msgstr ""
@ -1752,7 +1752,7 @@ msgid "Decimals"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:273
#: lib/block_scout_web/templates/transaction/overview.html.eex:281
msgid "Gas"
msgstr ""
@ -1799,8 +1799,8 @@ msgid "Transfers"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:134
#: lib/block_scout_web/templates/transaction/overview.html.eex:147
#: lib/block_scout_web/templates/transaction/overview.html.eex:142
#: lib/block_scout_web/templates/transaction/overview.html.eex:155
msgid "Copy Txn Input"
msgstr ""
@ -1838,7 +1838,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:324
#: lib/block_scout_web/views/transaction_view.ex:391
#: lib/block_scout_web/views/transaction_view.ex:395
msgid "Internal Transactions"
msgstr ""
@ -1848,7 +1848,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:331
#: lib/block_scout_web/views/transaction_view.ex:392
#: lib/block_scout_web/views/transaction_view.ex:396
msgid "Logs"
msgstr ""
@ -1881,26 +1881,26 @@ msgid "Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:232
#: lib/block_scout_web/templates/transaction/overview.html.eex:240
msgid " Token Burning"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:8
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:6
#: lib/block_scout_web/views/transaction_view.ex:328
#: lib/block_scout_web/views/transaction_view.ex:332
msgid "Token Burning"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:214
#: lib/block_scout_web/templates/transaction/overview.html.eex:222
msgid " Token Minting"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:10
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:327
#: lib/block_scout_web/views/transaction_view.ex:331
msgid "Token Minting"
msgstr ""
@ -1908,3 +1908,8 @@ msgstr ""
#: lib/block_scout_web/views/block_view.ex:62
msgid "Chore Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:58
msgid "Revert reason"
msgstr ""

@ -13,7 +13,7 @@ msgstr[0] ""
msgstr[1] ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:196
#: lib/block_scout_web/templates/transaction/overview.html.eex:204
msgid " Token Transfer"
msgstr ""
@ -59,7 +59,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:247
#: lib/block_scout_web/views/transaction_view.ex:251
msgid "(Awaiting internal transactions for status)"
msgstr ""
@ -193,7 +193,7 @@ msgid "Block %{block_number} - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:72
#: lib/block_scout_web/templates/transaction/overview.html.eex:80
msgid "Block Confirmations"
msgstr ""
@ -213,7 +213,7 @@ msgid "Block Mined, awaiting import..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:58
#: lib/block_scout_web/templates/transaction/overview.html.eex:66
msgid "Block Number"
msgstr ""
@ -355,12 +355,12 @@ msgid "Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:336
#: lib/block_scout_web/views/transaction_view.ex:340
msgid "Contract Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:333
#: lib/block_scout_web/views/transaction_view.ex:337
msgid "Contract Creation"
msgstr ""
@ -621,12 +621,12 @@ msgid "Error trying to fetch balances."
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:251
#: lib/block_scout_web/views/transaction_view.ex:255
msgid "Error: %{reason}"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:249
#: lib/block_scout_web/views/transaction_view.ex:253
msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
@ -646,8 +646,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/app.html.eex:32
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:29
#: lib/block_scout_web/templates/transaction/overview.html.eex:181
#: lib/block_scout_web/templates/transaction/overview.html.eex:255
#: lib/block_scout_web/templates/transaction/overview.html.eex:189
#: lib/block_scout_web/templates/transaction/overview.html.eex:263
#: lib/block_scout_web/views/wei_helpers.ex:78
msgid "Ether"
msgstr ""
@ -666,7 +666,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:73
#: lib/block_scout_web/templates/transaction/overview.html.eex:79
#: lib/block_scout_web/templates/transaction/overview.html.eex:87
msgid "Nonce"
msgstr ""
@ -753,8 +753,8 @@ msgid "Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:115
#: lib/block_scout_web/templates/transaction/overview.html.eex:119
#: lib/block_scout_web/templates/transaction/overview.html.eex:123
#: lib/block_scout_web/templates/transaction/overview.html.eex:127
msgid "Hex (Default)"
msgstr ""
@ -776,7 +776,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:248
#: lib/block_scout_web/views/transaction_view.ex:252
msgid "Success"
msgstr ""
@ -789,7 +789,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:21
#: lib/block_scout_web/templates/transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/overview.html.eex:84
#: lib/block_scout_web/templates/transaction/overview.html.eex:92
msgid "TX Fee"
msgstr ""
@ -891,7 +891,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:12
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:10
#: lib/block_scout_web/views/transaction_view.ex:329
#: lib/block_scout_web/views/transaction_view.ex:333
msgid "Token Transfer"
msgstr ""
@ -906,7 +906,7 @@ msgstr ""
#: lib/block_scout_web/views/address_view.ex:325
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:98
#: lib/block_scout_web/views/tokens/overview_view.ex:35
#: lib/block_scout_web/views/transaction_view.ex:390
#: lib/block_scout_web/views/transaction_view.ex:394
msgid "Token Transfers"
msgstr ""
@ -922,7 +922,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18
#: lib/block_scout_web/views/transaction_view.ex:339
#: lib/block_scout_web/views/transaction_view.ex:343
msgid "Transaction"
msgstr ""
@ -1005,7 +1005,7 @@ msgid "License ID"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:283
#: lib/block_scout_web/templates/transaction/overview.html.eex:291
msgid "Limit"
msgstr ""
@ -1159,8 +1159,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:59
#: lib/block_scout_web/views/transaction_view.ex:246
#: lib/block_scout_web/views/transaction_view.ex:280
#: lib/block_scout_web/views/transaction_view.ex:250
#: lib/block_scout_web/views/transaction_view.ex:284
msgid "Pending"
msgstr ""
@ -1201,14 +1201,14 @@ msgid "RPC"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:109
#: lib/block_scout_web/templates/transaction/overview.html.eex:117
msgid "Raw Input"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:7
#: lib/block_scout_web/views/transaction_view.ex:393
#: lib/block_scout_web/views/transaction_view.ex:397
msgid "Raw Trace"
msgstr ""
@ -1488,7 +1488,7 @@ msgid "Transaction Inputs"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:101
#: lib/block_scout_web/templates/transaction/overview.html.eex:109
msgid "Transaction Speed"
msgstr ""
@ -1518,7 +1518,7 @@ msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:122
#: lib/block_scout_web/templates/transaction/overview.html.eex:130
msgid "UTF-8"
msgstr ""
@ -1544,7 +1544,7 @@ msgid "Use the search box to find a hosted network, or select from the list of a
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:277
#: lib/block_scout_web/templates/transaction/overview.html.eex:285
msgid "Used"
msgstr ""
@ -1574,8 +1574,8 @@ msgid "Validator Info"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:181
#: lib/block_scout_web/templates/transaction/overview.html.eex:255
#: lib/block_scout_web/templates/transaction/overview.html.eex:189
#: lib/block_scout_web/templates/transaction/overview.html.eex:263
msgid "Value"
msgstr ""
@ -1752,7 +1752,7 @@ msgid "Decimals"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:273
#: lib/block_scout_web/templates/transaction/overview.html.eex:281
msgid "Gas"
msgstr ""
@ -1799,8 +1799,8 @@ msgid "Transfers"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:134
#: lib/block_scout_web/templates/transaction/overview.html.eex:147
#: lib/block_scout_web/templates/transaction/overview.html.eex:142
#: lib/block_scout_web/templates/transaction/overview.html.eex:155
msgid "Copy Txn Input"
msgstr ""
@ -1838,7 +1838,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:324
#: lib/block_scout_web/views/transaction_view.ex:391
#: lib/block_scout_web/views/transaction_view.ex:395
msgid "Internal Transactions"
msgstr ""
@ -1848,7 +1848,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:331
#: lib/block_scout_web/views/transaction_view.ex:392
#: lib/block_scout_web/views/transaction_view.ex:396
msgid "Logs"
msgstr ""
@ -1881,26 +1881,26 @@ msgid "Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:232
#: lib/block_scout_web/templates/transaction/overview.html.eex:240
msgid " Token Burning"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:8
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:6
#: lib/block_scout_web/views/transaction_view.ex:328
#: lib/block_scout_web/views/transaction_view.ex:332
msgid "Token Burning"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:214
#: lib/block_scout_web/templates/transaction/overview.html.eex:222
msgid " Token Minting"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:10
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:327
#: lib/block_scout_web/views/transaction_view.ex:331
msgid "Token Minting"
msgstr ""
@ -1908,3 +1908,8 @@ msgstr ""
#: lib/block_scout_web/views/block_view.ex:62
msgid "Chore Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:58
msgid "Revert reason"
msgstr ""

@ -1,6 +1,8 @@
defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
use BlockScoutWeb.ConnCase
import Mox
@moduletag capture_log: true
describe "gettxreceiptstatus" do
@ -520,7 +522,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
"index" => "#{log.index}"
}
],
"next_page_params" => nil
"next_page_params" => nil,
"revertReason" => ""
}
schema =
@ -576,6 +579,184 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
assert response["status"] == "1"
assert response["message"] == "OK"
end
test "with a txhash with revert reason from DB", %{conn: conn} do
block = insert(:block, number: 100)
transaction =
:transaction
|> insert(revert_reason: "No credit of that type")
|> with_block(block)
insert(:address)
params = %{
"module" => "transaction",
"action" => "gettxinfo",
"txhash" => "#{transaction.hash}"
}
assert response =
conn
|> get("/api", params)
|> json_response(200)
assert response["result"]["revertReason"] == "No credit of that type"
assert response["status"] == "1"
assert response["message"] == "OK"
end
test "with a txhash with empty revert reason from DB", %{conn: conn} do
block = insert(:block, number: 100)
transaction =
:transaction
|> insert(revert_reason: "")
|> with_block(block)
insert(:address)
params = %{
"module" => "transaction",
"action" => "gettxinfo",
"txhash" => "#{transaction.hash}"
}
assert response =
conn
|> get("/api", params)
|> json_response(200)
assert response["result"]["revertReason"] == ""
assert response["status"] == "1"
assert response["message"] == "OK"
end
test "with a txhash with revert reason from the archive node", %{conn: conn} do
block = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
transaction =
:transaction
|> insert(
error: "Reverted",
status: :error,
block_hash: block.hash,
block_number: block.number,
cumulative_gas_used: 884_322,
gas_used: 106_025,
index: 0,
hash: "0xac2a7dab94d965893199e7ee01649e2d66f0787a4c558b3118c09e80d4df8269"
)
insert(:address)
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn _json, [] ->
{:error, %{code: -32015, message: "VM execution error.", data: "revert: No credit of that type"}}
end
)
params = %{
"module" => "transaction",
"action" => "gettxinfo",
"txhash" => "#{transaction.hash}"
}
assert response =
conn
|> get("/api", params)
|> json_response(200)
assert response["result"]["revertReason"] == "No credit of that type"
assert response["status"] == "1"
assert response["message"] == "OK"
end
end
test "with a txhash with empty revert reason from the archive node", %{conn: conn} do
block = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
transaction =
:transaction
|> insert(
error: "Reverted",
status: :error,
block_hash: block.hash,
block_number: block.number,
cumulative_gas_used: 884_322,
gas_used: 106_025,
index: 0,
hash: "0xac2a7dab94d965893199e7ee01649e2d66f0787a4c558b3118c09e80d4df8269"
)
insert(:address)
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn _json, [] ->
{:error, %{code: -32015, message: "VM execution error.", data: ""}}
end
)
params = %{
"module" => "transaction",
"action" => "gettxinfo",
"txhash" => "#{transaction.hash}"
}
assert response =
conn
|> get("/api", params)
|> json_response(200)
assert response["result"]["revertReason"] == ""
assert response["status"] == "1"
assert response["message"] == "OK"
end
test "with a txhash with empty revert reason from DB if eth_call doesn't return an error", %{conn: conn} do
block = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
transaction =
:transaction
|> insert(
error: "Reverted",
status: :error,
block_hash: block.hash,
block_number: block.number,
cumulative_gas_used: 884_322,
gas_used: 106_025,
index: 0,
hash: "0xac2a7dab94d965893199e7ee01649e2d66f0787a4c558b3118c09e80d4df8269"
)
insert(:address)
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn _json, [] ->
{:ok}
end
)
params = %{
"module" => "transaction",
"action" => "gettxinfo",
"txhash" => "#{transaction.hash}"
}
assert response =
conn
|> get("/api", params)
|> json_response(200)
assert response["result"]["revertReason"] == ""
assert response["status"] == "1"
assert response["message"] == "OK"
end
defp resolve_schema(result \\ %{}) do

@ -9,7 +9,7 @@ defmodule EthereumJSONRPC.Transaction do
"""
require Logger
import EthereumJSONRPC, only: [quantity_to_integer: 1]
import EthereumJSONRPC, only: [quantity_to_integer: 1, integer_to_quantity: 1, request: 1]
alias EthereumJSONRPC
@ -313,6 +313,20 @@ defmodule EthereumJSONRPC.Transaction do
nil
end
def eth_call_request(id, block_number, data, to, from, gas, gas_price, value) do
block =
case block_number do
nil -> "latest"
block_number -> integer_to_quantity(block_number)
end
request(%{
id: id,
method: "eth_call",
params: [%{to: to, from: from, data: data, gas: gas, gas_price: gas_price, value: value}, block]
})
end
# double check that no new keys are being missed by requiring explicit match for passthrough
# `t:EthereumJSONRPC.address/0` and `t:EthereumJSONRPC.hash/0` pass through as `Explorer.Chain` can verify correct
# hash format

@ -28,6 +28,8 @@ defmodule Explorer.Chain do
alias Ecto.Adapters.SQL
alias Ecto.{Changeset, Multi}
alias EthereumJSONRPC.Transaction, as: EthereumJSONRPCTransaction
alias Explorer.Counters.LastFetchedCounter
alias Explorer.Chain
@ -2715,6 +2717,68 @@ defmodule Explorer.Chain do
def transaction_to_status(%Transaction{status: :error, error: error}) when is_binary(error), do: {:error, error}
def transaction_to_revert_reason(transaction) do
%Transaction{revert_reason: revert_reason} = transaction
if revert_reason == nil do
fetch_tx_revert_reason(transaction)
else
revert_reason
end
end
def fetch_tx_revert_reason(
%Transaction{
block_number: block_number,
to_address_hash: to_address_hash,
from_address_hash: from_address_hash,
input: data,
gas: gas,
gas_price: gas_price,
value: value
} = transaction
) do
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
req =
EthereumJSONRPCTransaction.eth_call_request(
0,
block_number,
data,
to_address_hash,
from_address_hash,
Decimal.to_integer(gas),
Wei.hex_format(gas_price),
Wei.hex_format(value)
)
data =
case EthereumJSONRPC.json_rpc(req, json_rpc_named_arguments) do
{:error, %{data: data}} ->
data
_ ->
""
end
revert_reason_parts = String.split(data, "revert: ")
formatted_revert_reason =
if Enum.count(revert_reason_parts) > 1 do
Enum.at(revert_reason_parts, 1)
else
data
end
if byte_size(formatted_revert_reason) > 0 do
transaction
|> Changeset.change(%{revert_reason: formatted_revert_reason})
|> Repo.update()
end
formatted_revert_reason
end
@doc """
The `t:Explorer.Chain.Transaction.t/0` or `t:Explorer.Chain.InternalTransaction.t/0` `value` of the `transaction` in
`unit`.

@ -30,7 +30,7 @@ defmodule Explorer.Chain.Transaction do
@optional_attrs ~w(block_hash block_number created_contract_address_hash cumulative_gas_used earliest_processing_start
error gas_used index created_contract_code_indexed_at status
to_address_hash)a
to_address_hash revert_reason)a
@required_attrs ~w(from_address_hash gas gas_price hash input nonce r s v value)a
@ -106,6 +106,7 @@ defmodule Explorer.Chain.Transaction do
* `internal_transactions` - transactions (value transfers) created while executing contract used for this
transaction
* `created_contract_code_indexed_at` - when created `address` code was fetched by `Indexer`
* `revert_reason` - revert reason of transaction
| `status` | `contract_creation_address_hash` | `input` | Token Transfer? | `internal_transactions_indexed_at` | `internal_transactions` | Description |
|----------|----------------------------------|------------|-----------------|-------------------------------------------|-------------------------|-----------------------------------------------------------------------------------------------------|
@ -129,6 +130,7 @@ defmodule Explorer.Chain.Transaction do
* `uncles` - uncle blocks where `forks` were collated
* `v` - The V field of the signature.
* `value` - wei transferred from `from_address` to `to_address`
* `revert_reason` - revert reason of transaction
"""
@type t :: %__MODULE__{
block: %Ecto.Association.NotLoaded{} | Block.t() | nil,
@ -159,7 +161,8 @@ defmodule Explorer.Chain.Transaction do
to_address_hash: Hash.Address.t() | nil,
uncles: %Ecto.Association.NotLoaded{} | [Block.t()],
v: v(),
value: Wei.t()
value: Wei.t(),
revert_reason: String.t()
}
@derive {Poison.Encoder,
@ -199,6 +202,7 @@ defmodule Explorer.Chain.Transaction do
field(:status, Status)
field(:v, :decimal)
field(:value, Wei)
field(:revert_reason, :string)
# A transient field for deriving old block hash during transaction upserts.
# Used to force refetch of a block in case a transaction is re-collated

@ -332,6 +332,7 @@ defmodule Explorer.Etherscan do
status
to_address_hash
value
revert_reason
)a
defp list_transactions(address_hash, max_block_number, options) do

@ -0,0 +1,9 @@
defmodule Explorer.Repo.Migrations.AlterTransactionsAddErrorReason do
use Ecto.Migration
def change do
alter table(:transactions) do
add(:revert_reason, :text)
end
end
end

@ -5165,4 +5165,32 @@ defmodule Explorer.ChainTest do
}
end
end
describe "transaction_to_revert_reason/1" do
test "returns correct revert_reason from DB" do
transaction = insert(:transaction, revert_reason: "No credit of that type")
assert Chain.transaction_to_revert_reason(transaction) == "No credit of that type"
end
test "returns correct revert_reason from the archive node" do
transaction =
insert(:transaction,
gas: 27319,
gas_price: "0x1b31d2900",
value: "0x86b3",
input: %Explorer.Chain.Data{bytes: <<1>>}
)
|> with_block(insert(:block, number: 1))
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn _json, [] ->
{:error, %{code: -32015, message: "VM execution error.", data: "revert: No credit of that type"}}
end
)
assert Chain.transaction_to_revert_reason(transaction) == "No credit of that type"
end
end
end

@ -440,8 +440,8 @@ defmodule Indexer.Fetcher.CoinBalanceTest do
{:ok, responses}
end)
bad_block_quantity = integer_to_quantity(bad_block_number)
res_bad = eth_block_number_fake_response(bad_block_quantity)
good_block_quantity = integer_to_quantity(good_block_number)
res_good = eth_block_number_fake_response(good_block_quantity)
EthereumJSONRPC.Mox
|> expect(:json_rpc, fn [
@ -449,11 +449,11 @@ defmodule Indexer.Fetcher.CoinBalanceTest do
id: 0,
jsonrpc: "2.0",
method: "eth_getBlockByNumber",
params: [bad_block_quantity, true]
params: [^good_block_quantity, true]
}
],
[] ->
{:ok, [res_bad]}
{:ok, [res_good]}
end)
assert {:retry, [{^address_hash_bytes, ^bad_block_number}]} =

Loading…
Cancel
Save