From d80bbf929777fdfa0c2cfd67020732fc86b71721 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 6 Feb 2019 15:36:47 +0300 Subject: [PATCH 1/9] fetch contract creation input data from transaction/internal transaction --- apps/explorer/lib/explorer/chain.ex | 26 +++++++++++ apps/explorer/test/explorer/chain_test.exs | 54 ++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 293aa3fa34..29434c2414 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1868,6 +1868,32 @@ defmodule Explorer.Chain do |> Data.to_string() end + @doc """ + Fetches contract creation input data. + """ + @spec contract_creation_input_data(String.t()) :: nil | String.t() + def contract_creation_input_data(address_hash) do + query = + from( + address in Address, + where: address.hash == ^address_hash, + preload: [:contracts_creation_internal_transaction, :contracts_creation_transaction] + ) + + transaction = Repo.one(query) + + cond do + is_nil(transaction) -> + nil + + !is_nil(transaction.contracts_creation_internal_transaction) -> + Data.to_string(transaction.contracts_creation_internal_transaction.input) + + !is_nil(transaction.contracts_creation_transaction) -> + Data.to_string(transaction.contracts_creation_transaction.input) + end + end + @doc """ Inserts a `t:SmartContract.t/0`. diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 13bd3ef766..6fef5835ff 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -3557,4 +3557,58 @@ defmodule Explorer.ChainTest do assert Chain.block_combined_rewards(block) == expected_value end end + + describe "contract_creation_input_data/1" do + test "fetches contract creation input data from contract creation transaction" do + address = insert(:address) + + input = %Data{ + bytes: <<1, 2, 3, 4, 5>> + } + + :transaction + |> insert(created_contract_address_hash: address.hash, input: input) + |> with_block() + + found_creation_data = Chain.contract_creation_input_data(address.hash) + + assert found_creation_data == Data.to_string(input) + end + + test "fetches contract creation input data from internal transaction" do + created_contract_address = insert(:address) + + transaction = + :transaction + |> insert() + |> with_block() + + input = %Data{ + bytes: <<1, 2, 3, 4, 5>> + } + + insert( + :internal_transaction_create, + transaction: transaction, + index: 0, + created_contract_address: created_contract_address, + block_number: transaction.block_number, + transaction_index: transaction.index, + input: input + ) + + assert Chain.contract_creation_input_data(created_contract_address.hash) == Data.to_string(input) + end + + test "can't find address" do + hash = %Hash{ + byte_count: 20, + bytes: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> + } + + found_creation_data = Chain.contract_creation_input_data(hash) + + assert is_nil(found_creation_data) + end + end end From 9f9a31711d74e740a581c02e0ea302d5c101542a Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 6 Feb 2019 16:31:27 +0300 Subject: [PATCH 2/9] verify smart contract constructor arguments --- .../verifier/constructor_arguments.ex | 20 ++++++++++++++ .../verifier/constructor_arguments_test.exs | 26 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex create mode 100644 apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs diff --git a/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex new file mode 100644 index 0000000000..d8b982cc40 --- /dev/null +++ b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex @@ -0,0 +1,20 @@ +defmodule Explorer.SmartContract.Verifier.ConstructorArguments do + @moduledoc """ + Smart contract contrstructor arguments verification logic. + """ + + alias Explorer.Chain + + def verify(address_hash, bytecode, arguments_data) do + arguments_data = String.replace(arguments_data, "0x", "") + creation_input_data = Chain.contract_creation_input_data(address_hash) + + expected_arguments_data = + creation_input_data + |> String.split(bytecode) + |> List.last() + |> String.replace("0x", "") + + expected_arguments_data == arguments_data + end +end diff --git a/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs new file mode 100644 index 0000000000..989f07dbce --- /dev/null +++ b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs @@ -0,0 +1,26 @@ +defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do + use Explorer.DataCase + + import Explorer.Factory + + alias Explorer.Chain.Data + alias Explorer.SmartContract.Verifier.ConstructorArguments + + describe "verify/3" do + test "verifies construct arguments" do + bytecode = "0x0102030" + constructor_arguments = "0x405" + address = insert(:address) + + input = %Data{ + bytes: <<1, 2, 3, 4, 5>> + } + + :transaction + |> insert(created_contract_address_hash: address.hash, input: input) + |> with_block() + + assert ConstructorArguments.verify(address.hash, bytecode, constructor_arguments) + end + end +end From 0f3c7585c8eac92343faf9343b6f8148340f0d02 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 7 Feb 2019 12:14:59 +0300 Subject: [PATCH 3/9] verify constructor arguments in Verifier --- apps/explorer/lib/explorer/chain.ex | 2 + .../lib/explorer/smart_contract/verifier.ex | 48 +++++++++---------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 29434c2414..62260df046 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1891,6 +1891,8 @@ defmodule Explorer.Chain do !is_nil(transaction.contracts_creation_transaction) -> Data.to_string(transaction.contracts_creation_transaction.input) + + true -> "" end end diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index 3291c87a68..e7cc8c78a4 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -9,39 +9,30 @@ defmodule Explorer.SmartContract.Verifier do alias Explorer.Chain alias Explorer.SmartContract.Solidity.CodeCompiler + alias Explorer.SmartContract.Verifier.ConstructorArguments def evaluate_authenticity(_, %{"name" => ""}), do: {:error, :name} def evaluate_authenticity(_, %{"contract_source_code" => ""}), do: {:error, :contract_source_code} - def evaluate_authenticity(address_hash, %{ - "name" => name, - "contract_source_code" => contract_source_code, - "optimization" => optimization, - "compiler_version" => compiler_version, - "external_libraries" => external_libraries - }) do - solc_output = CodeCompiler.run(name, compiler_version, contract_source_code, optimization, external_libraries) - - compare_bytecodes(solc_output, address_hash) - end + def evaluate_authenticity(address_hash, params) do + name = Map.fetch!(params, "name") + contract_source_code = Map.fetch!(params, "contract_source_code") + optimization = Map.fetch!(params, "optimization") + compiler_version = Map.fetch!(params, "compiler_version") + external_libraries = Map.get(params, "external_libraries", %{}) + constructor_arguments = Map.get(params, "constructor_arguments", "") - def evaluate_authenticity(address_hash, %{ - "name" => name, - "contract_source_code" => contract_source_code, - "optimization" => optimization, - "compiler_version" => compiler_version - }) do - solc_output = CodeCompiler.run(name, compiler_version, contract_source_code, optimization) + solc_output = CodeCompiler.run(name, compiler_version, contract_source_code, optimization, external_libraries) - compare_bytecodes(solc_output, address_hash) + compare_bytecodes(solc_output, address_hash, constructor_arguments) end - defp compare_bytecodes({:error, :name}, _), do: {:error, :name} - defp compare_bytecodes({:error, _}, _), do: {:error, :compilation} + defp compare_bytecodes({:error, :name}, _, _), do: {:error, :name} + defp compare_bytecodes({:error, _}, _, _), do: {:error, :compilation} - defp compare_bytecodes({:ok, %{"abi" => abi, "bytecode" => bytecode}}, address_hash) do + defp compare_bytecodes({:ok, %{"abi" => abi, "bytecode" => bytecode}}, address_hash, arguments_data) do generated_bytecode = extract_bytecode(bytecode) "0x" <> blockchain_bytecode = @@ -49,10 +40,15 @@ defmodule Explorer.SmartContract.Verifier do |> Chain.smart_contract_bytecode() |> extract_bytecode - if generated_bytecode == blockchain_bytecode do - {:ok, %{abi: abi}} - else - {:error, :generated_bytecode} + cond do + generated_bytecode != blockchain_bytecode -> + {:error, :generated_bytecode} + + !ConstructorArguments.verify(address_hash, bytecode, arguments_data) -> + {:error, :constructor_arguments} + + true -> + {:ok, %{abi: abi}} end end From 64764d6c8fa20eab8d9fe866272a88df9e23935e Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 7 Feb 2019 13:11:45 +0300 Subject: [PATCH 4/9] fix verifier, add tests --- apps/explorer/lib/explorer/chain.ex | 3 +- .../lib/explorer/smart_contract/verifier.ex | 2 +- .../explorer/smart_contract/verifier_test.exs | 51 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 62260df046..e58953404d 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1892,7 +1892,8 @@ defmodule Explorer.Chain do !is_nil(transaction.contracts_creation_transaction) -> Data.to_string(transaction.contracts_creation_transaction.input) - true -> "" + true -> + "" end end diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index e7cc8c78a4..b72aa470f8 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -44,7 +44,7 @@ defmodule Explorer.SmartContract.Verifier do generated_bytecode != blockchain_bytecode -> {:error, :generated_bytecode} - !ConstructorArguments.verify(address_hash, bytecode, arguments_data) -> + !ConstructorArguments.verify(address_hash, blockchain_bytecode, arguments_data) -> {:error, :constructor_arguments} true -> diff --git a/apps/explorer/test/explorer/smart_contract/verifier_test.exs b/apps/explorer/test/explorer/smart_contract/verifier_test.exs index 7d5a14be0e..a536532739 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier_test.exs @@ -56,6 +56,57 @@ defmodule Explorer.SmartContract.VerifierTest do assert abi != nil end + test "verifies smart contract with constructor arguments", %{ + contract_code_info: contract_code_info + } do + contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode) + + constructor_arguments = "0102030405" + + params = %{ + "contract_source_code" => contract_code_info.source_code, + "compiler_version" => contract_code_info.version, + "name" => contract_code_info.name, + "optimization" => contract_code_info.optimized, + "constructor_arguments" => constructor_arguments + } + + :transaction + |> insert( + created_contract_address_hash: contract_address.hash, + input: Verifier.extract_bytecode(contract_code_info.bytecode) <> constructor_arguments + ) + |> with_block() + + assert {:ok, %{abi: abi}} = Verifier.evaluate_authenticity(contract_address.hash, params) + assert abi != nil + end + + test "returns error when constructor arguments do not match", %{ + contract_code_info: contract_code_info + } do + contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode) + + constructor_arguments = "0102030405" + + params = %{ + "contract_source_code" => contract_code_info.source_code, + "compiler_version" => contract_code_info.version, + "name" => contract_code_info.name, + "optimization" => contract_code_info.optimized, + "constructor_arguments" => constructor_arguments + } + + :transaction + |> insert( + created_contract_address_hash: contract_address.hash, + input: Verifier.extract_bytecode(contract_code_info.bytecode) <> "010203" + ) + |> with_block() + + assert {:error, :constructor_arguments} = Verifier.evaluate_authenticity(contract_address.hash, params) + end + test "returns error when bytecode doesn't match", %{contract_code_info: contract_code_info} do contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode) From d73c09ad870e20cc91f3ef0a7b7a0a7ee01ece37 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 7 Feb 2019 13:44:12 +0300 Subject: [PATCH 5/9] fix nil input data --- apps/explorer/lib/explorer/chain.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index e58953404d..40b6a8c20d 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1884,12 +1884,12 @@ defmodule Explorer.Chain do cond do is_nil(transaction) -> - nil + "" - !is_nil(transaction.contracts_creation_internal_transaction) -> + transaction.contracts_creation_internal_transaction && transaction.contracts_creation_internal_transaction.input -> Data.to_string(transaction.contracts_creation_internal_transaction.input) - !is_nil(transaction.contracts_creation_transaction) -> + transaction.contracts_creation_transaction && transaction.contracts_creation_transaction.input -> Data.to_string(transaction.contracts_creation_transaction.input) true -> From da9d6e5f3153f6bf82cd49e606b30f31d8e8ab1f Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 7 Feb 2019 15:15:01 +0300 Subject: [PATCH 6/9] add constructor arguments field to smart contract --- .../lib/explorer/chain/smart_contract.ex | 12 +++++++- .../lib/explorer/smart_contract/publisher.ex | 10 +++++++ ...nstructor_arguments_to_smart_contracts.exs | 9 ++++++ apps/explorer/test/explorer/chain_test.exs | 2 +- .../smart_contract/publisher_test.exs | 30 +++++++++++++++++++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 apps/explorer/priv/repo/migrations/20190207105501_add_constructor_arguments_to_smart_contracts.exs diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index 7e78c7aa17..e61afea2d4 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -202,6 +202,7 @@ defmodule Explorer.Chain.SmartContract do field(:compiler_version, :string) field(:optimization, :boolean) field(:contract_source_code, :string) + field(:constructor_arguments, :string) field(:abi, {:array, :map}) belongs_to( @@ -217,7 +218,15 @@ defmodule Explorer.Chain.SmartContract do def changeset(%__MODULE__{} = smart_contract, attrs) do smart_contract - |> cast(attrs, [:name, :compiler_version, :optimization, :contract_source_code, :address_hash, :abi]) + |> cast(attrs, [ + :name, + :compiler_version, + :optimization, + :contract_source_code, + :address_hash, + :abi, + :constructor_arguments + ]) |> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash]) |> unique_constraint(:address_hash) end @@ -231,6 +240,7 @@ defmodule Explorer.Chain.SmartContract do defp error_message(:compilation), do: "There was an error compiling your contract." defp error_message(:generated_bytecode), do: "Bytecode does not match, please try again." + defp error_message(:constructor_arguments), do: "Constructor arguments do not match, please try again." defp error_message(:name), do: "Wrong contract name, please try again." defp error_message(_), do: "There was an error validating your contract, please try again." end diff --git a/apps/explorer/lib/explorer/smart_contract/publisher.ex b/apps/explorer/lib/explorer/smart_contract/publisher.ex index ef2a986ca2..a170f577ee 100644 --- a/apps/explorer/lib/explorer/smart_contract/publisher.ex +++ b/apps/explorer/lib/explorer/smart_contract/publisher.ex @@ -55,12 +55,22 @@ defmodule Explorer.SmartContract.Publisher do end defp attributes(address_hash, params, abi \\ %{}) do + constructor_arguments = params["constructor_arguments"] + + constructor_arguments = + if constructor_arguments != nil && constructor_arguments != "" do + constructor_arguments + else + nil + end + %{ address_hash: address_hash, name: params["name"], compiler_version: params["compiler_version"], optimization: params["optimization"], contract_source_code: params["contract_source_code"], + constructor_arguments: constructor_arguments, abi: abi } end diff --git a/apps/explorer/priv/repo/migrations/20190207105501_add_constructor_arguments_to_smart_contracts.exs b/apps/explorer/priv/repo/migrations/20190207105501_add_constructor_arguments_to_smart_contracts.exs new file mode 100644 index 0000000000..0c71e46d48 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20190207105501_add_constructor_arguments_to_smart_contracts.exs @@ -0,0 +1,9 @@ +defmodule Explorer.Repo.Migrations.AddConstructorArgumentsToSmartContracts do + use Ecto.Migration + + def change do + alter table(:smart_contracts) do + add(:constructor_arguments, :string, null: true) + end + end +end diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 6fef5835ff..807ab66c9d 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -3608,7 +3608,7 @@ defmodule Explorer.ChainTest do found_creation_data = Chain.contract_creation_input_data(hash) - assert is_nil(found_creation_data) + assert found_creation_data == "" end end end diff --git a/apps/explorer/test/explorer/smart_contract/publisher_test.exs b/apps/explorer/test/explorer/smart_contract/publisher_test.exs index 00641478bd..b459bed32a 100644 --- a/apps/explorer/test/explorer/smart_contract/publisher_test.exs +++ b/apps/explorer/test/explorer/smart_contract/publisher_test.exs @@ -7,6 +7,7 @@ defmodule Explorer.SmartContract.PublisherTest do alias Explorer.Chain.SmartContract alias Explorer.SmartContract.Publisher + alias Explorer.SmartContract.Verifier alias Explorer.Factory describe "publish/2" do @@ -30,9 +31,38 @@ defmodule Explorer.SmartContract.PublisherTest do assert smart_contract.compiler_version == valid_attrs["compiler_version"] assert smart_contract.optimization == valid_attrs["optimization"] assert smart_contract.contract_source_code == valid_attrs["contract_source_code"] + assert is_nil(smart_contract.constructor_arguments) assert smart_contract.abi != nil end + test "creates a smart contract with constructor arguments" do + contract_code_info = Factory.contract_code_info() + + contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode) + + constructor_arguments = "0102030405" + + params = %{ + "contract_source_code" => contract_code_info.source_code, + "compiler_version" => contract_code_info.version, + "name" => contract_code_info.name, + "optimization" => contract_code_info.optimized, + "constructor_arguments" => constructor_arguments + } + + :transaction + |> insert( + created_contract_address_hash: contract_address.hash, + input: Verifier.extract_bytecode(contract_code_info.bytecode) <> constructor_arguments + ) + |> with_block() + + response = Publisher.publish(contract_address.hash, params) + assert {:ok, %SmartContract{} = smart_contract} = response + + assert smart_contract.constructor_arguments == constructor_arguments + end + test "with invalid data returns error changeset" do address_hash = "" From 4240af044d0a7d6462811e321ea4cf6ee81f90bf Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 7 Feb 2019 15:34:18 +0300 Subject: [PATCH 7/9] add constructor arguments field to the view --- .../new.html.eex | 6 +++ apps/block_scout_web/priv/gettext/default.pot | 35 ++++++++++-------- .../priv/gettext/en/LC_MESSAGES/default.po | 37 +++++++++++-------- .../lib/explorer/smart_contract/publisher.ex | 4 +- 4 files changed, 49 insertions(+), 33 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex index 76a979372b..220426b31f 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex @@ -49,6 +49,12 @@ <%= error_tag f, :contract_source_code, id: "contract-source-code-help-block", class: "text-danger", "data-test": "contract-source-code-error" %> +
+ <%= label f, :contructor_arguments, gettext("Enter contructor arguments if the contract had any") %> + <%= textarea f, :constructor_arguments, class: "form-control monospace", rows: 3, "aria-describedby": "contract-constructor-arguments-help-block" %> + <%= error_tag f, :constructor_arguments, id: "contract-constructor-arguments-help-block", class: "text-danger", "data-test": "contract-constructor-arguments-error" %> +
+

<%= gettext "Contract Libraries" %>

diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index ca4cec215f..fe717f3054 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -197,7 +197,7 @@ msgid "Blocks Validated" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:119 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:125 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:24 msgid "Cancel" msgstr "" @@ -714,7 +714,7 @@ msgid "Request URL" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:117 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:123 msgid "Reset" msgstr "" @@ -1031,7 +1031,7 @@ msgid "Verify & Publish" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:116 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:122 msgid "Verify & publish" msgstr "" @@ -1172,7 +1172,7 @@ msgid "Loading..." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:114 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:120 msgid "Loading...." msgstr "" @@ -1570,56 +1570,61 @@ msgid "Genesis Block" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:60 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:66 msgid "1 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:55 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:61 msgid "1 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:70 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:76 msgid "2 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:65 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:71 msgid "2 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:80 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:86 msgid "3 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:75 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:81 msgid "3 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:90 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:96 msgid "4 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:85 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:91 msgid "4 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:100 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:106 msgid "5 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:95 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:101 msgid "5 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:52 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:58 msgid "Contract Libraries" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:53 +msgid "Enter contructor arguments if the contract has any" +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 009303d05f..2b443c0b45 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 @@ -197,7 +197,7 @@ msgid "Blocks Validated" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:119 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:125 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:24 msgid "Cancel" msgstr "" @@ -714,7 +714,7 @@ msgid "Request URL" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:117 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:123 msgid "Reset" msgstr "" @@ -1031,7 +1031,7 @@ msgid "Verify & Publish" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:116 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:122 msgid "Verify & publish" msgstr "" @@ -1172,7 +1172,7 @@ msgid "Loading..." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:114 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:120 msgid "Loading...." msgstr "" @@ -1570,56 +1570,61 @@ msgid "Genesis Block" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:60 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:66 msgid "1 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:55 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:61 msgid "1 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:70 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:76 msgid "2 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:65 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:71 msgid "2 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:80 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:86 msgid "3 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:75 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:81 msgid "3 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:90 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:96 msgid "4 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:85 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:91 msgid "4 Library Name" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:100 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:106 msgid "5 Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:95 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:101 msgid "5 Library Name" msgstr "" -#, elixir-format, fuzzy -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:52 +#, elixir-format +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:58 msgid "Contract Libraries" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:53 +msgid "Enter contructor arguments if the contract has any" +msgstr "" diff --git a/apps/explorer/lib/explorer/smart_contract/publisher.ex b/apps/explorer/lib/explorer/smart_contract/publisher.ex index a170f577ee..4cc4d4f0a1 100644 --- a/apps/explorer/lib/explorer/smart_contract/publisher.ex +++ b/apps/explorer/lib/explorer/smart_contract/publisher.ex @@ -57,7 +57,7 @@ defmodule Explorer.SmartContract.Publisher do defp attributes(address_hash, params, abi \\ %{}) do constructor_arguments = params["constructor_arguments"] - constructor_arguments = + clean_constructor_arguments = if constructor_arguments != nil && constructor_arguments != "" do constructor_arguments else @@ -70,7 +70,7 @@ defmodule Explorer.SmartContract.Publisher do compiler_version: params["compiler_version"], optimization: params["optimization"], contract_source_code: params["contract_source_code"], - constructor_arguments: constructor_arguments, + constructor_arguments: clean_constructor_arguments, abi: abi } end From 6912c3f307e32e4fe65744336974c3f628dc546b Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 7 Feb 2019 15:38:29 +0300 Subject: [PATCH 8/9] fix gettext --- apps/block_scout_web/priv/gettext/default.pot | 2 +- apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index fe717f3054..781c55af15 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -1626,5 +1626,5 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:53 -msgid "Enter contructor arguments if the contract has any" +msgid "Enter contructor arguments if the contract had any" 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 2b443c0b45..62ae365a66 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 @@ -1624,7 +1624,7 @@ msgstr "" msgid "Contract Libraries" msgstr "" -#, elixir-format +#, elixir-format, fuzzy #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:53 -msgid "Enter contructor arguments if the contract has any" +msgid "Enter contructor arguments if the contract had any" msgstr "" From 86b0518cfe6d702a952da582b3c70d2b0d1569e9 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 13 Feb 2019 12:20:31 +0300 Subject: [PATCH 9/9] consider whisper data when verifying constructor arguments --- .../lib/explorer/smart_contract/verifier.ex | 5 +++-- .../smart_contract/publisher_test.exs | 3 +-- .../solidity/code_compiler_test.exs | 11 ++++++---- .../verifier/constructor_arguments_test.exs | 20 ++++++++++++++++++- .../explorer/smart_contract/verifier_test.exs | 2 +- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index b72aa470f8..d7df613f33 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -38,10 +38,11 @@ defmodule Explorer.SmartContract.Verifier do "0x" <> blockchain_bytecode = address_hash |> Chain.smart_contract_bytecode() - |> extract_bytecode + + blockchain_bytecode_without_whisper = extract_bytecode(blockchain_bytecode) cond do - generated_bytecode != blockchain_bytecode -> + generated_bytecode != blockchain_bytecode_without_whisper -> {:error, :generated_bytecode} !ConstructorArguments.verify(address_hash, blockchain_bytecode, arguments_data) -> diff --git a/apps/explorer/test/explorer/smart_contract/publisher_test.exs b/apps/explorer/test/explorer/smart_contract/publisher_test.exs index b459bed32a..2807dd3189 100644 --- a/apps/explorer/test/explorer/smart_contract/publisher_test.exs +++ b/apps/explorer/test/explorer/smart_contract/publisher_test.exs @@ -7,7 +7,6 @@ defmodule Explorer.SmartContract.PublisherTest do alias Explorer.Chain.SmartContract alias Explorer.SmartContract.Publisher - alias Explorer.SmartContract.Verifier alias Explorer.Factory describe "publish/2" do @@ -53,7 +52,7 @@ defmodule Explorer.SmartContract.PublisherTest do :transaction |> insert( created_contract_address_hash: contract_address.hash, - input: Verifier.extract_bytecode(contract_code_info.bytecode) <> constructor_arguments + input: contract_code_info.bytecode <> constructor_arguments ) |> with_block() diff --git a/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs b/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs index 5bd3b24103..b030c900bb 100644 --- a/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs +++ b/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs @@ -163,9 +163,12 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do end defp remove_init_data_and_whisper_data(code) do - code - |> String.split("0029") - |> List.first() - |> String.split_at(-64) + {res, _} = + code + |> String.split("0029") + |> List.first() + |> String.split_at(-64) + + res end end diff --git a/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs index 989f07dbce..a9de1e2e5e 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs @@ -7,7 +7,7 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do alias Explorer.SmartContract.Verifier.ConstructorArguments describe "verify/3" do - test "verifies construct arguments" do + test "verifies constructor arguments" do bytecode = "0x0102030" constructor_arguments = "0x405" address = insert(:address) @@ -23,4 +23,22 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do assert ConstructorArguments.verify(address.hash, bytecode, constructor_arguments) end end + + test "veriies constructor constructor arguments with whisper data" do + bytecode = "0x0102035d943c575be8a2aee2bb7737a765fdd2c6e49b74cd2c92ab0fa8e4282d1a75ae0029" + constructor_arguments = "0x0405" + address = insert(:address) + + input = %Data{ + bytes: + <<1, 2, 3, 93, 148, 60, 87, 91, 232, 162, 174, 226, 187, 119, 55, 167, 101, 253, 210, 198, 228, 155, 116, 205, + 44, 146, 171, 15, 168, 228, 40, 45, 26, 117, 174, 0, 41, 4, 5>> + } + + :transaction + |> insert(created_contract_address_hash: address.hash, input: input) + |> with_block() + + assert ConstructorArguments.verify(address.hash, bytecode, constructor_arguments) + end end diff --git a/apps/explorer/test/explorer/smart_contract/verifier_test.exs b/apps/explorer/test/explorer/smart_contract/verifier_test.exs index a536532739..584bb568ef 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier_test.exs @@ -74,7 +74,7 @@ defmodule Explorer.SmartContract.VerifierTest do :transaction |> insert( created_contract_address_hash: contract_address.hash, - input: Verifier.extract_bytecode(contract_code_info.bytecode) <> constructor_arguments + input: contract_code_info.bytecode <> constructor_arguments ) |> with_block()