Choose contracts to be analyzed by the SMTChecker

This commit is contained in:
Leonardo Alt 2021-04-15 12:31:45 +02:00
parent c3f639b355
commit dd1865873e
79 changed files with 1068 additions and 24 deletions

View File

@ -13,6 +13,7 @@ Language Features:
Compiler Features:
* Analysis: Properly detect circular references to the bytecode of other contracts across all function calls.
* Commandline Interface: Model checker option ``--model-checker-targets`` also accepts ``outOfBounds``.
* Commandline Interface: New model checker option ``--model-checker-contracts`` allows users to select which contracts should be analyzed as the most derived.
* Low-Level Inliner: Inline ordinary jumps to small blocks and jumps to small blocks that terminate.
* SMTChecker: Deprecate ``pragma experimental SMTChecker;`` and set default model checker engine to ``none``.
* SMTChecker: Report local variables in CHC counterexamples.
@ -20,6 +21,7 @@ Compiler Features:
* SMTChecker: Support file level functions and constants.
* Standard JSON: Model checker option ``settings.modelChecker.targets`` also accepts ``outOfBounds``.
* Standard JSON: Model checker option ``settings.modelChecker.targets`` takes an array of string targets instead of string of comma separated targets.
* Standard JSON: New model checker option ``settings.modelChecker.contracts`` allows users to select which contracts should be analyzed as the most derived.
* Yul Optimizer: Added a new step FunctionSpecializer, that specializes a function with its literal arguments.
* Yul EVM Code Transform: Stack Optimization: Reuse slots of unused function arguments and defer allocating stack slots for return variables until after expression statements and assignments that do not reference them.
* NatSpec: Allow ``@notice`` tag on non-public state variables and local variable declarations. The documentation will only be part of the AST, under the field ``documentation``.

View File

@ -472,6 +472,35 @@ A common subset of targets might be, for example:
There is no precise heuristic on how and when to split verification targets,
but it can be useful especially when dealing with large contracts.
Verified Contracts
==================
By default all the deployable contracts in the given sources are analyzed separately as
the one that will be deployed. This means that if a contract has many direct
and indirect inheritance parents, all of them will be analyzed on their own,
even though only the most derived will be accessed directly on the blockchain.
This causes an unnecessary burden on the SMTChecker and the solver. To aid
cases like this, users can specify which contracts should be analyzed as the
deployed one. The parent contracts are of course still analyzed, but only in
the context of the most derived contract, reducing the complexity of the
encoding and generated queries. Note that abstract contracts are by default
not analyzed as the most derived by the SMTChecker.
The chosen contracts can be given via a comma-separated list (whitespace is not
allowed) of <source>:<contract> pairs in the CLI:
``--model-checker-contracts "<source1.sol:contract1>,<source2.sol:contract2>,<source2.sol:contract3>"``,
and via the object ``settings.modelChecker.contracts`` in the :ref:`JSON input<compiler-api>`,
which has the following form:
.. code-block:: none
contracts
{
"source1.sol": ["contract1"],
"source2.sol": ["contract2", "contract3"]
}
.. _smtchecker_engines:
Model Checking Engines

View File

