Add option to choose solver

This commit is contained in:
Leo Alt 2021-05-19 17:35:19 +02:00
parent e3184c737a
commit 6c8ecfa82c
53 changed files with 650 additions and 92 deletions

View File

@ -811,7 +811,7 @@ jobs:
t_ems_solcjs: t_ems_solcjs:
docker: docker:
- image: buildpack-deps:latest - image: << pipeline.parameters.ubuntu-2004-docker-image >>
environment: environment:
TERM: xterm TERM: xterm
steps: steps:
@ -822,7 +822,7 @@ jobs:
name: Install test dependencies name: Install test dependencies
command: | command: |
apt-get update apt-get update
apt-get install -qqy --no-install-recommends nodejs npm cvc4 apt-get install -qqy --no-install-recommends nodejs npm
- run: - run:
name: Test solcjs name: Test solcjs
no_output_timeout: 30m no_output_timeout: 30m

View File

@ -558,6 +558,39 @@ calls assume the called code is unknown and can do anything.
The CHC engine is much more powerful than BMC in terms of what it can prove, The CHC engine is much more powerful than BMC in terms of what it can prove,
and might require more computing resources. and might require more computing resources.
SMT and Horn solvers
====================
The two engines detailed above use automated theorem provers as their logical
backends. BMC uses an SMT solver, whereas CHC uses a Horn solver. Often the
same tool can act as both, as seen in `z3 <https://github.com/Z3Prover/z3>`_,
which is primarily an SMT solver and makes `Spacer
<https://spacer.bitbucket.io/>`_ available as a Horn solver, and `Eldarica
<https://github.com/uuverifiers/eldarica>`_ which does both.
The user can choose which solvers should be used, if available, via the CLI
option ``--model-checker-solvers {all,cvc4,smtlib2,z3}`` or the JSON option
``settings.modelChecker.solvers=[smtlib2,z3]``, where:
- ``cvc4`` is only available if the ``solc`` binary is compiled with it. Only BMC uses ``cvc4``.
- ``smtlib2`` outputs SMT/Horn queries in the `smtlib2 <http://smtlib.cs.uiowa.edu/>`_ format.
These can be used together with the compiler's `callback mechanism <https://github.com/ethereum/solc-js>`_ so that
any solver binary from the system can be employed to synchronously return the results of the queries to the compiler.
This is currently the only way to use Eldarica, for example, since it does not have a C++ API.
This can be used by both BMC and CHC depending on which solvers are called.
- ``z3`` is available
- if ``solc`` is compiled with it;
- if a dynamic ``z3`` library of version 4.8.x is installed in a Linux system (from Solidity 0.7.6);
- statically in ``soljson.js`` (from Solidity 0.6.9), that is, the Javascript binary of the compiler.
Since both BMC and CHC use ``z3``, and ``z3`` is available in a greater variety
of environments, including in the browser, most users will almost never need to be
concerned about this option. More advanced users might apply this option to try
alternative solvers on more complex problems.
Please note that certain combinations of chosen engine and solver will lead to
the SMTChecker doing nothing, for example choosing CHC and ``cvc4``.
******************************* *******************************
Abstraction and False Positives Abstraction and False Positives

View File

