Add VerificationControllerTest

pull/6744/head
Nikita Pozdniakov 2 years ago
parent d72bd5a1a1
commit 4a7211e5d1
No known key found for this signature in database
GPG Key ID: F344106F9804FE5F
  1. 1
      .github/workflows/config.yml
  2. 2
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
  3. 4
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/address_controller_test.exs
  4. 6
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
  5. 1
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/address_controller_test.exs
  6. 2
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/search_controller_test.exs
  7. 2
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/token_controller_test.exs
  8. 307
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/verification_controller_test.exs
  9. 2
      apps/block_scout_web/test/block_scout_web/controllers/transaction_state_controller_test.exs
  10. 8
      apps/block_scout_web/test/block_scout_web/views/tokens/smart_contract_view_test.exs
  11. 2
      apps/block_scout_web/test/support/channel_case.ex
  12. 15
      apps/explorer/lib/explorer/smart_contract/solc_downloader.ex
  13. 21
      apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
  14. 33
      apps/explorer/test/support/fixture/smart_contract/standard_input.json
  15. 105
      apps/explorer/test/support/fixture/smart_contract/vyper.vy

@ -583,3 +583,4 @@ jobs:
ACCOUNT_ENABLED: "true" ACCOUNT_ENABLED: "true"
ACCOUNT_REDIS_URL: "redis://localhost:6379" ACCOUNT_REDIS_URL: "redis://localhost:6379"
API_V2_ENABLED: "true" API_V2_ENABLED: "true"
ENABLE_SOURCIFY_INTEGRATION: "true"

@ -85,7 +85,7 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
"address_hash" => String.downcase(address_hash_string), "address_hash" => String.downcase(address_hash_string),
"compiler_version" => compiler_version "compiler_version" => compiler_version
} }
|> Map.put("autodetect_constructor_args", Map.get(params, "autodetect_constructor_args", false)) |> Map.put("autodetect_constructor_args", Map.get(params, "autodetect_constructor_args", true))
|> Map.put("constructor_arguments", Map.get(params, "constructor_args", "")) |> Map.put("constructor_arguments", Map.get(params, "constructor_args", ""))
|> Map.put("name", Map.get(params, "contract_name", "")) |> Map.put("name", Map.get(params, "contract_name", ""))

@ -102,8 +102,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
first_address_hash = to_string(first_address.hash) first_address_hash = to_string(first_address.hash)
second_address_hash = to_string(second_address.hash) second_address_hash = to_string(second_address.hash)
first_address_inserted_at = to_string(first_address.inserted_at) _first_address_inserted_at = to_string(first_address.inserted_at)
second_address_inserted_at = to_string(second_address.inserted_at) _second_address_inserted_at = to_string(second_address.inserted_at)
response = response =
conn conn

@ -187,7 +187,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
params: params, params: params,
conn: conn conn: conn
} do } do
[contract_1, contract_2, contract_3] = prepare_contracts() [_contract_1, contract_2, _contract_3] = prepare_contracts()
filter_params = filter_params =
params params
@ -213,7 +213,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
params: params, params: params,
conn: conn conn: conn
} do } do
[contract_1, contract_2, contract_3] = prepare_contracts() [_contract_1, contract_2, contract_3] = prepare_contracts()
filter_params = filter_params =
params params
@ -238,7 +238,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
params: params, params: params,
conn: conn conn: conn
} do } do
[contract_1, contract_2, contract_3] = prepare_contracts() [contract_1, contract_2, _contract_3] = prepare_contracts()
filter_params = filter_params =
params params

@ -7,7 +7,6 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
Address, Address,
Address.CoinBalance, Address.CoinBalance,
Block, Block,
Data,
InternalTransaction, InternalTransaction,
Log, Log,
Token, Token,

@ -82,7 +82,7 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
test "check pagination", %{conn: conn} do test "check pagination", %{conn: conn} do
name = "contract" name = "contract"
contracts = insert_list(51, :smart_contract, name: name) _contracts = insert_list(51, :smart_contract, name: name)
request = get(conn, "/api/v2/search?q=#{name}") request = get(conn, "/api/v2/search?q=#{name}")
assert response = json_response(request, 200) assert response = json_response(request, 200)

