diff --git a/apps/block_scout_web/assets/css/app.scss b/apps/block_scout_web/assets/css/app.scss index f83c741bc0..3c722e8ec9 100644 --- a/apps/block_scout_web/assets/css/app.scss +++ b/apps/block_scout_web/assets/css/app.scss @@ -81,6 +81,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts"; @import "components/token_tile_view_more"; @import "components/dropdown"; @import "components/loading-spinner"; +@import "components/transaction-input"; :export { primary: $primary; diff --git a/apps/block_scout_web/assets/css/components/_transaction-input.scss b/apps/block_scout_web/assets/css/components/_transaction-input.scss new file mode 100644 index 0000000000..63c3a847b8 --- /dev/null +++ b/apps/block_scout_web/assets/css/components/_transaction-input.scss @@ -0,0 +1,9 @@ +.raw-transaction-input{ + display: none; +} + +.transaction-input-text{ + resize: vertical; + overflow: auto; + word-break: break-all; +} diff --git a/apps/block_scout_web/assets/js/app.js b/apps/block_scout_web/assets/js/app.js index 83e3080c5c..b994bef9ef 100644 --- a/apps/block_scout_web/assets/js/app.js +++ b/apps/block_scout_web/assets/js/app.js @@ -44,3 +44,4 @@ import './lib/token_balance_dropdown_search' import './lib/token_transfers_toggle' import './lib/tooltip' import './lib/try_api' +import './lib/swappable_item' diff --git a/apps/block_scout_web/assets/js/lib/clipboard_buttons.js b/apps/block_scout_web/assets/js/lib/clipboard_buttons.js index d53851c84f..e195a68d0b 100644 --- a/apps/block_scout_web/assets/js/lib/clipboard_buttons.js +++ b/apps/block_scout_web/assets/js/lib/clipboard_buttons.js @@ -5,11 +5,14 @@ const clipboard = new ClipboardJS('[data-clipboard-text]') clipboard.on('success', ({trigger}) => { const copyButton = $(trigger) + copyButton.tooltip('dispose') + copyButton.tooltip({ title: 'Copied!', trigger: 'click', placement: 'top' }).tooltip('show') + setTimeout(() => { copyButton.tooltip('dispose') }, 1000) diff --git a/apps/block_scout_web/assets/js/lib/swappable_item.js b/apps/block_scout_web/assets/js/lib/swappable_item.js new file mode 100644 index 0000000000..866b416299 --- /dev/null +++ b/apps/block_scout_web/assets/js/lib/swappable_item.js @@ -0,0 +1,21 @@ +import $ from 'jquery' + +const swapItems = (element, event) => { + const $element = $(element) + const item = $element.parent().closest('[swappable-item]') + const next = item.nextAll('[swappable-item]:first') + + item.hide() + + if (next.length) { + next.show() + } else { + item.parent().find('[swappable-item]:first').show() + } + + return false +} + +$('[swappable-item] [swapper]').on('click', function (event) { + swapItems(this, event) +}) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex index c8131220d4..58b5dfb75d 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex @@ -16,6 +16,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do [created_contract_address: :names] => :optional, [from_address: :names] => :optional, [to_address: :names] => :optional, + [to_address: :smart_contract] => :optional, :token_transfers => :optional } ) do diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex index be3567f47c..b07386bcaa 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex @@ -16,6 +16,7 @@ defmodule BlockScoutWeb.TransactionLogController do [created_contract_address: :names] => :optional, [from_address: :names] => :required, [to_address: :names] => :optional, + [to_address: :smart_contract] => :optional, :token_transfers => :optional } ) do diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex index 6bafe04a3b..21440d0c8b 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex @@ -76,14 +76,100 @@
-
<%= gettext "Input" %>
-
-
-
-<%= @transaction.input %>
-                
+ <%= case decoded_input_data(@transaction) do %> + <% {:error, :contract_not_verified} -> %> +
<%= gettext "Input" %>
+
+
+ To see decoded input data, the contract must be verified. +
+
+ <% {:error, :could_not_decode} -> %> +
<%= gettext "Input" %>
+
+
+ Failed to decode input data. Some dynamic types are not currently supported. +
+
+ <% {:ok, method_id, text, mapping} -> %> +
<%= gettext "Input" %>
+
+ + + + + + + + + +
Method Id0x<%= method_id %>
Call<%= text %>
+ + + + + + + + + <%= for {{name, type, value}, index} <- Enum.with_index(mapping) do %> + + + + + <%= case type do %> + <% "address" -> %> + <% address = "0x" <> Base.encode16(value, case: :lower) %> + + + + <% _ -> %> + + + <% end %> + + <% end %> +
#NameTypeData
<%= index %><%= name %><%= type %> + + + + +
<%= value %> +
+ +
+
+ <% _ -> %> + <%= nil %> + <% end %> + + <%= unless @transaction.input.bytes in [<<>>, nil] do %> +
<%= gettext "Raw Input" %>
+
+
+
-
+
+ +
+ +
+                    <%= @transaction.input %>
+                  
+
+
+ + <% end %>
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 2f0d75d90c..6f630668b4 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 @@ -73,6 +73,10 @@ defmodule BlockScoutWeb.TransactionView do Cldr.Number.to_string!(gas) end + def decoded_input_data(transaction) do + Transaction.decoded_input_data(transaction) + end + @doc """ Converts a transaction's gas price to a displayable value. """ diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 6efd8d30f6..d52ded6643 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -283,12 +283,12 @@ msgid "Contract Address Pending" msgstr "" #, elixir-format -#: lib/block_scout_web/views/transaction_view.ex:127 +#: lib/block_scout_web/views/transaction_view.ex:131 msgid "Contract Call" msgstr "" #, elixir-format -#: lib/block_scout_web/views/transaction_view.ex:126 +#: lib/block_scout_web/views/transaction_view.ex:130 msgid "Contract Creation" msgstr "" @@ -403,7 +403,7 @@ msgstr "" #: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:16 #: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:19 #: lib/block_scout_web/templates/transaction/_tile.html.eex:26 -#: lib/block_scout_web/templates/transaction/overview.html.eex:96 +#: lib/block_scout_web/templates/transaction/overview.html.eex:182 #: lib/block_scout_web/views/wei_helpers.ex:72 msgid "Ether" msgstr "" @@ -442,7 +442,7 @@ msgid "GET" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:109 +#: lib/block_scout_web/templates/transaction/overview.html.eex:195 msgid "Gas" msgstr "" @@ -486,7 +486,9 @@ msgid "Indexing Tokens" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:79 +#: lib/block_scout_web/templates/transaction/overview.html.eex:81 +#: lib/block_scout_web/templates/transaction/overview.html.eex:88 +#: lib/block_scout_web/templates/transaction/overview.html.eex:95 msgid "Input" msgstr "" @@ -505,7 +507,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:213 -#: lib/block_scout_web/views/transaction_view.ex:176 +#: lib/block_scout_web/views/transaction_view.ex:180 msgid "Internal Transactions" msgstr "" @@ -523,7 +525,7 @@ msgid "Less than" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:121 +#: lib/block_scout_web/templates/transaction/overview.html.eex:207 msgid "Limit" msgstr "" @@ -531,7 +533,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:177 +#: lib/block_scout_web/views/transaction_view.ex:181 msgid "Logs" msgstr "" @@ -680,7 +682,7 @@ msgstr "" #: lib/block_scout_web/templates/layout/_topnav.html.eex:44 #: lib/block_scout_web/templates/transaction/overview.html.eex:54 #: lib/block_scout_web/views/transaction_view.ex:57 -#: lib/block_scout_web/views/transaction_view.ex:83 +#: lib/block_scout_web/views/transaction_view.ex:87 msgid "Pending" msgstr "" @@ -896,7 +898,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:4 #: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4 -#: lib/block_scout_web/views/transaction_view.ex:125 +#: lib/block_scout_web/views/transaction_view.ex:129 msgid "Token Transfer" msgstr "" @@ -908,7 +910,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:175 +#: lib/block_scout_web/views/transaction_view.ex:179 msgid "Token Transfers" msgstr "" @@ -950,7 +952,7 @@ msgid "Total transactions" msgstr "" #, elixir-format -#: lib/block_scout_web/views/transaction_view.ex:128 +#: lib/block_scout_web/views/transaction_view.ex:132 msgid "Transaction" msgstr "" @@ -1018,7 +1020,7 @@ msgid "Unique Token" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:114 +#: lib/block_scout_web/templates/transaction/overview.html.eex:200 msgid "Used" msgstr "" @@ -1039,7 +1041,7 @@ msgid "Validations" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:96 +#: lib/block_scout_web/templates/transaction/overview.html.eex:182 msgid "Value" msgstr "" @@ -1216,3 +1218,20 @@ msgstr "" #: lib/block_scout_web/templates/api_docs/index.html.eex:7 msgid "This API is provided for developers transitioning their applications from Etherscan to BlockScout. It supports GET and POST requests." msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/transaction/overview.html.eex:153 +msgid "Raw Input" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/transaction/overview.html.eex:156 +msgid "Show Raw Input" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/transaction/overview.html.eex:130 +#: lib/block_scout_web/templates/transaction/overview.html.eex:140 +#: lib/block_scout_web/templates/transaction/overview.html.eex:164 +msgid "copy" +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 22b5201e98..a4ad8ee9db 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 @@ -283,12 +283,12 @@ msgid "Contract Address Pending" msgstr "" #, elixir-format -#: lib/block_scout_web/views/transaction_view.ex:127 +#: lib/block_scout_web/views/transaction_view.ex:131 msgid "Contract Call" msgstr "" #, elixir-format -#: lib/block_scout_web/views/transaction_view.ex:126 +#: lib/block_scout_web/views/transaction_view.ex:130 msgid "Contract Creation" msgstr "" @@ -403,7 +403,7 @@ msgstr "" #: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:16 #: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:19 #: lib/block_scout_web/templates/transaction/_tile.html.eex:26 -#: lib/block_scout_web/templates/transaction/overview.html.eex:96 +#: lib/block_scout_web/templates/transaction/overview.html.eex:182 #: lib/block_scout_web/views/wei_helpers.ex:72 msgid "Ether" msgstr "POA" @@ -442,7 +442,7 @@ msgid "GET" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:109 +#: lib/block_scout_web/templates/transaction/overview.html.eex:195 msgid "Gas" msgstr "" @@ -486,7 +486,9 @@ msgid "Indexing Tokens" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:79 +#: lib/block_scout_web/templates/transaction/overview.html.eex:81 +#: lib/block_scout_web/templates/transaction/overview.html.eex:88 +#: lib/block_scout_web/templates/transaction/overview.html.eex:95 msgid "Input" msgstr "" @@ -505,7 +507,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:213 -#: lib/block_scout_web/views/transaction_view.ex:176 +#: lib/block_scout_web/views/transaction_view.ex:180 msgid "Internal Transactions" msgstr "" @@ -523,7 +525,7 @@ msgid "Less than" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:121 +#: lib/block_scout_web/templates/transaction/overview.html.eex:207 msgid "Limit" msgstr "" @@ -531,7 +533,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:177 +#: lib/block_scout_web/views/transaction_view.ex:181 msgid "Logs" msgstr "" @@ -680,7 +682,7 @@ msgstr "" #: lib/block_scout_web/templates/layout/_topnav.html.eex:44 #: lib/block_scout_web/templates/transaction/overview.html.eex:54 #: lib/block_scout_web/views/transaction_view.ex:57 -#: lib/block_scout_web/views/transaction_view.ex:83 +#: lib/block_scout_web/views/transaction_view.ex:87 msgid "Pending" msgstr "" @@ -896,7 +898,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:4 #: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4 -#: lib/block_scout_web/views/transaction_view.ex:125 +#: lib/block_scout_web/views/transaction_view.ex:129 msgid "Token Transfer" msgstr "" @@ -908,7 +910,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:175 +#: lib/block_scout_web/views/transaction_view.ex:179 msgid "Token Transfers" msgstr "" @@ -950,7 +952,7 @@ msgid "Total transactions" msgstr "" #, elixir-format -#: lib/block_scout_web/views/transaction_view.ex:128 +#: lib/block_scout_web/views/transaction_view.ex:132 msgid "Transaction" msgstr "" @@ -1018,7 +1020,7 @@ msgid "Unique Token" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:114 +#: lib/block_scout_web/templates/transaction/overview.html.eex:200 msgid "Used" msgstr "" @@ -1039,7 +1041,7 @@ msgid "Validations" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:96 +#: lib/block_scout_web/templates/transaction/overview.html.eex:182 msgid "Value" msgstr "" @@ -1216,3 +1218,20 @@ msgstr "" #: lib/block_scout_web/templates/api_docs/index.html.eex:7 msgid "This API is provided for developers transitioning their applications from Etherscan to BlockScout. It supports GET and POST requests." msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/transaction/overview.html.eex:153 +msgid "Raw Input" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/transaction/overview.html.eex:156 +msgid "Show Raw Input" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/transaction/overview.html.eex:130 +#: lib/block_scout_web/templates/transaction/overview.html.eex:140 +#: lib/block_scout_web/templates/transaction/overview.html.eex:164 +msgid "copy" +msgstr "" diff --git a/apps/ethereum_jsonrpc/mix.exs b/apps/ethereum_jsonrpc/mix.exs index 0ec61acd69..e2f8458821 100644 --- a/apps/ethereum_jsonrpc/mix.exs +++ b/apps/ethereum_jsonrpc/mix.exs @@ -79,7 +79,7 @@ defmodule EthereumJsonrpc.MixProject do # Convert unix timestamps in JSONRPC to DateTimes {:timex, "~> 3.4"}, # Encode/decode function names and arguments - {:ex_abi, "~> 0.1.16"}, + {:ex_abi, "~> 0.1.17"}, # `:verify_fun` for `Socket.Web.connect` {:ssl_verify_fun, "~> 1.1"}, # `EthereumJSONRPC.WebSocket` diff --git a/apps/explorer/lib/explorer/chain/transaction.ex b/apps/explorer/lib/explorer/chain/transaction.ex index fecf72722c..40a14b103e 100644 --- a/apps/explorer/lib/explorer/chain/transaction.ex +++ b/apps/explorer/lib/explorer/chain/transaction.ex @@ -3,8 +3,12 @@ defmodule Explorer.Chain.Transaction do use Explorer.Schema + require Logger + import Ecto.Query, only: [dynamic: 2, from: 2, preload: 3, subquery: 1, where: 3] + alias ABI.FunctionSelector + alias Ecto.Changeset alias Explorer.Chain.{ @@ -415,6 +419,54 @@ defmodule Explorer.Chain.Transaction do preload(query, [tt], token_transfers: ^token_transfers_query) end + # Because there is no contract association, we know the contract was not verified + def decoded_input_data(%__MODULE__{to_address: nil}), do: {:error, :no_to_address} + def decoded_input_data(%__MODULE__{input: %{bytes: bytes}}) when bytes in [nil, <<>>], do: {:error, :no_input_data} + def decoded_input_data(%__MODULE__{to_address: %{contract_code: nil}}), do: {:error, :not_a_contract_call} + def decoded_input_data(%__MODULE__{to_address: %{smart_contract: nil}}), do: {:error, :contract_not_verified} + + def decoded_input_data(%__MODULE__{input: %{bytes: data}, to_address: %{smart_contract: %{abi: abi}}, hash: hash}) do + with {:ok, {selector, values}} <- find_and_decode(abi, data, hash), + {:ok, mapping} <- selector_mapping(selector, values, hash), + identifier <- Base.encode16(selector.method_id, case: :lower), + text <- function_call(selector.function, mapping), + do: {:ok, identifier, text, mapping} + end + + defp function_call(name, mapping) do + text = + mapping + |> Stream.map(fn {name, type, _} -> [type, " ", name] end) + |> Enum.intersperse(", ") + + IO.iodata_to_binary([name, "(", text, ")"]) + end + + defp find_and_decode(abi, data, hash) do + result = + abi + |> ABI.parse_specification() + |> ABI.find_and_decode(data) + + {:ok, result} + rescue + _ -> + Logger.warn(fn -> ["Could not decode input data for transaction: ", Hash.to_iodata(hash)] end) + {:error, :could_not_decode} + end + + defp selector_mapping(selector, values, hash) do + types = Enum.map(selector.types, &FunctionSelector.encode_type/1) + + mapping = Enum.zip([selector.input_names, types, values]) + + {:ok, mapping} + rescue + _ -> + Logger.warn(fn -> ["Could not decode input data for transaction: ", Hash.to_iodata(hash)] end) + {:error, :could_not_decode} + end + @doc """ Adds to the given transaction's query a `where` with one of the conditions that the matched function returns. diff --git a/apps/explorer/test/explorer/chain/transaction_test.exs b/apps/explorer/test/explorer/chain/transaction_test.exs index 7855daa2a8..df82de13ff 100644 --- a/apps/explorer/test/explorer/chain/transaction_test.exs +++ b/apps/explorer/test/explorer/chain/transaction_test.exs @@ -213,4 +213,30 @@ defmodule Explorer.Chain.TransactionTest do assert last_nonce == nil end end + + describe "decoded_input_data/1" do + test "that a tranasction that is not a contract call returns a commensurate error" do + transaction = insert(:transaction) + + assert Transaction.decoded_input_data(transaction) == {:error, :not_a_contract_call} + end + + test "that a contract call transaction that has no verified contract returns a commensurate error" do + transaction = + :transaction + |> insert(to_address: insert(:contract_address)) + |> Repo.preload(to_address: :smart_contract) + + assert Transaction.decoded_input_data(transaction) == {:error, :contract_not_verified} + end + + test "that a contract call transaction that has a verified contract returns the decoded input data" do + transaction = + :transaction_to_verified_contract + |> insert() + |> Repo.preload(to_address: :smart_contract) + + assert Transaction.decoded_input_data(transaction) == {:ok, "60fe47b1", "set(uint256 x)", [{"x", "uint256", 50}]} + end + end end diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index 54f99731a8..bb0c7e702f 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -92,6 +92,26 @@ defmodule Explorer.Factory do } } """, + abi: [ + %{ + "constant" => false, + "inputs" => [%{"name" => "x", "type" => "uint256"}], + "name" => "set", + "outputs" => [], + "payable" => false, + "stateMutability" => "nonpayable", + "type" => "function" + }, + %{ + "constant" => true, + "inputs" => [], + "name" => "get", + "outputs" => [%{"name" => "", "type" => "uint256"}], + "payable" => false, + "stateMutability" => "view", + "type" => "function" + } + ], version: "v0.4.24+commit.e67f0147", optimized: false } @@ -419,6 +439,23 @@ defmodule Explorer.Factory do } end + def transaction_to_verified_contract_factory do + smart_contract = build(:smart_contract) + + address = %Address{ + hash: address_hash(), + contract_code: contract_code_info().bytecode, + smart_contract: smart_contract + } + + input_data = + "set(uint)" + |> ABI.encode([50]) + |> Base.encode16(case: :lower) + + build(:transaction, to_address: address, input: "0x" <> input_data) + end + def transaction_hash do {:ok, transaction_hash} = "transaction_hash" @@ -441,33 +478,15 @@ defmodule Explorer.Factory do end def smart_contract_factory() do + contract_code_info = contract_code_info() + %SmartContract{ address_hash: insert(:address).hash, - compiler_version: "0.4.24", - name: "SimpleStorage", - contract_source_code: - "pragma solidity ^0.4.24; contract SimpleStorage {uint storedData; function set(uint x) public {storedData = x; } function get() public constant returns (uint) {return storedData; } }", - optimization: false, - abi: [ - %{ - "constant" => false, - "inputs" => [%{"name" => "x", "type" => "uint256"}], - "name" => "set", - "outputs" => [], - "payable" => false, - "stateMutability" => "nonpayable", - "type" => "function" - }, - %{ - "constant" => true, - "inputs" => [], - "name" => "get", - "outputs" => [%{"name" => "", "type" => "uint256"}], - "payable" => false, - "stateMutability" => "view", - "type" => "function" - } - ] + compiler_version: contract_code_info.version, + name: contract_code_info.name, + contract_source_code: contract_code_info.source_code, + optimization: contract_code_info.optimized, + abi: contract_code_info.abi } end diff --git a/mix.lock b/mix.lock index 67b8ac8a69..eb2d1cd627 100644 --- a/mix.lock +++ b/mix.lock @@ -27,7 +27,7 @@ "earmark": {:hex, :earmark, "1.2.6", "b6da42b3831458d3ecc57314dff3051b080b9b2be88c2e5aa41cd642a5b044ed", [:mix], [], "hexpm"}, "ecto": {:hex, :ecto, "2.2.11", "4bb8f11718b72ba97a2696f65d247a379e739a0ecabf6a13ad1face79844791c", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"}, "elixir_make": {:hex, :elixir_make, "0.4.2", "332c649d08c18bc1ecc73b1befc68c647136de4f340b548844efc796405743bf", [:mix], [], "hexpm"}, - "ex_abi": {:hex, :ex_abi, "0.1.16", "3bb346968995f505b0f2fed1704321c572349e29614f5a2dbe2ae8fc0f18a89e", [:mix], [{:exth_crypto, "~> 0.1.4", [hex: :exth_crypto, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_abi": {:hex, :ex_abi, "0.1.17", "11822f88b3ed70773c64858a49321b3c51ed913128a3f9fc7a05fa7ceb19d8fa", [:mix], [{:exth_crypto, "~> 0.1.4", [hex: :exth_crypto, repo: "hexpm", optional: false]}], "hexpm"}, "ex_cldr": {:hex, :ex_cldr, "1.3.2", "8f4a00c99d1c537b8e8db7e7903f4bd78d82a7289502d080f70365392b13921b", [:mix], [{:abnf2, "~> 0.1", [hex: :abnf2, optional: false]}, {:decimal, "~> 1.4", [hex: :decimal, optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, optional: true]}, {:poison, "~> 2.1 or ~> 3.0", [hex: :poison, optional: true]}]}, "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "1.2.0", "ef27299922da913ffad1ed296cacf28b6452fc1243b77301dc17c03276c6ee34", [:mix], [{:decimal, "~> 1.4", [hex: :decimal, optional: false]}, {:ex_cldr, "~> 1.3", [hex: :ex_cldr, optional: false]}, {:poison, "~> 2.1 or ~> 3.1", [hex: :poison, optional: false]}]}, "ex_cldr_units": {:hex, :ex_cldr_units, "1.1.1", "b3c7256709bdeb3740a5f64ce2bce659eb9cf4cc1afb4cf94aba033b4a18bc5f", [:mix], [{:ex_cldr, "~> 1.0", [hex: :ex_cldr, optional: false]}, {:ex_cldr_numbers, "~> 1.0", [hex: :ex_cldr_numbers, optional: false]}]}, @@ -37,7 +37,7 @@ "exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], []}, "excoveralls": {:git, "https://github.com/KronicDeth/excoveralls.git", "0a859b68851eeba9b43eba59fbc8f9098299cfe1", [branch: "circle-workflows"]}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, - "exth_crypto": {:hex, :exth_crypto, "0.1.4", "11f9084dfd70d4f9e96f2710a472f4e6b23044b97530c719550c2b0450ffeb61", [:mix], [{:binary, "~> 0.0.4", [hex: :binary, optional: false]}, {:keccakf1600, "~> 2.0.0", [hex: :keccakf1600_orig, optional: false]}, {:libsecp256k1, "~> 0.1.3", [hex: :libsecp256k1, optional: false]}]}, + "exth_crypto": {:hex, :exth_crypto, "0.1.6", "8e636a9bcb75d8e32451be96e547a495121ed2178d078db294edb0f81f7cf2e8", [:mix], [{:binary, "~> 0.0.4", [hex: :binary, repo: "hexpm", optional: false]}, {:keccakf1600, "~> 2.0.0", [hex: :keccakf1600_orig, repo: "hexpm", optional: false]}, {:libsecp256k1, "~> 0.1.9", [hex: :libsecp256k1, repo: "hexpm", optional: false]}], "hexpm"}, "exvcr": {:hex, :exvcr, "0.10.3", "1ae3b97560430acfa88ebc737c85b2b7a9dbacd8a2b26789a19718b51ae3522c", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, "file_system": {:hex, :file_system, "0.2.6", "fd4dc3af89b9ab1dc8ccbcc214a0e60c41f34be251d9307920748a14bf41f1d3", [:mix], [], "hexpm"}, "floki": {:hex, :floki, "0.20.4", "be42ac911fece24b4c72f3b5846774b6e61b83fe685c2fc9d62093277fb3bc86", [:mix], [{:html_entities, "~> 0.4.0", [hex: :html_entities, repo: "hexpm", optional: false]}, {:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},