@ -40,6 +40,7 @@ SMTPortfolio::SMTPortfolio(
): ):
SolverInterface(_queryTimeout) SolverInterface(_queryTimeout)
{ {
if (_enabledSolvers.smtlib2)
m_solvers.emplace_back(make_unique<SMTLib2Interface>(move(_smtlib2Responses), move(_smtCallback), m_queryTimeout)); m_solvers.emplace_back(make_unique<SMTLib2Interface>(move(_smtlib2Responses), move(_smtCallback), m_queryTimeout));
#ifdef HAVE_Z3 #ifdef HAVE_Z3
if (_enabledSolvers.z3 && Z3Interface::available()) if (_enabledSolvers.z3 && Z3Interface::available())
@ -143,10 +144,11 @@ pair<CheckResult, vector<string>> SMTPortfolio::check(vector<Expression> const&
vector<string> SMTPortfolio::unhandledQueries() vector<string> SMTPortfolio::unhandledQueries()
{ {
// This code assumes that the constructor guarantees that // This code assumes that the constructor guarantees that
// SmtLib2Interface is in position 0. // SmtLib2Interface is in position 0, if enabled.
smtAssert(!m_solvers.empty(), ""); if (!m_solvers.empty())
smtAssert(dynamic_cast<SMTLib2Interface*>(m_solvers.front().get()), ""); if (auto smtlib2 = dynamic_cast<SMTLib2Interface*>(m_solvers.front().get()))
return m_solvers.front()->unhandledQueries(); return smtlib2->unhandledQueries();
return {};
} }
bool SMTPortfolio::solverAnswered(CheckResult result) bool SMTPortfolio::solverAnswered(CheckResult result)

View File

@ -23,10 +23,13 @@
#include <libsolutil/Common.h> #include <libsolutil/Common.h>
#include <range/v3/view.hpp>
#include <cstdio> #include <cstdio>
#include <map> #include <map>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
@ -36,16 +39,71 @@ namespace solidity::smtutil
struct SMTSolverChoice struct SMTSolverChoice
{ {
bool cvc4 = false; bool cvc4 = false;
bool smtlib2 = false;
bool z3 = false; bool z3 = false;
static constexpr SMTSolverChoice All() { return {true, true}; } static constexpr SMTSolverChoice All() { return {true, true, true}; }
static constexpr SMTSolverChoice CVC4() { return {true, false}; } static constexpr SMTSolverChoice CVC4() { return {true, false, false}; }
static constexpr SMTSolverChoice Z3() { return {false, true}; } static constexpr SMTSolverChoice SMTLIB2() { return {false, true, false}; }
static constexpr SMTSolverChoice None() { return {false, false}; } static constexpr SMTSolverChoice Z3() { return {false, false, true}; }
static constexpr SMTSolverChoice None() { return {false, false, false}; }
static std::optional<SMTSolverChoice> fromString(std::string const& _solvers)
{
SMTSolverChoice solvers;
if (_solvers == "all")
{
smtAssert(solvers.setSolver("cvc4"), "");
smtAssert(solvers.setSolver("smtlib2"), "");
smtAssert(solvers.setSolver("z3"), "");
}
else
for (auto&& s: _solvers | ranges::views::split(',') | ranges::to<std::vector<std::string>>())
if (!solvers.setSolver(s))
return {};
return solvers;
}
SMTSolverChoice& operator&(SMTSolverChoice const& _other)
{
cvc4 &= _other.cvc4;
smtlib2 &= _other.smtlib2;
z3 &= _other.z3;
return *this;
}
SMTSolverChoice& operator&=(SMTSolverChoice const& _other)
{
return *this & _other;
}
bool operator!=(SMTSolverChoice const& _other) const noexcept { return !(*this == _other); }
bool operator==(SMTSolverChoice const& _other) const noexcept
{
return cvc4 == _other.cvc4 &&
smtlib2 == _other.smtlib2 &&
z3 == _other.z3;
}
bool setSolver(std::string const& _solver)
{
static std::set<std::string> const solvers{"cvc4", "smtlib2", "z3"};
if (!solvers.count(_solver))
return false;
if (_solver == "cvc4")
cvc4 = true;
else if (_solver == "smtlib2")
smtlib2 = true;
else if (_solver == "z3")
z3 = true;
return true;
}
bool none() { return !some(); } bool none() { return !some(); }
bool some() { return cvc4 || z3; } bool some() { return cvc4 || smtlib2 || z3; }
bool all() { return cvc4 && z3; } bool all() { return cvc4 && smtlib2 && z3; }
}; };
enum class CheckResult enum class CheckResult

View File

@ -40,16 +40,15 @@ BMC::BMC(
ErrorReporter& _errorReporter, ErrorReporter& _errorReporter,
map<h256, string> const& _smtlib2Responses, map<h256, string> const& _smtlib2Responses,
ReadCallback::Callback const& _smtCallback, ReadCallback::Callback const& _smtCallback,
smtutil::SMTSolverChoice _enabledSolvers,
ModelCheckerSettings const& _settings, ModelCheckerSettings const& _settings,
CharStreamProvider const& _charStreamProvider CharStreamProvider const& _charStreamProvider
): ):
SMTEncoder(_context, _settings, _charStreamProvider), SMTEncoder(_context, _settings, _charStreamProvider),
m_interface(make_unique<smtutil::SMTPortfolio>(_smtlib2Responses, _smtCallback, _enabledSolvers, _settings.timeout)), m_interface(make_unique<smtutil::SMTPortfolio>(_smtlib2Responses, _smtCallback, _settings.solvers, _settings.timeout)),
m_outerErrorReporter(_errorReporter) m_outerErrorReporter(_errorReporter)
{ {
#if defined (HAVE_Z3) || defined (HAVE_CVC4) #if defined (HAVE_Z3) || defined (HAVE_CVC4)
if (_enabledSolvers.some()) if (m_settings.solvers.cvc4 || m_settings.solvers.z3)
if (!_smtlib2Responses.empty()) if (!_smtlib2Responses.empty())
m_errorReporter.warning( m_errorReporter.warning(
5622_error, 5622_error,
@ -63,6 +62,20 @@ BMC::BMC(
void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>> _solvedTargets) void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>> _solvedTargets)
{ {
if (m_interface->solvers() == 0)
{
if (!m_noSolverWarning)
{
m_noSolverWarning = true;
m_outerErrorReporter.warning(
7710_error,
SourceLocation(),
"BMC analysis was not possible since no SMT solver was found and enabled."
);
}
return;
}
if (SMTEncoder::analyze(_source)) if (SMTEncoder::analyze(_source))
{ {
m_solvedTargets = move(_solvedTargets); m_solvedTargets = move(_solvedTargets);
@ -75,11 +88,14 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
_source.accept(*this); _source.accept(*this);
} }
solAssert(m_interface->solvers() > 0, "");
// If this check is true, Z3 and CVC4 are not available // If this check is true, Z3 and CVC4 are not available
// and the query answers were not provided, since SMTPortfolio // and the query answers were not provided, since SMTPortfolio
// guarantees that SmtLib2Interface is the first solver. // guarantees that SmtLib2Interface is the first solver, if enabled.
if (!m_interface->unhandledQueries().empty() && m_interface->solvers() == 1) if (
!m_interface->unhandledQueries().empty() &&
m_interface->solvers() == 1 &&
m_settings.solvers.smtlib2
)
{ {
if (!m_noSolverWarning) if (!m_noSolverWarning)
{ {
@ -87,7 +103,8 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
m_outerErrorReporter.warning( m_outerErrorReporter.warning(
8084_error, 8084_error,
SourceLocation(), SourceLocation(),
"BMC analysis was not possible since no SMT solver (Z3 or CVC4) was found." "BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available."
" None of the installed solvers was enabled."
#ifdef HAVE_Z3_DLOPEN #ifdef HAVE_Z3_DLOPEN
" Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3." " Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3."
#endif #endif
@ -916,9 +933,12 @@ void BMC::checkCondition(
solAssert(!_callStack.empty(), ""); solAssert(!_callStack.empty(), "");
std::ostringstream message; std::ostringstream message;
message << "BMC: " << _description << " happens here."; message << "BMC: " << _description << " happens here.";
std::ostringstream modelMessage; std::ostringstream modelMessage;
// Sometimes models have complex smtlib2 expressions that SMTLib2Interface fails to parse.
if (values.size() == expressionNames.size())
{
modelMessage << "Counterexample:\n"; modelMessage << "Counterexample:\n";
solAssert(values.size() == expressionNames.size(), "");
map<string, string> sortedModel; map<string, string> sortedModel;
for (size_t i = 0; i < values.size(); ++i) for (size_t i = 0; i < values.size(); ++i)
if (expressionsToEvaluate.at(i).name != values.at(i)) if (expressionsToEvaluate.at(i).name != values.at(i))
@ -926,6 +946,7 @@ void BMC::checkCondition(
for (auto const& eval: sortedModel) for (auto const& eval: sortedModel)
modelMessage << " " << eval.first << " = " << eval.second << "\n"; modelMessage << " " << eval.first << " = " << eval.second << "\n";
}
m_errorReporter.warning( m_errorReporter.warning(
_errorHappens, _errorHappens,

View File

@ -62,7 +62,6 @@ public:
langutil::ErrorReporter& _errorReporter, langutil::ErrorReporter& _errorReporter,
std::map<h256, std::string> const& _smtlib2Responses, std::map<h256, std::string> const& _smtlib2Responses,
ReadCallback::Callback const& _smtCallback, ReadCallback::Callback const& _smtCallback,
smtutil::SMTSolverChoice _enabledSolvers,
ModelCheckerSettings const& _settings, ModelCheckerSettings const& _settings,
langutil::CharStreamProvider const& _charStreamProvider langutil::CharStreamProvider const& _charStreamProvider
); );

View File

@ -56,26 +56,38 @@ CHC::CHC(
ErrorReporter& _errorReporter, ErrorReporter& _errorReporter,
[[maybe_unused]] map<util::h256, string> const& _smtlib2Responses, [[maybe_unused]] map<util::h256, string> const& _smtlib2Responses,
[[maybe_unused]] ReadCallback::Callback const& _smtCallback, [[maybe_unused]] ReadCallback::Callback const& _smtCallback,
SMTSolverChoice _enabledSolvers,
ModelCheckerSettings const& _settings, ModelCheckerSettings const& _settings,
CharStreamProvider const& _charStreamProvider CharStreamProvider const& _charStreamProvider
): ):
SMTEncoder(_context, _settings, _charStreamProvider), SMTEncoder(_context, _settings, _charStreamProvider),
m_outerErrorReporter(_errorReporter), m_outerErrorReporter(_errorReporter)
m_enabledSolvers(_enabledSolvers)
{ {
bool usesZ3 = _enabledSolvers.z3; bool usesZ3 = m_settings.solvers.z3;
#ifdef HAVE_Z3 #ifdef HAVE_Z3
usesZ3 = usesZ3 && Z3Interface::available(); usesZ3 = usesZ3 && Z3Interface::available();
#else #else
usesZ3 = false; usesZ3 = false;
#endif #endif
if (!usesZ3) if (!usesZ3 && m_settings.solvers.smtlib2)
m_interface = make_unique<CHCSmtLib2Interface>(_smtlib2Responses, _smtCallback, m_settings.timeout); m_interface = make_unique<CHCSmtLib2Interface>(_smtlib2Responses, _smtCallback, m_settings.timeout);
} }
void CHC::analyze(SourceUnit const& _source) void CHC::analyze(SourceUnit const& _source)
{ {
if (!m_settings.solvers.z3 && !m_settings.solvers.smtlib2)
{
if (!m_noSolverWarning)
{
m_noSolverWarning = true;
m_outerErrorReporter.warning(
7649_error,
SourceLocation(),
"CHC analysis was not possible since no Horn solver was enabled."
);
}
return;
}
if (SMTEncoder::analyze(_source)) if (SMTEncoder::analyze(_source))
{ {
resetSourceAnalysis(); resetSourceAnalysis();
@ -92,6 +104,8 @@ void CHC::analyze(SourceUnit const& _source)
} }
bool ranSolver = true; bool ranSolver = true;
// If ranSolver is true here it's because an SMT solver callback was
// actually given and the queries were solved.
if (auto const* smtLibInterface = dynamic_cast<CHCSmtLib2Interface const*>(m_interface.get())) if (auto const* smtLibInterface = dynamic_cast<CHCSmtLib2Interface const*>(m_interface.get()))
ranSolver = smtLibInterface->unhandledQueries().empty(); ranSolver = smtLibInterface->unhandledQueries().empty();
if (!ranSolver && !m_noSolverWarning) if (!ranSolver && !m_noSolverWarning)
@ -103,7 +117,8 @@ void CHC::analyze(SourceUnit const& _source)
#ifdef HAVE_Z3_DLOPEN #ifdef HAVE_Z3_DLOPEN
"CHC analysis was not possible since libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " was not found." "CHC analysis was not possible since libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " was not found."
#else #else
"CHC analysis was not possible since no integrated z3 SMT solver was found." "CHC analysis was not possible. No Horn solver was available."
" None of the installed solvers was enabled."
#endif #endif
); );
} }
@ -933,7 +948,7 @@ void CHC::resetSourceAnalysis()
bool usesZ3 = false; bool usesZ3 = false;
#ifdef HAVE_Z3 #ifdef HAVE_Z3
usesZ3 = m_enabledSolvers.z3 && Z3Interface::available(); usesZ3 = m_settings.solvers.z3 && Z3Interface::available();
if (usesZ3) if (usesZ3)
{ {
/// z3::fixedpoint does not have a reset mechanism, so we need to create another. /// z3::fixedpoint does not have a reset mechanism, so we need to create another.
@ -1427,6 +1442,8 @@ pair<CheckResult, CHCSolverInterface::CexGraph> CHC::query(smtutil::Expression c
case CheckResult::SATISFIABLE: case CheckResult::SATISFIABLE:
{ {
#ifdef HAVE_Z3 #ifdef HAVE_Z3
if (m_settings.solvers.z3)
{
// Even though the problem is SAT, Spacer's pre processing makes counterexamples incomplete. // Even though the problem is SAT, Spacer's pre processing makes counterexamples incomplete.
// We now disable those optimizations and check whether we can still solve the problem. // We now disable those optimizations and check whether we can still solve the problem.
auto* spacer = dynamic_cast<Z3CHCInterface*>(m_interface.get()); auto* spacer = dynamic_cast<Z3CHCInterface*>(m_interface.get());
@ -1441,6 +1458,7 @@ pair<CheckResult, CHCSolverInterface::CexGraph> CHC::query(smtutil::Expression c
cex = move(cexNoOpt); cex = move(cexNoOpt);
spacer->setSpacerOptions(true); spacer->setSpacerOptions(true);
}
#endif #endif
break; break;
} }

View File

@ -56,7 +56,6 @@ public:
langutil::ErrorReporter& _errorReporter, langutil::ErrorReporter& _errorReporter,
std::map<util::h256, std::string> const& _smtlib2Responses, std::map<util::h256, std::string> const& _smtlib2Responses,
ReadCallback::Callback const& _smtCallback, ReadCallback::Callback const& _smtCallback,
smtutil::SMTSolverChoice _enabledSolvers,
ModelCheckerSettings const& _settings, ModelCheckerSettings const& _settings,
langutil::CharStreamProvider const& _charStreamProvider langutil::CharStreamProvider const& _charStreamProvider
); );
@ -393,9 +392,6 @@ private:
/// ErrorReporter that comes from CompilerStack. /// ErrorReporter that comes from CompilerStack.
langutil::ErrorReporter& m_outerErrorReporter; langutil::ErrorReporter& m_outerErrorReporter;
/// SMT solvers that are chosen at runtime.
smtutil::SMTSolverChoice m_enabledSolvers;
}; };
} }

View File

@ -35,14 +35,13 @@ ModelChecker::ModelChecker(
langutil::CharStreamProvider const& _charStreamProvider, langutil::CharStreamProvider const& _charStreamProvider,
map<h256, string> const& _smtlib2Responses, map<h256, string> const& _smtlib2Responses,
ModelCheckerSettings _settings, ModelCheckerSettings _settings,
ReadCallback::Callback const& _smtCallback, ReadCallback::Callback const& _smtCallback
smtutil::SMTSolverChoice _enabledSolvers
): ):
m_errorReporter(_errorReporter), m_errorReporter(_errorReporter),
m_settings(_settings), m_settings(move(_settings)),
m_context(), m_context(),
m_bmc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, _enabledSolvers, m_settings, _charStreamProvider), m_bmc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, m_settings, _charStreamProvider),
m_chc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, _enabledSolvers, m_settings, _charStreamProvider) m_chc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, m_settings, _charStreamProvider)
{ {
} }
@ -135,7 +134,7 @@ vector<string> ModelChecker::unhandledQueries()
solidity::smtutil::SMTSolverChoice ModelChecker::availableSolvers() solidity::smtutil::SMTSolverChoice ModelChecker::availableSolvers()
{ {
smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::None(); smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::SMTLIB2();
#ifdef HAVE_Z3 #ifdef HAVE_Z3
available.z3 = solidity::smtutil::Z3Interface::available(); available.z3 = solidity::smtutil::Z3Interface::available();
#endif #endif

View File

@ -52,8 +52,7 @@ public:
langutil::CharStreamProvider const& _charStreamProvider, langutil::CharStreamProvider const& _charStreamProvider,
std::map<solidity::util::h256, std::string> const& _smtlib2Responses, std::map<solidity::util::h256, std::string> const& _smtlib2Responses,
ModelCheckerSettings _settings = ModelCheckerSettings{}, ModelCheckerSettings _settings = ModelCheckerSettings{},
ReadCallback::Callback const& _smtCallback = ReadCallback::Callback(), ReadCallback::Callback const& _smtCallback = ReadCallback::Callback()
smtutil::SMTSolverChoice _enabledSolvers = smtutil::SMTSolverChoice::All()
); );
// TODO This should be removed for 0.9.0. // TODO This should be removed for 0.9.0.

View File

@ -113,6 +113,7 @@ struct ModelCheckerSettings
{ {
ModelCheckerContracts contracts = ModelCheckerContracts::Default(); ModelCheckerContracts contracts = ModelCheckerContracts::Default();
ModelCheckerEngine engine = ModelCheckerEngine::None(); ModelCheckerEngine engine = ModelCheckerEngine::None();
smtutil::SMTSolverChoice solvers = smtutil::SMTSolverChoice::All();
ModelCheckerTargets targets = ModelCheckerTargets::Default(); ModelCheckerTargets targets = ModelCheckerTargets::Default();
std::optional<unsigned> timeout; std::optional<unsigned> timeout;
@ -122,6 +123,7 @@ struct ModelCheckerSettings
return return
contracts == _other.contracts && contracts == _other.contracts &&
engine == _other.engine && engine == _other.engine &&
solvers == _other.solvers &&
targets == _other.targets && targets == _other.targets &&
timeout == _other.timeout; timeout == _other.timeout;
} }

View File

@ -95,7 +95,6 @@ static int g_compilerStackCounts = 0;
CompilerStack::CompilerStack(ReadCallback::Callback _readFile): CompilerStack::CompilerStack(ReadCallback::Callback _readFile):
m_readFile{std::move(_readFile)}, m_readFile{std::move(_readFile)},
m_enabledSMTSolvers{smtutil::SMTSolverChoice::All()},
m_errorReporter{m_errorList} m_errorReporter{m_errorList}
{ {
// Because TypeProvider is currently a singleton API, we must ensure that // Because TypeProvider is currently a singleton API, we must ensure that
@ -228,13 +227,6 @@ void CompilerStack::setModelCheckerSettings(ModelCheckerSettings _settings)
m_modelCheckerSettings = _settings; m_modelCheckerSettings = _settings;
} }
void CompilerStack::setSMTSolverChoice(smtutil::SMTSolverChoice _enabledSMTSolvers)
{
if (m_stackState >= ParsedAndImported)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set enabled SMT solvers before parsing."));
m_enabledSMTSolvers = _enabledSMTSolvers;
}
void CompilerStack::setLibraries(std::map<std::string, util::h160> const& _libraries) void CompilerStack::setLibraries(std::map<std::string, util::h160> const& _libraries)
{ {
if (m_stackState >= ParsedAndImported) if (m_stackState >= ParsedAndImported)
@ -299,7 +291,6 @@ void CompilerStack::reset(bool _keepSettings)
m_viaIR = false; m_viaIR = false;
m_evmVersion = langutil::EVMVersion(); m_evmVersion = langutil::EVMVersion();
m_modelCheckerSettings = ModelCheckerSettings{}; m_modelCheckerSettings = ModelCheckerSettings{};
m_enabledSMTSolvers = smtutil::SMTSolverChoice::All();
m_generateIR = false; m_generateIR = false;
m_generateEwasm = false; m_generateEwasm = false;
m_revertStrings = RevertStrings::Default; m_revertStrings = RevertStrings::Default;
@ -555,7 +546,7 @@ bool CompilerStack::analyze()
if (noErrors) if (noErrors)
{ {
ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile, m_enabledSMTSolvers); ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile);
auto allSources = applyMap(m_sourceOrder, [](Source const* _source) { return _source->ast; }); auto allSources = applyMap(m_sourceOrder, [](Source const* _source) { return _source->ast; });
modelChecker.enableAllEnginesIfPragmaPresent(allSources); modelChecker.enableAllEnginesIfPragmaPresent(allSources);
modelChecker.checkRequestedSourcesAndContracts(allSources); modelChecker.checkRequestedSourcesAndContracts(allSources);

View File

@ -176,8 +176,6 @@ public:
/// Set model checker settings. /// Set model checker settings.
void setModelCheckerSettings(ModelCheckerSettings _settings); void setModelCheckerSettings(ModelCheckerSettings _settings);
/// Set which SMT solvers should be enabled.
void setSMTSolverChoice(smtutil::SMTSolverChoice _enabledSolvers);
/// Sets the requested contract names by source. /// Sets the requested contract names by source.
/// If empty, no filtering is performed and every contract /// If empty, no filtering is performed and every contract
@ -480,7 +478,6 @@ private:
bool m_viaIR = false; bool m_viaIR = false;
langutil::EVMVersion m_evmVersion; langutil::EVMVersion m_evmVersion;
ModelCheckerSettings m_modelCheckerSettings; ModelCheckerSettings m_modelCheckerSettings;
smtutil::SMTSolverChoice m_enabledSMTSolvers;
std::map<std::string, std::set<std::string>> m_requestedContractNames; std::map<std::string, std::set<std::string>> m_requestedContractNames;
bool m_generateEvmBytecode = true; bool m_generateEvmBytecode = true;
bool m_generateIR = false; bool m_generateIR = false;

View File

@ -442,7 +442,7 @@ std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
std::optional<Json::Value> checkModelCheckerSettingsKeys(Json::Value const& _input) std::optional<Json::Value> checkModelCheckerSettingsKeys(Json::Value const& _input)
{ {
static set<string> keys{"contracts", "engine", "targets", "timeout"}; static set<string> keys{"contracts", "engine", "solvers", "targets", "timeout"};
return checkKeys(_input, keys, "modelChecker"); return checkKeys(_input, keys, "modelChecker");
} }
@ -951,6 +951,24 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
ret.modelCheckerSettings.engine = *engine; ret.modelCheckerSettings.engine = *engine;
} }
if (modelCheckerSettings.isMember("solvers"))
{
auto const& solversArray = modelCheckerSettings["solvers"];
if (!solversArray.isArray())
return formatFatalError("JSONError", "settings.modelChecker.solvers must be an array.");
smtutil::SMTSolverChoice solvers;
for (auto const& s: solversArray)
{
if (!s.isString())
return formatFatalError("JSONError", "Every target in settings.modelChecker.solvers must be a string.");
if (!solvers.setSolver(s.asString()))
return formatFatalError("JSONError", "Invalid model checker solvers requested.");
}
ret.modelCheckerSettings.solvers = solvers;
}
if (modelCheckerSettings.isMember("targets")) if (modelCheckerSettings.isMember("targets"))
{ {
auto const& targetsArray = modelCheckerSettings["targets"]; auto const& targetsArray = modelCheckerSettings["targets"];

View File

@ -227,7 +227,8 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False):
"1988", "2066", "3356", "1988", "2066", "3356",
"3893", "3996", "4010", "4802", "3893", "3996", "4010", "4802",
"5272", "5622", "7128", "7400", "5272", "5622", "7128", "7400",
"7589", "7593", "8065", "8084", "8140", "7589", "7593", "7649", "7710",
"8065", "8084", "8140",
"8312", "8592", "9134", "9609", "8312", "8592", "9134", "9609",
} }

View File

@ -87,6 +87,7 @@ static string const g_strMetadataHash = "metadata-hash";
static string const g_strMetadataLiteral = "metadata-literal"; static string const g_strMetadataLiteral = "metadata-literal";
static string const g_strModelCheckerContracts = "model-checker-contracts"; static string const g_strModelCheckerContracts = "model-checker-contracts";
static string const g_strModelCheckerEngine = "model-checker-engine"; static string const g_strModelCheckerEngine = "model-checker-engine";
static string const g_strModelCheckerSolvers = "model-checker-solvers";
static string const g_strModelCheckerTargets = "model-checker-targets"; static string const g_strModelCheckerTargets = "model-checker-targets";
static string const g_strModelCheckerTimeout = "model-checker-timeout"; static string const g_strModelCheckerTimeout = "model-checker-timeout";
static string const g_strNatspecDev = "devdoc"; static string const g_strNatspecDev = "devdoc";
@ -723,6 +724,11 @@ General Information)").c_str(),
po::value<string>()->value_name("all,bmc,chc,none")->default_value("none"), po::value<string>()->value_name("all,bmc,chc,none")->default_value("none"),
"Select model checker engine." "Select model checker engine."
) )
(
g_strModelCheckerSolvers.c_str(),
po::value<string>()->value_name("all,cvc4,z3,smtlib2")->default_value("all"),
"Select model checker solvers."
)
( (
g_strModelCheckerTargets.c_str(), g_strModelCheckerTargets.c_str(),
po::value<string>()->value_name("default,constantCondition,underflow,overflow,divByZero,balance,assert,popEmptyArray,outOfBounds")->default_value("default"), po::value<string>()->value_name("default,constantCondition,underflow,overflow,divByZero,balance,assert,popEmptyArray,outOfBounds")->default_value("default"),
@ -1089,6 +1095,18 @@ General Information)").c_str(),
m_options.modelChecker.settings.engine = *engine; m_options.modelChecker.settings.engine = *engine;
} }
if (m_args.count(g_strModelCheckerSolvers))
{
string solversStr = m_args[g_strModelCheckerSolvers].as<string>();
optional<smtutil::SMTSolverChoice> solvers = smtutil::SMTSolverChoice::fromString(solversStr);
if (!solvers)
{
serr() << "Invalid option for --" << g_strModelCheckerSolvers << ": " << solversStr << endl;
return false;
}
m_options.modelChecker.settings.solvers = *solvers;
}
if (m_args.count(g_strModelCheckerTargets)) if (m_args.count(g_strModelCheckerTargets))
{ {
string targetsStr = m_args[g_strModelCheckerTargets].as<string>(); string targetsStr = m_args[g_strModelCheckerTargets].as<string>();
@ -1108,6 +1126,7 @@ General Information)").c_str(),
m_options.modelChecker.initialize = m_options.modelChecker.initialize =
m_args.count(g_strModelCheckerContracts) || m_args.count(g_strModelCheckerContracts) ||
m_args.count(g_strModelCheckerEngine) || m_args.count(g_strModelCheckerEngine) ||
m_args.count(g_strModelCheckerSolvers) ||
m_args.count(g_strModelCheckerTargets) || m_args.count(g_strModelCheckerTargets) ||
m_args.count(g_strModelCheckerTimeout); m_args.count(g_strModelCheckerTimeout);
m_options.output.experimentalViaIR = (m_args.count(g_strExperimentalViaIR) > 0); m_options.output.experimentalViaIR = (m_args.count(g_strExperimentalViaIR) > 0);

View File

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

View File

@ -0,0 +1,12 @@
Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
test.constructor()
test.f(0)
--> model_checker_solvers_all/input.sol:5:3:
|
5 | assert(x > 0);
| ^^^^^^^^^^^^^

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract test {
function f(uint x) public pure {
assert(x > 0);
}
}

View File

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

View File

@ -0,0 +1,12 @@
Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
test.constructor()
test.f(0)
--> model_checker_solvers_all_implicit/input.sol:5:3:
|
5 | assert(x > 0);
| ^^^^^^^^^^^^^

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract test {
function f(uint x) public pure {
assert(x > 0);
}
}

View File

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

View File

@ -0,0 +1,3 @@
Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.
Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract test {
function f(uint x) public pure {
assert(x > 0);
}
}

View File

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

View File

@ -0,0 +1 @@
Invalid option for --model-checker-solvers: ultraSolver

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract test {
function f(uint x) public pure {
assert(x > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-solvers z3, smtlib2

View File

@ -0,0 +1 @@
"smtlib2" is not found.

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract test {
function f(uint x) public pure {
assert(x > 0);
}
}

View File

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

View File

@ -0,0 +1,12 @@
Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
test.constructor()
test.f(0)
--> model_checker_solvers_z3/input.sol:5:3:
|
5 | assert(x > 0);
| ^^^^^^^^^^^^^

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract test {
function f(uint x) public pure {
assert(x > 0);
}
}

View File

@ -0,0 +1 @@
--model-checker-engine all --model-checker-solvers z3,smtlib2

View File

@ -0,0 +1,12 @@
Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
test.constructor()
test.f(0)
--> model_checker_solvers_z3_smtlib2/input.sol:5:3:
|
5 | assert(x > 0);
| ^^^^^^^^^^^^^

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract test {
function f(uint x) public pure {
assert(x > 0);
}
}

View File

@ -0,0 +1,17 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
}
},
"settings":
{
"modelChecker":
{
"engine": "all"
}
}
}

View File

@ -0,0 +1,21 @@
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
C.constructor()
C.f(0)
--> A:4:47:
|
4 | contract C { function f(uint x) public pure { assert(x > 0); } }
| ^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
C.constructor()
C.f(0)","severity":"warning","sourceLocation":{"end":119,"file":"A","start":106},"type":"Warning"}],"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,18 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"solvers": []
}
}
}

