fix: resolve false positive constructor arguments

pull/1875/head
zachdaniel 6 years ago
parent 8f66fb48bf
commit e08b9f7ecc
  1. 1
      CHANGELOG.md
  2. 6
      apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
  3. 31
      apps/explorer/lib/explorer/smart_contract/verifier.ex
  4. 18
      apps/explorer/test/explorer/smart_contract/verifier_test.exs

@ -25,6 +25,7 @@
- [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code
- [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete
- [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance
- [#1875](https://github.com/poanetwork/blockscout/pull/1875) - fix: resolve false positive constructor arguments
### Chore

@ -63,6 +63,7 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
}
}
"""
@spec run(Keyword.t()) :: {:ok, map} | {:error, :compilation | :name}
def run(params) do
name = Keyword.fetch!(params, :name)
compiler_version = Keyword.fetch!(params, :compiler_version)
@ -108,9 +109,14 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
{:error, %Jason.DecodeError{}} ->
{:error, :compilation}
{:error, reason} when reason in [:name, :compilation] ->
{:error, reason}
error ->
parse_error(error)
end
else
{:error, :compilation}
end
end

@ -86,17 +86,32 @@ defmodule Explorer.SmartContract.Verifier do
In order to discover the bytecode we need to remove the `swarm source` from
the hash.
`64` characters to the left of `0029` are the `swarm source`. The rest on
the left is the `bytecode` to be validated.
For more information on the swarm hash, check out:
https://solidity.readthedocs.io/en/v0.5.3/metadata.html#encoding-of-the-metadata-hash-in-the-bytecode
"""
def extract_bytecode("0x" <> code) do
"0x" <> extract_bytecode(code)
end
def extract_bytecode(code) do
{bytecode, _swarm_source} =
code
|> String.split("0029")
|> List.first()
|> String.split_at(-64)
do_extract_bytecode([], String.downcase(code))
end
bytecode
defp do_extract_bytecode(extracted, remaining) do
case remaining do
<<>> ->
extracted
|> Enum.reverse()
|> :binary.list_to_bin()
"a165627a7a72305820" <> <<_::binary-size(64)>> <> "0029" <> _constructor_arguments ->
extracted
|> Enum.reverse()
|> :binary.list_to_bin()
<<next::binary-size(2)>> <> rest ->
do_extract_bytecode([next | extracted], rest)
end
end
def next_evm_version(current_evm_version) do

@ -181,7 +181,7 @@ defmodule Explorer.SmartContract.VerifierTest do
swarm_source = "3c381c1b48b38d050c54d7ef296ecd411040e19420dfec94772b9c49ae106a0b"
bytecode =
"0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a72305820"
"0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600"
assert bytecode == Verifier.extract_bytecode(code)
assert bytecode != code
@ -189,5 +189,21 @@ defmodule Explorer.SmartContract.VerifierTest do
assert String.contains?(bytecode, "0029") == false
assert String.contains?(bytecode, swarm_source) == false
end
test "extracts everything to the left of the swarm hash" do
code =
"0x608060405234801561001057600080fd5b5060df80610010029f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a723058203c381c1b48b38d050c54d7ef296ecd411040e19420dfec94772b9c49ae106a0b0029"
swarm_source = "3c381c1b48b38d050c54d7ef296ecd411040e19420dfec94772b9c49ae106a0b"
bytecode =
"0x608060405234801561001057600080fd5b5060df80610010029f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600"
assert bytecode == Verifier.extract_bytecode(code)
assert bytecode != code
assert String.contains?(code, bytecode) == true
assert String.contains?(bytecode, "0029") == true
assert String.contains?(bytecode, swarm_source) == false
end
end
end

Loading…
Cancel
Save