@ -377,6 +377,12 @@ Input Description
// The modelChecker object is experimental and subject to changes.
"modelChecker":
{
// Chose which contracts should be analyzed as the deployed one.
contracts:
{
"source1.sol": ["contract1"],
"source2.sol": ["contract2", "contract3"]
},
// Choose which model checker engine to use: all (default), bmc, chc, none.
"engine": "chc",
// Choose which targets should be checked: constantCondition,

View File

@ -41,10 +41,9 @@ BMC::BMC(
smtutil::SMTSolverChoice _enabledSolvers,
ModelCheckerSettings const& _settings
):
SMTEncoder(_context),
SMTEncoder(_context, _settings),
m_interface(make_unique<smtutil::SMTPortfolio>(_smtlib2Responses, _smtCallback, _enabledSolvers, _settings.timeout)),
m_outerErrorReporter(_errorReporter),
m_settings(_settings)
m_outerErrorReporter(_errorReporter)
{
#if defined (HAVE_Z3) || defined (HAVE_CVC4)
if (_enabledSolvers.some())
@ -838,7 +837,7 @@ void BMC::addVerificationTarget(
Expression const* _expression
)
{
if (!m_settings.targets.has(_type) || (m_currentContract && !m_currentContract->canBeDeployed()))
if (!m_settings.targets.has(_type) || (m_currentContract && !shouldAnalyze(*m_currentContract)))
return;
BMCVerificationTarget target{

View File

@ -193,8 +193,6 @@ private:
/// Targets that were already proven.
std::map<ASTNode const*, std::set<VerificationTargetType>> m_solvedTargets;
ModelCheckerSettings const& m_settings;
};
}

View File

@ -59,10 +59,9 @@ CHC::CHC(
SMTSolverChoice _enabledSolvers,
ModelCheckerSettings const& _settings
):
SMTEncoder(_context),
SMTEncoder(_context, _settings),
m_outerErrorReporter(_errorReporter),
m_enabledSolvers(_enabledSolvers),
m_settings(_settings)
m_enabledSolvers(_enabledSolvers)
{
bool usesZ3 = _enabledSolvers.z3;
#ifdef HAVE_Z3
@ -198,7 +197,7 @@ void CHC::endVisit(ContractDefinition const& _contract)
setCurrentBlock(*m_constructorSummaries.at(&_contract));
solAssert(&_contract == m_currentContract, "");
if (_contract.canBeDeployed())
if (shouldAnalyze(_contract))
{
auto constructor = _contract.constructor();
auto txConstraints = state().txTypeConstraints();
@ -283,7 +282,7 @@ void CHC::endVisit(FunctionDefinition const& _function)
!_function.isConstructor() &&
_function.isPublic() &&
contractFunctions(*m_currentContract).count(&_function) &&
m_currentContract->canBeDeployed()
shouldAnalyze(*m_currentContract)
)
{
auto sum = summary(_function);

View File

@ -374,8 +374,6 @@ private:
/// SMT solvers that are chosen at runtime.
smtutil::SMTSolverChoice m_enabledSolvers;
ModelCheckerSettings const& m_settings;
};
}

View File

@ -22,6 +22,7 @@
#endif
#include <range/v3/algorithm/any_of.hpp>
#include <range/v3/view.hpp>
using namespace std;
using namespace solidity;
@ -54,6 +55,38 @@ void ModelChecker::enableAllEnginesIfPragmaPresent(vector<shared_ptr<SourceUnit>
m_settings.engine = ModelCheckerEngine::All();
}
void ModelChecker::checkRequestedSourcesAndContracts(vector<shared_ptr<SourceUnit>> const& _sources)
{
map<string, set<string>> exist;
for (auto const& source: _sources)
for (auto node: source->nodes())
if (auto contract = dynamic_pointer_cast<ContractDefinition>(node))
exist[contract->sourceUnitName()].insert(contract->name());
// Requested sources
for (auto const& sourceName: m_settings.contracts.contracts | ranges::views::keys)
{
if (!exist.count(sourceName))
{
m_errorReporter.warning(
9134_error,
SourceLocation(),
"Requested source \"" + sourceName + "\" does not exist."
);
continue;
}
auto const& source = exist.at(sourceName);
// Requested contracts in source `s`.
for (auto const& contract: m_settings.contracts.contracts.at(sourceName))
if (!source.count(contract))
m_errorReporter.warning(
7400_error,
SourceLocation(),
"Requested contract \"" + contract + "\" does not exist in source \"" + sourceName + "\"."
);
}
}
void ModelChecker::analyze(SourceUnit const& _source)
{
// TODO This should be removed for 0.9.0.

View File

@ -58,6 +58,10 @@ public:
// TODO This should be removed for 0.9.0.
void enableAllEnginesIfPragmaPresent(std::vector<std::shared_ptr<SourceUnit>> const& _sources);
/// Generates error messages if the requested sources and contracts
/// do not exist.
void checkRequestedSourcesAndContracts(std::vector<std::shared_ptr<SourceUnit>> const& _sources);
void analyze(SourceUnit const& _sources);
/// This is used if the SMT solver is not directly linked into this binary.

View File

@ -62,3 +62,20 @@ bool ModelCheckerTargets::setFromString(string const& _target)
targets.insert(targetStrings.at(_target));
return true;
}
std::optional<ModelCheckerContracts> ModelCheckerContracts::fromString(string const& _contracts)
{
map<string, set<string>> chosen;
if (_contracts == "default")
return ModelCheckerContracts::Default();
for (auto&& sourceContract: _contracts | views::split(',') | ranges::to<vector<string>>())
{
auto&& names = sourceContract | views::split(':') | ranges::to<vector<string>>();
if (names.size() != 2 || names.at(0).empty() || names.at(1).empty())
return {};
chosen[names.at(0)].insert(names.at(1));
}
return ModelCheckerContracts{chosen};
}

View File

@ -26,6 +26,33 @@
namespace solidity::frontend
{
struct ModelCheckerContracts
{
/// By default all contracts are analyzed.
static ModelCheckerContracts Default() { return {}; }
/// Parses a string of the form <path>:<contract>,<path>:contract,...
/// and returns nullopt if a path or contract name is empty.
static std::optional<ModelCheckerContracts> fromString(std::string const& _contracts);
/// @returns true if all contracts should be analyzed.
bool isDefault() const { return contracts.empty(); }
bool has(std::string const& _source) const { return contracts.count(_source); }
bool has(std::string const& _source, std::string const& _contract) const
{
return has(_source) && contracts.at(_source).count(_contract);
}
/// Represents which contracts should be analyzed by the SMTChecker
/// as the most derived.
/// The key is the source file. If the map is empty, all sources must be analyzed.
/// For each source, contracts[source] represents the contracts in that source
/// that should be analyzed.
/// If the set of contracts is empty, all contracts in that source should be analyzed.
std::map<std::string, std::set<std::string>> contracts;
};
struct ModelCheckerEngine
{
bool bmc = false;
@ -58,7 +85,7 @@ enum class VerificationTargetType { ConstantCondition, Underflow, Overflow, Unde
struct ModelCheckerTargets
{
static ModelCheckerTargets All() { return *fromString("default"); }
static ModelCheckerTargets Default() { return *fromString("default"); }
static std::optional<ModelCheckerTargets> fromString(std::string const& _targets);
@ -75,8 +102,9 @@ struct ModelCheckerTargets
struct ModelCheckerSettings
{
ModelCheckerContracts contracts = ModelCheckerContracts::Default();
ModelCheckerEngine engine = ModelCheckerEngine::None();
ModelCheckerTargets targets = ModelCheckerTargets::All();
ModelCheckerTargets targets = ModelCheckerTargets::Default();
std::optional<unsigned> timeout;
};

View File

@ -43,9 +43,13 @@ using namespace solidity::util;
using namespace solidity::langutil;
using namespace solidity::frontend;
SMTEncoder::SMTEncoder(smt::EncodingContext& _context):
SMTEncoder::SMTEncoder(
smt::EncodingContext& _context,
ModelCheckerSettings const& _settings
):
m_errorReporter(m_smtErrors),
m_context(_context)
m_context(_context),
m_settings(_settings)
{
}
@ -992,6 +996,15 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
}
}
bool SMTEncoder::shouldAnalyze(ContractDefinition const& _contract) const
{
if (!_contract.canBeDeployed())
return false;
return m_settings.contracts.isDefault() ||
m_settings.contracts.has(_contract.sourceUnitName(), _contract.name());
}
void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
{
solAssert(*_funCall.annotation().kind == FunctionCallKind::TypeConversion, "");

View File

@ -51,7 +51,10 @@ namespace solidity::frontend
class SMTEncoder: public ASTConstVisitor
{
public:
SMTEncoder(smt::EncodingContext& _context);
SMTEncoder(
smt::EncodingContext& _context,
ModelCheckerSettings const& _settings
);
/// @returns true if engine should proceed with analysis.
bool analyze(SourceUnit const& _sources);
@ -203,6 +206,10 @@ protected:
void visitFunctionIdentifier(Identifier const& _identifier);
void visitPublicGetter(FunctionCall const& _funCall);
/// @returns true if @param _contract is set for analysis in the settings
/// and it is not abstract.
bool shouldAnalyze(ContractDefinition const& _contract) const;
bool isPublicGetter(Expression const& _expr);
/// Encodes a modifier or function body according to the modifier
@ -455,6 +462,8 @@ protected:
/// Stores the context of the encoding.
smt::EncodingContext& m_context;
ModelCheckerSettings const& m_settings;
smt::SymbolicState& state();
};

View File

@ -547,7 +547,9 @@ bool CompilerStack::analyze()
if (noErrors)
{
ModelChecker modelChecker(m_errorReporter, m_smtlib2Responses, m_modelCheckerSettings, m_readFile, m_enabledSMTSolvers);
modelChecker.enableAllEnginesIfPragmaPresent(applyMap(m_sourceOrder, [](Source const* _source) { return _source->ast; }));
auto allSources = applyMap(m_sourceOrder, [](Source const* _source) { return _source->ast; });
modelChecker.enableAllEnginesIfPragmaPresent(allSources);
modelChecker.checkRequestedSourcesAndContracts(allSources);
for (Source const* source: m_sourceOrder)
if (source->ast)
modelChecker.analyze(*source->ast);

View File

@ -435,7 +435,7 @@ std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
std::optional<Json::Value> checkModelCheckerSettingsKeys(Json::Value const& _input)
{
static set<string> keys{"engine", "targets", "timeout"};
static set<string> keys{"contracts", "engine", "targets", "timeout"};
return checkKeys(_input, keys, "modelChecker");
}
@ -901,6 +901,37 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
if (auto result = checkModelCheckerSettingsKeys(modelCheckerSettings))
return *result;
if (modelCheckerSettings.isMember("contracts"))
{
auto const& sources = modelCheckerSettings["contracts"];
if (!sources.isObject() && !sources.isNull())
return formatFatalError("JSONError", "settings.modelChecker.contracts is not a JSON object.");
map<string, set<string>> sourceContracts;
for (auto const& source: sources.getMemberNames())
{
if (source.empty())
return formatFatalError("JSONError", "Source name cannot be empty.");
auto const& contracts = sources[source];
if (!contracts.isArray())
return formatFatalError("JSONError", "Source contracts must be an array.");
for (auto const& contract: contracts)
{
if (!contract.isString())
return formatFatalError("JSONError", "Every contract in settings.modelChecker.contracts must be a string.");
if (contract.asString().empty())
return formatFatalError("JSONError", "Contract name cannot be empty.");
sourceContracts[source].insert(contract.asString());
}
if (sourceContracts[source].empty())
return formatFatalError("JSONError", "Source contracts must be a non-empty array.");
}
ret.modelCheckerSettings.contracts = {move(sourceContracts)};
}
if (modelCheckerSettings.isMember("engine"))
{
if (!modelCheckerSettings["engine"].isString())

View File

@ -223,9 +223,9 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False):
"1584", "1823",
"1988", "2066", "3356",
"3893", "3996", "4010", "4802",
"5272", "5622", "7128",
"5272", "5622", "7128", "7400",
"7589", "7593", "8065", "8084", "8140",
"8312", "8592", "9609",
"8312", "8592", "9134", "9609",
}
new_source_only_ids = source_only_ids - old_source_only_ids

View File

@ -155,6 +155,7 @@ static string const g_strMachine = "machine";
static string const g_strMetadata = "metadata";
static string const g_strMetadataHash = "metadata-hash";
static string const g_strMetadataLiteral = "metadata-literal";
static string const g_strModelCheckerContracts = "model-checker-contracts";
static string const g_strModelCheckerEngine = "model-checker-engine";
static string const g_strModelCheckerTargets = "model-checker-targets";
static string const g_strModelCheckerTimeout = "model-checker-timeout";
@ -226,6 +227,7 @@ static string const g_argMachine = g_strMachine;
static string const g_argMetadata = g_strMetadata;
static string const g_argMetadataHash = g_strMetadataHash;
static string const g_argMetadataLiteral = g_strMetadataLiteral;
static string const g_argModelCheckerContracts = g_strModelCheckerContracts;
static string const g_argModelCheckerEngine = g_strModelCheckerEngine;
static string const g_argModelCheckerTargets = g_strModelCheckerTargets;
static string const g_argModelCheckerTimeout = g_strModelCheckerTimeout;
@ -1052,6 +1054,13 @@ General Information)").c_str(),
po::options_description smtCheckerOptions("Model Checker Options");
smtCheckerOptions.add_options()
(
g_strModelCheckerContracts.c_str(),
po::value<string>()->value_name("default,<source>:<contract>")->default_value("default"),
"Select which contracts should be analyzed using the form <source>:<contract>."
"Multiple pairs <source>:<contract> can be selected at the same time, separated by a comma "
"and no spaces."
)
(
g_strModelCheckerEngine.c_str(),
po::value<string>()->value_name("all,bmc,chc,none")->default_value("none"),
@ -1415,6 +1424,19 @@ bool CommandLineInterface::processInput()
}
}
if (m_args.count(g_argModelCheckerContracts))
{
string contractsStr = m_args[g_argModelCheckerContracts].as<string>();
optional<ModelCheckerContracts> contracts = ModelCheckerContracts::fromString(contractsStr);
if (!contracts)
{
serr() << "Invalid option for --" << g_argModelCheckerContracts << ": " << contractsStr << endl;
return false;
}
m_modelCheckerSettings.contracts = move(*contracts);
}
if (m_args.count(g_argModelCheckerEngine))
{
string engineStr = m_args[g_argModelCheckerEngine].as<string>();
@ -1452,7 +1474,12 @@ bool CommandLineInterface::processInput()
m_compiler->useMetadataLiteralSources(true);
if (m_args.count(g_argMetadataHash))
m_compiler->setMetadataHash(m_metadataHash);
if (m_args.count(g_argModelCheckerEngine) || m_args.count(g_argModelCheckerTimeout))
if (
m_args.count(g_argModelCheckerContracts) ||
m_args.count(g_argModelCheckerEngine) ||
m_args.count(g_argModelCheckerTargets) ||
m_args.count(g_argModelCheckerTimeout)
)
m_compiler->setModelCheckerSettings(m_modelCheckerSettings);
if (m_args.count(g_argInputFile))
m_compiler->setRemappings(m_remappings);

View File

@ -0,0 +1 @@
--model-checker-engine all

View File

@ -0,0 +1,25 @@
Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
B.constructor()
B.f(0)
--> model_checker_contracts_all/input.sol:5:3:
|
5 | assert(x > 0);
| ^^^^^^^^^^^^^
Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
A.g(0)
--> model_checker_contracts_all/input.sol:10:3:
|
10 | assert(y > 0);
| ^^^^^^^^^^^^^

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts model_checker_contracts_all_explicit/input.sol:B,model_checker_contracts_all_explicit/input.sol:A

View File

@ -0,0 +1,25 @@
Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
B.constructor()
B.f(0)
--> model_checker_contracts_all_explicit/input.sol:5:3:
|
5 | assert(x > 0);
| ^^^^^^^^^^^^^
Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
A.g(0)
--> model_checker_contracts_all_explicit/input.sol:10:3:
|
10 | assert(y > 0);
| ^^^^^^^^^^^^^

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts model_checker_contracts_inexistent_contract/input.sol:

View File

@ -0,0 +1 @@
Invalid option for --model-checker-contracts: model_checker_contracts_inexistent_contract/input.sol:

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts a.sol:

View File

@ -0,0 +1 @@
Invalid option for --model-checker-contracts: a.sol:

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts :A

View File

@ -0,0 +1 @@
Invalid option for --model-checker-contracts: :A

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts model_checker_contracts_inexistent_contract/input.sol:C

View File

@ -0,0 +1 @@
Warning: Requested contract "C" does not exist in source "model_checker_contracts_inexistent_contract/input.sol".

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts model_checker_contracts_inexistent_source/A.sol:A

View File

@ -0,0 +1 @@
Warning: Requested source "model_checker_contracts_inexistent_source/A.sol" does not exist.

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts model_checker_contracts_all_explicit/input.sol:,model_checker_contracts_all_explicit/input.sol:A

View File

@ -0,0 +1 @@
Invalid option for --model-checker-contracts: model_checker_contracts_all_explicit/input.sol:,model_checker_contracts_all_explicit/input.sol:A

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts model_checker_contracts_only_one/input.sol:A

View File

@ -0,0 +1,25 @@
Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
B.f(0)
--> model_checker_contracts_only_one/input.sol:5:3:
|
5 | assert(x > 0);
| ^^^^^^^^^^^^^
Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
A.g(0)
--> model_checker_contracts_only_one/input.sol:10:3:
|
10 | assert(y > 0);
| ^^^^^^^^^^^^^

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-contracts :C

View File

@ -0,0 +1 @@
Invalid option for --model-checker-contracts: :C

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function f(uint x) public pure {
assert(x > 0);
}
}
contract A is B {
function g(uint y) public pure {
assert(y > 0);
}
}

View File

@ -0,0 +1,28 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all"
}
}
}

