|
|
@ -1,5 +1,6 @@ |
|
|
|
defmodule BlockScoutWeb.API.RPC.ContractControllerTest do |
|
|
|
defmodule BlockScoutWeb.API.RPC.ContractControllerTest do |
|
|
|
use BlockScoutWeb.ConnCase |
|
|
|
use BlockScoutWeb.ConnCase |
|
|
|
|
|
|
|
alias Explorer.Chain.SmartContract |
|
|
|
alias Explorer.{Chain, Factory} |
|
|
|
alias Explorer.{Chain, Factory} |
|
|
|
|
|
|
|
|
|
|
|
describe "listcontracts" do |
|
|
|
describe "listcontracts" do |
|
|
@ -70,10 +71,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 +93,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 +119,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 +166,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 +188,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 +211,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 +234,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 +261,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 +400,11 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do |
|
|
|
"CompilerVersion" => "", |
|
|
|
"CompilerVersion" => "", |
|
|
|
"OptimizationUsed" => "", |
|
|
|
"OptimizationUsed" => "", |
|
|
|
"DecompiledSourceCode" => "", |
|
|
|
"DecompiledSourceCode" => "", |
|
|
|
"DecompilerVersion" => "" |
|
|
|
"DecompilerVersion" => "", |
|
|
|
|
|
|
|
"ConstructorArguments" => "", |
|
|
|
|
|
|
|
"EVMVersion" => "", |
|
|
|
|
|
|
|
"ExternalLibraries" => "", |
|
|
|
|
|
|
|
"OptimizationRuns" => "" |
|
|
|
} |
|
|
|
} |
|
|
|
] |
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
@ -439,7 +420,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 +437,156 @@ 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" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert response = |
|
|
|
|
|
|
|
conn |
|
|
|
|
|
|
|
|> get("/api", params) |
|
|
|
|
|
|
|
|> json_response(200) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert response["result"] == expected_result |
|
|
|
|
|
|
|
assert response["status"] == "1" |
|
|
|
|
|
|
|
assert response["message"] == "OK" |
|
|
|
|
|
|
|
assert :ok = ExJsonSchema.Validator.validate(getsourcecode_schema(), response) |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test "with constructor arguments", %{conn: conn} do |
|
|
|
|
|
|
|
contract = |
|
|
|
|
|
|
|
insert(:smart_contract, |
|
|
|
|
|
|
|
optimization: true, |
|
|
|
|
|
|
|
optimization_runs: 200, |
|
|
|
|
|
|
|
evm_version: "default", |
|
|
|
|
|
|
|
constructor_arguments: |
|
|
|
|
|
|
|
"00000000000000000000000008e7592ce0d7ebabf42844b62ee6a878d4e1913e000000000000000000000000e1b6037da5f1d756499e184ca15254a981c92546" |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
params = %{ |
|
|
|
|
|
|
|
"module" => "contract", |
|
|
|
|
|
|
|
"action" => "getsourcecode", |
|
|
|
|
|
|
|
"address" => to_string(contract.address_hash) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expected_result = [ |
|
|
|
|
|
|
|
%{ |
|
|
|
|
|
|
|
"Address" => to_string(contract.address_hash), |
|
|
|
|
|
|
|
"SourceCode" => |
|
|
|
|
|
|
|
"/**\n* Submitted for verification at blockscout.com on #{contract.inserted_at}\n*/\n" <> |
|
|
|
|
|
|
|
contract.contract_source_code, |
|
|
|
|
|
|
|
"ABI" => Jason.encode!(contract.abi), |
|
|
|
|
|
|
|
"ContractName" => contract.name, |
|
|
|
|
|
|
|
"CompilerVersion" => contract.compiler_version, |
|
|
|
|
|
|
|
"OptimizationUsed" => "true", |
|
|
|
|
|
|
|
"OptimizationRuns" => 200, |
|
|
|
|
|
|
|
"EVMVersion" => "default", |
|
|
|
|
|
|
|
"ConstructorArguments" => |
|
|
|
|
|
|
|
"00000000000000000000000008e7592ce0d7ebabf42844b62ee6a878d4e1913e000000000000000000000000e1b6037da5f1d756499e184ca15254a981c92546" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert response = |
|
|
|
|
|
|
|
conn |
|
|
|
|
|
|
|
|> get("/api", params) |
|
|
|
|
|
|
|
|> json_response(200) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert response["result"] == expected_result |
|
|
|
|
|
|
|
assert response["status"] == "1" |
|
|
|
|
|
|
|
assert response["message"] == "OK" |
|
|
|
|
|
|
|
assert :ok = ExJsonSchema.Validator.validate(getsourcecode_schema(), response) |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test "with external library", %{conn: conn} do |
|
|
|
|
|
|
|
smart_contract_bytecode = |
|
|
|
|
|
|
|
"0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582040d82a7379b1ee1632ad4d8a239954fd940277b25628ead95259a85c5eddb2120029" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
created_contract_address = |
|
|
|
|
|
|
|
insert( |
|
|
|
|
|
|
|
:address, |
|
|
|
|
|
|
|
hash: "0x0f95fa9bc0383e699325f2658d04e8d96d87b90c", |
|
|
|
|
|
|
|
contract_code: smart_contract_bytecode |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
transaction = |
|
|
|
|
|
|
|
:transaction |
|
|
|
|
|
|
|
|> insert() |
|
|
|
|
|
|
|
|> with_block() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
insert( |
|
|
|
|
|
|
|
:internal_transaction_create, |
|
|
|
|
|
|
|
transaction: transaction, |
|
|
|
|
|
|
|
index: 0, |
|
|
|
|
|
|
|
created_contract_address: created_contract_address, |
|
|
|
|
|
|
|
created_contract_code: smart_contract_bytecode, |
|
|
|
|
|
|
|
block_number: transaction.block_number, |
|
|
|
|
|
|
|
transaction_index: transaction.index |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
valid_attrs = %{ |
|
|
|
|
|
|
|
address_hash: "0x0f95fa9bc0383e699325f2658d04e8d96d87b90c", |
|
|
|
|
|
|
|
name: "Test", |
|
|
|
|
|
|
|
compiler_version: "0.4.23", |
|
|
|
|
|
|
|
contract_source_code: |
|
|
|
|
|
|
|
"pragma solidity ^0.4.23; contract SimpleStorage {uint storedData; function set(uint x) public {storedData = x; } function get() public constant returns (uint) {return storedData; } }", |
|
|
|
|
|
|
|
abi: [ |
|
|
|
|
|
|
|
%{ |
|
|
|
|
|
|
|
"constant" => false, |
|
|
|
|
|
|
|
"inputs" => [%{"name" => "x", "type" => "uint256"}], |
|
|
|
|
|
|
|
"name" => "set", |
|
|
|
|
|
|
|
"outputs" => [], |
|
|
|
|
|
|
|
"payable" => false, |
|
|
|
|
|
|
|
"stateMutability" => "nonpayable", |
|
|
|
|
|
|
|
"type" => "function" |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
%{ |
|
|
|
|
|
|
|
"constant" => true, |
|
|
|
|
|
|
|
"inputs" => [], |
|
|
|
|
|
|
|
"name" => "get", |
|
|
|
|
|
|
|
"outputs" => [%{"name" => "", "type" => "uint256"}], |
|
|
|
|
|
|
|
"payable" => false, |
|
|
|
|
|
|
|
"stateMutability" => "view", |
|
|
|
|
|
|
|
"type" => "function" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
optimization: true, |
|
|
|
|
|
|
|
optimization_runs: 200, |
|
|
|
|
|
|
|
evm_version: "default" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
external_libraries = [ |
|
|
|
|
|
|
|
%SmartContract.ExternalLibrary{:address_hash => "0xb18aed9518d735482badb4e8b7fd8d2ba425ce95", :name => "Test"}, |
|
|
|
|
|
|
|
%SmartContract.ExternalLibrary{:address_hash => "0x283539e1b1daf24cdd58a3e934d55062ea663c3f", :name => "Test2"} |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, %SmartContract{} = contract} = Chain.create_smart_contract(valid_attrs, external_libraries) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
params = %{ |
|
|
|
|
|
|
|
"module" => "contract", |
|
|
|
|
|
|
|
"action" => "getsourcecode", |
|
|
|
|
|
|
|
"address" => to_string(contract.address_hash) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expected_result = [ |
|
|
|
|
|
|
|
%{ |
|
|
|
|
|
|
|
"Address" => to_string(contract.address_hash), |
|
|
|
|
|
|
|
"SourceCode" => |
|
|
|
|
|
|
|
"/**\n* Submitted for verification at blockscout.com on #{contract.inserted_at}\n*/\n" <> |
|
|
|
|
|
|
|
contract.contract_source_code, |
|
|
|
|
|
|
|
"ABI" => Jason.encode!(contract.abi), |
|
|
|
|
|
|
|
"ContractName" => contract.name, |
|
|
|
|
|
|
|
"CompilerVersion" => contract.compiler_version, |
|
|
|
|
|
|
|
"OptimizationUsed" => "true", |
|
|
|
|
|
|
|
"OptimizationRuns" => 200, |
|
|
|
|
|
|
|
"EVMVersion" => "default", |
|
|
|
|
|
|
|
"ExternalLibraries" => [ |
|
|
|
|
|
|
|
%{"name" => "Test", "address_hash" => "0xb18aed9518d735482badb4e8b7fd8d2ba425ce95"}, |
|
|
|
|
|
|
|
%{"name" => "Test2", "address_hash" => "0x283539e1b1daf24cdd58a3e934d55062ea663c3f"} |
|
|
|
|
|
|
|
] |
|
|
|
} |
|
|
|
} |
|
|
|
] |
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
@ -508,9 +633,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 +702,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 |
|
|
|