diff --git a/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex index d6d1572f10..d37a395f6b 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex @@ -6,30 +6,37 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do alias Explorer.Chain def verify(address_hash, arguments_data) do - arguments_data = String.replace(arguments_data, "0x", "") + arguments_data = + arguments_data |> String.trim_trailing() |> String.trim_leading() |> String.replace("0x", "") |> IO.inspect() address_hash |> Chain.contract_creation_input_data() |> String.replace("0x", "") - |> extract_constructor_arguments() - |> Kernel.==(arguments_data) + |> extract_constructor_arguments(arguments_data) end - defp extract_constructor_arguments(<<>>), do: "" + defp extract_constructor_arguments(code, passed_constructor_arguments) do + case code do + "a165627a7a72305820" <> <<_::binary-size(64)>> <> "0029" <> constructor_arguments -> + if passed_constructor_arguments == constructor_arguments do + true + else + extract_constructor_arguments(constructor_arguments, passed_constructor_arguments) + end - defp extract_constructor_arguments("a165627a7a72305820" <> <<_::binary-size(64)>> <> "0029" <> constructor_arguments) do - constructor_arguments - end + "a265627a7a72305820" <> + <<_::binary-size(64)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0032" <> constructor_arguments -> + if passed_constructor_arguments == constructor_arguments do + true + else + extract_constructor_arguments(constructor_arguments, passed_constructor_arguments) + end - # Solidity >= 0.5.9; https://github.com/ethereum/solidity/blob/aa4ee3a1559ebc0354926af962efb3fcc7dc15bd/docs/metadata.rst - defp extract_constructor_arguments( - "a265627a7a72305820" <> - <<_::binary-size(64)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0032" <> constructor_arguments - ) do - constructor_arguments - end + <<>> -> + false - defp extract_constructor_arguments(<<_::binary-size(2)>> <> rest) do - extract_constructor_arguments(rest) + <<_::binary-size(2)>> <> rest -> + extract_constructor_arguments(rest, passed_constructor_arguments) + end 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 a5e019c86f..6d1a0fb7ca 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 @@ -24,4 +24,24 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do assert ConstructorArguments.verify(address.hash, constructor_arguments) end + + test "verifies with multiple nested constructor arguments" do + address = insert(:address) + + constructor_arguments = + "000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0" + + input = + "a165627a7a72305820fbfa6f8a2024760ef0e0eb29a332c9a820526e92f8b4fbcce6f00c7643234b1400297b6c4b278d165a6b33958f8ea5dfb00c8c9d4d0acf1985bef5d10786898bc3e7a165627a7a723058203c2db82e7c80cd1e371fe349b03d49b812c324ba4a3fcd063b7bc2662353c5de0029000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0" + + input_data = %Data{ + bytes: Base.decode16!(input, case: :lower) + } + + :transaction + |> insert(created_contract_address_hash: address.hash, input: input_data) + |> with_block() + + assert ConstructorArguments.verify(address.hash, constructor_arguments) + end end