@ -1,7 +1,7 @@
defmodule BlockScoutWeb.API.V2.TokenControllerTest do defmodule BlockScoutWeb.API.V2.TokenControllerTest do
use BlockScoutWeb.ConnCase use BlockScoutWeb.ConnCase
alias Explorer.{Chain, Repo} alias Explorer.Repo
alias Explorer.Chain.{Address, Token, TokenTransfer} alias Explorer.Chain.{Address, Token, TokenTransfer}

@ -154,7 +154,7 @@ defmodule BlockScoutWeb.TransactionStateControllerTest do
[%{id: id, method: "eth_getBalance", params: _}], _options -> [%{id: id, method: "eth_getBalance", params: _}], _options ->
{:ok, [%{id: id, result: integer_to_quantity(123)}]} {:ok, [%{id: id, result: integer_to_quantity(123)}]}
[%{id: id, method: "eth_getBlockByNumber", params: _}], _options -> [%{id: _id, method: "eth_getBlockByNumber", params: _}], _options ->
{:ok, {:ok,
[ [
%{ %{

@ -130,12 +130,4 @@ defmodule BlockScoutWeb.Tokens.SmartContractViewTest do
refute SmartContractView.named_argument?(arguments) refute SmartContractView.named_argument?(arguments)
end end
end end
defp wrap_it(output, length \\ -1) do
if length > @max_size do
"<details class=\"py-2 word-break-all\"><summary>Click to view</summary>#{output}</details>"
else
"<span class=\"word-break-all\" style=\"line-height: 3;\">#{output}</span>"
end
end
end end

@ -29,7 +29,7 @@ defmodule BlockScoutWeb.ChannelCase do
@dialyzer {:nowarn_function, __ex_unit_setup_0: 1} @dialyzer {:nowarn_function, __ex_unit_setup_0: 1}
setup tags do setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Explorer.Repo) _ = Ecto.Adapters.SQL.Sandbox.checkout(Explorer.Repo)
unless tags[:async] do unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()})

@ -9,14 +9,22 @@ defmodule Explorer.SmartContract.SolcDownloader do
@latest_compiler_refetch_time :timer.minutes(30) @latest_compiler_refetch_time :timer.minutes(30)
defp debug(value, key) do
require Logger
Logger.configure(truncate: :infinity)
Logger.info(key)
Logger.info(Kernel.inspect(value, limit: :infinity, printable_limit: :infinity))
value
end
def ensure_exists(version) do def ensure_exists(version) do
path = file_path(version) path = file_path(version) |> debug("filepath")
if File.exists?(path) && version !== "latest" do if File.exists?(path) && version !== "latest" do
path path |> debug("first if")
else else
compiler_versions = compiler_versions =
case CompilerVersion.fetch_versions(:solc) do case CompilerVersion.fetch_versions(:solc) |> debug("fetch version") do
{:ok, compiler_versions} -> {:ok, compiler_versions} ->
compiler_versions compiler_versions
@ -94,6 +102,7 @@ defmodule Explorer.SmartContract.SolcDownloader do
download_path download_path
|> HTTPoison.get!([], timeout: 60_000, recv_timeout: 60_000) |> HTTPoison.get!([], timeout: 60_000, recv_timeout: 60_000)
|> debug("HTTPoison download solcjs")
|> Map.get(:body) |> Map.get(:body)
end end
end end

@ -23,18 +23,17 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
do: {:error, :contract_source_code} do: {:error, :contract_source_code}
def evaluate_authenticity(address_hash, params) do def evaluate_authenticity(address_hash, params) do
# TODO: remove comments try do
# try do
evaluate_authenticity_inner(RustVerifierInterface.enabled?(), address_hash, params) evaluate_authenticity_inner(RustVerifierInterface.enabled?(), address_hash, params)
# rescue rescue
# exception -> exception ->
# Logger.error(fn -> Logger.error(fn ->
# [ [
# "Error while verifying smart-contract address: #{address_hash}, params: #{inspect(params, limit: :infinity, printable_limit: :infinity)}: ", "Error while verifying smart-contract address: #{address_hash}, params: #{inspect(params, limit: :infinity, printable_limit: :infinity)}: ",
# Exception.format(:error, exception) Exception.format(:error, exception)
# ] ]
# end) end)
# end end
end end
defp evaluate_authenticity_inner(true, address_hash, params) do defp evaluate_authenticity_inner(true, address_hash, params) do

@ -0,0 +1,33 @@
{
"language": "Solidity",
"sources": {
"./simple_storage.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @title Owner\n * @dev Set & change owner\n */\ncontract Owner {\n\n address private owner;\n \n // event for EVM logging 2345678ewqwertyui54567890987654345678\n event OwnerSet(address indexed oldOwner, address indexed newOwner);\n \n // modifier to check if caller is owner\n modifier isOwner() {\n // If the first argument of 'require' evaluates to 'false', execution terminates and all\n // changes to the state and to Ether balances are reverted.\n // This used to consume all gas in old EVM versions, but not anymore.\n // It is often a good idea to use 'require' to check if functions are called correctly.\n // As a second argument, you can also provide an explanation about what went wrong.\n require(msg.sender == owner, \"Caller is not owner\");\n _;\n }\n \n /**\n * @dev Set contract deployer as owner\n */\n constructor(uint112 abc, address abb, bytes32 ghnc) {\n // console.log(\"Owner contract deployed by:\", msg.sender);\n owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor\n emit OwnerSet(address(0), owner);\n }\n\n /**\n * @dev Change owner\n * @param newOwner address of new owner\n */\n function changeOwner(address newOwner) public isOwner {\n emit OwnerSet(owner, newOwner);\n owner = newOwner;\n }\n\n /**\n * @dev Return owner address \n * @return address of owner\n */\n function getOwner() external view returns (address) {\n return owner;\n }\n}"
}
},
"settings": {
"evmVersion":"london",
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 199
},
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers"
],
"": [
"id",
"ast"
]
}
}
}
}

