|
19 | 19 | #include <libsolidity/formal/CHC.h>
|
20 | 20 |
|
21 | 21 | #include <libsolidity/formal/ArraySlicePredicate.h>
|
| 22 | +#include <libsolidity/formal/ExpressionFormatter.h> |
22 | 23 | #include <libsolidity/formal/EldaricaCHCSmtLib2Interface.h>
|
23 |
| -#include <libsolidity/formal/Invariants.h> |
24 | 24 | #include <libsolidity/formal/ModelChecker.h>
|
25 | 25 | #include <libsolidity/formal/PredicateInstance.h>
|
26 | 26 | #include <libsolidity/formal/PredicateSort.h>
|
@@ -2134,6 +2134,58 @@ void CHC::checkVerificationTargets()
|
2134 | 2134 | m_safeTargets[m_verificationTargets.at(id).errorNode].insert(m_verificationTargets.at(id));
|
2135 | 2135 | }
|
2136 | 2136 |
|
| 2137 | +namespace |
| 2138 | +{ |
| 2139 | +std::map<Predicate const*, std::set<std::string>> collectInvariants( |
| 2140 | + smtutil::Expression const& _proof, |
| 2141 | + std::set<Predicate const*> const& _predicates, |
| 2142 | + ModelCheckerInvariants const& _invariantsSetting |
| 2143 | +) |
| 2144 | +{ |
| 2145 | + std::set<std::string> targets; |
| 2146 | + if (_invariantsSetting.has(InvariantType::Contract)) |
| 2147 | + targets.insert("interface_"); |
| 2148 | + if (_invariantsSetting.has(InvariantType::Reentrancy)) |
| 2149 | + targets.insert("nondet_interface_"); |
| 2150 | + |
| 2151 | + std::map<std::string, std::pair<smtutil::Expression, smtutil::Expression>> equalities; |
| 2152 | + // Collect equalities where one of the sides is a predicate we're interested in. |
| 2153 | + util::BreadthFirstSearch<smtutil::Expression const*>{{&_proof}}.run([&](auto&& _expr, auto&& _addChild) { |
| 2154 | + if (_expr->name == "=") |
| 2155 | + for (auto const& t: targets) |
| 2156 | + { |
| 2157 | + auto arg0 = _expr->arguments.at(0); |
| 2158 | + auto arg1 = _expr->arguments.at(1); |
| 2159 | + if (boost::algorithm::starts_with(arg0.name, t)) |
| 2160 | + equalities.insert({arg0.name, {arg0, std::move(arg1)}}); |
| 2161 | + else if (boost::algorithm::starts_with(arg1.name, t)) |
| 2162 | + equalities.insert({arg1.name, {arg1, std::move(arg0)}}); |
| 2163 | + } |
| 2164 | + for (auto const& arg: _expr->arguments) |
| 2165 | + _addChild(&arg); |
| 2166 | + }); |
| 2167 | + |
| 2168 | + std::map<Predicate const*, std::set<std::string>> invariants; |
| 2169 | + for (auto pred: _predicates) |
| 2170 | + { |
| 2171 | + auto predName = pred->functor().name; |
| 2172 | + if (!equalities.count(predName)) |
| 2173 | + continue; |
| 2174 | + |
| 2175 | + solAssert(pred->contextContract(), ""); |
| 2176 | + |
| 2177 | + auto const& [predExpr, invExpr] = equalities.at(predName); |
| 2178 | + |
| 2179 | + static std::set<std::string> const ignore{"true", "false"}; |
| 2180 | + auto r = substitute(invExpr, pred->expressionSubstitution(predExpr)); |
| 2181 | + // No point in reporting true/false as invariants. |
| 2182 | + if (!ignore.count(r.name)) |
| 2183 | + invariants[pred].insert(toSolidityStr(r)); |
| 2184 | + } |
| 2185 | + return invariants; |
| 2186 | +} |
| 2187 | +} // namespace |
| 2188 | + |
2137 | 2189 | void CHC::checkAndReportTarget(
|
2138 | 2190 | CHCVerificationTarget const& _target,
|
2139 | 2191 | std::vector<CHCQueryPlaceholder> const& _placeholders,
|
|
0 commit comments