View File

@ -0,0 +1,41 @@
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
B.constructor()
B.g(0)
--> Source:5:7:
|
5 | \t\t\t\t\t\tassert(y > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
B.constructor()
B.g(0)","severity":"warning","sourceLocation":{"end":137,"file":"Source","start":124},"type":"Warning"},{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)
--> Source:10:7:
|
10 | \t\t\t\t\t\tassert(x > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)","severity":"warning","sourceLocation":{"end":231,"file":"Source","start":218},"type":"Warning"}],"sources":{"Source":{"id":0}}}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": ["A", "B"]
}
}
}
}

View File

@ -0,0 +1,41 @@
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
B.constructor()
B.g(0)
--> Source:5:7:
|
5 | \t\t\t\t\t\tassert(y > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
B.constructor()
B.g(0)","severity":"warning","sourceLocation":{"end":137,"file":"Source","start":124},"type":"Warning"},{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)
--> Source:10:7:
|
10 | \t\t\t\t\t\tassert(x > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)","severity":"warning","sourceLocation":{"end":231,"file":"Source","start":218},"type":"Warning"}],"sources":{"Source":{"id":0}}}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": []
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Source contracts must be a non-empty array.","message":"Source contracts must be a non-empty array.","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": [""]
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Contract name cannot be empty.","message":"Contract name cannot be empty.","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"": ["A"]
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Source name cannot be empty.","message":"Source name cannot be empty.","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": ["C"]
}
}
}
}

