Skip to content

Commit

Permalink
fix: split constructor args for verification
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdaniel committed May 7, 2019
1 parent e08b9f7 commit c3a5218
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do

alias Explorer.SmartContract.SolcDownloader

require Logger

@new_contract_name "New.sol"
@allowed_evm_versions ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"]

Expand Down Expand Up @@ -101,7 +103,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
]
)

with {:ok, contracts} <- Jason.decode(response),
with {:ok, decoded} <- Jason.decode(response),
{:ok, contracts} <- get_contracts(decoded),
%{"abi" => abi, "evm" => %{"deployedBytecode" => %{"object" => bytecode}}} <-
get_contract_info(contracts, name) do
{:ok, %{"abi" => abi, "bytecode" => bytecode, "name" => name}}
Expand All @@ -113,7 +116,9 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
{:error, reason}

error ->
parse_error(error)
error = parse_error(error)
Logger.warn(["There was an error compiling a provided contract: ", inspect(error)])
{:error, :compilation}
end
else
{:error, :compilation}
Expand All @@ -139,10 +144,15 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
end
end

def parse_error(%{"error" => error}), do: {:error, [error]}
def parse_error(%{"errors" => errors}), do: {:error, errors}
def parse_error({:error, %{"error" => error}}), do: {:error, [error]}
def parse_error({:error, %{"errors" => errors}}), do: {:error, errors}
def parse_error({:error, _} = error), do: error

# Older solc-bin versions don't use filename as contract key
defp get_contracts(%{"contracts" => %{"New.sol" => contracts}}), do: {:ok, contracts}
defp get_contracts(%{"contracts" => %{"" => contracts}}), do: {:ok, contracts}
defp get_contracts(response), do: {:error, response}

defp optimize_value(false), do: "0"
defp optimize_value("false"), do: "0"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do

def verify(address_hash, arguments_data) do
arguments_data = String.replace(arguments_data, "0x", "")
creation_input_data = Chain.contract_creation_input_data(address_hash)

data_with_swarm =
creation_input_data
|> String.split("0029")
|> List.first()
|> Kernel.<>("0029")
address_hash
|> Chain.contract_creation_input_data()
|> String.replace("0x", "")
|> extract_constructor_arguments()
|> Kernel.==(arguments_data)
end

defp extract_constructor_arguments(<<>>), do: ""

expected_arguments_data =
creation_input_data
|> String.split(data_with_swarm)
|> List.last()
|> String.replace("0x", "")
defp extract_constructor_arguments("a165627a7a72305820" <> <<_::binary-size(64)>> <> "0029" <> constructor_arguments) do
constructor_arguments
end

expected_arguments_data == arguments_data
defp extract_constructor_arguments(<<_::binary-size(2)>> <> rest) do
extract_constructor_arguments(rest)
end
end
4 changes: 1 addition & 3 deletions apps/explorer/priv/compile_solc.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,4 @@ const input = {


const output = JSON.parse(solc.compile(JSON.stringify(input)))
/** Older solc-bin versions don't use filename as contract key */
const response = output.contracts[newContractName] || output.contracts['']
console.log(JSON.stringify(response));
console.log(JSON.stringify(output));
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do
alias Explorer.SmartContract.Verifier.ConstructorArguments

test "veriies constructor constructor arguments with whisper data" do
constructor_arguments = "0x0405"
constructor_arguments = Base.encode16(:crypto.strong_rand_bytes(64), case: :lower)
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>>
input =
"a165627a7a72305820" <>
Base.encode16(:crypto.strong_rand_bytes(32), case: :lower) <> "0029" <> constructor_arguments

input_data = %Data{
bytes: Base.decode16!(input, case: :lower)
}

:transaction
|> insert(created_contract_address_hash: address.hash, input: input)
|> insert(created_contract_address_hash: address.hash, input: input_data)
|> with_block()

assert ConstructorArguments.verify(address.hash, constructor_arguments)
Expand Down

0 comments on commit c3a5218

Please sign in to comment.