diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index 4c2daa680c..4303cf5b6b 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -69,7 +69,8 @@ defmodule Explorer.SmartContract.Verifier do blockchain_bytecode_without_whisper = extract_bytecode(blockchain_bytecode) cond do - generated_bytecode != blockchain_bytecode_without_whisper -> + generated_bytecode != blockchain_bytecode_without_whisper && + !try_library_verification(generated_bytecode, blockchain_bytecode_without_whisper) -> {:error, :generated_bytecode} has_constructor_with_params?(abi) && @@ -81,6 +82,17 @@ defmodule Explorer.SmartContract.Verifier do end end + defp try_library_verification( + "730000000000000000000000000000000000000000" <> bytecode, + <<_address::binary-size(42)>> <> bytecode + ) do + true + end + + defp try_library_verification(_, _) do + false + end + @doc """ In order to discover the bytecode we need to remove the `swarm source` from the hash. diff --git a/apps/explorer/test/explorer/smart_contract/verifier_test.exs b/apps/explorer/test/explorer/smart_contract/verifier_test.exs index fba0622964..088820beea 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier_test.exs @@ -144,6 +144,34 @@ defmodule Explorer.SmartContract.VerifierTest do assert abi != nil end + test "verifies a library" do + bytecode = + "0x7349f540c22cba15c47a08c235e20081474201a742301460806040526004361060335760003560e01c8063c2985578146038575b600080fd5b603e60b0565b6040805160208082528351818301528351919283929083019185019080838360005b8381101560765781810151838201526020016060565b50505050905090810190601f16801560a25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b604080518082019091526003815262666f6f60e81b60208201529056fea265627a7a72315820174b282a3ef3b9778d79fbc2e4c36bc939c54dfaaaa51d3122ee6e648093844c64736f6c634300050b0032" + + contract_address = insert(:contract_address, contract_code: bytecode) + + code = """ + pragma solidity 0.5.11; + + library Foo { + function foo() external pure returns (string memory) { + return "foo"; + } + } + """ + + params = %{ + "contract_source_code" => code, + "compiler_version" => "v0.5.11+commit.c082d0b4", + "evm_version" => "default", + "name" => "Foo", + "optimization" => true + } + + assert {:ok, %{abi: abi}} = Verifier.evaluate_authenticity(contract_address.hash, params) + assert abi != nil + end + test "verifies smart contract compiled with Solidity 0.5.9 (includes new metadata in bytecode) with constructor args" do path = File.cwd!() <> "/test/support/fixture/smart_contract/solidity_0.5.9_smart_contract.sol" contract = File.read!(path)