View File

@ -0,0 +1,5 @@
{"errors":[{"component":"general","errorCode":"7649","formattedMessage":"Warning: CHC analysis was not possible since no Horn solver was enabled.
","message":"CHC analysis was not possible since no Horn solver was enabled.","severity":"warning","type":"Warning"},{"component":"general","errorCode":"7710","formattedMessage":"Warning: BMC analysis was not possible since no SMT solver was found and enabled.
","message":"BMC analysis was not possible since no SMT solver was found and enabled.","severity":"warning","type":"Warning"}],"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,18 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"solvers": ["smtlib2"]
}
}
}

View File

@ -0,0 +1,138 @@
{"auxiliaryInputRequested":{"smtlib2queries":{"0x4ee925df3426fec84707cea517cc52ed216229bfde71458a69e7edeece2c071e":"(set-option :produce-models true)
(set-logic ALL)
(declare-fun |error_0| () Int)
(declare-fun |this_0| () Int)
(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int))))))
(declare-fun |state_0| () |state_type|)
(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int)))))
(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.chainid| Int) (|block.coinbase| Int) (|block.difficulty| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int)))))
(declare-fun |tx_0| () |tx_type|)
(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int)))))
(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int))))))
(declare-fun |crypto_0| () |crypto_type|)
(declare-datatypes ((|abi_type| 0)) (((|abi_type|))))
(declare-fun |abi_0| () |abi_type|)
(declare-fun |x_3_0| () Int)
(declare-fun |expr_7_0| () Int)
(declare-fun |expr_8_0| () Int)
(declare-fun |expr_9_1| () Bool)
(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1)))
(declare-const |EVALEXPR_0| Int)
(assert (= |EVALEXPR_0| x_3_0))
(check-sat)
(get-value (|EVALEXPR_0| ))
","0x540d6953fff999f72ca33d8af8b900986dc012a365fc1b8572aa9d9978f1392b":"(set-logic HORN)
(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int))))))
(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int)))))
(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.chainid| Int) (|block.coinbase| Int) (|block.difficulty| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int)))))
(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int)))))
(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int))))))
(declare-datatypes ((|abi_type| 0)) (((|abi_type|))))
(declare-fun |interface_0_C_14_0| (Int |abi_type| |crypto_type| |state_type| ) Bool)
(declare-fun |nondet_interface_1_C_14_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool)
(declare-fun |summary_constructor_2_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|))
(=> (= error_0 0) (nondet_interface_1_C_14_0 error_0 this_0 abi_0 crypto_0 state_0 state_0))))
(declare-fun |summary_3_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (nondet_interface_1_C_14_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_3_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 x_3_0 state_2 x_3_1))) (nondet_interface_1_C_14_0 error_1 this_0 abi_0 crypto_0 state_0 state_2))))
(declare-fun |block_4_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool)
(declare-fun |block_5_f_12_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(block_4_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (block_4_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true)) true) (block_5_f_12_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))))
(declare-fun |block_6_return_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool)
(declare-fun |block_7_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (block_5_f_12_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true))))))) (and (not expr_9_1) (= error_1 1))) (block_7_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (block_7_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (summary_3_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (block_5_f_12_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= error_1 error_0) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true)))))))) true) (block_6_return_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (block_6_return_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) true) true) (summary_3_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (interface_0_C_14_0 this_0 abi_0 crypto_0 state_0) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (summary_3_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)) (= error_0 0))) (interface_0_C_14_0 this_0 abi_0 crypto_0 state_1))))
(declare-fun |contract_initializer_8_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool)
(declare-fun |contract_initializer_entry_9_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_9_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))))
(declare-fun |contract_initializer_after_init_10_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (contract_initializer_entry_9_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_10_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (contract_initializer_after_init_10_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_8_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))))
(declare-fun |implicit_constructor_entry_11_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (and (= state_1 state_0) (= error_0 0)) true) true) (implicit_constructor_entry_11_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (implicit_constructor_entry_11_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_8_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (implicit_constructor_entry_11_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_8_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int))
(=> (and (and (summary_constructor_2_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14_0 this_0 abi_0 crypto_0 state_1))))
(declare-fun |error_target_2_0| () Bool)
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int))
(=> (and (and (interface_0_C_14_0 this_0 abi_0 crypto_0 state_0) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (summary_3_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)) (= error_0 1))) error_target_2_0)))
(assert
(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int))
(=> error_target_2_0 false)))
(check-sat)"}},"errors":[{"component":"general","errorCode":"3996","formattedMessage":"Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.
","message":"CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.","severity":"warning","type":"Warning"},{"component":"general","errorCode":"8084","formattedMessage":"Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.
","message":"BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.","severity":"warning","type":"Warning"}],"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,18 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"solvers": ["z3"]
}
}
}

