merge master

pull/1815/head
saneery 6 years ago
commit 3cc9a7c4f4
  1. 2
      CHANGELOG.md
  2. 74
      apps/block_scout_web/lib/block_scout_web/controllers/api/v1/verified_smart_contract_controller.ex
  3. 1
      apps/block_scout_web/lib/block_scout_web/router.ex
  4. 72
      apps/block_scout_web/test/block_scout_web/controllers/api/v1/verified_smart_contract_controller_test.exs
  5. 7
      rel/commands/clear_build.sh

@ -3,11 +3,13 @@
### Features
- [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x"
- [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request
### Fixes
### Chore
- [#1814](https://github.com/poanetwork/blockscout/pull/1814) - Clear build artefacts script
## 1.3.10-beta

@ -0,0 +1,74 @@
defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
use BlockScoutWeb, :controller
alias Explorer.Chain
alias Explorer.Chain.Hash.Address
alias Explorer.SmartContract.Publisher
def create(conn, params) do
with {:ok, hash} <- validate_address_hash(params["address_hash"]),
:ok <- smart_contract_exists?(hash),
:ok <- verified_smart_contract_exists?(hash) do
external_libraries = fetch_external_libraries(params)
case Publisher.publish(hash, params, external_libraries) do
{:ok, _} ->
send_resp(conn, :created, Jason.encode!(%{status: :success}))
{:error, changeset} ->
errors =
changeset.errors
|> Enum.into(%{}, fn {field, {message, _}} ->
{field, message}
end)
send_resp(conn, :unprocessable_entity, encode(errors))
end
else
:invalid_address ->
send_resp(conn, :unprocessable_entity, encode(%{error: "address_hash is invalid"}))
:not_found ->
send_resp(conn, :unprocessable_entity, encode(%{error: "address is not found"}))
:contract_exists ->
send_resp(
conn,
:unprocessable_entity,
encode(%{error: "verified code already exists for this address"})
)
end
end
defp smart_contract_exists?(address_hash) do
case Chain.hash_to_address(address_hash) do
{:ok, _address} -> :ok
_ -> :not_found
end
end
defp validate_address_hash(address_hash) do
case Address.cast(address_hash) do
{:ok, hash} -> {:ok, hash}
:error -> :invalid_address
end
end
defp verified_smart_contract_exists?(address_hash) do
if Chain.address_hash_to_smart_contract(address_hash) do
:contract_exists
else
:ok
end
end
defp encode(data) do
Jason.encode!(data)
end
defp fetch_external_libraries(params) do
keys = Enum.flat_map(1..5, fn i -> ["library#{i}_name", "library#{i}_address"] end)
Map.take(params, keys)
end
end

@ -24,6 +24,7 @@ defmodule BlockScoutWeb.Router do
get("/supply", SupplyController, :supply)
resources("/decompiled_smart_contract", DecompiledSmartContractController, only: [:create])
resources("/verified_smart_contracts", VerifiedSmartContractController, only: [:create])
end
scope "/api", BlockScoutWeb.API.RPC do

@ -0,0 +1,72 @@
defmodule BlockScoutWeb.API.V1.VerifiedControllerTest do
use BlockScoutWeb.ConnCase
alias Explorer.Factory
# alias Explorer.Chain.DecompiledSmartContract
# import Ecto.Query,
# only: [from: 2]
test "verifying a standard smart contract", %{conn: conn} do
contract_code_info = Factory.contract_code_info()
contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode)
params = %{
"address_hash" => to_string(contract_address.hash),
"name" => contract_code_info.name,
"compiler_version" => contract_code_info.version,
"optimization" => contract_code_info.optimized,
"contract_source_code" => contract_code_info.source_code
}
response = post(conn, api_v1_verified_smart_contract_path(conn, :create), params)
assert response.status == 201
assert Jason.decode!(response.resp_body) == %{"status" => "success"}
end
test "verifying a smart contract with external libraries", %{conn: conn} do
contract_data =
"#{File.cwd!()}/test/support/fixture/smart_contract/compiler_tests.json"
|> File.read!()
|> Jason.decode!()
|> List.first()
%{
"compiler_version" => compiler_version,
"external_libraries" => external_libraries,
"name" => name,
"optimize" => optimize,
"contract" => contract_source_code,
"expected_bytecode" => expected_bytecode
} = contract_data
contract_address = insert(:contract_address, contract_code: "0x" <> expected_bytecode)
params = %{
"address_hash" => to_string(contract_address.hash),
"name" => name,
"compiler_version" => compiler_version,
"optimization" => optimize,
"contract_source_code" => contract_source_code
}
params_with_external_libraries =
external_libraries
|> Enum.with_index()
|> Enum.reduce(params, fn {{name, address}, index}, acc ->
name_key = "library#{index + 1}_name"
address_key = "library#{index + 1}_address"
acc
|> Map.put(name_key, name)
|> Map.put(address_key, address)
end)
response = post(conn, api_v1_verified_smart_contract_path(conn, :create), params_with_external_libraries)
assert response.status == 201
assert Jason.decode!(response.resp_body) == %{"status" => "success"}
end
end

@ -0,0 +1,7 @@
#!/bin/sh
rm -rf ./_build
rm -rf ./deps
rm -rf ./logs/dev
rm -rf ./apps/explorer/node_modules
rm -rf ./apps/block_scout_web/assets/node_modules
Loading…
Cancel
Save