Extend getsourcecode API view with new output fields

pull/2857/head
Victor Baranov 5 years ago
parent 7286cbfa60
commit b5bce41ab9
  1. 1
      CHANGELOG.md
  2. 96
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/contract_view.ex
  3. 65
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs

@ -1,6 +1,7 @@
## Current ## Current
### Features ### Features
- [#2857](https://github.com/poanetwork/blockscout/pull/2857) - Extend getsourcecode API view with new output fields
- [#2787](https://github.com/poanetwork/blockscout/pull/2787) - async fetching of address counters - [#2787](https://github.com/poanetwork/blockscout/pull/2787) - async fetching of address counters
- [#2791](https://github.com/poanetwork/blockscout/pull/2791) - add ipc client - [#2791](https://github.com/poanetwork/blockscout/pull/2791) - add ipc client
- [#2449](https://github.com/poanetwork/blockscout/pull/2449) - add ability to send notification events through postgres notify - [#2449](https://github.com/poanetwork/blockscout/pull/2449) - add ability to send notification events through postgres notify

@ -35,7 +35,11 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
"CompilerVersion" => "", "CompilerVersion" => "",
"DecompiledSourceCode" => "", "DecompiledSourceCode" => "",
"DecompilerVersion" => decompiler_version(nil), "DecompilerVersion" => decompiler_version(nil),
"OptimizationUsed" => "" "OptimizationUsed" => "",
"OptimizationRuns" => "",
"EVMVersion" => "",
"ConstructorArguments" => "",
"ExternalLibraries" => ""
} }
end end
@ -43,6 +47,64 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
decompiled_smart_contract = latest_decompiled_smart_contract(address.decompiled_smart_contracts) decompiled_smart_contract = latest_decompiled_smart_contract(address.decompiled_smart_contracts)
contract = address.smart_contract || %{} contract = address.smart_contract || %{}
optimization = Map.get(contract, :optimization, "")
contract_output = %{
"Address" => to_string(address.hash)
}
contract_output
|> set_decompiled_contract_data(decompiled_smart_contract)
|> set_optimization_runs(contract, optimization)
|> set_constructor_arguments(contract)
|> set_external_libraries(contract)
|> set_verified_contract_data(contract, address, optimization)
end
defp set_decompiled_contract_data(contract_output, decompiled_smart_contract) do
if decompiled_smart_contract do
contract_output
|> Map.put_new(:DecompiledSourceCode, decompiled_source_code(decompiled_smart_contract))
|> Map.put_new(:DecompilerVersion, decompiler_version(decompiled_smart_contract))
else
contract_output
end
end
defp set_optimization_runs(contract_output, contract, optimization) do
optimization_runs = Map.get(contract, :optimization_runs, "")
if optimization && optimization != "" do
contract_output
|> Map.put_new(:OptimizationRuns, optimization_runs)
else
contract_output
end
end
defp set_constructor_arguments(contract_output, contract) do
constructor_arguments = Map.get(contract, :constructor_arguments, "")
if constructor_arguments && constructor_arguments != "" do
contract_output
|> Map.put_new(:ConstructorArguments, constructor_arguments)
else
contract_output
end
end
defp set_external_libraries(contract_output, contract) do
external_libraries = Map.get(contract, :external_libraries, [])
if Enum.count(external_libraries) > 0 do
contract_output
|> Map.put_new(:ExternalLibraries, external_libraries)
else
contract_output
end
end
defp set_verified_contract_data(contract_output, contract, address, optimization) do
contract_abi = contract_abi =
if is_nil(address.smart_contract) do if is_nil(address.smart_contract) do
"Contract source code not verified" "Contract source code not verified"
@ -51,27 +113,28 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
end end
contract_optimization = contract_optimization =
case Map.get(contract, :optimization, "") do case optimization do
true -> true ->
"1" "true"
false -> false ->
"0" "false"
"" -> "" ->
"" ""
end end
%{ if Map.equal?(contract, %{}) do
"Address" => to_string(address.hash), contract_output
"SourceCode" => Map.get(contract, :contract_source_code, ""), else
"ABI" => contract_abi, contract_output
"ContractName" => Map.get(contract, :name, ""), |> Map.put_new(:SourceCode, Map.get(contract, :contract_source_code, ""))
"DecompiledSourceCode" => decompiled_source_code(decompiled_smart_contract), |> Map.put_new(:ABI, contract_abi)
"DecompilerVersion" => decompiler_version(decompiled_smart_contract), |> Map.put_new(:ContractName, Map.get(contract, :name, ""))
"CompilerVersion" => Map.get(contract, :compiler_version, ""), |> Map.put_new(:CompilerVersion, Map.get(contract, :compiler_version, ""))
"OptimizationUsed" => contract_optimization |> Map.put_new(:OptimizationUsed, contract_optimization)
} |> Map.put_new(:EVMVersion, Map.get(contract, :evm_version, ""))
end
end end
defp prepare_contract(%Address{ defp prepare_contract(%Address{
@ -80,10 +143,7 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
}) do }) do
%{ %{
"Address" => to_string(hash), "Address" => to_string(hash),
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified"
"ContractName" => "",
"CompilerVersion" => "",
"OptimizationUsed" => ""
} }
end end

@ -70,10 +70,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == [ assert response["result"] == [
%{ %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(address.hash), "Address" => to_string(address.hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} }
] ]
@ -95,10 +92,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == [ assert response["result"] == [
%{ %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(address.hash), "Address" => to_string(address.hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} }
] ]
@ -124,10 +118,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == [ assert response["result"] == [
%{ %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(address.hash), "Address" => to_string(address.hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} }
] ]
@ -174,10 +165,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == [ assert response["result"] == [
%{ %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(decompiled_smart_contract.address_hash), "Address" => to_string(decompiled_smart_contract.address_hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} }
] ]
@ -199,10 +187,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == [ assert response["result"] == [
%{ %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(smart_contract.address_hash), "Address" => to_string(smart_contract.address_hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} }
] ]
@ -225,10 +210,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert %{ assert %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(smart_contract.address_hash), "Address" => to_string(smart_contract.address_hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} in response["result"] } in response["result"]
refute to_string(non_match.address_hash) in Enum.map(response["result"], &Map.get(&1, "Address")) refute to_string(non_match.address_hash) in Enum.map(response["result"], &Map.get(&1, "Address"))
@ -251,10 +233,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == [ assert response["result"] == [
%{ %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(contract_address.hash), "Address" => to_string(contract_address.hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} }
] ]
@ -281,10 +260,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == [ assert response["result"] == [
%{ %{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(contract_address.hash), "Address" => to_string(contract_address.hash)
"CompilerVersion" => "",
"ContractName" => "",
"OptimizationUsed" => ""
} }
] ]
@ -423,7 +399,11 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"CompilerVersion" => "", "CompilerVersion" => "",
"OptimizationUsed" => "", "OptimizationUsed" => "",
"DecompiledSourceCode" => "", "DecompiledSourceCode" => "",
"DecompilerVersion" => "" "DecompilerVersion" => "",
"ConstructorArguments" => "",
"EVMVersion" => "",
"ExternalLibraries" => "",
"OptimizationRuns" => ""
} }
] ]
@ -439,7 +419,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
end end
test "with a verified contract address", %{conn: conn} do test "with a verified contract address", %{conn: conn} do
contract = insert(:smart_contract, optimization: true) contract = insert(:smart_contract, optimization: true, optimization_runs: 200, evm_version: "default")
params = %{ params = %{
"module" => "contract", "module" => "contract",
@ -456,12 +436,12 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"ABI" => Jason.encode!(contract.abi), "ABI" => Jason.encode!(contract.abi),
"ContractName" => contract.name, "ContractName" => contract.name,
"CompilerVersion" => contract.compiler_version, "CompilerVersion" => contract.compiler_version,
"DecompiledSourceCode" => "Contract source code not decompiled.",
# The contract's optimization value is true, so the expected value # The contract's optimization value is true, so the expected value
# for `OptimizationUsed` is "1". If it was false, the expected value # for `OptimizationUsed` is "1". If it was false, the expected value
# would be "0". # would be "0".
"DecompilerVersion" => "", "OptimizationUsed" => "true",
"OptimizationUsed" => "1" "OptimizationRuns" => 200,
"EVMVersion" => "default"
} }
] ]
@ -508,9 +488,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"ABI" => Jason.encode!(contract_code_info.abi), "ABI" => Jason.encode!(contract_code_info.abi),
"ContractName" => contract_code_info.name, "ContractName" => contract_code_info.name,
"CompilerVersion" => contract_code_info.version, "CompilerVersion" => contract_code_info.version,
"DecompiledSourceCode" => "Contract source code not decompiled.", "OptimizationUsed" => "false",
"DecompilerVersion" => "", "EVMVersion" => nil
"OptimizationUsed" => "0"
} }
assert response["status"] == "1" assert response["status"] == "1"
@ -578,9 +557,9 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
contract_source_code contract_source_code
assert result["ContractName"] == name assert result["ContractName"] == name
assert result["DecompiledSourceCode"] == "Contract source code not decompiled." assert result["DecompiledSourceCode"] == nil
assert result["DecompilerVersion"] == "" assert result["DecompilerVersion"] == nil
assert result["OptimizationUsed"] == "1" assert result["OptimizationUsed"] == "true"
assert :ok = ExJsonSchema.Validator.validate(verify_schema(), response) assert :ok = ExJsonSchema.Validator.validate(verify_schema(), response)
end end
end end

Loading…
Cancel
Save