View File

@ -0,0 +1,3 @@
{"errors":[{"component":"general","errorCode":"7400","formattedMessage":"Warning: Requested contract \"C\" does not exist in source \"Source\".
","message":"Requested contract \"C\" does not exist in source \"Source\".","severity":"warning","type":"Warning"}],"sources":{"Source":{"id":0}}}

View File

@ -0,0 +1,43 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
},
"Source2":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
import 'Source';
contract C is A {
function h(uint z) public pure {
assert(z > 100);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": ["A"], "Source2": ["C"]
}
}
}
}

View File

@ -0,0 +1,101 @@
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
B.g(0)
--> Source:5:7:
|
5 | \t\t\t\t\t\tassert(y > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
B.g(0)","severity":"warning","sourceLocation":{"end":137,"file":"Source","start":124},"type":"Warning"},{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)
--> Source:10:7:
|
10 | \t\t\t\t\t\tassert(x > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)","severity":"warning","sourceLocation":{"end":231,"file":"Source","start":218},"type":"Warning"},{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
B.g(0)
--> Source:5:7:
|
5 | \t\t\t\t\t\tassert(y > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
B.g(0)","severity":"warning","sourceLocation":{"end":137,"file":"Source","start":124},"type":"Warning"},{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)
--> Source:10:7:
|
10 | \t\t\t\t\t\tassert(x > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)","severity":"warning","sourceLocation":{"end":231,"file":"Source","start":218},"type":"Warning"},{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
z = 0
Transaction trace:
C.constructor()
C.h(0)
--> Source2:6:7:
|
6 | \t\t\t\t\t\tassert(z > 100);
| \t\t\t\t\t\t^^^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
z = 0
Transaction trace:
C.constructor()
C.h(0)","severity":"warning","sourceLocation":{"end":165,"file":"Source2","start":150},"type":"Warning"}],"sources":{"Source":{"id":0},"Source2":{"id":1}}}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": ["A"]
}
}
}
}

