@@ -65,6 +65,52 @@ bool CHC::visit(ContractDefinition const& _contract)
65
65
if (!SMTEncoder::visit (_contract))
66
66
return false ;
67
67
68
+ m_stateVariables = _contract.stateVariablesIncludingInherited ();
69
+
70
+ for (auto const & var: m_stateVariables)
71
+ // SMT solvers do not support function types as arguments.
72
+ if (var->type ()->category () == Type::Category::Function)
73
+ m_stateSorts.push_back (make_shared<smt::Sort>(smt::Kind::Int));
74
+ else
75
+ m_stateSorts.push_back (smt::smtSort (*var->type ()));
76
+
77
+ string interfaceName = " interface_" + _contract.name () + " _" + to_string (_contract.id ());
78
+ m_interfacePredicate = createBlock (interfaceSort (), interfaceName);
79
+
80
+ // TODO create static instances for Bool/Int sorts in SolverInterface.
81
+ auto boolSort = make_shared<smt::Sort>(smt::Kind::Bool);
82
+ auto errorFunctionSort = make_shared<smt::FunctionSort>(
83
+ vector<smt::SortPointer>(),
84
+ boolSort
85
+ );
86
+ m_errorPredicate = createBlock (errorFunctionSort, " error" );
87
+
88
+ // If the contract has a constructor it is handled as a function.
89
+ // Otherwise we zero-initialize all state vars.
90
+ // TODO take into account state vars init values.
91
+ if (!_contract.constructor ())
92
+ {
93
+ string constructorName = " constructor_" + _contract.name () + " _" + to_string (_contract.id ());
94
+ m_constructorPredicate = createBlock (constructorSort (), constructorName);
95
+
96
+ for (auto const & var: m_stateVariables)
97
+ {
98
+ auto const & symbVar = m_context.variable (*var);
99
+ symbVar->increaseIndex ();
100
+ m_interface->declareVariable (symbVar->currentName (), *symbVar->sort ());
101
+ m_context.setZeroValue (*symbVar);
102
+ }
103
+
104
+ smt::Expression constructorAppl = (*m_constructorPredicate)({});
105
+ m_interface->addRule (constructorAppl, constructorName);
106
+
107
+ smt::Expression constructorInterface = smt::Expression::implies (
108
+ constructorAppl && m_context.assertions (),
109
+ interface ()
110
+ );
111
+ m_interface->addRule (constructorInterface, constructorName + " _to_" + interfaceName);
112
+ }
113
+
68
114
return true ;
69
115
}
70
116
@@ -73,6 +119,11 @@ void CHC::endVisit(ContractDefinition const& _contract)
73
119
if (!shouldVisit (_contract))
74
120
return ;
75
121
122
+ auto errorAppl = (*m_errorPredicate)({});
123
+ for (auto const & target: m_verificationTargets)
124
+ if (query (errorAppl, target->location ()))
125
+ m_safeAssertions.insert (target);
126
+
76
127
SMTEncoder::endVisit (_contract);
77
128
}
78
129
@@ -131,6 +182,8 @@ void CHC::visitAssert(FunctionCall const&)
131
182
132
183
void CHC::reset ()
133
184
{
185
+ m_stateSorts.clear ();
186
+ m_stateVariables.clear ();
134
187
m_verificationTargets.clear ();
135
188
m_safeAssertions.clear ();
136
189
}
@@ -155,6 +208,71 @@ bool CHC::shouldVisit(FunctionDefinition const& _function) const
155
208
return false ;
156
209
}
157
210
211
+ smt::SortPointer CHC::constructorSort ()
212
+ {
213
+ solAssert (m_currentContract, " " );
214
+ auto boolSort = make_shared<smt::Sort>(smt::Kind::Bool);
215
+ if (!m_currentContract->constructor ())
216
+ return make_shared<smt::FunctionSort>(vector<smt::SortPointer>{}, boolSort);
217
+ return functionSort (*m_currentContract->constructor ());
218
+ }
219
+
220
+ smt::SortPointer CHC::interfaceSort ()
221
+ {
222
+ auto boolSort = make_shared<smt::Sort>(smt::Kind::Bool);
223
+ return make_shared<smt::FunctionSort>(
224
+ m_stateSorts,
225
+ boolSort
226
+ );
227
+ }
228
+
229
+ smt::SortPointer CHC::functionSort (FunctionDefinition const & _function)
230
+ {
231
+ auto boolSort = make_shared<smt::Sort>(smt::Kind::Bool);
232
+ auto const & funType = dynamic_cast <FunctionType const &>(*_function.type ());
233
+ return make_shared<smt::FunctionSort>(
234
+ smt::smtSort (funType.parameterTypes ()),
235
+ boolSort
236
+ );
237
+ }
238
+
239
+ unique_ptr<smt::SymbolicFunctionVariable> CHC::createBlock (smt::SortPointer _sort, string const & _name)
240
+ {
241
+ auto block = make_unique<smt::SymbolicFunctionVariable>(
242
+ _sort,
243
+ _name,
244
+ m_context
245
+ );
246
+ m_interface->registerRelation (block->currentValue ());
247
+ return block;
248
+ }
249
+
250
+ smt::Expression CHC::constructor ()
251
+ {
252
+ solAssert (m_currentContract, " " );
253
+
254
+ if (!m_currentContract->constructor ())
255
+ return (*m_constructorPredicate)({});
256
+
257
+ vector<smt::Expression> paramExprs;
258
+ for (auto const & var: m_currentContract->constructor ()->parameters ())
259
+ paramExprs.push_back (m_context.variable (*var)->currentValue ());
260
+ return (*m_constructorPredicate)(paramExprs);
261
+ }
262
+
263
+ smt::Expression CHC::interface ()
264
+ {
265
+ vector<smt::Expression> paramExprs;
266
+ for (auto const & var: m_stateVariables)
267
+ paramExprs.push_back (m_context.variable (*var)->currentValue ());
268
+ return (*m_interfacePredicate)(paramExprs);
269
+ }
270
+
271
+ smt::Expression CHC::error ()
272
+ {
273
+ return (*m_errorPredicate)({});
274
+ }
275
+
158
276
bool CHC::query (smt::Expression const & _query, langutil::SourceLocation const & _location)
159
277
{
160
278
smt::CheckResult result;
0 commit comments