@ -0,0 +1,105 @@
from vyper.interfaces import ERC20
implements: ERC20
event Transfer:
sender: indexed(address)
receiver: indexed(address)
value: uint256
event Approval:
owner: indexed(address)
spender: indexed(address)
value: uint256
name: public(String[64])
symbol: public(String[32])
decimals: public(uint256)
balanceOf: public(HashMap[address, uint256])
allowance: public(HashMap[address, HashMap[address, uint256]])
totalSupply: public(uint256)
minter: address
_supply: uint256
_check: uint256 #1% of the total supply check
@external
def __init__():
self._supply = 10_000_000_000
self._check = 100_000_000
self.decimals = 18
self.name = 'Kooopa'
self.symbol = 'KOO'
init_supply: uint256 = self._supply * 10 ** self.decimals
self.balanceOf[msg.sender] = init_supply
self.totalSupply = init_supply
self.minter = msg.sender
log Transfer(ZERO_ADDRESS, msg.sender, init_supply)
@internal
def _transfer(_from : address, _to : address, _value : uint256) -> bool:
assert _value <= self._check, 'Transfer limit of 1%(100 Million) Tokens'
TargetBalance: uint256 = self.balanceOf[_to] + _value
assert TargetBalance <= self._check, 'Single wallet cannot hold more than 1%(100 Million) Tokens'
self.balanceOf[_from] -= _value
self.balanceOf[_to] += _value
log Transfer(_from, _to, _value)
return True
@external
def transfer(_to : address, _value : uint256) -> bool:
self._transfer(msg.sender, _to, _value)
return True
@external
def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
self._transfer(_from, _to, _value)
self.allowance[_from][msg.sender] -= _value
return True
@external
def approve(_spender : address, _value : uint256) -> bool:
assert _value <= self._check, 'Cant Approve more than 1%(100 Million) Tokens for transfer'
self.allowance[msg.sender][_spender] = _value
log Approval(msg.sender, _spender, _value)
return True
@external
def mint(_to: address, _value: uint256):
assert msg.sender == self.minter
assert _to != ZERO_ADDRESS
self.totalSupply += _value
self.balanceOf[_to] += _value
log Transfer(ZERO_ADDRESS, _to, _value)
@internal
def _burn(_to: address, _value: uint256):
assert _to != ZERO_ADDRESS
self.totalSupply -= _value
self.balanceOf[_to] -= _value
log Transfer(_to, ZERO_ADDRESS, _value)
@external
def burn(_value: uint256):
self._burn(msg.sender, _value)
@external
def burnFrom(_to: address, _value: uint256):
self.allowance[_to][msg.sender] -= _value
self._burn(_to, _value)
Loading…
Cancel
Save