View File

@ -0,0 +1,41 @@
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
B.g(0)
--> Source:5:7:
|
5 | \t\t\t\t\t\tassert(y > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
y = 0
Transaction trace:
A.constructor()
B.g(0)","severity":"warning","sourceLocation":{"end":137,"file":"Source","start":124},"type":"Warning"},{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)
--> Source:10:7:
|
10 | \t\t\t\t\t\tassert(x > 0);
| \t\t\t\t\t\t^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
A.constructor()
A.f(0)","severity":"warning","sourceLocation":{"end":231,"file":"Source","start":218},"type":"Warning"}],"sources":{"Source":{"id":0}}}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Sourceee": ["A"]
}
}
}
}

View File

@ -0,0 +1,3 @@
{"errors":[{"component":"general","errorCode":"9134","formattedMessage":"Warning: Requested source \"Sourceee\" does not exist.
","message":"Requested source \"Sourceee\" does not exist.","severity":"warning","type":"Warning"}],"sources":{"Source":{"id":0}}}

View File

@ -0,0 +1,29 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts": 2
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"settings.modelChecker.contracts is not a JSON object.","message":"settings.modelChecker.contracts is not a JSON object.","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": 2
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Source contracts must be an array.","message":"Source contracts must be an array.","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,32 @@
{
"language": "Solidity",
"sources":
{
"Source":
{
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract B {
function g(uint y) public pure {
assert(y > 0);
}
}
contract A is B {
function f(uint x) public pure {
assert(x > 0);
}
}"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"contracts":
{
"Source": [2]
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Every contract in settings.modelChecker.contracts must be a string.","message":"Every contract in settings.modelChecker.contracts must be a string.","severity":"error","type":"JSONError"}]}

View File

@ -16,6 +16,7 @@
*/
// SPDX-License-Identifier: GPL-3.0
#include "libsolidity/formal/ModelCheckerSettings.h"
#include <test/tools/fuzzer_common.h>
#include <libsolidity/interface/CompilerStack.h>
@ -99,7 +100,12 @@ void FuzzerUtil::testCompiler(
if (_forceSMT)
{
forceSMT(_input);
compiler.setModelCheckerSettings({frontend::ModelCheckerEngine::All(), frontend::ModelCheckerTargets::All(), /*timeout=*/1});
compiler.setModelCheckerSettings({
frontend::ModelCheckerContracts::Default(),
frontend::ModelCheckerEngine::All(),
frontend::ModelCheckerTargets::Default(),
/*timeout=*/1
});
}
compiler.setSources(_input);
compiler.setEVMVersion(evmVersion);