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 """
Smart contract contrstructor arguments verification logic.
"""
alias ABI.{FunctionSelector, TypeDecoder}
alias Explorer.Chain
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
if verify_older_version(creation_code, contract_code, arguments_data) do
if verify_older_version(creation_code, contract_code, check_func) do
true
else
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.
# 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
|> String.split(contract_code)
|> List.last()
|> Kernel.==(arguments_data)
|> check_func.()
end
defp extract_constructor_arguments(code, check_func) do
@ -74,18 +74,30 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do
end
end
# def find_contructor_arguments(address_hash, contract_code, abi) do
# arguments_data = arguments_data |> String.trim_trailing() |> String.trim_leading("0x")
def find_contructor_arguments(address_hash, contract_code, abi) do
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 =
# address_hash
# |> Chain.contract_creation_input_data()
# |> String.replace("0x", "")
input_types = Enum.map(constructor_abi["inputs"], &FunctionSelector.parse_specification_type/1)
# if verify_older_version(creation_code, contract_code, arguments_data) do
# true
# else
# extract_constructor_arguments(creation_code, arguments_data)
# end
# end
check_func = fn assumed_arguments ->
try do
_ =
assumed_arguments
|> Base.decode16!(case: :mixed)
|> 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

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

Loading…
Cancel
Save