diff --git a/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex b/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
index a6f58ac33e..8fa133550f 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
@@ -48,30 +48,70 @@ defmodule BlockScoutWeb.TransactionView do
{unquote(TokenTransfer.transfer_function_signature()) <> params, ^zero_wei} ->
types = [:address, {:uint, 256}]
- try do
- [address, value] =
- params
- |> Base.decode16!(case: :mixed)
- |> TypeDecoder.decode_raw(types)
+ [address, value] = decode_params(params, types)
- decimal_value = Decimal.new(value)
+ decimal_value = Decimal.new(value)
- Enum.find(token_transfers, fn token_transfer ->
- token_transfer.to_address_hash.bytes == address && token_transfer.amount == decimal_value
- end)
- rescue
- _ -> nil
- end
+ Enum.find(token_transfers, fn token_transfer ->
+ token_transfer.to_address_hash.bytes == address && token_transfer.amount == decimal_value
+ end)
_ ->
nil
end
+ rescue
+ _ -> nil
end
def erc20_token_transfer(_, _) do
nil
end
+ def erc721_token_transfer(
+ %Transaction{
+ status: :ok,
+ created_contract_address_hash: nil,
+ input: input,
+ value: value
+ },
+ token_transfers
+ ) do
+ zero_wei = %Wei{value: Decimal.new(0)}
+
+ # https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721.sol#L35
+ {from_address, to_address} =
+ case {to_string(input), value} do
+ # transferFrom(address,address,uint256)
+ {"0x23b872dd" <> params, ^zero_wei} ->
+ types = [:address, :address, {:uint, 256}]
+ [from_address, to_address, _value] = decode_params(params, types)
+ {from_address, to_address}
+
+ # safeTransferFrom(address,address,uint256)
+ {"0x42842e0e" <> params, ^zero_wei} ->
+ types = [:address, :address, {:uint, 256}]
+ [from_address, to_address, _value] = decode_params(params, types)
+ {from_address, to_address}
+
+ # safeTransferFrom(address,address,uint256,bytes)
+ {"0xb88d4fde" <> params, ^zero_wei} ->
+ types = [:address, :address, {:uint, 256}, :bytes]
+ [from_address, to_address, _value, _data] = decode_params(params, types)
+ {from_address, to_address}
+
+ _ ->
+ nil
+ end
+
+ Enum.find(token_transfers, fn token_transfer ->
+ token_transfer.from_address_hash.bytes == from_address && token_transfer.to_address_hash.bytes == to_address
+ end)
+ rescue
+ _ -> nil
+ end
+
+ def erc721_token_transfer(_, _), do: nil
+
def processing_time_duration(%Transaction{block: nil}) do
:pending
end
@@ -298,4 +338,10 @@ defmodule BlockScoutWeb.TransactionView do
defp tab_name(["token_transfers"]), do: gettext("Token Transfers")
defp tab_name(["internal_transactions"]), do: gettext("Internal Transactions")
defp tab_name(["logs"]), do: gettext("Logs")
+
+ defp decode_params(params, types) do
+ params
+ |> Base.decode16!(case: :mixed)
+ |> TypeDecoder.decode_raw(types)
+ end
end
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot
index 7010a68126..55621eb6ef 100644
--- a/apps/block_scout_web/priv/gettext/default.pot
+++ b/apps/block_scout_web/priv/gettext/default.pot
@@ -49,7 +49,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:169
+#: lib/block_scout_web/views/transaction_view.ex:209
msgid "(Awaiting internal transactions for status)"
msgstr ""
@@ -278,12 +278,12 @@ msgid "Contract Address Pending"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:246
+#: lib/block_scout_web/views/transaction_view.ex:286
msgid "Contract Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:245
+#: lib/block_scout_web/views/transaction_view.ex:285
msgid "Contract Creation"
msgstr ""
@@ -377,12 +377,12 @@ msgid "Error trying to fetch balances."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:173
+#: lib/block_scout_web/views/transaction_view.ex:213
msgid "Error: %{reason}"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:171
+#: lib/block_scout_web/views/transaction_view.ex:211
msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
@@ -392,7 +392,7 @@ msgstr ""
#: lib/block_scout_web/templates/layout/app.html.eex:66
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:27
-#: lib/block_scout_web/templates/transaction/overview.html.eex:163
+#: lib/block_scout_web/templates/transaction/overview.html.eex:181
#: lib/block_scout_web/views/wei_helpers.ex:72
msgid "Ether"
msgstr ""
@@ -431,7 +431,7 @@ msgid "GET"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:176
+#: lib/block_scout_web/templates/transaction/overview.html.eex:194
msgid "Gas"
msgstr ""
@@ -495,7 +495,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:43
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:295
-#: lib/block_scout_web/views/transaction_view.ex:299
+#: lib/block_scout_web/views/transaction_view.ex:339
msgid "Internal Transactions"
msgstr ""
@@ -513,7 +513,7 @@ msgid "Less than"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:188
+#: lib/block_scout_web/templates/transaction/overview.html.eex:206
msgid "Limit"
msgstr ""
@@ -521,7 +521,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:21
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/index.html.eex:10
-#: lib/block_scout_web/views/transaction_view.ex:300
+#: lib/block_scout_web/views/transaction_view.ex:340
msgid "Logs"
msgstr ""
@@ -533,7 +533,7 @@ msgid "Market Cap"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:154
+#: lib/block_scout_web/views/transaction_view.ex:194
msgid "Max of"
msgstr ""
@@ -661,8 +661,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:44
-#: lib/block_scout_web/views/transaction_view.ex:168
-#: lib/block_scout_web/views/transaction_view.ex:202
+#: lib/block_scout_web/views/transaction_view.ex:208
+#: lib/block_scout_web/views/transaction_view.ex:242
msgid "Pending"
msgstr ""
@@ -762,7 +762,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
-#: lib/block_scout_web/views/transaction_view.ex:170
+#: lib/block_scout_web/views/transaction_view.ex:210
msgid "Success"
msgstr ""
@@ -872,9 +872,10 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:4
-#: lib/block_scout_web/templates/transaction/overview.html.eex:147
+#: lib/block_scout_web/templates/transaction/overview.html.eex:148
+#: lib/block_scout_web/templates/transaction/overview.html.eex:165
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
-#: lib/block_scout_web/views/transaction_view.ex:244
+#: lib/block_scout_web/views/transaction_view.ex:284
msgid "Token Transfer"
msgstr ""
@@ -886,7 +887,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:36
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:10
#: lib/block_scout_web/views/tokens/overview_view.ex:35
-#: lib/block_scout_web/views/transaction_view.ex:298
+#: lib/block_scout_web/views/transaction_view.ex:338
msgid "Token Transfers"
msgstr ""
@@ -927,7 +928,7 @@ msgid "Total transactions"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:247
+#: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction"
msgstr ""
@@ -994,7 +995,7 @@ msgid "Unique Token"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:181
+#: lib/block_scout_web/templates/transaction/overview.html.eex:199
msgid "Used"
msgstr ""
@@ -1015,7 +1016,7 @@ msgid "Validations"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:163
+#: lib/block_scout_web/templates/transaction/overview.html.eex:181
msgid "Value"
msgstr ""
@@ -1735,6 +1736,11 @@ msgid "Optimization runs"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:147
+#: lib/block_scout_web/templates/transaction/overview.html.eex:148
msgid "ERC-20"
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/transaction/overview.html.eex:165
+msgid "ERC-721"
+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 8a18c60018..7d7554d7d7 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
@@ -49,7 +49,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:169
+#: lib/block_scout_web/views/transaction_view.ex:209
msgid "(Awaiting internal transactions for status)"
msgstr ""
@@ -278,12 +278,12 @@ msgid "Contract Address Pending"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:246
+#: lib/block_scout_web/views/transaction_view.ex:286
msgid "Contract Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:245
+#: lib/block_scout_web/views/transaction_view.ex:285
msgid "Contract Creation"
msgstr ""
@@ -377,12 +377,12 @@ msgid "Error trying to fetch balances."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:173
+#: lib/block_scout_web/views/transaction_view.ex:213
msgid "Error: %{reason}"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:171
+#: lib/block_scout_web/views/transaction_view.ex:211
msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
@@ -392,7 +392,7 @@ msgstr ""
#: lib/block_scout_web/templates/layout/app.html.eex:66
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:27
-#: lib/block_scout_web/templates/transaction/overview.html.eex:163
+#: lib/block_scout_web/templates/transaction/overview.html.eex:181
#: lib/block_scout_web/views/wei_helpers.ex:72
msgid "Ether"
msgstr "POA"
@@ -431,7 +431,7 @@ msgid "GET"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:176
+#: lib/block_scout_web/templates/transaction/overview.html.eex:194
msgid "Gas"
msgstr ""
@@ -495,7 +495,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:43
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:295
-#: lib/block_scout_web/views/transaction_view.ex:299
+#: lib/block_scout_web/views/transaction_view.ex:339
msgid "Internal Transactions"
msgstr ""
@@ -513,7 +513,7 @@ msgid "Less than"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:188
+#: lib/block_scout_web/templates/transaction/overview.html.eex:206
msgid "Limit"
msgstr ""
@@ -521,7 +521,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:21
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/index.html.eex:10
-#: lib/block_scout_web/views/transaction_view.ex:300
+#: lib/block_scout_web/views/transaction_view.ex:340
msgid "Logs"
msgstr ""
@@ -533,7 +533,7 @@ msgid "Market Cap"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:154
+#: lib/block_scout_web/views/transaction_view.ex:194
msgid "Max of"
msgstr ""
@@ -661,8 +661,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:44
-#: lib/block_scout_web/views/transaction_view.ex:168
-#: lib/block_scout_web/views/transaction_view.ex:202
+#: lib/block_scout_web/views/transaction_view.ex:208
+#: lib/block_scout_web/views/transaction_view.ex:242
msgid "Pending"
msgstr ""
@@ -762,7 +762,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
-#: lib/block_scout_web/views/transaction_view.ex:170
+#: lib/block_scout_web/views/transaction_view.ex:210
msgid "Success"
msgstr ""
@@ -872,9 +872,10 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:4
-#: lib/block_scout_web/templates/transaction/overview.html.eex:147
+#: lib/block_scout_web/templates/transaction/overview.html.eex:148
+#: lib/block_scout_web/templates/transaction/overview.html.eex:165
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
-#: lib/block_scout_web/views/transaction_view.ex:244
+#: lib/block_scout_web/views/transaction_view.ex:284
msgid "Token Transfer"
msgstr ""
@@ -886,7 +887,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:36
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:10
#: lib/block_scout_web/views/tokens/overview_view.ex:35
-#: lib/block_scout_web/views/transaction_view.ex:298
+#: lib/block_scout_web/views/transaction_view.ex:338
msgid "Token Transfers"
msgstr ""
@@ -927,7 +928,7 @@ msgid "Total transactions"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:247
+#: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction"
msgstr ""
@@ -994,7 +995,7 @@ msgid "Unique Token"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:181
+#: lib/block_scout_web/templates/transaction/overview.html.eex:199
msgid "Used"
msgstr ""
@@ -1015,7 +1016,7 @@ msgid "Validations"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:163
+#: lib/block_scout_web/templates/transaction/overview.html.eex:181
msgid "Value"
msgstr ""
@@ -1735,6 +1736,11 @@ msgid "Optimization runs"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/overview.html.eex:147
+#: lib/block_scout_web/templates/transaction/overview.html.eex:148
msgid "ERC-20"
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/transaction/overview.html.eex:165
+msgid "ERC-721"
+msgstr ""
diff --git a/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs
index 2a3e5492ed..e8efeff6a0 100644
--- a/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs
@@ -47,6 +47,30 @@ defmodule BlockScoutWeb.TransactionViewTest do
end
end
+ describe "erc721_token_transfer/2" do
+ test "finds token transfer" do
+ from_address_hash = "0x7a30272c902563b712245696f0a81c5a0e45ddc8"
+ to_address_hash = "0xb544cead8b660aae9f2e37450f7be2ffbc501793"
+ from_address = insert(:address, hash: from_address_hash)
+ to_address = insert(:address, hash: to_address_hash)
+ block = insert(:block)
+
+ transaction =
+ insert(:transaction,
+ input:
+ "0x23b872dd0000000000000000000000007a30272c902563b712245696f0a81c5a0e45ddc8000000000000000000000000b544cead8b660aae9f2e37450f7be2ffbc5017930000000000000000000000000000000000000000000000000000000000000002",
+ value: Decimal.new(0),
+ created_contract_address_hash: nil
+ )
+ |> with_block(block, status: :ok)
+
+ token_transfer =
+ insert(:token_transfer, from_address: from_address, to_address: to_address, transaction: transaction)
+
+ assert TransactionView.erc721_token_transfer(transaction, [token_transfer]) == token_transfer
+ end
+ end
+
describe "processing_time_duration/2" do
test "returns :pending if the transaction has no block" do
transaction = build(:transaction, block: nil)