View File

@ -0,0 +1,21 @@
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
C.constructor()
C.f(0)
--> A:4:47:
|
4 | contract C { function f(uint x) public pure { assert(x > 0); } }
| ^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
C.constructor()
C.f(0)","severity":"warning","sourceLocation":{"end":119,"file":"A","start":106},"type":"Warning"}],"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,18 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
}
},
"settings":
{
"modelChecker":
{
"engine": "all",
"solvers": ["z3", "smtlib2"]
}
}
}

View File

@ -0,0 +1,21 @@
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"Warning: CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
C.constructor()
C.f(0)
--> A:4:47:
|
4 | contract C { function f(uint x) public pure { assert(x > 0); } }
| ^^^^^^^^^^^^^
","message":"CHC: Assertion violation happens here.
Counterexample:
x = 0
Transaction trace:
C.constructor()
C.f(0)","severity":"warning","sourceLocation":{"end":119,"file":"A","start":106},"type":"Warning"}],"sources":{"A":{"id":0}}}

View File

@ -47,8 +47,10 @@ function solcjs_test
cp -Rf "$SOLCJS_INPUT_DIR/DAO" test/ cp -Rf "$SOLCJS_INPUT_DIR/DAO" test/
printLog "Copying SMTChecker tests..." printLog "Copying SMTChecker tests..."
cp -Rf "$TEST_DIR"/test/libsolidity/smtCheckerTests test/ # We do not copy all tests because that takes too long.
rm -rf test/smtCheckerTests/imports cp -Rf "$TEST_DIR"/test/libsolidity/smtCheckerTests/external_calls test/smtCheckerTests/
cp -Rf "$TEST_DIR"/test/libsolidity/smtCheckerTests/loops test/smtCheckerTests/
cp -Rf "$TEST_DIR"/test/libsolidity/smtCheckerTests/invariants test/smtCheckerTests/
# Update version (needed for some tests) # Update version (needed for some tests)
echo "Updating package.json to version $VERSION" echo "Updating package.json to version $VERSION"

