add find_contructor_arguments

pull/2821/head
Ayrat Badykov 5 years ago
parent 71d92e600c
commit e383413e7f
No known key found for this signature in database
GPG Key ID: B44668E265E9396F
  1. 44
      apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex
  2. 105
      apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs

@ -2,7 +2,7 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do
@moduledoc """ @moduledoc """
Smart contract contrstructor arguments verification logic. Smart contract contrstructor arguments verification logic.
""" """
alias ABI.{FunctionSelector, TypeDecoder}
alias Explorer.Chain alias Explorer.Chain
def verify(address_hash, contract_code, arguments_data) do def verify(address_hash, contract_code, arguments_data) do
@ -15,7 +15,7 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do
check_func = fn assumed_arguments -> assumed_arguments == arguments_data end check_func = fn assumed_arguments -> assumed_arguments == arguments_data end
if verify_older_version(creation_code, contract_code, arguments_data) do if verify_older_version(creation_code, contract_code, check_func) do
true true
else else
extract_constructor_arguments(creation_code, check_func) extract_constructor_arguments(creation_code, check_func)
@ -24,11 +24,11 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do
# Earlier versions of Solidity didn't have whisper code. # Earlier versions of Solidity didn't have whisper code.
# constructor argument were directly appended to source code # constructor argument were directly appended to source code
defp verify_older_version(creation_code, contract_code, arguments_data) do defp verify_older_version(creation_code, contract_code, check_func) do
creation_code creation_code
|> String.split(contract_code) |> String.split(contract_code)
|> List.last() |> List.last()
|> Kernel.==(arguments_data) |> check_func.()
end end
defp extract_constructor_arguments(code, check_func) do defp extract_constructor_arguments(code, check_func) do
@ -74,18 +74,30 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do
end end
end end
# def find_contructor_arguments(address_hash, contract_code, abi) do def find_contructor_arguments(address_hash, contract_code, abi) do
# arguments_data = arguments_data |> String.trim_trailing() |> String.trim_leading("0x") creation_code =
address_hash
|> Chain.contract_creation_input_data()
|> String.replace("0x", "")
constructor_abi = Enum.find(abi, fn el -> el["type"] == "constructor" && el["inputs"] != [] end)
# creation_code = input_types = Enum.map(constructor_abi["inputs"], &FunctionSelector.parse_specification_type/1)
# address_hash
# |> Chain.contract_creation_input_data()
# |> String.replace("0x", "")
# if verify_older_version(creation_code, contract_code, arguments_data) do check_func = fn assumed_arguments ->
# true try do
# else _ =
# extract_constructor_arguments(creation_code, arguments_data) assumed_arguments
# end |> Base.decode16!(case: :mixed)
# end |> TypeDecoder.decode_raw(input_types)
assumed_arguments
rescue
_ -> false
end
end
verify_older_version(creation_code, contract_code, check_func) ||
extract_constructor_arguments(creation_code, check_func)
end
end end

@ -6,63 +6,86 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do
alias Explorer.Chain.Data alias Explorer.Chain.Data
alias Explorer.SmartContract.Verifier.ConstructorArguments alias Explorer.SmartContract.Verifier.ConstructorArguments
test "veriies constructor constructor arguments with whisper data" do describe "verify/3" do
constructor_arguments = Base.encode16(:crypto.strong_rand_bytes(64), case: :lower) test "veriies constructor constructor arguments with whisper data" do
address = insert(:address) constructor_arguments = Base.encode16(:crypto.strong_rand_bytes(64), case: :lower)
address = insert(:address)
input = input =
"a165627a7a72305820" <> "a165627a7a72305820" <>
Base.encode16(:crypto.strong_rand_bytes(32), case: :lower) <> "0029" <> constructor_arguments Base.encode16(:crypto.strong_rand_bytes(32), case: :lower) <> "0029" <> constructor_arguments
input_data = %Data{ input_data = %Data{
bytes: Base.decode16!(input, case: :lower) bytes: Base.decode16!(input, case: :lower)
} }
:transaction :transaction
|> insert(created_contract_address_hash: address.hash, input: input_data) |> insert(created_contract_address_hash: address.hash, input: input_data)
|> with_block() |> with_block()
assert ConstructorArguments.verify(address.hash, "", constructor_arguments) assert ConstructorArguments.verify(address.hash, "", constructor_arguments)
end end
test "verifies with multiple nested constructor arguments" do test "verifies with multiple nested constructor arguments" do
address = insert(:address) address = insert(:address)
constructor_arguments = constructor_arguments =
"000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0" "000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0"
input = input =
"a165627a7a72305820fbfa6f8a2024760ef0e0eb29a332c9a820526e92f8b4fbcce6f00c7643234b1400297b6c4b278d165a6b33958f8ea5dfb00c8c9d4d0acf1985bef5d10786898bc3e7a165627a7a723058203c2db82e7c80cd1e371fe349b03d49b812c324ba4a3fcd063b7bc2662353c5de0029000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0" "a165627a7a72305820fbfa6f8a2024760ef0e0eb29a332c9a820526e92f8b4fbcce6f00c7643234b1400297b6c4b278d165a6b33958f8ea5dfb00c8c9d4d0acf1985bef5d10786898bc3e7a165627a7a723058203c2db82e7c80cd1e371fe349b03d49b812c324ba4a3fcd063b7bc2662353c5de0029000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0"
input_data = %Data{ input_data = %Data{
bytes: Base.decode16!(input, case: :lower) bytes: Base.decode16!(input, case: :lower)
} }
:transaction :transaction
|> insert(created_contract_address_hash: address.hash, input: input_data) |> insert(created_contract_address_hash: address.hash, input: input_data)
|> with_block() |> with_block()
assert ConstructorArguments.verify(address.hash, "", constructor_arguments) assert ConstructorArguments.verify(address.hash, "", constructor_arguments)
end end
test "verifies older version of Solidity where constructor_arguments were directly appended to source code" do
address = insert(:address)
constructor_arguments =
"000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0"
test "verifies older version of Solidity where constructor_arguments were directly appended to source code" do source_code = "0001"
address = insert(:address)
constructor_arguments = input = source_code <> constructor_arguments
"000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0"
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, source_code, constructor_arguments)
end
end
source_code = "0001" describe "find_contructor_arguments/3" do
test "finds contructor arguments" do
address = insert(:address)
expected_contructor_arguments =
"000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0"
input = source_code <> constructor_arguments input =
"a165627a7a72305820fbfa6f8a2024760ef0e0eb29a332c9a820526e92f8b4fbcce6f00c7643234b1400297b6c4b278d165a6b33958f8ea5dfb00c8c9d4d0acf1985bef5d10786898bc3e7a165627a7a723058203c2db82e7c80cd1e371fe349b03d49b812c324ba4a3fcd063b7bc2662353c5de0029000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae00000000000000000000000000000000000000000000000000000000590b09b0"
input_data = %Data{ input_data = %Data{
bytes: Base.decode16!(input, case: :lower) bytes: Base.decode16!(input, case: :lower)
} }
:transaction :transaction
|> insert(created_contract_address_hash: address.hash, input: input_data) |> insert(created_contract_address_hash: address.hash, input: input_data)
|> with_block() |> with_block()
assert ConstructorArguments.verify(address.hash, source_code, constructor_arguments) assert ConstructorArguments.find_contructor_arguments(address.hash, "", %{})
end
end end
end end

Loading…
Cancel
Save