View File

@ -29,21 +29,13 @@ SMTCheckerTest::SMTCheckerTest(string const& _filename): SyntaxTest(_filename, E
{ {
auto const& choice = m_reader.stringSetting("SMTSolvers", "any"); auto const& choice = m_reader.stringSetting("SMTSolvers", "any");
if (choice == "any") if (choice == "any")
m_enabledSolvers = smtutil::SMTSolverChoice::All(); m_modelCheckerSettings.solvers = smtutil::SMTSolverChoice::All();
else if (choice == "z3")
m_enabledSolvers = smtutil::SMTSolverChoice::Z3();
else if (choice == "cvc4")
m_enabledSolvers = smtutil::SMTSolverChoice::CVC4();
else if (choice == "none") else if (choice == "none")
m_enabledSolvers = smtutil::SMTSolverChoice::None(); m_modelCheckerSettings.solvers = smtutil::SMTSolverChoice::None();
else else if (!m_modelCheckerSettings.solvers.setSolver(choice))
BOOST_THROW_EXCEPTION(runtime_error("Invalid SMT solver choice.")); BOOST_THROW_EXCEPTION(runtime_error("Invalid SMT solver choice."));
auto available = ModelChecker::availableSolvers(); m_modelCheckerSettings.solvers &= ModelChecker::availableSolvers();
if (!available.z3)
m_enabledSolvers.z3 = false;
if (!available.cvc4)
m_enabledSolvers.cvc4 = false;
auto engine = ModelCheckerEngine::fromString(m_reader.stringSetting("SMTEngine", "all")); auto engine = ModelCheckerEngine::fromString(m_reader.stringSetting("SMTEngine", "all"));
if (engine) if (engine)
@ -51,7 +43,7 @@ SMTCheckerTest::SMTCheckerTest(string const& _filename): SyntaxTest(_filename, E
else else
BOOST_THROW_EXCEPTION(runtime_error("Invalid SMT engine choice.")); BOOST_THROW_EXCEPTION(runtime_error("Invalid SMT engine choice."));
if (m_enabledSolvers.none() || m_modelCheckerSettings.engine.none()) if (m_modelCheckerSettings.solvers.none() || m_modelCheckerSettings.engine.none())
m_shouldRun = false; m_shouldRun = false;
auto const& ignoreCex = m_reader.stringSetting("SMTIgnoreCex", "no"); auto const& ignoreCex = m_reader.stringSetting("SMTIgnoreCex", "no");
@ -66,7 +58,6 @@ SMTCheckerTest::SMTCheckerTest(string const& _filename): SyntaxTest(_filename, E
TestCase::TestResult SMTCheckerTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) TestCase::TestResult SMTCheckerTest::run(ostream& _stream, string const& _linePrefix, bool _formatted)
{ {
setupCompiler(); setupCompiler();
compiler().setSMTSolverChoice(m_enabledSolvers);
compiler().setModelCheckerSettings(m_modelCheckerSettings); compiler().setModelCheckerSettings(m_modelCheckerSettings);
parseAndAnalyze(); parseAndAnalyze();
filterObtainedErrors(); filterObtainedErrors();

View File

@ -27,6 +27,7 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <liblangutil/EVMVersion.h> #include <liblangutil/EVMVersion.h>
#include <libsmtutil/SolverInterface.h>
#include <libsolidity/interface/Version.h> #include <libsolidity/interface/Version.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -82,6 +83,7 @@ BOOST_AUTO_TEST_CASE(no_options)
expectedOptions.modelChecker.settings = { expectedOptions.modelChecker.settings = {
ModelCheckerContracts::Default(), ModelCheckerContracts::Default(),
ModelCheckerEngine::None(), ModelCheckerEngine::None(),
smtutil::SMTSolverChoice::All(),
ModelCheckerTargets::Default(), ModelCheckerTargets::Default(),
nullopt, nullopt,
}; };
@ -150,6 +152,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
"--yul-optimizations=agf", "--yul-optimizations=agf",
"--model-checker-contracts=contract1.yul:A,contract2.yul:B", "--model-checker-contracts=contract1.yul:A,contract2.yul:B",
"--model-checker-engine=bmc", "--model-checker-engine=bmc",
"--model-checker-solvers=z3,smtlib2",
"--model-checker-targets=underflow,divByZero", "--model-checker-targets=underflow,divByZero",
"--model-checker-timeout=5", "--model-checker-timeout=5",
}; };
@ -207,6 +210,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
expectedOptions.modelChecker.settings = { expectedOptions.modelChecker.settings = {
{{{"contract1.yul", {"A"}}, {"contract2.yul", {"B"}}}}, {{{"contract1.yul", {"A"}}, {"contract2.yul", {"B"}}}},
{true, false}, {true, false},
{false, true, true},
{{VerificationTargetType::Underflow, VerificationTargetType::DivByZero}}, {{VerificationTargetType::Underflow, VerificationTargetType::DivByZero}},
5, 5,
}; };
@ -276,6 +280,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
"contract1.yul:A," "contract1.yul:A,"
"contract2.yul:B", "contract2.yul:B",
"--model-checker-engine=bmc", // Ignored in assembly mode "--model-checker-engine=bmc", // Ignored in assembly mode
"--model-checker-solvers=z3,smtlib2", // Ignored in assembly mode
"--model-checker-targets=" // Ignored in assembly mode "--model-checker-targets=" // Ignored in assembly mode
"underflow," "underflow,"
"divByZero", "divByZero",
@ -372,6 +377,7 @@ BOOST_AUTO_TEST_CASE(standard_json_mode_options)
"contract1.yul:A," "contract1.yul:A,"
"contract2.yul:B", "contract2.yul:B",
"--model-checker-engine=bmc", // Ignored in Standard JSON mode "--model-checker-engine=bmc", // Ignored in Standard JSON mode
"--model-checker-solvers=z3,smtlib2", // Ignored in Standard JSON mode
"--model-checker-targets=" // Ignored in Standard JSON mode "--model-checker-targets=" // Ignored in Standard JSON mode
"underflow," "underflow,"
"divByZero", "divByZero",

View File

@ -16,7 +16,6 @@
*/ */
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
#include "libsolidity/formal/ModelCheckerSettings.h"
#include <test/tools/fuzzer_common.h> #include <test/tools/fuzzer_common.h>
#include <libsolidity/interface/OptimiserSettings.h> #include <libsolidity/interface/OptimiserSettings.h>
@ -105,6 +104,7 @@ void FuzzerUtil::testCompiler(
compiler.setModelCheckerSettings({ compiler.setModelCheckerSettings({
frontend::ModelCheckerContracts::Default(), frontend::ModelCheckerContracts::Default(),
frontend::ModelCheckerEngine::All(), frontend::ModelCheckerEngine::All(),
smtutil::SMTSolverChoice::All(),
frontend::ModelCheckerTargets::Default(), frontend::ModelCheckerTargets::Default(),
/*timeout=*/1 /*timeout=*/1
}); });