Coverage Report

Created: 2026-06-30 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/libsolidity/formal/SMTEncoder.cpp
Line
Count
Source
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
19
#include <libsolidity/formal/SMTEncoder.h>
20
21
#include <libsolidity/ast/TypeProvider.h>
22
#include <libsolidity/formal/SymbolicState.h>
23
#include <libsolidity/formal/SymbolicTypes.h>
24
25
#include <libsolidity/analysis/ConstantEvaluator.h>
26
27
#include <libyul/AST.h>
28
#include <libyul/optimiser/Semantics.h>
29
30
#include <libsmtutil/SMTPortfolio.h>
31
#include <libsmtutil/Helpers.h>
32
33
#include <liblangutil/CharStreamProvider.h>
34
35
#include <libsolutil/Algorithms.h>
36
#include <libsolutil/FunctionSelector.h>
37
38
#include <range/v3/view.hpp>
39
40
#include <limits>
41
#include <deque>
42
43
using namespace solidity;
44
using namespace solidity::util;
45
using namespace solidity::langutil;
46
using namespace solidity::frontend;
47
using namespace std::string_literals;
48
49
SMTEncoder::SMTEncoder(
50
  smt::EncodingContext& _context,
51
  ModelCheckerSettings _settings,
52
  UniqueErrorReporter& _errorReporter,
53
  UniqueErrorReporter& _unsupportedErrorReporter,
54
  ErrorReporter& _provedSafeReporter,
55
  langutil::CharStreamProvider const& _charStreamProvider
56
):
57
25.1k
  m_errorReporter(_errorReporter),
58
25.1k
  m_unsupportedErrors(_unsupportedErrorReporter),
59
25.1k
  m_provedSafeReporter(_provedSafeReporter),
60
25.1k
  m_context(_context),
61
25.1k
  m_settings(std::move(_settings)),
62
25.1k
  m_charStreamProvider(_charStreamProvider)
63
25.1k
{
64
25.1k
}
65
66
void SMTEncoder::resetSourceAnalysis()
67
26.8k
{
68
26.8k
  m_freeFunctions.clear();
69
26.8k
}
70
71
bool SMTEncoder::visit(ContractDefinition const& _contract)
72
27.8k
{
73
27.8k
  solAssert(m_currentContract, "");
74
75
27.8k
  for (auto const& node: _contract.subNodes())
76
47.2k
    if (
77
47.2k
      !std::dynamic_pointer_cast<FunctionDefinition>(node) &&
78
20.5k
      !std::dynamic_pointer_cast<VariableDeclaration>(node)
79
47.2k
    )
80
6.19k
      node->accept(*this);
81
82
27.8k
  for (auto const& base: _contract.annotation().linearizedBaseContracts)
83
31.3k
  {
84
    // Look for all the constructor invocations bottom up.
85
31.3k
    if (auto const& constructor =  base->constructor())
86
4.10k
      for (auto const& invocation: constructor->modifiers())
87
712
      {
88
712
        auto refDecl = invocation->name().annotation().referencedDeclaration;
89
712
        if (auto const& baseContract = dynamic_cast<ContractDefinition const*>(refDecl))
90
522
        {
91
522
          solAssert(!m_baseConstructorCalls.count(baseContract), "");
92
522
          m_baseConstructorCalls[baseContract] = invocation.get();
93
522
        }
94
712
      }
95
31.3k
  }
96
  // Functions are visited first since they might be used
97
  // for state variable initialization which is part of
98
  // the constructor.
99
  // Constructors are visited as part of the constructor
100
  // hierarchy inlining.
101
27.8k
  for (auto const* function: contractFunctionsWithoutVirtual(_contract) + allFreeFunctions())
102
30.7k
    if (!function->isConstructor())
103
26.6k
      function->accept(*this);
104
105
  // Constructors need to be handled by the engines separately.
106
107
27.8k
  return false;
108
27.8k
}
109
110
void SMTEncoder::endVisit(ContractDefinition const& _contract)
111
27.8k
{
112
27.8k
  m_context.resetAllVariables();
113
114
27.8k
  m_baseConstructorCalls.clear();
115
116
27.8k
  solAssert(m_currentContract == &_contract, "");
117
27.8k
  m_currentContract = nullptr;
118
119
27.8k
  if (m_callStack.empty())
120
27.8k
    m_context.popSolver();
121
27.8k
}
122
123
bool SMTEncoder::visit(ImportDirective const&)
124
1.67k
{
125
  // do not visit because the identifier therein will confuse us.
126
1.67k
  return false;
127
1.67k
}
128
129
void SMTEncoder::endVisit(VariableDeclaration const& _varDecl)
130
50.8k
{
131
  // State variables are handled by the constructor.
132
50.8k
  if (_varDecl.isLocalVariable() &&_varDecl.value())
133
0
    assignment(_varDecl, *_varDecl.value());
134
50.8k
}
135
136
bool SMTEncoder::visit(ModifierDefinition const&)
137
742
{
138
742
  return false;
139
742
}
140
141
bool SMTEncoder::visit(FunctionDefinition const& _function)
142
32.3k
{
143
32.3k
  solAssert(m_currentContract, "");
144
145
32.3k
  m_modifierDepthStack.push_back(-1);
146
147
32.3k
  initializeLocalVariables(_function);
148
149
32.3k
  _function.parameterList().accept(*this);
150
32.3k
  if (_function.returnParameterList())
151
32.3k
    _function.returnParameterList()->accept(*this);
152
153
32.3k
  visitFunctionOrModifier();
154
155
32.3k
  return false;
156
32.3k
}
157
158
void SMTEncoder::visitFunctionOrModifier()
159
33.9k
{
160
33.9k
  solAssert(!m_callStack.empty(), "");
161
33.9k
  solAssert(!m_modifierDepthStack.empty(), "");
162
163
33.9k
  ++m_modifierDepthStack.back();
164
33.9k
  FunctionDefinition const& function = dynamic_cast<FunctionDefinition const&>(*m_callStack.back().first);
165
166
33.9k
  if (m_modifierDepthStack.back() == static_cast<int>(function.modifiers().size()))
167
32.4k
  {
168
32.4k
    if (function.isImplemented())
169
31.7k
    {
170
31.7k
      pushInlineFrame(function);
171
31.7k
      function.body().accept(*this);
172
31.7k
      popInlineFrame(function);
173
31.7k
    }
174
32.4k
  }
175
1.50k
  else
176
1.50k
  {
177
1.50k
    solAssert(m_modifierDepthStack.back() < static_cast<int>(function.modifiers().size()), "");
178
1.50k
    ASTPointer<ModifierInvocation> const& modifierInvocation =
179
1.50k
      function.modifiers()[static_cast<size_t>(m_modifierDepthStack.back())];
180
1.50k
    solAssert(modifierInvocation, "");
181
1.50k
    auto refDecl = modifierInvocation->name().annotation().referencedDeclaration;
182
1.50k
    if (dynamic_cast<ContractDefinition const*>(refDecl))
183
522
      visitFunctionOrModifier();
184
979
    else if (auto modifier = resolveModifierInvocation(*modifierInvocation, m_currentContract))
185
979
    {
186
979
      m_scopes.push_back(modifier);
187
979
      inlineModifierInvocation(modifierInvocation.get(), modifier);
188
979
      solAssert(m_scopes.back() == modifier, "");
189
979
      m_scopes.pop_back();
190
979
    }
191
0
    else
192
979
      solAssert(false, "");
193
1.50k
  }
194
195
33.9k
  --m_modifierDepthStack.back();
196
33.9k
}
197
198
void SMTEncoder::inlineModifierInvocation(ModifierInvocation const* _invocation, CallableDeclaration const* _definition)
199
1.23k
{
200
1.23k
  solAssert(_invocation, "");
201
1.23k
  _invocation->accept(*this);
202
203
1.23k
  std::vector<smtutil::Expression> args;
204
1.23k
  if (auto const* arguments = _invocation->arguments())
205
691
  {
206
691
    auto const& modifierParams = _definition->parameters();
207
691
    solAssert(modifierParams.size() == arguments->size(), "");
208
1.36k
    for (unsigned i = 0; i < arguments->size(); ++i)
209
678
      args.push_back(expr(*arguments->at(i), modifierParams.at(i)->type()));
210
691
  }
211
212
1.23k
  initializeFunctionCallParameters(*_definition, args);
213
214
1.23k
  pushCallStack({_definition, _invocation});
215
1.23k
  pushInlineFrame(*_definition);
216
1.23k
  if (auto modifier = dynamic_cast<ModifierDefinition const*>(_definition))
217
979
  {
218
979
    if (modifier->isImplemented())
219
957
      modifier->body().accept(*this);
220
979
    popCallStack();
221
979
  }
222
253
  else if (auto function = dynamic_cast<FunctionDefinition const*>(_definition))
223
253
  {
224
253
    if (function->isImplemented())
225
253
      function->accept(*this);
226
    // Functions are popped from the callstack in endVisit(FunctionDefinition)
227
253
  }
228
1.23k
  popInlineFrame(*_definition);
229
1.23k
}
230
231
void SMTEncoder::inlineConstructorHierarchy(ContractDefinition const& _contract)
232
14.5k
{
233
14.5k
  auto const& hierarchy = m_currentContract->annotation().linearizedBaseContracts;
234
14.5k
  auto it = find(begin(hierarchy), end(hierarchy), &_contract);
235
14.5k
  solAssert(it != end(hierarchy), "");
236
237
14.5k
  auto nextBase = it + 1;
238
  // Initialize the base contracts here as long as their constructors are implicit,
239
  // stop when the first explicit constructor is found.
240
15.8k
  while (nextBase != end(hierarchy))
241
1.82k
  {
242
1.82k
    if (auto baseConstructor = (*nextBase)->constructor())
243
508
    {
244
508
      createLocalVariables(*baseConstructor);
245
      // If any subcontract explicitly called baseConstructor, use those arguments.
246
508
      if (m_baseConstructorCalls.count(*nextBase))
247
253
        inlineModifierInvocation(m_baseConstructorCalls.at(*nextBase), baseConstructor);
248
255
      else if (baseConstructor->isImplemented())
249
255
      {
250
        // The first constructor found is handled like a function
251
        // and its pushed into the callstack there.
252
        // This if avoids duplication in the callstack.
253
255
        if (!m_callStack.empty())
254
255
          pushCallStack({baseConstructor, nullptr});
255
255
        baseConstructor->accept(*this);
256
        // popped by endVisit(FunctionDefinition)
257
255
      }
258
508
      break;
259
508
    }
260
1.31k
    else
261
1.31k
    {
262
1.31k
      initializeStateVariables(**nextBase);
263
1.31k
      ++nextBase;
264
1.31k
    }
265
1.82k
  }
266
267
14.5k
  initializeStateVariables(_contract);
268
14.5k
}
269
270
bool SMTEncoder::visit(PlaceholderStatement const&)
271
1.10k
{
272
1.10k
  solAssert(!m_callStack.empty(), "");
273
1.10k
  auto lastCall = popCallStack();
274
1.10k
  visitFunctionOrModifier();
275
1.10k
  pushCallStack(lastCall);
276
1.10k
  return true;
277
1.10k
}
278
279
void SMTEncoder::endVisit(FunctionDefinition const&)
280
32.3k
{
281
32.3k
  solAssert(m_currentContract, "");
282
283
32.3k
  popCallStack();
284
32.3k
  solAssert(m_modifierDepthStack.back() == -1, "");
285
32.3k
  m_modifierDepthStack.pop_back();
286
32.3k
  if (m_callStack.empty())
287
30.0k
    m_context.popSolver();
288
32.3k
}
289
290
bool SMTEncoder::visit(Block const& _block)
291
35.0k
{
292
35.0k
  if (_block.unchecked())
293
294
  {
294
294
    solAssert(m_checked, "");
295
294
    m_checked = false;
296
294
  }
297
35.0k
  return true;
298
35.0k
}
299
300
void SMTEncoder::endVisit(Block const& _block)
301
35.0k
{
302
35.0k
  if (_block.unchecked())
303
294
  {
304
294
    solAssert(!m_checked, "");
305
294
    m_checked = true;
306
294
  }
307
35.0k
}
308
309
bool SMTEncoder::visit(InlineAssembly const& _inlineAsm)
310
3.98k
{
311
  /// This is very similar to `yul::Assignments`, except I need to collect `Identifier`s and not just names as `YulString`s.
312
3.98k
  struct AssignedExternalsCollector: public yul::ASTWalker
313
3.98k
  {
314
3.98k
    AssignedExternalsCollector(InlineAssembly const& _inlineAsm): externalReferences(_inlineAsm.annotation().externalReferences)
315
3.98k
    {
316
3.98k
      this->operator()(_inlineAsm.operations().root());
317
3.98k
    }
318
319
3.98k
    std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> const& externalReferences;
320
3.98k
    std::set<VariableDeclaration const*> assignedVars;
321
322
3.98k
    using yul::ASTWalker::operator();
323
3.98k
    void operator()(yul::Assignment const& _assignment)
324
3.98k
    {
325
1.64k
      auto const& vars = _assignment.variableNames;
326
1.64k
      for (auto const& identifier: vars)
327
1.65k
        if (auto externalInfo = util::valueOrNullptr(externalReferences, &identifier))
328
1.34k
          if (auto varDecl = dynamic_cast<VariableDeclaration const*>(externalInfo->declaration))
329
1.34k
            assignedVars.insert(varDecl);
330
1.64k
    }
331
3.98k
  };
332
333
3.98k
  yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.dialect(), _inlineAsm.operations().root());
334
3.98k
  if (sideEffectsCollector.invalidatesMemory())
335
1.08k
    resetMemoryVariables();
336
3.98k
  if (sideEffectsCollector.invalidatesStorage())
337
1.46k
    resetStorageVariables();
338
339
3.98k
  auto assignedVars = AssignedExternalsCollector(_inlineAsm).assignedVars;
340
3.98k
  for (auto const* var: assignedVars)
341
914
  {
342
914
    solAssert(var, "");
343
914
    solAssert(var->isLocalVariable(), "Non-local variable assigned in inlined assembly");
344
914
    m_context.resetVariable(*var);
345
914
  }
346
347
3.98k
  m_unsupportedErrors.warning(
348
3.98k
    7737_error,
349
3.98k
    _inlineAsm.location(),
350
3.98k
    "Inline assembly may cause SMTChecker to produce spurious warnings (false positives)."
351
3.98k
  );
352
3.98k
  return false;
353
3.98k
}
354
355
void SMTEncoder::pushInlineFrame(CallableDeclaration const&)
356
16.9k
{
357
16.9k
  pushPathCondition(currentPathConditions());
358
16.9k
}
359
360
void SMTEncoder::popInlineFrame(CallableDeclaration const&)
361
16.9k
{
362
16.9k
  popPathCondition();
363
16.9k
}
364
365
void SMTEncoder::endVisit(VariableDeclarationStatement const& _varDecl)
366
7.99k
{
367
7.99k
  if (auto init = _varDecl.initialValue())
368
5.50k
    expressionToTupleAssignment(_varDecl.declarations(), *init);
369
7.99k
}
370
371
bool SMTEncoder::visit(Assignment const& _assignment)
372
19.7k
{
373
  // RHS must be visited before LHS; as opposed to what Assignment::accept does
374
19.7k
  _assignment.rightHandSide().accept(*this);
375
19.7k
  _assignment.leftHandSide().accept(*this);
376
19.7k
  return false;
377
19.7k
}
378
379
void SMTEncoder::endVisit(Assignment const& _assignment)
380
19.7k
{
381
19.7k
  createExpr(_assignment);
382
383
19.7k
  Token op = _assignment.assignmentOperator();
384
19.7k
  solAssert(TokenTraits::isAssignmentOp(op), "");
385
386
19.7k
  if (!isSupportedType(*_assignment.annotation().type))
387
273
  {
388
    // Give it a new index anyway to keep the SSA scheme sound.
389
390
273
    Expression const* base = &_assignment.leftHandSide();
391
273
    if (auto const* indexAccess = dynamic_cast<IndexAccess const*>(base))
392
42
      base = leftmostBase(*indexAccess);
393
394
273
    if (auto varDecl = identifierToVariable(*base))
395
195
      m_context.newValue(*varDecl);
396
273
  }
397
19.5k
  else
398
19.5k
  {
399
19.5k
    if (dynamic_cast<TupleType const*>(_assignment.rightHandSide().annotation().type))
400
337
      tupleAssignment(_assignment.leftHandSide(), _assignment.rightHandSide());
401
19.1k
    else
402
19.1k
    {
403
19.1k
      auto const& type = _assignment.annotation().type;
404
19.1k
      auto rightHandSide = op == Token::Assign ?
405
18.0k
        expr(_assignment.rightHandSide(), type) :
406
19.1k
        compoundAssignment(_assignment);
407
19.1k
      defineExpr(_assignment, rightHandSide);
408
19.1k
      assignment(
409
19.1k
        _assignment.leftHandSide(),
410
19.1k
        expr(_assignment, type),
411
19.1k
        type
412
19.1k
      );
413
19.1k
    }
414
19.5k
  }
415
19.7k
}
416
417
void SMTEncoder::endVisit(TupleExpression const& _tuple)
418
8.86k
{
419
8.86k
  if (_tuple.annotation().type->category() == Type::Category::Function)
420
235
    return;
421
422
8.62k
  if (_tuple.annotation().type->category() == Type::Category::TypeType)
423
57
    return;
424
425
8.56k
  createExpr(_tuple);
426
427
8.56k
  if (_tuple.isInlineArray())
428
1.20k
  {
429
    // Add constraints for the length and values as it is known.
430
1.20k
    auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_tuple));
431
1.20k
    smtAssert(symbArray, "Inline array must be represented with SymbolicArrayVariable");
432
1.20k
    auto originalType = symbArray->originalType();
433
1.20k
    auto arrayType = dynamic_cast<ArrayType const*>(originalType);
434
1.20k
    smtAssert(arrayType, "Type of inline array must be ArrayType");
435
2.18k
    addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c, arrayType->baseType()); }));
436
1.20k
  }
437
7.36k
  else
438
7.36k
  {
439
12.3k
    auto values = applyMap(_tuple.components(), [this](auto const& component) -> std::optional<smtutil::Expression> {
440
12.3k
      if (component)
441
12.2k
      {
442
12.2k
        if (!m_context.knownExpression(*component))
443
12
            createExpr(*component);
444
12.2k
        return expr(*component);
445
12.2k
      }
446
148
      return {};
447
12.3k
    });
448
7.36k
    defineExpr(_tuple, values);
449
7.36k
  }
450
8.56k
}
451
452
void SMTEncoder::endVisit(UnaryOperation const& _op)
453
7.25k
{
454
  /// For constant expressions, we need to shortcut here
455
  /// due to potentially unknown rational number sizes that
456
  /// can appear in intermediary operations, e.g., ~(2**256 - 1).
457
7.25k
  if (isConstant(_op))
458
1.48k
    return;
459
460
5.77k
  if (TokenTraits::isBitOp(_op.getOperator()) && !*_op.annotation().userDefinedFunction)
461
2.15k
    return bitwiseNotOperation(_op);
462
463
3.62k
  createExpr(_op);
464
465
  // User-defined operators are essentially function calls.
466
3.62k
  if (*_op.annotation().userDefinedFunction)
467
22
    return;
468
469
3.60k
  auto const& subExpr = innermostTuple(_op.subExpression());
470
3.60k
  auto type = _op.annotation().type;
471
3.60k
  switch (_op.getOperator())
472
3.60k
  {
473
506
  case Token::Not: // !
474
506
  {
475
506
    solAssert(smt::isBool(*type), "");
476
506
    defineExpr(_op, !expr(subExpr));
477
506
    break;
478
0
  }
479
2.13k
  case Token::Inc: // ++ (pre- or postfix)
480
2.49k
  case Token::Dec: // -- (pre- or postfix)
481
2.49k
  {
482
2.49k
    solAssert(smt::isInteger(*type) || smt::isFixedPoint(*type), "");
483
2.49k
    solAssert(subExpr.annotation().willBeWrittenTo, "");
484
2.49k
    auto innerValue = expr(subExpr);
485
2.49k
    auto newValue = arithmeticOperation(
486
2.49k
      _op.getOperator() == Token::Inc ? Token::Add : Token::Sub,
487
2.49k
      innerValue,
488
2.49k
      smtutil::Expression(size_t(1)),
489
2.49k
      _op.annotation().type,
490
2.49k
      _op
491
2.49k
    ).first;
492
2.49k
    defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue);
493
2.49k
    assignment(subExpr, newValue);
494
2.49k
    break;
495
2.13k
  }
496
310
  case Token::Sub: // -
497
310
  {
498
310
    defineExpr(_op, 0 - expr(subExpr));
499
310
    break;
500
2.13k
  }
501
294
  case Token::Delete:
502
294
  {
503
294
    if (auto decl = identifierToVariable(subExpr))
504
208
    {
505
208
      m_context.newValue(*decl);
506
208
      m_context.setZeroValue(*decl);
507
208
    }
508
86
    else
509
86
    {
510
86
      solAssert(m_context.knownExpression(subExpr), "");
511
86
      auto const& symbVar = m_context.expression(subExpr);
512
86
      symbVar->increaseIndex();
513
86
      m_context.setZeroValue(*symbVar);
514
86
      if (
515
86
        dynamic_cast<IndexAccess const*>(&subExpr) ||
516
24
        dynamic_cast<MemberAccess const*>(&subExpr)
517
86
      )
518
86
        indexOrMemberAssignment(subExpr, symbVar->currentValue());
519
      // Empty push added a zero value anyway, so no need to delete extra.
520
0
      else if (!isEmptyPush(subExpr))
521
0
        solAssert(false, "");
522
86
    }
523
294
    break;
524
2.13k
  }
525
0
  default:
526
0
    solAssert(false, "");
527
3.60k
  }
528
3.60k
}
529
530
bool SMTEncoder::visit(UnaryOperation const& _op)
531
7.25k
{
532
7.25k
  return !shortcutRationalNumber(_op);
533
7.25k
}
534
535
bool SMTEncoder::visit(BinaryOperation const& _op)
536
32.7k
{
537
32.7k
  if (shortcutRationalNumber(_op))
538
3.68k
    return false;
539
29.0k
  if (TokenTraits::isBooleanOp(_op.getOperator()) && !*_op.annotation().userDefinedFunction)
540
519
  {
541
519
    booleanOperation(_op);
542
519
    return false;
543
519
  }
544
28.5k
  return true;
545
29.0k
}
546
547
void SMTEncoder::endVisit(BinaryOperation const& _op)
548
32.7k
{
549
  /// If _op is const evaluated the RationalNumber shortcut was taken.
550
32.7k
  if (isConstant(_op))
551
3.68k
    return;
552
29.0k
  if (TokenTraits::isBooleanOp(_op.getOperator()) && !*_op.annotation().userDefinedFunction)
553
519
    return;
554
555
28.5k
  createExpr(_op);
556
557
  // User-defined operators are essentially function calls.
558
28.5k
  if (*_op.annotation().userDefinedFunction)
559
60
    return;
560
561
28.5k
  if (TokenTraits::isArithmeticOp(_op.getOperator()))
562
18.2k
    arithmeticOperation(_op);
563
10.2k
  else if (TokenTraits::isCompareOp(_op.getOperator()))
564
9.44k
    compareOperation(_op);
565
830
  else if (TokenTraits::isBitOp(_op.getOperator()) || TokenTraits::isShiftOp(_op.getOperator()))
566
830
    bitwiseOperation(_op);
567
0
  else
568
830
    solAssert(false, "");
569
28.5k
}
570
571
bool SMTEncoder::visit(Conditional const& _op)
572
1.20k
{
573
1.20k
  _op.condition().accept(*this);
574
575
1.20k
  auto indicesEndTrue = visitBranch(&_op.trueExpression(), expr(_op.condition())).first;
576
577
1.20k
  auto indicesEndFalse = visitBranch(&_op.falseExpression(), !expr(_op.condition())).first;
578
579
1.20k
  mergeVariables(expr(_op.condition()), indicesEndTrue, indicesEndFalse);
580
581
1.20k
  defineExpr(_op, smtutil::Expression::ite(
582
1.20k
    expr(_op.condition()),
583
1.20k
    expr(_op.trueExpression(), _op.annotation().type),
584
1.20k
    expr(_op.falseExpression(), _op.annotation().type)
585
1.20k
  ));
586
587
1.20k
  return false;
588
1.20k
}
589
590
bool SMTEncoder::visit(FunctionCall const& _funCall)
591
26.9k
{
592
26.9k
  auto functionCallKind = *_funCall.annotation().kind;
593
26.9k
  if (functionCallKind != FunctionCallKind::FunctionCall)
594
5.61k
    return true;
595
596
21.3k
  FunctionType const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
597
  // We do not want to visit the TypeTypes in the second argument of `abi.decode`.
598
  // Those types are checked/used in SymbolicState::buildABIFunctions.
599
21.3k
  if (funType.kind() == FunctionType::Kind::ABIDecode)
600
242
  {
601
242
    if (auto arg = _funCall.arguments().front())
602
242
      arg->accept(*this);
603
242
    return false;
604
242
  }
605
606
  // We do not really need to visit the expression in a wrap/unwrap no-op call,
607
  // so we just ignore the function call expression to avoid "unsupported" warnings.
608
21.1k
  else if (
609
21.1k
    funType.kind() == FunctionType::Kind::Wrap ||
610
20.7k
    funType.kind() == FunctionType::Kind::Unwrap
611
21.1k
  )
612
513
  {
613
513
    if (auto arg = _funCall.arguments().front())
614
513
      arg->accept(*this);
615
513
    return false;
616
513
  }
617
20.5k
  return true;
618
21.3k
}
619
620
void SMTEncoder::endVisit(FunctionCall const& _funCall)
621
25.3k
{
622
25.3k
  auto functionCallKind = *_funCall.annotation().kind;
623
624
25.3k
  createExpr(_funCall);
625
25.3k
  if (functionCallKind == FunctionCallKind::StructConstructorCall)
626
247
  {
627
247
    visitStructConstructorCall(_funCall);
628
247
    return;
629
247
  }
630
631
25.1k
  if (functionCallKind == FunctionCallKind::TypeConversion)
632
5.36k
  {
633
5.36k
    visitTypeConversion(_funCall);
634
5.36k
    return;
635
5.36k
  }
636
637
19.7k
  FunctionType const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
638
639
19.7k
  std::vector<ASTPointer<Expression const>> const args = _funCall.arguments();
640
19.7k
  switch (funType.kind())
641
19.7k
  {
642
4.28k
  case FunctionType::Kind::Assert:
643
4.28k
    visitAssert(_funCall);
644
4.28k
    break;
645
775
  case FunctionType::Kind::Require:
646
775
    visitRequire(_funCall);
647
775
    break;
648
225
  case FunctionType::Kind::Revert:
649
    // Revert is a special case of require and equals to `require(false)`
650
225
    addPathImpliedExpression(smtutil::Expression(false));
651
225
    break;
652
66
  case FunctionType::Kind::GasLeft:
653
66
    visitGasLeft(_funCall);
654
66
    break;
655
1.75k
  case FunctionType::Kind::External:
656
1.75k
    if (publicGetter(_funCall.expression()))
657
361
      visitPublicGetter(_funCall);
658
1.75k
    break;
659
177
  case FunctionType::Kind::BytesConcat:
660
177
    visitBytesConcat(_funCall);
661
177
    break;
662
242
  case FunctionType::Kind::ABIDecode:
663
585
  case FunctionType::Kind::ABIEncode:
664
759
  case FunctionType::Kind::ABIEncodePacked:
665
803
  case FunctionType::Kind::ABIEncodeWithSelector:
666
841
  case FunctionType::Kind::ABIEncodeCall:
667
881
  case FunctionType::Kind::ABIEncodeWithSignature:
668
881
    visitABIFunction(_funCall);
669
881
    break;
670
1.89k
  case FunctionType::Kind::Internal:
671
1.92k
  case FunctionType::Kind::BareStaticCall:
672
2.31k
  case FunctionType::Kind::BareCall:
673
2.31k
    break;
674
262
  case FunctionType::Kind::KECCAK256:
675
302
  case FunctionType::Kind::ECRecover:
676
330
  case FunctionType::Kind::SHA256:
677
494
  case FunctionType::Kind::RIPEMD160:
678
494
    visitCryptoFunction(_funCall);
679
494
    break;
680
42
  case FunctionType::Kind::BlockHash:
681
42
    defineExpr(_funCall, state().blockhash(expr(*_funCall.arguments().at(0))));
682
42
    break;
683
2
  case FunctionType::Kind::BlobHash:
684
2
    visitBlobHash(_funCall);
685
2
    break;
686
75
  case FunctionType::Kind::AddMod:
687
101
  case FunctionType::Kind::MulMod:
688
101
    visitAddMulMod(_funCall);
689
101
    break;
690
190
  case FunctionType::Kind::Unwrap:
691
513
  case FunctionType::Kind::Wrap:
692
513
    visitWrapUnwrap(_funCall);
693
513
    break;
694
30
  case FunctionType::Kind::Send:
695
155
  case FunctionType::Kind::Transfer:
696
155
  {
697
155
    auto const& memberAccess = dynamic_cast<MemberAccess const&>(_funCall.expression());
698
155
    auto const& address = memberAccess.expression();
699
155
    auto const& value = args.front();
700
155
    solAssert(value, "");
701
702
155
    smtutil::Expression thisBalance = state().balance();
703
155
    setSymbolicUnknownValue(thisBalance, TypeProvider::uint256(), m_context);
704
705
155
    state().transfer(state().thisAddress(), expr(address), expr(*value));
706
155
    break;
707
30
  }
708
2.22k
  case FunctionType::Kind::ArrayPush:
709
2.22k
    arrayPush(_funCall);
710
2.22k
    break;
711
354
  case FunctionType::Kind::ArrayPop:
712
354
    arrayPop(_funCall);
713
354
    break;
714
2.34k
  case FunctionType::Kind::Event:
715
2.45k
  case FunctionType::Kind::Error:
716
    // This can be safely ignored.
717
2.45k
    break;
718
1.95k
  case FunctionType::Kind::ObjectCreation:
719
1.95k
    visitObjectCreation(_funCall);
720
1.95k
    return;
721
595
  case FunctionType::Kind::Creation:
722
595
    if (!m_settings.engine.chc || !m_settings.externalCalls.isTrusted())
723
595
      m_unsupportedErrors.warning(
724
595
        8729_error,
725
595
        _funCall.location(),
726
595
        "Contract deployment is only supported in the trusted mode for external calls"
727
595
        " with the CHC engine."
728
595
      );
729
595
    break;
730
350
  case FunctionType::Kind::DelegateCall:
731
350
  case FunctionType::Kind::BareCallCode:
732
370
  case FunctionType::Kind::BareDelegateCall:
733
414
  default:
734
414
    m_unsupportedErrors.warning(
735
414
      4588_error,
736
414
      _funCall.location(),
737
414
      "Assertion checker does not yet implement this type of function call."
738
414
    );
739
19.7k
  }
740
19.7k
}
741
742
bool SMTEncoder::visit(ModifierInvocation const& _node)
743
1.23k
{
744
1.23k
  if (auto const* args = _node.arguments())
745
691
    for (auto const& arg: *args)
746
678
      if (arg)
747
678
        arg->accept(*this);
748
1.23k
  return false;
749
1.23k
}
750
751
void SMTEncoder::initContract(ContractDefinition const& _contract)
752
27.8k
{
753
27.8k
  solAssert(m_currentContract == nullptr, "");
754
27.8k
  m_currentContract = &_contract;
755
756
27.8k
  m_context.reset();
757
27.8k
  m_context.pushSolver();
758
27.8k
  createStateVariables(_contract);
759
27.8k
  clearIndices(m_currentContract, nullptr);
760
27.8k
  m_checked = true;
761
27.8k
}
762
763
void SMTEncoder::initFunction(FunctionDefinition const& _function)
764
30.0k
{
765
30.0k
  solAssert(m_callStack.empty(), "");
766
30.0k
  solAssert(m_currentContract, "");
767
30.0k
  m_context.pushSolver();
768
30.0k
  m_pathConditions.clear();
769
30.0k
  pushCallStack({&_function, nullptr});
770
30.0k
  m_uninterpretedTerms.clear();
771
30.0k
  createStateVariables(*m_currentContract);
772
30.0k
  createLocalVariables(_function);
773
30.0k
  m_arrayAssignmentHappened = false;
774
30.0k
  clearIndices(m_currentContract, &_function);
775
30.0k
  m_checked = true;
776
30.0k
}
777
778
void SMTEncoder::visitAssert(FunctionCall const& _funCall)
779
4.28k
{
780
4.28k
  auto const& args = _funCall.arguments();
781
4.28k
  solAssert(args.size() == 1, "");
782
4.28k
  solAssert(args.front()->annotation().type->category() == Type::Category::Bool, "");
783
4.28k
}
784
785
void SMTEncoder::visitRequire(FunctionCall const& _funCall)
786
775
{
787
775
  auto const& args = _funCall.arguments();
788
775
  solAssert(args.size() >= 1, "");
789
775
  solAssert(args.front()->annotation().type->category() == Type::Category::Bool, "");
790
775
  addPathImpliedExpression(expr(*args.front()));
791
775
}
792
793
void SMTEncoder::visitBytesConcat(FunctionCall const& _funCall)
794
177
{
795
177
  auto const& args = _funCall.sortedArguments();
796
797
  // bytes.concat call with no arguments returns an empty array
798
177
  if (args.size() == 0)
799
4
  {
800
4
    defineExpr(_funCall, smt::zeroValue(TypeProvider::bytesMemory()));
801
4
    return;
802
4
  }
803
804
  // bytes.concat with single argument of type bytes memory
805
173
  if (args.size() == 1 && args.front()->annotation().type->category() == frontend::Type::Category::Array)
806
8
  {
807
8
    defineExpr(_funCall, expr(*args.front(), TypeProvider::bytesMemory()));
808
8
    return;
809
8
  }
810
811
165
  auto const& [name, inTypes, outType] = state().bytesConcatFunctionTypes(&_funCall);
812
165
  solAssert(inTypes.size() == args.size(), "");
813
814
165
  auto symbFunction = state().bytesConcatFunction(&_funCall);
815
165
  auto out = createSelectExpressionForFunction(symbFunction, args, inTypes, args.size());
816
817
165
  defineExpr(_funCall, out);
818
165
}
819
820
void SMTEncoder::visitABIFunction(FunctionCall const& _funCall)
821
881
{
822
881
  auto symbFunction = state().abiFunction(&_funCall);
823
881
  auto const& [name, inTypes, outTypes] = state().abiFunctionTypes(&_funCall);
824
825
881
  auto const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
826
881
  auto kind = funType.kind();
827
881
  auto const& args = _funCall.sortedArguments();
828
881
  auto argsActualLength = kind == FunctionType::Kind::ABIDecode ? 1 : args.size();
829
830
881
  solAssert(inTypes.size() == argsActualLength, "");
831
881
  if (argsActualLength == 0)
832
46
  {
833
46
    defineExpr(_funCall, smt::zeroValue(TypeProvider::bytesMemory()));
834
46
    return;
835
46
  }
836
837
835
  auto out = createSelectExpressionForFunction(symbFunction, args, inTypes, argsActualLength);
838
835
  if (outTypes.size() == 1)
839
801
    defineExpr(_funCall, out);
840
34
  else
841
34
  {
842
34
    auto symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_funCall));
843
34
    solAssert(symbTuple, "");
844
34
    solAssert(symbTuple->components().size() == outTypes.size(), "");
845
34
    solAssert(out.sort->kind == smtutil::Kind::Tuple, "");
846
847
34
    symbTuple->increaseIndex();
848
104
    for (unsigned i = 0; i < symbTuple->components().size(); ++i)
849
70
      m_context.addAssertion(symbTuple->component(i) == smtutil::Expression::tuple_get(out, i));
850
34
  }
851
835
}
852
853
void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
854
494
{
855
494
  auto const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
856
494
  auto kind = funType.kind();
857
494
  auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::bytesStorage());
858
494
  std::optional<smtutil::Expression> result;
859
494
  if (kind == FunctionType::Kind::KECCAK256)
860
262
    result = smtutil::Expression::select(state().cryptoFunction("keccak256"), arg0);
861
232
  else if (kind == FunctionType::Kind::SHA256)
862
28
    result = smtutil::Expression::select(state().cryptoFunction("sha256"), arg0);
863
204
  else if (kind == FunctionType::Kind::RIPEMD160)
864
164
    result = smtutil::Expression::select(state().cryptoFunction("ripemd160"), arg0);
865
40
  else if (kind == FunctionType::Kind::ECRecover)
866
40
  {
867
40
    auto e = state().cryptoFunction("ecrecover");
868
40
    auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::fixedBytes(32));
869
40
    auto arg1 = expr(*_funCall.arguments().at(1), TypeProvider::uint(8));
870
40
    auto arg2 = expr(*_funCall.arguments().at(2), TypeProvider::fixedBytes(32));
871
40
    auto arg3 = expr(*_funCall.arguments().at(3), TypeProvider::fixedBytes(32));
872
40
    auto inputSort = dynamic_cast<smtutil::ArraySort&>(*e.sort).domain;
873
40
    auto ecrecoverInput = smtutil::Expression::tuple_constructor(
874
40
      smtutil::Expression(std::make_shared<smtutil::SortSort>(inputSort), ""),
875
40
      {arg0, arg1, arg2, arg3}
876
40
    );
877
40
    result = smtutil::Expression::select(e, ecrecoverInput);
878
40
  }
879
0
  else
880
40
    solAssert(false, "");
881
882
494
  defineExpr(_funCall, *result);
883
494
}
884
885
void SMTEncoder::visitGasLeft(FunctionCall const& _funCall)
886
66
{
887
66
  std::string gasLeft = "gasleft";
888
  // We increase the variable index since gasleft changes
889
  // inside a tx.
890
66
  defineGlobalVariable(gasLeft, _funCall, true);
891
66
  auto const& symbolicVar = m_context.globalSymbol(gasLeft);
892
66
  unsigned index = symbolicVar->index();
893
  // We set the current value to unknown anyway to add type constraints.
894
66
  m_context.setUnknownValue(*symbolicVar);
895
66
  if (index > 0)
896
44
    m_context.addAssertion(symbolicVar->currentValue() <= symbolicVar->valueAtIndex(index - 1));
897
66
}
898
899
void SMTEncoder::visitBlobHash(FunctionCall const& _funCall)
900
2
{
901
2
  constexpr unsigned BLOB_TRANSACTION_LIMIT = 9; // Since pectra
902
2
  auto indexExpr = expr(*_funCall.arguments().at(0));
903
2
  auto valueExpr = smtutil::Expression::ite(
904
2
    indexExpr >= BLOB_TRANSACTION_LIMIT,
905
2
    smtutil::Expression(u256(0)),
906
2
    state().blobhash(indexExpr)
907
2
  );
908
2
  defineExpr(_funCall, std::move(valueExpr));
909
2
}
910
911
void SMTEncoder::visitAddMulMod(FunctionCall const& _funCall)
912
101
{
913
101
  auto const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
914
101
  auto kind = funType.kind();
915
101
  solAssert(kind == FunctionType::Kind::AddMod || kind == FunctionType::Kind::MulMod, "");
916
101
  auto const& args = _funCall.arguments();
917
101
  solAssert(args.at(0) && args.at(1) && args.at(2), "");
918
101
  auto x = expr(*args.at(0));
919
101
  auto y = expr(*args.at(1));
920
101
  auto k = expr(*args.at(2));
921
101
  auto const& intType = dynamic_cast<IntegerType const&>(*_funCall.annotation().type);
922
923
101
  if (kind == FunctionType::Kind::AddMod)
924
75
    defineExpr(_funCall, divModWithSlacks(x + y, k, intType).second);
925
26
  else
926
26
    defineExpr(_funCall, divModWithSlacks(x * y, k, intType).second);
927
101
}
928
929
void SMTEncoder::visitWrapUnwrap(FunctionCall const& _funCall)
930
513
{
931
513
  auto const& args = _funCall.arguments();
932
513
  smtAssert(args.size() == 1, "Expected exactly one argument to wrap/unwrap");
933
513
  auto const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
934
513
  auto const* argType = funType.parameterTypes().front();
935
513
  defineExpr(_funCall, expr(*args.front(), argType));
936
513
}
937
938
void SMTEncoder::visitObjectCreation(FunctionCall const& _funCall)
939
1.95k
{
940
1.95k
  auto const& args = _funCall.arguments();
941
1.95k
  solAssert(args.size() >= 1, "");
942
1.95k
  auto argType = args.front()->annotation().type->category();
943
1.95k
  solAssert(argType == Type::Category::Integer || argType == Type::Category::RationalNumber, "");
944
945
1.95k
  smtutil::Expression arraySize = expr(*args.front());
946
1.95k
  setSymbolicUnknownValue(arraySize, TypeProvider::uint256(), m_context);
947
1.95k
  auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_funCall));
948
1.95k
  solAssert(symbArray, "");
949
1.95k
  smt::setSymbolicZeroValue(*symbArray, m_context);
950
1.95k
  auto zeroElements = symbArray->elements();
951
1.95k
  symbArray->increaseIndex();
952
1.95k
  m_context.addAssertion(symbArray->length() == arraySize);
953
1.95k
  m_context.addAssertion(symbArray->elements() == zeroElements);
954
1.95k
}
955
956
void SMTEncoder::endVisit(Identifier const& _identifier)
957
94.5k
{
958
94.5k
  if (auto decl = identifierToVariable(_identifier))
959
78.5k
  {
960
78.5k
    if (decl->isConstant())
961
1.00k
      defineExpr(_identifier, constantExpr(_identifier, *decl));
962
77.5k
    else
963
77.5k
      defineExpr(_identifier, currentValue(*decl));
964
78.5k
  }
965
15.9k
  else if (_identifier.annotation().type->category() == Type::Category::Function)
966
11.3k
    visitFunctionIdentifier(_identifier);
967
4.57k
  else if (_identifier.name() == "now")
968
0
    defineGlobalVariable(_identifier.name(), _identifier);
969
4.57k
  else if (_identifier.name() == "this")
970
2.30k
  {
971
2.30k
    defineExpr(_identifier, state().thisAddress());
972
2.30k
    m_uninterpretedTerms.insert(&_identifier);
973
2.30k
  }
974
  // Ignore type identifiers
975
2.27k
  else if (dynamic_cast<TypeType const*>(_identifier.annotation().type))
976
1.49k
    return;
977
  // Ignore module identifiers
978
780
  else if (dynamic_cast<ModuleType const*>(_identifier.annotation().type))
979
85
    return;
980
  // Ignore user defined value type identifiers
981
695
  else if (dynamic_cast<UserDefinedValueType const*>(_identifier.annotation().type))
982
0
    return;
983
  // Ignore the builtin abi, it is handled in FunctionCall.
984
  // TODO: ignore MagicType in general (abi, block, msg, tx, type)
985
695
  else if (auto magicType = dynamic_cast<MagicType const*>(_identifier.annotation().type); magicType && magicType->kind() == MagicType::Kind::ABI)
986
681
  {
987
681
    solAssert(_identifier.name() == "abi", "");
988
681
    return;
989
681
  }
990
14
  else
991
14
    createExpr(_identifier);
992
94.5k
}
993
994
void SMTEncoder::endVisit(ElementaryTypeNameExpression const& _typeName)
995
5.26k
{
996
5.26k
  auto const& typeType = dynamic_cast<TypeType const&>(*_typeName.annotation().type);
997
5.26k
  auto result = smt::newSymbolicVariable(
998
5.26k
    *TypeProvider::uint256(),
999
5.26k
    typeType.actualType()->toString(false),
1000
5.26k
    m_context
1001
5.26k
  );
1002
5.26k
  solAssert(!result.first && result.second, "");
1003
5.26k
  m_context.createExpression(_typeName, result.second);
1004
5.26k
}
1005
1006
namespace // helpers for SMTEncoder::visitPublicGetter
1007
{
1008
1009
bool isReturnedFromStructGetter(Type const* _type)
1010
237
{
1011
  // So far it seems that only Mappings and ordinary Arrays are not returned.
1012
237
  auto category = _type->category();
1013
237
  if (category == Type::Category::Mapping)
1014
0
    return false;
1015
237
  if (category == Type::Category::Array)
1016
110
    return dynamic_cast<ArrayType const&>(*_type).isByteArrayOrString();
1017
  // default
1018
127
  return true;
1019
237
}
1020
1021
std::vector<std::string> structGetterReturnedMembers(StructType const& _structType)
1022
85
{
1023
85
  std::vector<std::string> returnedMembers;
1024
85
  for (auto const& member: _structType.nativeMembers(nullptr))
1025
237
    if (isReturnedFromStructGetter(member.type))
1026
186
      returnedMembers.push_back(member.name);
1027
85
  return returnedMembers;
1028
85
}
1029
1030
}
1031
1032
void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
1033
479
{
1034
479
  auto var = publicGetter(_funCall.expression());
1035
479
  solAssert(var && var->isStateVariable(), "");
1036
479
  solAssert(m_context.knownExpression(_funCall), "");
1037
479
  auto paramExpectedTypes = replaceUserTypes(FunctionType(*var).parameterTypes());
1038
479
  auto actualArguments = _funCall.arguments();
1039
479
  solAssert(actualArguments.size() == paramExpectedTypes.size(), "");
1040
479
  std::deque<smtutil::Expression> symbArguments;
1041
759
  for (unsigned i = 0; i < paramExpectedTypes.size(); ++i)
1042
280
    symbArguments.push_back(expr(*actualArguments[i], paramExpectedTypes[i]));
1043
1044
  // See FunctionType::FunctionType(VariableDeclaration const& _varDecl)
1045
  // to understand the return types of public getters.
1046
479
  Type const* type = var->type();
1047
479
  smtutil::Expression currentExpr = currentValue(*var);
1048
759
  while (true)
1049
759
  {
1050
759
    if (
1051
759
      type->isValueType() ||
1052
374
      (type->category() == Type::Category::Array && dynamic_cast<ArrayType const&>(*type).isByteArrayOrString())
1053
759
    )
1054
394
    {
1055
394
      solAssert(symbArguments.empty(), "");
1056
394
      defineExpr(_funCall, currentExpr);
1057
394
      return;
1058
394
    }
1059
365
    switch (type->category())
1060
365
    {
1061
216
      case Type::Category::Array:
1062
280
      case Type::Category::Mapping:
1063
280
      {
1064
280
        solAssert(!symbArguments.empty(), "");
1065
        // For nested arrays/mappings, each argument in the call is an index to the next layer.
1066
        // We mirror this with `select` after unpacking the SMT-LIB array expression.
1067
280
        currentExpr = smtutil::Expression::select(smtutil::Expression::tuple_get(currentExpr, 0), symbArguments.front());
1068
280
        symbArguments.pop_front();
1069
280
        if (auto arrayType = dynamic_cast<ArrayType const*>(type))
1070
216
          type = arrayType->baseType();
1071
64
        else if (auto mappingType = dynamic_cast<MappingType const*>(type))
1072
64
          type = mappingType->valueType();
1073
0
        else
1074
64
          solAssert(false, "");
1075
280
        break;
1076
216
      }
1077
85
      case Type::Category::Struct:
1078
85
      {
1079
85
        solAssert(symbArguments.empty(), "");
1080
85
        smt::SymbolicStructVariable structVar(dynamic_cast<StructType const*>(type), "struct_temp_" + std::to_string(_funCall.id()), m_context);
1081
85
        m_context.addAssertion(structVar.currentValue() == currentExpr);
1082
85
        auto returnedMembers = structGetterReturnedMembers(dynamic_cast<StructType const&>(*structVar.type()));
1083
85
        solAssert(!returnedMembers.empty(), "");
1084
186
        auto returnedValues = applyMap(returnedMembers, [&](std::string const& memberName) -> std::optional<smtutil::Expression> { return structVar.member(memberName); });
1085
85
        defineExpr(_funCall, returnedValues);
1086
85
        return;
1087
216
      }
1088
0
      default:
1089
0
      {
1090
        // Unsupported cases, do nothing and the getter will be abstracted.
1091
0
        return;
1092
216
      }
1093
365
    }
1094
365
  }
1095
479
}
1096
1097
bool SMTEncoder::shouldEncode(ContractDefinition const& _contract) const
1098
83.9k
{
1099
83.9k
  return _contract.canBeDeployed();
1100
83.9k
}
1101
1102
bool SMTEncoder::shouldAnalyzeVerificationTargetsFor(SourceUnit const& _source) const
1103
13.4k
{
1104
13.4k
  return m_settings.contracts.isDefault() ||
1105
0
    m_settings.contracts.has(*_source.annotation().path);
1106
13.4k
}
1107
1108
bool SMTEncoder::shouldAnalyzeVerificationTargetsFor(ContractDefinition const& _contract) const
1109
28.2k
{
1110
28.2k
  if (!shouldEncode(_contract))
1111
7
    return false;
1112
1113
28.2k
  return m_settings.contracts.isDefault() ||
1114
0
    m_settings.contracts.has(_contract.sourceUnitName(), _contract.name());
1115
28.2k
}
1116
1117
void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
1118
5.36k
{
1119
5.36k
  solAssert(*_funCall.annotation().kind == FunctionCallKind::TypeConversion, "");
1120
5.36k
  solAssert(_funCall.arguments().size() == 1, "");
1121
1122
5.36k
  auto argument = _funCall.arguments().front();
1123
5.36k
  auto const argType = argument->annotation().type;
1124
5.36k
  auto const funCallType = _funCall.annotation().type;
1125
1126
5.36k
  auto symbArg = expr(*argument, funCallType);
1127
1128
5.36k
  if (smt::isStringLiteral(*argType) && smt::isFixedBytes(*funCallType))
1129
114
  {
1130
114
    defineExpr(_funCall, symbArg);
1131
114
    return;
1132
114
  }
1133
1134
5.24k
  ArrayType const* arrayType = dynamic_cast<ArrayType const*>(argType);
1135
5.24k
  if (auto sliceType = dynamic_cast<ArraySliceType const*>(argType))
1136
185
    arrayType = &sliceType->arrayType();
1137
1138
5.24k
  if (arrayType && arrayType->isByteArrayOrString() && smt::isFixedBytes(*funCallType))
1139
126
  {
1140
126
    auto array = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*argument));
1141
126
    bytesToFixedBytesAssertions(*array, _funCall);
1142
126
    return;
1143
126
  }
1144
1145
  // TODO Simplify this whole thing for 0.8.0 where weird casts are disallowed.
1146
1147
5.12k
  unsigned argSize = argType->storageBytes();
1148
5.12k
  unsigned castSize = funCallType->storageBytes();
1149
5.12k
  bool castIsSigned = smt::isNumber(*funCallType) && smt::isSigned(funCallType);
1150
5.12k
  bool argIsSigned = smt::isNumber(*argType) && smt::isSigned(argType);
1151
5.12k
  std::optional<smtutil::Expression> symbMin;
1152
5.12k
  std::optional<smtutil::Expression> symbMax;
1153
5.12k
  if (smt::isNumber(*funCallType))
1154
4.78k
  {
1155
4.78k
    symbMin = smt::minValue(funCallType);
1156
4.78k
    symbMax = smt::maxValue(funCallType);
1157
4.78k
  }
1158
5.12k
  if (argSize == castSize)
1159
2.83k
  {
1160
    // If sizes are the same, it's possible that the signs are different.
1161
2.83k
    if (smt::isNumber(*funCallType) && smt::isNumber(*argType))
1162
2.49k
    {
1163
      // castIsSigned && !argIsSigned => might overflow if arg > castType.max
1164
      // !castIsSigned && argIsSigned => might underflow if arg < castType.min
1165
      // !castIsSigned && !argIsSigned => ok
1166
      // castIsSigned && argIsSigned => ok
1167
1168
2.49k
      if (castIsSigned && !argIsSigned)
1169
146
      {
1170
146
        auto wrap = smtutil::Expression::ite(
1171
146
          symbArg > *symbMax,
1172
146
          symbArg - (*symbMax - *symbMin + 1),
1173
146
          symbArg
1174
146
        );
1175
146
        defineExpr(_funCall, wrap);
1176
146
      }
1177
2.34k
      else if (!castIsSigned && argIsSigned)
1178
48
      {
1179
48
        auto wrap = smtutil::Expression::ite(
1180
48
          symbArg < *symbMin,
1181
48
          symbArg + (*symbMax + 1),
1182
48
          symbArg
1183
48
        );
1184
48
        defineExpr(_funCall, wrap);
1185
48
      }
1186
2.29k
      else
1187
2.29k
        defineExpr(_funCall, symbArg);
1188
2.49k
    }
1189
341
    else
1190
341
      defineExpr(_funCall, symbArg);
1191
2.83k
  }
1192
2.29k
  else if (castSize > argSize)
1193
207
  {
1194
207
    solAssert(smt::isNumber(*funCallType), "");
1195
    // RationalNumbers have size 32.
1196
207
    solAssert(argType->category() != Type::Category::RationalNumber, "");
1197
1198
    // castIsSigned && !argIsSigned => ok
1199
    // castIsSigned && argIsSigned => ok
1200
    // !castIsSigned && !argIsSigned => ok except for FixedBytesType, need to adjust padding
1201
    // !castIsSigned && argIsSigned => might underflow if arg < castType.min
1202
1203
207
    if (!castIsSigned && argIsSigned)
1204
0
    {
1205
0
      auto wrap = smtutil::Expression::ite(
1206
0
        symbArg < *symbMin,
1207
0
        symbArg + (*symbMax + 1),
1208
0
        symbArg
1209
0
      );
1210
0
      defineExpr(_funCall, wrap);
1211
0
    }
1212
207
    else if (!castIsSigned && !argIsSigned)
1213
183
    {
1214
183
      if (auto const* fixedCast = dynamic_cast<FixedBytesType const*>(funCallType))
1215
96
      {
1216
96
        auto const* fixedArg = dynamic_cast<FixedBytesType const*>(argType);
1217
96
        solAssert(fixedArg, "");
1218
96
        auto diff = fixedCast->numBytes() - fixedArg->numBytes();
1219
96
        solAssert(diff > 0, "");
1220
96
        auto bvSize = fixedCast->numBytes() * 8;
1221
96
        defineExpr(
1222
96
          _funCall,
1223
96
          smtutil::Expression::bv2int(smtutil::Expression::int2bv(symbArg, bvSize) << smtutil::Expression::int2bv(diff * 8, bvSize))
1224
96
        );
1225
96
      }
1226
87
      else
1227
87
        defineExpr(_funCall, symbArg);
1228
183
    }
1229
24
    else
1230
24
      defineExpr(_funCall, symbArg);
1231
207
  }
1232
2.08k
  else // castSize < argSize
1233
2.08k
  {
1234
2.08k
    solAssert(smt::isNumber(*funCallType), "");
1235
1236
2.08k
    RationalNumberType const* rationalType = isConstant(*argument);
1237
2.08k
    if (rationalType)
1238
1.89k
    {
1239
      // The TypeChecker guarantees that a constant fits in the cast size.
1240
1.89k
      defineExpr(_funCall, symbArg);
1241
1.89k
      return;
1242
1.89k
    }
1243
1244
189
    auto const* fixedCast = dynamic_cast<FixedBytesType const*>(funCallType);
1245
189
    auto const* fixedArg = dynamic_cast<FixedBytesType const*>(argType);
1246
189
    if (fixedCast && fixedArg)
1247
36
    {
1248
36
      createExpr(_funCall);
1249
36
      auto diff = argSize - castSize;
1250
36
      solAssert(fixedArg->numBytes() - fixedCast->numBytes() == diff, "");
1251
1252
36
      auto argValueBV = smtutil::Expression::int2bv(symbArg, argSize * 8);
1253
36
      auto shr = smtutil::Expression::int2bv(diff * 8, argSize * 8);
1254
36
      solAssert(!castIsSigned, "");
1255
36
      defineExpr(_funCall, smtutil::Expression::bv2int(argValueBV >> shr));
1256
36
    }
1257
153
    else
1258
153
    {
1259
153
      auto argValueBV = smtutil::Expression::int2bv(symbArg, castSize * 8);
1260
153
      defineExpr(_funCall, smtutil::Expression::bv2int(argValueBV, castIsSigned));
1261
153
    }
1262
189
  }
1263
5.12k
}
1264
1265
void SMTEncoder::visitFunctionIdentifier(Identifier const& _identifier)
1266
11.3k
{
1267
11.3k
  auto const& fType = dynamic_cast<FunctionType const&>(*_identifier.annotation().type);
1268
11.3k
  if (replaceUserTypes(fType.returnParameterTypes()).size() == 1)
1269
2.69k
  {
1270
2.69k
    defineGlobalVariable(fType.identifier(), _identifier);
1271
2.69k
    m_context.createExpression(_identifier, m_context.globalSymbol(fType.identifier()));
1272
2.69k
  }
1273
11.3k
}
1274
1275
void SMTEncoder::visitStructConstructorCall(FunctionCall const& _funCall)
1276
247
{
1277
247
  solAssert(*_funCall.annotation().kind == FunctionCallKind::StructConstructorCall, "");
1278
247
  if (smt::isNonRecursiveStruct(*_funCall.annotation().type))
1279
243
  {
1280
243
    auto& structSymbolicVar = dynamic_cast<smt::SymbolicStructVariable&>(*m_context.expression(_funCall));
1281
243
    auto structType = dynamic_cast<StructType const*>(structSymbolicVar.type());
1282
243
    solAssert(structType, "");
1283
243
    auto const& structMembers = structType->structDefinition().members();
1284
243
    solAssert(structMembers.size() == _funCall.sortedArguments().size(), "");
1285
243
    auto args = _funCall.sortedArguments();
1286
243
    structSymbolicVar.assignAllMembers(applyMap(
1287
243
      ranges::views::zip(args, structMembers),
1288
413
      [this] (auto const& argMemberPair) { return expr(*argMemberPair.first, argMemberPair.second->type()); }
1289
243
    ));
1290
243
  }
1291
1292
247
}
1293
1294
void SMTEncoder::endVisit(Literal const& _literal)
1295
78.7k
{
1296
78.7k
  solAssert(_literal.annotation().type, "Expected type for AST node");
1297
78.7k
  Type const& type = *_literal.annotation().type;
1298
78.7k
  if (smt::isNumber(type))
1299
63.7k
    defineExpr(_literal, smtutil::Expression(type.literalValue(&_literal)));
1300
14.9k
  else if (smt::isBool(type))
1301
2.10k
    defineExpr(_literal, smtutil::Expression(_literal.token() == Token::TrueLiteral ? true : false));
1302
12.8k
  else if (smt::isStringLiteral(type))
1303
12.8k
  {
1304
12.8k
    createExpr(_literal);
1305
1306
    // Add constraints for the length and values as it is known.
1307
12.8k
    auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_literal));
1308
12.8k
    solAssert(symbArray, "");
1309
1310
12.8k
    addArrayLiteralAssertions(
1311
12.8k
      *symbArray,
1312
267k
      applyMap(_literal.value(), [](unsigned char c) { return smtutil::Expression{size_t(c)}; })
1313
12.8k
    );
1314
12.8k
  }
1315
0
  else
1316
12.8k
    solAssert(false, "");
1317
78.7k
}
1318
1319
void SMTEncoder::addArrayLiteralAssertions(
1320
  smt::SymbolicArrayVariable& _symArray,
1321
  std::vector<smtutil::Expression> const& _elementValues
1322
)
1323
14.0k
{
1324
14.0k
  m_context.addAssertion(_symArray.length() == _elementValues.size());
1325
1326
  // Assert to the solver that _elementValues are exactly the elements at the beginning of the array.
1327
  // Since we create new symbolic representation for every array literal in the source file, we want to ensure that
1328
  // representations of two equal literals are also equal. For this reason we always start from constant-zero array.
1329
  // This ensures SMT-LIB arrays (which are infinite) are also equal beyond the length of the Solidity array literal.
1330
14.0k
  auto type = _symArray.type();
1331
14.0k
  smtAssert(type);
1332
14.0k
  auto valueType = [&]() {
1333
14.0k
    if (auto const* arrayType = dynamic_cast<ArrayType const*>(type))
1334
1.20k
      return arrayType->baseType();
1335
12.8k
    if (smt::isStringLiteral(*type))
1336
12.8k
      return TypeProvider::stringMemory()->baseType();
1337
0
    smtAssert(false);
1338
0
  }();
1339
14.0k
  auto tupleSort = std::dynamic_pointer_cast<smtutil::TupleSort>(smt::smtSort(*type));
1340
14.0k
  auto sortSort = std::make_shared<smtutil::SortSort>(tupleSort->components.front());
1341
14.0k
  smtutil::Expression arrayExpr = smtutil::Expression::const_array(smtutil::Expression(sortSort), smt::zeroValue(valueType));
1342
14.0k
  smtAssert(arrayExpr.sort->kind == smtutil::Kind::Array);
1343
284k
  for (size_t i = 0; i < _elementValues.size(); i++)
1344
269k
    arrayExpr = smtutil::Expression::store(arrayExpr, smtutil::Expression(i), _elementValues[i]);
1345
14.0k
  m_context.addAssertion(_symArray.elements() == arrayExpr);
1346
14.0k
}
1347
1348
void SMTEncoder::bytesToFixedBytesAssertions(
1349
  smt::SymbolicArrayVariable& _symArray,
1350
  Expression const& _fixedBytes
1351
)
1352
126
{
1353
126
  auto const& fixed = dynamic_cast<FixedBytesType const&>(*_fixedBytes.annotation().type);
1354
126
  auto intType = TypeProvider::uint256();
1355
126
  std::string suffix = std::to_string(_fixedBytes.id()) + "_" + std::to_string(m_context.newUniqueId());
1356
126
  smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context);
1357
126
  m_context.addAssertion(k.currentValue() == 0);
1358
126
  size_t n = fixed.numBytes();
1359
1.24k
  for (size_t i = 0; i < n; i++)
1360
1.11k
  {
1361
1.11k
    auto kPrev = k.currentValue();
1362
1.11k
    m_context.addAssertion((smtutil::Expression::select(_symArray.elements(), i) * (u256(1) << ((n - i - 1) * 8))) + kPrev == k.increaseIndex());
1363
1.11k
  }
1364
126
  m_context.addAssertion(expr(_fixedBytes) == k.currentValue());
1365
126
}
1366
1367
void SMTEncoder::endVisit(Return const& _return)
1368
10.7k
{
1369
10.7k
  if (_return.expression() && m_context.knownExpression(*_return.expression()))
1370
9.96k
  {
1371
9.96k
    auto returnParams = m_callStack.back().first->returnParameters();
1372
9.96k
    if (returnParams.size() > 1)
1373
1.57k
    {
1374
1.57k
      auto const& symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(*_return.expression()));
1375
1.57k
      solAssert(symbTuple, "");
1376
1.57k
      solAssert(symbTuple->components().size() == returnParams.size(), "");
1377
1378
1.57k
      auto const* tupleType = dynamic_cast<TupleType const*>(_return.expression()->annotation().type);
1379
1.57k
      solAssert(tupleType, "");
1380
1.57k
      auto const& types = tupleType->components();
1381
1.57k
      solAssert(types.size() == returnParams.size(), "");
1382
1383
5.50k
      for (unsigned i = 0; i < returnParams.size(); ++i)
1384
3.92k
        assignment(*returnParams.at(i), symbTuple->component(i, types.at(i), returnParams.at(i)->type()));
1385
1.57k
    }
1386
8.38k
    else if (returnParams.size() == 1)
1387
8.38k
      assignment(*returnParams.front(), expr(*_return.expression(), returnParams.front()->type()));
1388
9.96k
  }
1389
10.7k
}
1390
1391
bool SMTEncoder::visit(MemberAccess const& _memberAccess)
1392
14.6k
{
1393
14.6k
  createExpr(_memberAccess);
1394
1395
14.6k
  auto const& accessType = _memberAccess.annotation().type;
1396
14.6k
  if (accessType->category() == Type::Category::Function)
1397
7.52k
  {
1398
7.52k
    auto const* functionType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
1399
7.52k
    if (functionType && functionType->hasDeclaration())
1400
3.27k
      defineExpr(
1401
3.27k
        _memberAccess,
1402
3.27k
        util::selectorFromSignatureU32(functionType->richIdentifier())
1403
3.27k
      );
1404
1405
7.52k
    return true;
1406
7.52k
  }
1407
1408
7.12k
  Expression const& memberExpr = innermostTuple(_memberAccess.expression());
1409
1410
7.12k
  auto const& exprType = memberExpr.annotation().type;
1411
7.12k
  solAssert(exprType, "");
1412
1413
7.12k
  if (exprType->category() == Type::Category::Magic)
1414
1.19k
  {
1415
1.19k
    if (auto const* identifier = dynamic_cast<Identifier const*>(&memberExpr))
1416
857
    {
1417
857
      auto const& name = identifier->name();
1418
857
      solAssert(name == "block" || name == "msg" || name == "tx", "");
1419
857
      auto memberName = _memberAccess.memberName();
1420
1421
      // TODO remove this for 0.9.0
1422
857
      if (name == "block" && memberName == "difficulty")
1423
16
        memberName = "prevrandao";
1424
1425
857
      defineExpr(_memberAccess, state().txMember(name + "." + memberName));
1426
857
    }
1427
337
    else if (auto magicType = dynamic_cast<MagicType const*>(exprType))
1428
337
    {
1429
337
      if (magicType->kind() == MagicType::Kind::Block)
1430
0
        defineExpr(_memberAccess, state().txMember("block." + _memberAccess.memberName()));
1431
337
      else if (magicType->kind() == MagicType::Kind::Message)
1432
0
        defineExpr(_memberAccess, state().txMember("msg." + _memberAccess.memberName()));
1433
337
      else if (magicType->kind() == MagicType::Kind::Transaction)
1434
0
        defineExpr(_memberAccess, state().txMember("tx." + _memberAccess.memberName()));
1435
337
      else if (magicType->kind() == MagicType::Kind::MetaType)
1436
337
      {
1437
337
        auto const& memberName = _memberAccess.memberName();
1438
337
        if (memberName == "min" || memberName == "max")
1439
257
        {
1440
257
          if (IntegerType const* integerType = dynamic_cast<IntegerType const*>(magicType->typeArgument()))
1441
247
            defineExpr(_memberAccess, memberName == "min" ? integerType->minValue() : integerType->maxValue());
1442
10
          else if (EnumType const* enumType = dynamic_cast<EnumType const*>(magicType->typeArgument()))
1443
10
            defineExpr(_memberAccess, memberName == "min" ? enumType->minValue() : enumType->maxValue());
1444
257
        }
1445
80
        else if (memberName == "interfaceId")
1446
12
        {
1447
12
          ContractDefinition const& contract = dynamic_cast<ContractType const&>(*magicType->typeArgument()).contractDefinition();
1448
12
          defineExpr(_memberAccess, contract.interfaceId());
1449
12
        }
1450
68
        else
1451
          // NOTE: supporting name, creationCode, runtimeCode would be easy enough, but the bytes/string they return are not
1452
          //       at all usable in the SMT checker currently
1453
68
          m_unsupportedErrors.warning(
1454
68
            7507_error,
1455
68
            _memberAccess.location(),
1456
68
            "Assertion checker does not yet support this expression."
1457
68
          );
1458
1459
337
      }
1460
337
    }
1461
0
    else
1462
337
      solAssert(false, "");
1463
1464
1.19k
    return false;
1465
1.19k
  }
1466
5.92k
  else if (smt::isNonRecursiveStruct(*exprType))
1467
3.36k
  {
1468
3.36k
    memberExpr.accept(*this);
1469
3.36k
    auto const& symbStruct = std::dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(memberExpr));
1470
3.36k
    defineExpr(_memberAccess, symbStruct->member(_memberAccess.memberName()));
1471
3.36k
    return false;
1472
3.36k
  }
1473
2.56k
  else if (exprType->category() == Type::Category::TypeType)
1474
269
  {
1475
269
    auto const* decl = expressionToDeclaration(memberExpr);
1476
269
    if (dynamic_cast<EnumDefinition const*>(decl))
1477
160
    {
1478
160
      auto enumType = dynamic_cast<EnumType const*>(accessType);
1479
160
      solAssert(enumType, "");
1480
160
      defineExpr(_memberAccess, enumType->memberValue(_memberAccess.memberName()));
1481
1482
160
      return false;
1483
160
    }
1484
109
    else if (dynamic_cast<ContractDefinition const*>(decl))
1485
109
    {
1486
109
      if (auto const* var = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
1487
81
      {
1488
81
        if (var->isConstant())
1489
16
          defineExpr(_memberAccess, constantExpr(_memberAccess, *var));
1490
65
        else
1491
65
          defineExpr(_memberAccess, currentValue(*var));
1492
81
        return false;
1493
81
      }
1494
109
    }
1495
269
  }
1496
2.30k
  else if (exprType->category() == Type::Category::Address)
1497
253
  {
1498
253
    memberExpr.accept(*this);
1499
253
    if (_memberAccess.memberName() == "balance")
1500
185
    {
1501
185
      defineExpr(_memberAccess, state().balance(expr(memberExpr)));
1502
185
      setSymbolicUnknownValue(*m_context.expression(_memberAccess), m_context);
1503
185
      m_uninterpretedTerms.insert(&_memberAccess);
1504
185
      return false;
1505
185
    }
1506
253
  }
1507
2.04k
  else if (exprType->category() == Type::Category::Array)
1508
1.52k
  {
1509
1.52k
    memberExpr.accept(*this);
1510
1.52k
    if (_memberAccess.memberName() == "length")
1511
1.52k
    {
1512
1.52k
      auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberExpr));
1513
1.52k
      solAssert(symbArray, "");
1514
1.52k
      defineExpr(_memberAccess, symbArray->length());
1515
1.52k
      m_uninterpretedTerms.insert(&_memberAccess);
1516
1.52k
      setSymbolicUnknownValue(
1517
1.52k
        expr(_memberAccess),
1518
1.52k
        _memberAccess.annotation().type,
1519
1.52k
        m_context
1520
1.52k
      );
1521
1.52k
    }
1522
1.52k
    return false;
1523
1.52k
  }
1524
526
  else if (
1525
526
    auto const* functionType = dynamic_cast<FunctionType const*>(exprType);
1526
526
    functionType &&
1527
422
    _memberAccess.memberName() == "selector" &&
1528
324
    functionType->hasDeclaration()
1529
526
  )
1530
298
  {
1531
298
    defineExpr(_memberAccess, functionType->externalIdentifier());
1532
298
    return false;
1533
298
  }
1534
228
  else if (exprType->category() == Type::Category::Module)
1535
70
  {
1536
70
    if (auto const* var = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
1537
22
    {
1538
22
      solAssert(var->isConstant(), "");
1539
22
      defineExpr(_memberAccess, constantExpr(_memberAccess, *var));
1540
22
      return false;
1541
22
    }
1542
70
  }
1543
1544
302
  m_unsupportedErrors.warning(
1545
302
    7650_error,
1546
302
    _memberAccess.location(),
1547
302
    "Assertion checker does not yet support this expression."
1548
302
  );
1549
1550
302
  return true;
1551
7.12k
}
1552
1553
void SMTEncoder::endVisit(IndexAccess const& _indexAccess)
1554
27.5k
{
1555
27.5k
  createExpr(_indexAccess);
1556
1557
27.5k
  if (_indexAccess.annotation().type->category() == Type::Category::TypeType)
1558
50
    return;
1559
1560
27.5k
  makeOutOfBoundsVerificationTarget(_indexAccess);
1561
1562
27.5k
  if (auto const* type = dynamic_cast<FixedBytesType const*>(_indexAccess.baseExpression().annotation().type))
1563
992
  {
1564
992
    smtutil::Expression base = expr(_indexAccess.baseExpression());
1565
1566
992
    if (type->numBytes() == 1)
1567
876
      defineExpr(_indexAccess, base);
1568
116
    else
1569
116
    {
1570
116
      auto [bvSize, isSigned] = smt::typeBvSizeAndSignedness(_indexAccess.baseExpression().annotation().type);
1571
116
      solAssert(!isSigned, "");
1572
116
      solAssert(bvSize >= 16, "");
1573
116
      solAssert(bvSize % 8 == 0, "");
1574
1575
116
      smtutil::Expression idx = expr(*_indexAccess.indexExpression());
1576
1577
116
      auto bvBase = smtutil::Expression::int2bv(base, bvSize);
1578
116
      auto bvShl = smtutil::Expression::int2bv(idx * 8, bvSize);
1579
116
      auto bvShr = smtutil::Expression::int2bv(bvSize - 8, bvSize);
1580
116
      auto result = (bvBase << bvShl) >> bvShr;
1581
1582
116
      auto anyValue = expr(_indexAccess);
1583
116
      m_context.expression(_indexAccess)->increaseIndex();
1584
116
      unsigned numBytes = bvSize / 8;
1585
116
      auto withBound = smtutil::Expression::ite(
1586
116
        idx < numBytes,
1587
116
        smtutil::Expression::bv2int(result, false),
1588
116
        anyValue
1589
116
      );
1590
116
      defineExpr(_indexAccess, withBound);
1591
116
    }
1592
992
    return;
1593
992
  }
1594
1595
26.5k
  std::shared_ptr<smt::SymbolicVariable> array;
1596
26.5k
  if (auto const* id = dynamic_cast<Identifier const*>(&_indexAccess.baseExpression()))
1597
15.4k
  {
1598
15.4k
    auto varDecl = identifierToVariable(*id);
1599
15.4k
    solAssert(varDecl, "");
1600
15.4k
    array = m_context.variable(*varDecl);
1601
1602
15.4k
    if (varDecl && varDecl->isConstant())
1603
0
      m_context.addAssertion(currentValue(*varDecl) == expr(*id));
1604
15.4k
  }
1605
11.0k
  else
1606
11.0k
  {
1607
11.0k
    solAssert(m_context.knownExpression(_indexAccess.baseExpression()), "");
1608
11.0k
    array = m_context.expression(_indexAccess.baseExpression());
1609
11.0k
  }
1610
1611
26.5k
  auto arrayVar = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(array);
1612
26.5k
  solAssert(arrayVar, "");
1613
1614
26.5k
  Type const* baseType = _indexAccess.baseExpression().annotation().type;
1615
26.5k
  defineExpr(_indexAccess, smtutil::Expression::select(
1616
26.5k
    arrayVar->elements(),
1617
26.5k
    expr(*_indexAccess.indexExpression(), keyType(baseType))
1618
26.5k
  ));
1619
26.5k
  setSymbolicUnknownValue(
1620
26.5k
    expr(_indexAccess),
1621
26.5k
    _indexAccess.annotation().type,
1622
26.5k
    m_context
1623
26.5k
  );
1624
26.5k
  m_uninterpretedTerms.insert(&_indexAccess);
1625
26.5k
}
1626
1627
void SMTEncoder::endVisit(IndexRangeAccess const& _indexRangeAccess)
1628
430
{
1629
430
  createExpr(_indexRangeAccess);
1630
  /// The actual slice is created by CHC which also assigns the length.
1631
430
}
1632
1633
void SMTEncoder::arrayAssignment()
1634
1.39k
{
1635
1.39k
  m_arrayAssignmentHappened = true;
1636
1.39k
}
1637
1638
void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expression const& _rightHandSide)
1639
5.97k
{
1640
5.97k
  auto toStore = _rightHandSide;
1641
5.97k
  auto const* lastExpr = &_expr;
1642
15.5k
  while (true)
1643
15.5k
  {
1644
15.5k
    if (auto const* indexAccess = dynamic_cast<IndexAccess const*>(lastExpr))
1645
7.99k
    {
1646
7.99k
      auto const& base = indexAccess->baseExpression();
1647
7.99k
      if (dynamic_cast<Identifier const*>(&base))
1648
4.89k
        base.accept(*this);
1649
1650
7.99k
      Type const* baseType = base.annotation().type;
1651
7.99k
      auto indexExpr = expr(*indexAccess->indexExpression(), keyType(baseType));
1652
7.99k
      auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(base));
1653
7.99k
      solAssert(symbArray, "");
1654
7.99k
      toStore = smtutil::Expression::tuple_constructor(
1655
7.99k
        smtutil::Expression(std::make_shared<smtutil::SortSort>(smt::smtSort(*baseType)), baseType->toString(true)),
1656
7.99k
        {smtutil::Expression::store(symbArray->elements(), indexExpr, toStore), symbArray->length()}
1657
7.99k
      );
1658
7.99k
      defineExpr(*indexAccess, smtutil::Expression::select(
1659
7.99k
        symbArray->elements(),
1660
7.99k
        indexExpr
1661
7.99k
      ));
1662
7.99k
      lastExpr = &indexAccess->baseExpression();
1663
7.99k
    }
1664
7.59k
    else if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(lastExpr))
1665
1.62k
    {
1666
1.62k
      auto const& base = memberAccess->expression();
1667
1.62k
      if (dynamic_cast<Identifier const*>(&base))
1668
1.07k
        base.accept(*this);
1669
1670
1.62k
      if (
1671
1.62k
        auto const* structType = dynamic_cast<StructType const*>(base.annotation().type);
1672
1.62k
        structType && structType->recursive()
1673
1.62k
      )
1674
4
      {
1675
4
        m_unsupportedErrors.warning(
1676
4
          4375_error,
1677
4
          memberAccess->location(),
1678
4
          "Assertion checker does not support recursive structs."
1679
4
        );
1680
4
        return;
1681
4
      }
1682
1.62k
      if (auto varDecl = identifierToVariable(*memberAccess))
1683
4
      {
1684
4
        if (varDecl->hasReferenceOrMappingType())
1685
4
          resetReferences(*varDecl);
1686
1687
4
        assignment(*varDecl, toStore);
1688
4
        break;
1689
4
      }
1690
1691
1.62k
      auto symbStruct = std::dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(base));
1692
1.62k
      solAssert(symbStruct, "");
1693
1.62k
      symbStruct->assignMember(memberAccess->memberName(), toStore);
1694
1.62k
      toStore = symbStruct->currentValue();
1695
1.62k
      defineExpr(*memberAccess, symbStruct->member(memberAccess->memberName()));
1696
1.62k
      lastExpr = &memberAccess->expression();
1697
1.62k
    }
1698
5.97k
    else if (auto const& id = dynamic_cast<Identifier const*>(lastExpr))
1699
5.96k
    {
1700
5.96k
      auto varDecl = identifierToVariable(*id);
1701
5.96k
      solAssert(varDecl, "");
1702
1703
5.96k
      if (varDecl->hasReferenceOrMappingType())
1704
5.96k
        resetReferences(*varDecl);
1705
1706
5.96k
      assignment(*varDecl, toStore);
1707
5.96k
      defineExpr(*id, currentValue(*varDecl));
1708
5.96k
      break;
1709
5.96k
    }
1710
10
    else
1711
10
    {
1712
10
      auto type = lastExpr->annotation().type;
1713
10
      if (
1714
10
        dynamic_cast<ReferenceType const*>(type) ||
1715
4
        dynamic_cast<MappingType const*>(type)
1716
10
      )
1717
10
        resetReferences(type);
1718
1719
10
      assignment(*m_context.expression(*lastExpr), toStore);
1720
10
      break;
1721
10
    }
1722
15.5k
  }
1723
5.97k
}
1724
1725
void SMTEncoder::arrayPush(FunctionCall const& _funCall)
1726
2.22k
{
1727
2.22k
  auto memberAccess = dynamic_cast<MemberAccess const*>(&_funCall.expression());
1728
2.22k
  solAssert(memberAccess, "");
1729
2.22k
  auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
1730
2.22k
  solAssert(symbArray, "");
1731
2.22k
  auto oldLength = symbArray->length();
1732
2.22k
  m_context.addAssertion(oldLength >= 0);
1733
  // Real world assumption: the array length is assumed to not overflow.
1734
  // This assertion guarantees that both the current and updated lengths have the above property.
1735
2.22k
  m_context.addAssertion(oldLength + 1 < (smt::maxValue(*TypeProvider::uint256()) - 1));
1736
1737
2.22k
  auto const& arguments = _funCall.arguments();
1738
2.22k
  auto arrayType = dynamic_cast<ArrayType const*>(symbArray->type());
1739
2.22k
  solAssert(arrayType, "");
1740
2.22k
  auto elementType = arrayType->baseType();
1741
2.22k
  smtutil::Expression element = arguments.empty() ?
1742
944
    smt::zeroValue(elementType) :
1743
2.22k
    expr(*arguments.front(), elementType);
1744
2.22k
  smtutil::Expression store = smtutil::Expression::store(
1745
2.22k
    symbArray->elements(),
1746
2.22k
    oldLength,
1747
2.22k
    element
1748
2.22k
  );
1749
2.22k
  symbArray->increaseIndex();
1750
2.22k
  m_context.addAssertion(symbArray->elements() == store);
1751
2.22k
  m_context.addAssertion(symbArray->length() == oldLength + 1);
1752
1753
2.22k
  if (arguments.empty())
1754
944
    defineExpr(_funCall, element);
1755
1756
2.22k
  assignment(memberAccess->expression(), symbArray->currentValue());
1757
2.22k
}
1758
1759
void SMTEncoder::arrayPop(FunctionCall const& _funCall)
1760
354
{
1761
354
  auto memberAccess = dynamic_cast<MemberAccess const*>(cleanExpression(_funCall.expression()));
1762
354
  solAssert(memberAccess, "");
1763
354
  auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
1764
354
  solAssert(symbArray, "");
1765
1766
354
  makeArrayPopVerificationTarget(_funCall);
1767
1768
354
  auto oldElements = symbArray->elements();
1769
354
  auto oldLength = symbArray->length();
1770
1771
354
  symbArray->increaseIndex();
1772
354
  m_context.addAssertion(symbArray->elements() == oldElements);
1773
354
  auto newLength = smtutil::Expression::ite(
1774
354
    oldLength > 0,
1775
354
    oldLength - 1,
1776
354
    0
1777
354
  );
1778
354
  m_context.addAssertion(symbArray->length() == newLength);
1779
1780
354
  assignment(memberAccess->expression(), symbArray->currentValue());
1781
354
}
1782
1783
void SMTEncoder::defineGlobalVariable(std::string const& _name, Expression const& _expr, bool _increaseIndex)
1784
2.75k
{
1785
2.75k
  if (!m_context.knownGlobalSymbol(_name))
1786
1.62k
  {
1787
1.62k
    bool abstract = m_context.createGlobalSymbol(_name, _expr);
1788
1.62k
    if (abstract)
1789
46
      m_unsupportedErrors.warning(
1790
46
        1695_error,
1791
46
        _expr.location(),
1792
46
        "Assertion checker does not yet support this global variable."
1793
46
      );
1794
1.62k
  }
1795
1.13k
  else if (_increaseIndex)
1796
44
    m_context.globalSymbol(_name)->increaseIndex();
1797
  // The default behavior is not to increase the index since
1798
  // most of the global values stay the same throughout a tx.
1799
2.75k
  if (isSupportedType(*_expr.annotation().type))
1800
66
    defineExpr(_expr, m_context.globalSymbol(_name)->currentValue());
1801
2.75k
}
1802
1803
bool SMTEncoder::shortcutRationalNumber(Expression const& _expr)
1804
40.0k
{
1805
40.0k
  RationalNumberType const* rationalType = isConstant(_expr);
1806
40.0k
  if (!rationalType)
1807
34.8k
    return false;
1808
1809
5.16k
  if (rationalType->isNegative())
1810
2.60k
    defineExpr(_expr, smtutil::Expression(u2s(rationalType->literalValue(nullptr))));
1811
2.56k
  else
1812
2.56k
    defineExpr(_expr, smtutil::Expression(rationalType->literalValue(nullptr)));
1813
5.16k
  return true;
1814
40.0k
}
1815
1816
void SMTEncoder::arithmeticOperation(BinaryOperation const& _op)
1817
18.2k
{
1818
18.2k
  auto type = _op.annotation().commonType;
1819
18.2k
  solAssert(type, "");
1820
18.2k
  solAssert(type->category() == Type::Category::Integer || type->category() == Type::Category::FixedPoint, "");
1821
18.2k
  switch (_op.getOperator())
1822
18.2k
  {
1823
2.52k
  case Token::Add:
1824
8.66k
  case Token::Sub:
1825
12.7k
  case Token::Mul:
1826
13.5k
  case Token::Div:
1827
14.2k
  case Token::Mod:
1828
14.2k
  {
1829
14.2k
    auto values = arithmeticOperation(
1830
14.2k
      _op.getOperator(),
1831
14.2k
      expr(_op.leftExpression()),
1832
14.2k
      expr(_op.rightExpression()),
1833
14.2k
      _op.annotation().commonType,
1834
14.2k
      _op
1835
14.2k
    );
1836
14.2k
    defineExpr(_op, values.first);
1837
14.2k
    break;
1838
13.5k
  }
1839
3.99k
  default:
1840
3.99k
    m_unsupportedErrors.warning(
1841
3.99k
      5188_error,
1842
3.99k
      _op.location(),
1843
3.99k
      "Assertion checker does not yet implement this operator."
1844
3.99k
    );
1845
18.2k
  }
1846
18.2k
}
1847
1848
std::pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
1849
  Token _op,
1850
  smtutil::Expression const& _left,
1851
  smtutil::Expression const& _right,
1852
  Type const* _commonType,
1853
  Expression const& _operation
1854
)
1855
17.3k
{
1856
17.3k
  static std::set<Token> validOperators{
1857
17.3k
    Token::Add,
1858
17.3k
    Token::Sub,
1859
17.3k
    Token::Mul,
1860
17.3k
    Token::Div,
1861
17.3k
    Token::Mod
1862
17.3k
  };
1863
17.3k
  solAssert(validOperators.count(_op), "");
1864
17.3k
  solAssert(_commonType, "");
1865
17.3k
  solAssert(
1866
17.3k
    _commonType->category() == Type::Category::Integer || _commonType->category() == Type::Category::FixedPoint,
1867
17.3k
    ""
1868
17.3k
  );
1869
1870
17.3k
  IntegerType const* intType = nullptr;
1871
17.3k
  if (auto type = dynamic_cast<IntegerType const*>(_commonType))
1872
17.0k
    intType = type;
1873
340
  else
1874
340
    intType = TypeProvider::uint256();
1875
1876
17.3k
  auto valueUnbounded = [&]() -> smtutil::Expression {
1877
17.3k
    switch (_op)
1878
17.3k
    {
1879
5.02k
    case Token::Add: return _left + _right;
1880
6.64k
    case Token::Sub: return _left - _right;
1881
4.21k
    case Token::Mul: return _left * _right;
1882
822
    case Token::Div: return divModWithSlacks(_left, _right, *intType).first;
1883
697
    case Token::Mod: return divModWithSlacks(_left, _right, *intType).second;
1884
0
    default: solAssert(false, "");
1885
17.3k
    }
1886
17.3k
  }();
1887
1888
17.3k
  if (m_checked)
1889
17.1k
    return {valueUnbounded, valueUnbounded};
1890
1891
249
  if (_op == Token::Div || _op == Token::Mod)
1892
20
  {
1893
    // mod and unsigned division never underflow/overflow
1894
20
    if (_op == Token::Mod || !intType->isSigned())
1895
20
      return {valueUnbounded, valueUnbounded};
1896
1897
    // The only case where division overflows is
1898
    // - type is signed
1899
    // - LHS is type.min
1900
    // - RHS is -1
1901
    // the result is then -(type.min), which wraps back to type.min
1902
0
    smtutil::Expression maxLeft = _left == smt::minValue(*intType);
1903
0
    smtutil::Expression minusOneRight = _right == std::numeric_limits<size_t >::max();
1904
0
    smtutil::Expression wrap = smtutil::Expression::ite(maxLeft && minusOneRight, smt::minValue(*intType), valueUnbounded);
1905
0
    return {wrap, valueUnbounded};
1906
20
  }
1907
1908
229
  auto symbMin = smt::minValue(*intType);
1909
229
  auto symbMax = smt::maxValue(*intType);
1910
1911
229
  smtutil::Expression intValueRange = (0 - symbMin) + symbMax + 1;
1912
229
  std::string suffix = std::to_string(_operation.id()) + "_" + std::to_string(m_context.newUniqueId());
1913
229
  smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context);
1914
229
  smt::SymbolicIntVariable m(intType, intType, "m_" + suffix, m_context);
1915
1916
  // To wrap around valueUnbounded in case of overflow or underflow, we replace it with a k, given:
1917
  // 1. k + m * intValueRange = valueUnbounded
1918
  // 2. k is in range of the desired integer type
1919
229
  auto wrap = k.currentValue();
1920
229
  m_context.addAssertion(valueUnbounded == (k.currentValue() + intValueRange * m.currentValue()));
1921
229
  m_context.addAssertion(k.currentValue() >= symbMin);
1922
229
  m_context.addAssertion(k.currentValue() <= symbMax);
1923
1924
  // TODO this could be refined:
1925
  // for unsigned types it's enough to check only the upper bound.
1926
229
  auto value = smtutil::Expression::ite(
1927
229
    valueUnbounded > symbMax,
1928
229
    wrap,
1929
229
    smtutil::Expression::ite(
1930
229
      valueUnbounded < symbMin,
1931
229
      wrap,
1932
229
      valueUnbounded
1933
229
    )
1934
229
  );
1935
1936
229
  return {value, valueUnbounded};
1937
249
}
1938
1939
smtutil::Expression SMTEncoder::bitwiseOperation(
1940
  Token _op,
1941
  smtutil::Expression const& _left,
1942
  smtutil::Expression const& _right,
1943
  Type const* _commonType
1944
)
1945
1.29k
{
1946
1.29k
  static std::set<Token> validOperators{
1947
1.29k
    Token::BitAnd,
1948
1.29k
    Token::BitOr,
1949
1.29k
    Token::BitXor,
1950
1.29k
    Token::SHL,
1951
1.29k
    Token::SHR,
1952
1.29k
    Token::SAR
1953
1.29k
  };
1954
1.29k
  solAssert(validOperators.count(_op), "");
1955
1.29k
  solAssert(_commonType, "");
1956
1957
1.29k
  auto [bvSize, isSigned] = smt::typeBvSizeAndSignedness(_commonType);
1958
1959
1.29k
  auto bvLeft = smtutil::Expression::int2bv(_left, bvSize);
1960
1.29k
  auto bvRight = smtutil::Expression::int2bv(_right, bvSize);
1961
1962
1.29k
  std::optional<smtutil::Expression> result;
1963
1.29k
  switch (_op)
1964
1.29k
  {
1965
498
    case Token::BitAnd:
1966
498
      result = bvLeft & bvRight;
1967
498
      break;
1968
215
    case Token::BitOr:
1969
215
      result = bvLeft | bvRight;
1970
215
      break;
1971
302
    case Token::BitXor:
1972
302
      result = bvLeft ^ bvRight;
1973
302
      break;
1974
110
    case Token::SHL:
1975
110
      result = bvLeft << bvRight;
1976
110
      break;
1977
4
    case Token::SHR:
1978
4
      result = bvLeft >> bvRight;
1979
4
      break;
1980
161
    case Token::SAR:
1981
161
      result = isSigned ?
1982
12
        smtutil::Expression::ashr(bvLeft, bvRight) :
1983
161
        bvLeft >> bvRight;
1984
161
      break;
1985
0
    default:
1986
0
      solAssert(false, "");
1987
1.29k
  }
1988
1989
1.29k
  solAssert(result.has_value(), "");
1990
1.29k
  return smtutil::Expression::bv2int(*result, isSigned);
1991
1.29k
}
1992
1993
void SMTEncoder::compareOperation(BinaryOperation const& _op)
1994
9.44k
{
1995
9.44k
  auto commonType = _op.annotation().commonType;
1996
9.44k
  solAssert(commonType, "");
1997
1998
9.44k
  if (isSupportedType(*commonType))
1999
9.38k
  {
2000
9.38k
    smtutil::Expression left(expr(_op.leftExpression(), commonType));
2001
9.38k
    smtutil::Expression right(expr(_op.rightExpression(), commonType));
2002
9.38k
    Token op = _op.getOperator();
2003
9.38k
    std::shared_ptr<smtutil::Expression> value;
2004
9.38k
    if (smt::isNumber(*commonType))
2005
9.21k
    {
2006
9.21k
      value = std::make_shared<smtutil::Expression>(
2007
9.21k
        op == Token::Equal ? (left == right) :
2008
9.21k
        op == Token::NotEqual ? (left != right) :
2009
4.58k
        op == Token::LessThan ? (left < right) :
2010
3.92k
        op == Token::LessThanOrEqual ? (left <= right) :
2011
1.90k
        op == Token::GreaterThan ? (left > right) :
2012
1.72k
        /*op == Token::GreaterThanOrEqual*/ (left >= right)
2013
9.21k
      );
2014
9.21k
    }
2015
167
    else // Bool
2016
167
    {
2017
167
      solUnimplementedAssert(smt::isBool(*commonType), "Operation not yet supported");
2018
167
      value = std::make_shared<smtutil::Expression>(
2019
167
        op == Token::Equal ? (left == right) :
2020
167
        /*op == Token::NotEqual*/ (left != right)
2021
167
      );
2022
167
    }
2023
    // TODO: check that other values for op are not possible.
2024
9.38k
    defineExpr(_op, *value);
2025
9.38k
  }
2026
66
  else
2027
66
    m_unsupportedErrors.warning(
2028
66
      7229_error,
2029
66
      _op.location(),
2030
66
      "Assertion checker does not yet implement the type " + _op.annotation().commonType->toString() + " for comparisons"
2031
66
    );
2032
9.44k
}
2033
2034
void SMTEncoder::booleanOperation(BinaryOperation const& _op)
2035
519
{
2036
519
  solAssert(_op.getOperator() == Token::And || _op.getOperator() == Token::Or, "");
2037
519
  solAssert(_op.annotation().commonType, "");
2038
519
  solAssert(_op.annotation().commonType->category() == Type::Category::Bool, "");
2039
  // @TODO check that both of them are not constant
2040
519
  _op.leftExpression().accept(*this);
2041
519
  if (_op.getOperator() == Token::And)
2042
303
  {
2043
303
    auto indicesAfterSecond = visitBranch(&_op.rightExpression(), expr(_op.leftExpression())).first;
2044
303
    mergeVariables(!expr(_op.leftExpression()), copyVariableIndices(), indicesAfterSecond);
2045
303
    defineExpr(_op, expr(_op.leftExpression()) && expr(_op.rightExpression()));
2046
303
  }
2047
216
  else
2048
216
  {
2049
216
    auto indicesAfterSecond = visitBranch(&_op.rightExpression(), !expr(_op.leftExpression())).first;
2050
216
    mergeVariables(expr(_op.leftExpression()), copyVariableIndices(), indicesAfterSecond);
2051
216
    defineExpr(_op, expr(_op.leftExpression()) || expr(_op.rightExpression()));
2052
216
  }
2053
519
}
2054
2055
void SMTEncoder::bitwiseOperation(BinaryOperation const& _op)
2056
830
{
2057
830
  auto op = _op.getOperator();
2058
830
  solAssert(TokenTraits::isBitOp(op) || TokenTraits::isShiftOp(op), "");
2059
830
  auto commonType = _op.annotation().commonType;
2060
830
  solAssert(commonType, "");
2061
2062
830
  defineExpr(_op, bitwiseOperation(
2063
830
    _op.getOperator(),
2064
830
    expr(_op.leftExpression(), commonType),
2065
830
    expr(_op.rightExpression(), commonType),
2066
830
    commonType
2067
830
  ));
2068
830
}
2069
2070
void SMTEncoder::bitwiseNotOperation(UnaryOperation const& _op)
2071
2.15k
{
2072
2.15k
  solAssert(_op.getOperator() == Token::BitNot, "");
2073
2074
2.15k
  auto [bvSize, isSigned] = smt::typeBvSizeAndSignedness(_op.annotation().type);
2075
2076
2.15k
  auto bvOperand = smtutil::Expression::int2bv(expr(_op.subExpression(), _op.annotation().type), bvSize);
2077
2.15k
  defineExpr(_op, smtutil::Expression::bv2int(~bvOperand, isSigned));
2078
2.15k
}
2079
2080
std::pair<smtutil::Expression, smtutil::Expression> SMTEncoder::divModWithSlacks(
2081
  smtutil::Expression _left,
2082
  smtutil::Expression _right,
2083
  IntegerType const& _type
2084
)
2085
1.62k
{
2086
1.62k
  if (m_settings.divModNoSlacks)
2087
1.62k
    return {_left / _right, _left % _right};
2088
2089
0
  IntegerType const* intType = &_type;
2090
0
  std::string suffix = "div_mod_" + std::to_string(m_context.newUniqueId());
2091
0
  smt::SymbolicIntVariable dSymb(intType, intType, "d_" + suffix, m_context);
2092
0
  smt::SymbolicIntVariable rSymb(intType, intType, "r_" + suffix, m_context);
2093
0
  auto d = dSymb.currentValue();
2094
0
  auto r = rSymb.currentValue();
2095
2096
  // x / y = d and x % y = r iff d * y + r = x and
2097
  // either x >= 0 and 0 <= r < abs(y) (or just 0 <= r < y for unsigned)
2098
  // or     x < 0 and -abs(y) < r <= 0
2099
0
  m_context.addAssertion(((d * _right) + r) == _left);
2100
0
  if (_type.isSigned())
2101
0
    m_context.addAssertion(
2102
0
      (_left >= 0 && 0 <= r && (_right == 0 || r < smtutil::abs(_right))) ||
2103
0
      (_left < 0 && ((_right == 0 || 0 - smtutil::abs(_right) < r) && r <= 0))
2104
0
    );
2105
0
  else // unsigned version
2106
0
    m_context.addAssertion(0 <= r && (_right == 0 || r < _right));
2107
2108
0
  auto divResult = smtutil::Expression::ite(_right == 0, 0, d);
2109
0
  auto modResult = smtutil::Expression::ite(_right == 0, 0, r);
2110
0
  return {divResult, modResult};
2111
1.62k
}
2112
2113
void SMTEncoder::assignment(Expression const& _left, smtutil::Expression const& _right)
2114
5.24k
{
2115
5.24k
  assignment(_left, _right, _left.annotation().type);
2116
5.24k
}
2117
2118
void SMTEncoder::assignment(
2119
  Expression const& _left,
2120
  smtutil::Expression const& _right,
2121
  Type const* _type
2122
)
2123
25.0k
{
2124
25.0k
  solAssert(
2125
25.0k
    _left.annotation().type->category() != Type::Category::Tuple,
2126
25.0k
    "Tuple assignments should be handled by tupleAssignment."
2127
25.0k
  );
2128
2129
25.0k
  Expression const* left = cleanExpression(_left);
2130
2131
25.0k
  if (!isSupportedType(*_type))
2132
30
  {
2133
    // Give it a new index anyway to keep the SSA scheme sound.
2134
30
    if (auto varDecl = identifierToVariable(*left))
2135
30
      m_context.newValue(*varDecl);
2136
30
  }
2137
25.0k
  else if (auto varDecl = identifierToVariable(*left))
2138
18.9k
  {
2139
18.9k
    if (varDecl->hasReferenceOrMappingType())
2140
9.67k
      resetReferences(*varDecl);
2141
18.9k
    assignment(*varDecl, _right);
2142
18.9k
  }
2143
6.07k
  else if (
2144
6.07k
    dynamic_cast<IndexAccess const*>(left) ||
2145
1.44k
    dynamic_cast<MemberAccess const*>(left)
2146
6.07k
  )
2147
5.89k
    indexOrMemberAssignment(*left, _right);
2148
178
  else if (auto const* funCall = dynamic_cast<FunctionCall const*>(left))
2149
178
  {
2150
178
    if (auto funType = dynamic_cast<FunctionType const*>(funCall->expression().annotation().type))
2151
178
    {
2152
178
      if (funType->kind() == FunctionType::Kind::ArrayPush)
2153
174
      {
2154
174
        auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression());
2155
174
        solAssert(memberAccess, "");
2156
174
        auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
2157
174
        solAssert(symbArray, "");
2158
2159
174
        auto oldLength = symbArray->length();
2160
174
        auto store = smtutil::Expression::store(
2161
174
          symbArray->elements(),
2162
174
          symbArray->length() - 1,
2163
174
          _right
2164
174
        );
2165
174
        symbArray->increaseIndex();
2166
174
        m_context.addAssertion(symbArray->elements() == store);
2167
174
        m_context.addAssertion(symbArray->length() == oldLength);
2168
174
        assignment(memberAccess->expression(), symbArray->currentValue());
2169
174
      }
2170
4
      else if (funType->kind() == FunctionType::Kind::Internal)
2171
4
      {
2172
4
        for (auto type: replaceUserTypes(funType->returnParameterTypes()))
2173
4
          if (type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type))
2174
4
            resetReferences(type);
2175
4
      }
2176
178
    }
2177
178
  }
2178
0
  else
2179
178
    solAssert(false, "");
2180
25.0k
}
2181
2182
void SMTEncoder::tupleAssignment(Expression const& _left, Expression const& _right)
2183
367
{
2184
367
  auto lTuple = dynamic_cast<TupleExpression const*>(&innermostTuple(_left));
2185
367
  solAssert(lTuple, "");
2186
367
  Expression const& right = innermostTuple(_right);
2187
2188
367
  auto const& lComponents = lTuple->components();
2189
2190
  // If both sides are tuple expressions, we individually and potentially
2191
  // recursively assign each pair of components.
2192
  // This is because of potential type conversion.
2193
367
  if (auto rTuple = dynamic_cast<TupleExpression const*>(&right))
2194
295
  {
2195
295
    auto const& rComponents = rTuple->components();
2196
295
    solAssert(lComponents.size() == rComponents.size(), "");
2197
918
    for (unsigned i = 0; i < lComponents.size(); ++i)
2198
623
    {
2199
623
      if (!lComponents.at(i) || !rComponents.at(i))
2200
82
        continue;
2201
541
      auto const& lExpr = *lComponents.at(i);
2202
541
      auto const& rExpr = *rComponents.at(i);
2203
541
      if (lExpr.annotation().type->category() == Type::Category::Tuple)
2204
30
        tupleAssignment(lExpr, rExpr);
2205
511
      else
2206
511
      {
2207
511
        auto type = lExpr.annotation().type;
2208
511
        assignment(lExpr, expr(rExpr, type), type);
2209
511
      }
2210
541
    }
2211
295
  }
2212
72
  else
2213
72
  {
2214
72
    auto rType = dynamic_cast<TupleType const*>(right.annotation().type);
2215
72
    solAssert(rType, "");
2216
2217
72
    auto const& rComponents = rType->components();
2218
72
    solAssert(lComponents.size() == rComponents.size(), "");
2219
2220
72
    auto symbRight = expr(right);
2221
72
    solAssert(symbRight.sort->kind == smtutil::Kind::Tuple, "");
2222
2223
281
    for (unsigned i = 0; i < lComponents.size(); ++i)
2224
209
      if (auto component = lComponents.at(i); component && rComponents.at(i))
2225
143
        assignment(*component, smtutil::Expression::tuple_get(symbRight, i), component->annotation().type);
2226
72
  }
2227
367
}
2228
2229
smtutil::Expression SMTEncoder::compoundAssignment(Assignment const& _assignment)
2230
1.13k
{
2231
1.13k
  static std::map<Token, Token> const compoundToArithmetic{
2232
1.13k
    {Token::AssignAdd, Token::Add},
2233
1.13k
    {Token::AssignSub, Token::Sub},
2234
1.13k
    {Token::AssignMul, Token::Mul},
2235
1.13k
    {Token::AssignDiv, Token::Div},
2236
1.13k
    {Token::AssignMod, Token::Mod}
2237
1.13k
  };
2238
1.13k
  static std::map<Token, Token> const compoundToBitwise{
2239
1.13k
    {Token::AssignBitAnd, Token::BitAnd},
2240
1.13k
    {Token::AssignBitOr, Token::BitOr},
2241
1.13k
    {Token::AssignBitXor, Token::BitXor},
2242
1.13k
    {Token::AssignShl, Token::SHL},
2243
1.13k
    {Token::AssignShr, Token::SHR},
2244
1.13k
    {Token::AssignSar, Token::SAR}
2245
1.13k
  };
2246
1.13k
  Token op = _assignment.assignmentOperator();
2247
1.13k
  solAssert(compoundToArithmetic.count(op) || compoundToBitwise.count(op), "");
2248
2249
1.13k
  auto decl = identifierToVariable(_assignment.leftHandSide());
2250
2251
1.13k
  if (compoundToBitwise.count(op))
2252
460
    return bitwiseOperation(
2253
460
      compoundToBitwise.at(op),
2254
460
      decl ? currentValue(*decl) : expr(_assignment.leftHandSide(), _assignment.annotation().type),
2255
460
      expr(_assignment.rightHandSide(), _assignment.annotation().type),
2256
460
      _assignment.annotation().type
2257
460
    );
2258
2259
674
  auto values = arithmeticOperation(
2260
674
    compoundToArithmetic.at(op),
2261
674
    decl ? currentValue(*decl) : expr(_assignment.leftHandSide(), _assignment.annotation().type),
2262
674
    expr(_assignment.rightHandSide(), _assignment.annotation().type),
2263
674
    _assignment.annotation().type,
2264
674
    _assignment
2265
674
  );
2266
674
  return values.first;
2267
1.13k
}
2268
2269
void SMTEncoder::expressionToTupleAssignment(std::vector<std::shared_ptr<VariableDeclaration>> const& _variables, Expression const& _rhs)
2270
5.58k
{
2271
5.58k
  auto symbolicVar = m_context.expression(_rhs);
2272
5.58k
  if (_variables.size() > 1)
2273
329
  {
2274
329
    auto symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(symbolicVar);
2275
329
    solAssert(symbTuple, "");
2276
329
    auto const& symbComponents = symbTuple->components();
2277
329
    solAssert(symbComponents.size() == _variables.size(), "");
2278
329
    auto tupleType = dynamic_cast<TupleType const*>(_rhs.annotation().type);
2279
329
    solAssert(tupleType, "");
2280
329
    auto const& typeComponents = tupleType->components();
2281
329
    solAssert(typeComponents.size() == symbComponents.size(), "");
2282
1.10k
    for (unsigned i = 0; i < symbComponents.size(); ++i)
2283
778
    {
2284
778
      auto param = _variables.at(i);
2285
778
      if (param)
2286
606
      {
2287
606
        solAssert(m_context.knownVariable(*param), "");
2288
606
        assignment(*param, symbTuple->component(i, typeComponents[i], param->type()));
2289
606
      }
2290
778
    }
2291
329
  }
2292
5.25k
  else if (_variables.size() == 1)
2293
5.25k
  {
2294
5.25k
    auto const& var = *_variables.front();
2295
5.25k
    solAssert(m_context.knownVariable(var), "");
2296
5.25k
    assignment(var, _rhs);
2297
5.25k
  }
2298
5.58k
}
2299
2300
void SMTEncoder::assignment(VariableDeclaration const& _variable, Expression const& _value)
2301
9.95k
{
2302
  // In general, at this point, the SMT sorts of _variable and _value are the same,
2303
  // even if there is implicit conversion.
2304
  // This is a special case where the SMT sorts are different.
2305
  // For now we are unaware of other cases where this happens, but if they do appear
2306
  // we should extract this into an `implicitConversion` function.
2307
9.95k
  assignment(_variable, expr(_value, _variable.type()));
2308
9.95k
}
2309
2310
void SMTEncoder::assignment(VariableDeclaration const& _variable, smtutil::Expression const& _value)
2311
47.8k
{
2312
47.8k
  Type const* type = _variable.type();
2313
47.8k
  if (type->category() == Type::Category::Mapping)
2314
1.39k
    arrayAssignment();
2315
47.8k
  assignment(*m_context.variable(_variable), _value);
2316
47.8k
}
2317
2318
void SMTEncoder::assignment(smt::SymbolicVariable& _symVar, smtutil::Expression const& _value)
2319
23.3k
{
2320
23.3k
  m_context.addAssertion(_symVar.increaseIndex() == _value);
2321
23.3k
}
2322
2323
std::pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
2324
  ASTNode const* _statement,
2325
  smtutil::Expression _condition
2326
)
2327
3.77k
{
2328
3.77k
  return visitBranch(_statement, &_condition);
2329
3.77k
}
2330
2331
std::pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
2332
  ASTNode const* _statement,
2333
  smtutil::Expression const* _condition
2334
)
2335
4.07k
{
2336
4.07k
  auto indicesBeforeBranch = copyVariableIndices();
2337
4.07k
  if (_condition)
2338
3.77k
    pushPathCondition(*_condition);
2339
4.07k
  _statement->accept(*this);
2340
4.07k
  auto pathConditionOnExit = currentPathConditions();
2341
4.07k
  if (_condition)
2342
3.77k
    popPathCondition();
2343
4.07k
  auto indicesAfterBranch = copyVariableIndices();
2344
4.07k
  resetVariableIndices(indicesBeforeBranch);
2345
4.07k
  return {indicesAfterBranch, pathConditionOnExit};
2346
4.07k
}
2347
2348
void SMTEncoder::initializeFunctionCallParameters(CallableDeclaration const& _function, std::vector<smtutil::Expression> const& _callArgs)
2349
3.06k
{
2350
3.06k
  auto const& funParams = _function.parameters();
2351
3.06k
  solAssert(funParams.size() == _callArgs.size(), "");
2352
4.86k
  for (unsigned i = 0; i < funParams.size(); ++i)
2353
1.79k
    if (createVariable(*funParams[i]))
2354
1.79k
    {
2355
1.79k
      m_context.addAssertion(_callArgs[i] == m_context.newValue(*funParams[i]));
2356
1.79k
      if (funParams[i]->annotation().type->category() == Type::Category::Mapping)
2357
4
        m_arrayAssignmentHappened = true;
2358
1.79k
    }
2359
2360
3.06k
  std::vector<VariableDeclaration const*> localVars;
2361
3.06k
  if (auto const* fun = dynamic_cast<FunctionDefinition const*>(&_function))
2362
2.08k
    localVars = localVariablesIncludingModifiers(*fun, m_currentContract);
2363
979
  else
2364
979
    localVars = _function.localVariables();
2365
3.06k
  for (auto const& variable: localVars)
2366
508
    if (createVariable(*variable))
2367
508
    {
2368
508
      m_context.newValue(*variable);
2369
508
      m_context.setZeroValue(*variable);
2370
508
    }
2371
2372
3.06k
  if (_function.returnParameterList())
2373
2.08k
    for (auto const& retParam: _function.returnParameters())
2374
1.40k
      if (createVariable(*retParam))
2375
1.40k
      {
2376
1.40k
        m_context.newValue(*retParam);
2377
1.40k
        m_context.setZeroValue(*retParam);
2378
1.40k
      }
2379
3.06k
}
2380
2381
void SMTEncoder::createStateVariables(ContractDefinition const& _contract)
2382
72.4k
{
2383
72.4k
  for (auto var: stateVariablesIncludingInheritedAndPrivate(_contract))
2384
38.7k
    createVariable(*var);
2385
72.4k
}
2386
2387
void SMTEncoder::initializeStateVariables(ContractDefinition const& _contract)
2388
15.8k
{
2389
15.8k
  for (auto var: _contract.stateVariables())
2390
7.61k
  {
2391
7.61k
    solAssert(m_context.knownVariable(*var), "");
2392
7.61k
    m_context.setZeroValue(*var);
2393
7.61k
  }
2394
2395
15.8k
  for (auto var: _contract.stateVariables())
2396
7.61k
    if (var->value())
2397
2.32k
    {
2398
2.32k
      var->value()->accept(*this);
2399
2.32k
      assignment(*var, *var->value());
2400
2.32k
    }
2401
15.8k
}
2402
2403
void SMTEncoder::createLocalVariables(FunctionDefinition const& _function)
2404
30.5k
{
2405
30.5k
  for (auto const& variable: localVariablesIncludingModifiers(_function, m_currentContract))
2406
8.33k
    createVariable(*variable);
2407
2408
30.5k
  for (auto const& param: _function.parameters())
2409
14.5k
    createVariable(*param);
2410
2411
30.5k
  if (_function.returnParameterList())
2412
30.5k
    for (auto const& retParam: _function.returnParameters())
2413
16.3k
      createVariable(*retParam);
2414
30.5k
}
2415
2416
void SMTEncoder::initializeLocalVariables(FunctionDefinition const& _function)
2417
32.3k
{
2418
32.3k
  for (auto const& variable: localVariablesIncludingModifiers(_function, m_currentContract))
2419
8.45k
  {
2420
8.45k
    solAssert(m_context.knownVariable(*variable), "");
2421
8.45k
    m_context.setZeroValue(*variable);
2422
8.45k
  }
2423
2424
32.3k
  for (auto const& param: _function.parameters())
2425
15.6k
  {
2426
15.6k
    solAssert(m_context.knownVariable(*param), "");
2427
15.6k
    m_context.setUnknownValue(*param);
2428
15.6k
  }
2429
2430
32.3k
  if (_function.returnParameterList())
2431
32.3k
    for (auto const& retParam: _function.returnParameters())
2432
17.7k
    {
2433
17.7k
      solAssert(m_context.knownVariable(*retParam), "");
2434
17.7k
      m_context.setZeroValue(*retParam);
2435
17.7k
    }
2436
32.3k
}
2437
2438
void SMTEncoder::resetStateVariables()
2439
14.5k
{
2440
44.0k
  m_context.resetVariables([&](VariableDeclaration const& _variable) { return _variable.isStateVariable(); });
2441
14.5k
}
2442
2443
void SMTEncoder::resetMemoryVariables()
2444
1.08k
{
2445
1.49k
  m_context.resetVariables([&](VariableDeclaration const& _variable) {
2446
1.49k
    return _variable.referenceLocation() == VariableDeclaration::Location::Memory;
2447
1.49k
  });
2448
1.08k
}
2449
2450
void SMTEncoder::resetStorageVariables()
2451
2.98k
{
2452
7.67k
  m_context.resetVariables([&](VariableDeclaration const& _variable) {
2453
7.67k
    return _variable.referenceLocation() == VariableDeclaration::Location::Storage || _variable.isStateVariable();
2454
7.67k
  });
2455
2.98k
}
2456
2457
void SMTEncoder::resetBalances()
2458
1.51k
{
2459
1.51k
  state().newBalances();
2460
1.51k
}
2461
2462
void SMTEncoder::resetReferences(VariableDeclaration const& _varDecl)
2463
15.6k
{
2464
39.7k
  m_context.resetVariables([&](VariableDeclaration const& _var) {
2465
39.7k
    if (_var == _varDecl)
2466
15.6k
      return false;
2467
2468
    // If both are state variables no need to clear knowledge.
2469
24.0k
    if (_var.isStateVariable() && _varDecl.isStateVariable())
2470
5.46k
      return false;
2471
2472
18.6k
    return sameTypeOrSubtype(_var.type(), _varDecl.type());
2473
24.0k
  });
2474
15.6k
}
2475
2476
void SMTEncoder::resetReferences(Type const* _type)
2477
14
{
2478
44
  m_context.resetVariables([&](VariableDeclaration const& _var) {
2479
44
    return sameTypeOrSubtype(_var.type(), _type);
2480
44
  });
2481
14
}
2482
2483
bool SMTEncoder::sameTypeOrSubtype(Type const* _a, Type const* _b)
2484
18.6k
{
2485
18.6k
  bool foundSame = false;
2486
2487
18.6k
  solidity::util::BreadthFirstSearch<Type const*> bfs{{_a}};
2488
27.2k
  bfs.run([&](auto _type, auto&& _addChild) {
2489
27.2k
    if (*typeWithoutPointer(_b) == *typeWithoutPointer(_type))
2490
1.91k
    {
2491
1.91k
      foundSame = true;
2492
1.91k
      bfs.abort();
2493
1.91k
    }
2494
27.2k
    if (auto const* mapType = dynamic_cast<MappingType const*>(_type))
2495
386
      _addChild(mapType->valueType());
2496
26.8k
    else if (auto const* arrayType = dynamic_cast<ArrayType const*>(_type))
2497
5.37k
      _addChild(arrayType->baseType());
2498
21.4k
    else if (auto const* structType = dynamic_cast<StructType const*>(_type))
2499
1.91k
      for (auto const& member: structType->nativeMembers(nullptr))
2500
4.00k
        _addChild(member.type);
2501
27.2k
  });
2502
2503
18.6k
  return foundSame;
2504
18.6k
}
2505
2506
bool SMTEncoder::isSupportedType(Type const& _type) const
2507
57.0k
{
2508
57.0k
  return smt::isSupportedType(*underlyingType(&_type));
2509
57.0k
}
2510
2511
Type const* SMTEncoder::typeWithoutPointer(Type const* _type)
2512
54.4k
{
2513
54.4k
  if (auto refType = dynamic_cast<ReferenceType const*>(_type))
2514
32.7k
    return TypeProvider::withLocationIfReference(refType->location(), _type);
2515
21.7k
  return _type;
2516
54.4k
}
2517
2518
void SMTEncoder::mergeVariables(smtutil::Expression const& _condition, VariableIndices const& _indicesEndTrue, VariableIndices const& _indicesEndFalse)
2519
5.66k
{
2520
5.66k
  for (auto const& entry: _indicesEndTrue)
2521
23.7k
  {
2522
23.7k
    VariableDeclaration const* var = entry.first;
2523
23.7k
    auto trueIndex = entry.second;
2524
23.7k
    if (_indicesEndFalse.count(var) && _indicesEndFalse.at(var) != trueIndex)
2525
6.02k
    {
2526
6.02k
      m_context.addAssertion(m_context.newValue(*var) == smtutil::Expression::ite(
2527
6.02k
        _condition,
2528
6.02k
        valueAtIndex(*var, trueIndex),
2529
6.02k
        valueAtIndex(*var, _indicesEndFalse.at(var)))
2530
6.02k
      );
2531
6.02k
    }
2532
23.7k
  }
2533
5.66k
}
2534
2535
smtutil::Expression SMTEncoder::currentValue(VariableDeclaration const& _decl) const
2536
151k
{
2537
151k
  solAssert(m_context.knownVariable(_decl), "");
2538
151k
  return m_context.variable(_decl)->currentValue();
2539
151k
}
2540
2541
smtutil::Expression SMTEncoder::valueAtIndex(VariableDeclaration const& _decl, unsigned _index) const
2542
41.5k
{
2543
41.5k
  solAssert(m_context.knownVariable(_decl), "");
2544
41.5k
  return m_context.variable(_decl)->valueAtIndex(_index);
2545
41.5k
}
2546
2547
bool SMTEncoder::createVariable(VariableDeclaration const& _varDecl)
2548
114k
{
2549
114k
  if (m_context.knownVariable(_varDecl))
2550
88.3k
    return true;
2551
25.7k
  bool abstract = m_context.createVariable(_varDecl);
2552
25.7k
  if (abstract)
2553
17
  {
2554
17
    m_unsupportedErrors.warning(
2555
17
      8115_error,
2556
17
      _varDecl.location(),
2557
17
      "Assertion checker does not yet support the type of this variable."
2558
17
    );
2559
17
    return false;
2560
17
  }
2561
25.6k
  return true;
2562
25.7k
}
2563
2564
smtutil::Expression SMTEncoder::expr(Expression const& _e, Type const* _targetType)
2565
698k
{
2566
698k
  if (!m_context.knownExpression(_e))
2567
101
  {
2568
101
    m_unsupportedErrors.warning(6031_error, _e.location(), "Internal error: Expression undefined for SMT solver." );
2569
101
    createExpr(_e);
2570
101
  }
2571
2572
698k
  return m_context.expression(_e)->currentValue(underlyingType(_targetType));
2573
698k
}
2574
2575
void SMTEncoder::createExpr(Expression const& _e)
2576
413k
{
2577
413k
  bool abstract = m_context.createExpression(_e);
2578
413k
  if (abstract)
2579
498
    m_unsupportedErrors.warning(
2580
498
      8364_error,
2581
498
      _e.location(),
2582
498
      "Assertion checker does not yet implement type " + _e.annotation().type->toString()
2583
498
    );
2584
413k
}
2585
2586
void SMTEncoder::defineExpr(Expression const& _e, smtutil::Expression _value)
2587
271k
{
2588
271k
  auto type = _e.annotation().type;
2589
271k
  createExpr(_e);
2590
271k
  solAssert(_value.sort->kind != smtutil::Kind::Function, "Equality operator applied to type that is not fully supported");
2591
271k
  if (!smt::isInaccessibleDynamic(*type))
2592
271k
    m_context.addAssertion(expr(_e) == _value);
2593
2594
271k
  if (m_checked && smt::isNumber(*type))
2595
171k
    m_context.addAssertion(smtutil::Expression::implies(
2596
171k
      currentPathConditions(),
2597
171k
      smt::symbolicUnknownConstraints(expr(_e), type)
2598
171k
    ));
2599
271k
}
2600
2601
void SMTEncoder::defineExpr(Expression const& _e, std::vector<std::optional<smtutil::Expression>> const& _values)
2602
12.0k
{
2603
12.0k
  if (_values.size() == 1 && _values.front())
2604
6.43k
  {
2605
6.43k
    defineExpr(_e, *_values.front());
2606
6.43k
    return;
2607
6.43k
  }
2608
5.64k
  auto const& symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_e));
2609
5.64k
  solAssert(symbTuple, "");
2610
5.64k
  symbTuple->increaseIndex();
2611
5.64k
  auto const& symbComponents = symbTuple->components();
2612
5.64k
  solAssert(symbComponents.size() == _values.size(), "");
2613
5.64k
  auto tupleType = dynamic_cast<TupleType const*>(_e.annotation().type);
2614
5.64k
  solAssert(tupleType, "");
2615
5.64k
  solAssert(tupleType->components().size() == symbComponents.size(), "");
2616
15.4k
  for (unsigned i = 0; i < symbComponents.size(); ++i)
2617
9.83k
    if (_values[i] && !smt::isInaccessibleDynamic(*tupleType->components()[i]))
2618
9.68k
      m_context.addAssertion(symbTuple->component(i) == *_values[i]);
2619
5.64k
}
2620
2621
void SMTEncoder::popPathCondition()
2622
23.3k
{
2623
23.3k
  solAssert(m_pathConditions.size() > 0, "Cannot pop path condition, empty.");
2624
23.3k
  m_pathConditions.pop_back();
2625
23.3k
}
2626
2627
void SMTEncoder::pushPathCondition(smtutil::Expression const& _e)
2628
23.3k
{
2629
23.3k
  m_pathConditions.push_back(currentPathConditions() && _e);
2630
23.3k
}
2631
2632
void SMTEncoder::setPathCondition(smtutil::Expression const& _e)
2633
6.45k
{
2634
6.45k
  if (m_pathConditions.empty())
2635
0
    m_pathConditions.push_back(_e);
2636
6.45k
  else
2637
6.45k
    m_pathConditions.back() = _e;
2638
6.45k
}
2639
2640
smtutil::Expression SMTEncoder::currentPathConditions()
2641
267k
{
2642
267k
  if (m_pathConditions.empty())
2643
139k
    return smtutil::Expression(true);
2644
128k
  return m_pathConditions.back();
2645
267k
}
2646
2647
SecondarySourceLocation SMTEncoder::callStackMessage(std::vector<CallStackEntry> const& _callStack)
2648
0
{
2649
0
  SecondarySourceLocation callStackLocation;
2650
0
  solAssert(!_callStack.empty(), "");
2651
0
  callStackLocation.append("Callstack:", SourceLocation());
2652
0
  for (auto const& call: _callStack | ranges::views::reverse)
2653
0
    if (call.second)
2654
0
      callStackLocation.append("", call.second->location());
2655
0
  return callStackLocation;
2656
0
}
2657
2658
std::pair<CallableDeclaration const*, ASTNode const*> SMTEncoder::popCallStack()
2659
46.9k
{
2660
46.9k
  solAssert(!m_callStack.empty(), "");
2661
46.9k
  auto lastCalled = m_callStack.back();
2662
46.9k
  m_callStack.pop_back();
2663
46.9k
  return lastCalled;
2664
46.9k
}
2665
2666
void SMTEncoder::pushCallStack(CallStackEntry _entry)
2667
46.9k
{
2668
46.9k
  m_callStack.push_back(_entry);
2669
46.9k
}
2670
2671
void SMTEncoder::addPathImpliedExpression(smtutil::Expression const& _e)
2672
1.00k
{
2673
1.00k
  m_context.addAssertion(smtutil::Expression::implies(currentPathConditions(), _e));
2674
1.00k
}
2675
2676
bool SMTEncoder::isRootFunction()
2677
18.6k
{
2678
18.6k
  return m_callStack.size() == 1;
2679
18.6k
}
2680
2681
bool SMTEncoder::visitedFunction(FunctionDefinition const* _funDef)
2682
2.13k
{
2683
2.13k
  for (auto const& call: m_callStack)
2684
2.62k
    if (call.first == _funDef)
2685
296
      return true;
2686
1.83k
  return false;
2687
2.13k
}
2688
2689
ContractDefinition const* SMTEncoder::currentScopeContract()
2690
21.7k
{
2691
21.7k
  for (auto&& f: m_callStack | ranges::views::reverse | ranges::views::keys)
2692
21.5k
    if (auto fun = dynamic_cast<FunctionDefinition const*>(f))
2693
21.0k
      return fun->annotation().contract;
2694
704
  return nullptr;
2695
21.7k
}
2696
2697
SMTEncoder::VariableIndices SMTEncoder::copyVariableIndices()
2698
16.8k
{
2699
16.8k
  VariableIndices indices;
2700
16.8k
  for (auto const& var: m_context.variables())
2701
64.8k
    indices.emplace(var.first, var.second->index());
2702
16.8k
  return indices;
2703
16.8k
}
2704
2705
void SMTEncoder::resetVariableIndices(VariableIndices const& _indices)
2706
5.41k
{
2707
5.41k
  for (auto const& var: _indices)
2708
16.8k
    m_context.variable(*var.first)->setIndex(var.second);
2709
5.41k
}
2710
2711
void SMTEncoder::clearIndices(ContractDefinition const* _contract, FunctionDefinition const* _function)
2712
205k
{
2713
205k
  solAssert(_contract, "");
2714
205k
  for (auto var: stateVariablesIncludingInheritedAndPrivate(*_contract))
2715
109k
    m_context.variable(*var)->resetIndex();
2716
205k
  if (_function)
2717
105k
  {
2718
105k
    for (auto const& var: _function->parameters() + _function->returnParameters())
2719
112k
      m_context.variable(*var)->resetIndex();
2720
105k
    for (auto const& var: localVariablesIncludingModifiers(*_function, _contract))
2721
41.7k
      m_context.variable(*var)->resetIndex();
2722
105k
  }
2723
205k
  state().reset();
2724
205k
}
2725
2726
Expression const* SMTEncoder::leftmostBase(IndexAccess const& _indexAccess)
2727
42
{
2728
42
  Expression const* base = &_indexAccess.baseExpression();
2729
42
  while (auto access = dynamic_cast<IndexAccess const*>(base))
2730
0
    base = &access->baseExpression();
2731
42
  return base;
2732
42
}
2733
2734
Type const* SMTEncoder::keyType(Type const* _type)
2735
34.5k
{
2736
34.5k
  if (auto const* mappingType = dynamic_cast<MappingType const*>(_type))
2737
3.54k
    return mappingType->keyType();
2738
31.0k
  if (
2739
31.0k
    dynamic_cast<ArrayType const*>(_type) ||
2740
172
    dynamic_cast<ArraySliceType const*>(_type)
2741
31.0k
  )
2742
31.0k
    return TypeProvider::uint256();
2743
0
  else
2744
31.0k
    solAssert(false, "");
2745
31.0k
}
2746
2747
Expression const& SMTEncoder::innermostTuple(Expression const& _expr)
2748
35.5k
{
2749
35.5k
  auto const* tuple = dynamic_cast<TupleExpression const*>(&_expr);
2750
35.5k
  if (!tuple || tuple->isInlineArray())
2751
34.1k
    return _expr;
2752
2753
1.35k
  Expression const* expr = tuple;
2754
2.34k
  while (tuple && !tuple->isInlineArray() && tuple->components().size() == 1)
2755
983
  {
2756
983
    expr = tuple->components().front().get();
2757
983
    tuple = dynamic_cast<TupleExpression const*>(expr);
2758
983
  }
2759
1.35k
  solAssert(expr, "");
2760
1.35k
  return *expr;
2761
35.5k
}
2762
2763
Type const* SMTEncoder::underlyingType(Type const* _type)
2764
756k
{
2765
756k
  if (auto userType = dynamic_cast<UserDefinedValueType const*>(_type))
2766
790
    _type = &userType->underlyingType();
2767
756k
  return _type;
2768
756k
}
2769
2770
TypePointers SMTEncoder::replaceUserTypes(TypePointers const& _types)
2771
11.8k
{
2772
11.8k
  return applyMap(_types, [](auto _type) {
2773
3.37k
    if (auto userType = dynamic_cast<UserDefinedValueType const*>(_type))
2774
14
      return &userType->underlyingType();
2775
3.36k
    return _type;
2776
3.37k
  });
2777
11.8k
}
2778
2779
std::pair<Expression const*, FunctionCallOptions const*> SMTEncoder::functionCallExpression(FunctionCall const& _funCall)
2780
23.8k
{
2781
23.8k
  Expression const* callExpr = &innermostTuple(_funCall.expression());
2782
23.8k
  auto const* callOptions = dynamic_cast<FunctionCallOptions const*>(callExpr);
2783
23.8k
  if (callOptions)
2784
461
    callExpr = &callOptions->expression();
2785
2786
23.8k
  return {callExpr, callOptions};
2787
23.8k
}
2788
2789
Expression const* SMTEncoder::cleanExpression(Expression const& _expr)
2790
28.7k
{
2791
28.7k
  auto const* expr = &_expr;
2792
28.7k
  if (auto const* tuple = dynamic_cast<TupleExpression const*>(expr))
2793
58
    return cleanExpression(innermostTuple(*tuple));
2794
28.6k
  if (auto const* functionCall = dynamic_cast<FunctionCall const*>(expr))
2795
198
    if (*functionCall->annotation().kind == FunctionCallKind::TypeConversion)
2796
12
    {
2797
12
      auto typeType = dynamic_cast<TypeType const*>(functionCall->expression().annotation().type);
2798
12
      solAssert(typeType, "");
2799
12
      if (auto const* arrayType = dynamic_cast<ArrayType const*>(typeType->actualType()))
2800
12
        if (arrayType->isByteArrayOrString())
2801
12
        {
2802
          // this is a cast to `bytes`
2803
12
          solAssert(functionCall->arguments().size() == 1, "");
2804
12
          Expression const& arg = *functionCall->arguments()[0];
2805
12
          if (
2806
12
            auto const* argArrayType = dynamic_cast<ArrayType const*>(arg.annotation().type);
2807
12
            argArrayType && argArrayType->isByteArrayOrString()
2808
12
          )
2809
12
            return cleanExpression(arg);
2810
12
        }
2811
12
    }
2812
28.6k
  solAssert(expr, "");
2813
28.6k
  return expr;
2814
28.6k
}
2815
2816
Declaration const* SMTEncoder::expressionToDeclaration(Expression const& _expr) const
2817
3.30k
{
2818
3.30k
  if (auto const* identifier = dynamic_cast<Identifier const*>(&_expr))
2819
2.25k
    return identifier->annotation().referencedDeclaration;
2820
1.04k
  if (auto const* outerMemberAccess = dynamic_cast<MemberAccess const*>(&_expr))
2821
98
    return outerMemberAccess->annotation().referencedDeclaration;
2822
946
  return nullptr;
2823
1.04k
}
2824
2825
VariableDeclaration const* SMTEncoder::identifierToVariable(Expression const& _expr) const
2826
144k
{
2827
  // We do not use `expressionToDeclaration` here because we are not interested in
2828
  // struct.field, for example.
2829
144k
  if (auto const* identifier = dynamic_cast<Identifier const*>(&_expr))
2830
136k
    if (auto const* varDecl = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration))
2831
120k
    {
2832
120k
      solAssert(m_context.knownVariable(*varDecl), "");
2833
120k
      return varDecl;
2834
120k
    }
2835
  // But we are interested in "contract.var", because that is the same as just "var".
2836
24.1k
  if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_expr))
2837
3.03k
    if (dynamic_cast<ContractDefinition const*>(expressionToDeclaration(
2838
3.03k
      *cleanExpression(memberAccess->expression())
2839
3.03k
    )))
2840
55
      if (auto const* varDecl = dynamic_cast<VariableDeclaration const*>(memberAccess->annotation().referencedDeclaration))
2841
55
      {
2842
55
        solAssert(m_context.knownVariable(*varDecl), "");
2843
55
        return varDecl;
2844
55
      }
2845
2846
24.0k
  return nullptr;
2847
24.1k
}
2848
2849
MemberAccess const* SMTEncoder::isEmptyPush(Expression const& _expr) const
2850
0
{
2851
0
  if (
2852
0
    auto const* funCall = dynamic_cast<FunctionCall const*>(&_expr);
2853
0
    funCall && funCall->arguments().empty()
2854
0
  )
2855
0
  {
2856
0
    auto const& funType = dynamic_cast<FunctionType const&>(*funCall->expression().annotation().type);
2857
0
    if (funType.kind() == FunctionType::Kind::ArrayPush)
2858
0
      return &dynamic_cast<MemberAccess const&>(funCall->expression());
2859
0
  }
2860
0
  return nullptr;
2861
0
}
2862
2863
smtutil::Expression SMTEncoder::contractAddressValue(FunctionCall const& _f)
2864
2.11k
{
2865
2.11k
  FunctionType const& funType = dynamic_cast<FunctionType const&>(*_f.expression().annotation().type);
2866
2.11k
  if (funType.kind() == FunctionType::Kind::Internal)
2867
1.71k
    return state().thisAddress();
2868
409
  auto [funExpr, funOptions] = functionCallExpression(_f);
2869
409
  if (MemberAccess const* callBase = dynamic_cast<MemberAccess const*>(funExpr))
2870
409
    return expr(callBase->expression());
2871
0
  smtAssert(false, "Unexpected function call type encountered while getting contract address!");
2872
0
}
2873
2874
4.11k
VariableDeclaration const* SMTEncoder::publicGetter(Expression const& _expr) const {
2875
4.11k
  if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_expr))
2876
3.38k
    if (auto variableDeclaration = dynamic_cast<VariableDeclaration const*>(memberAccess->annotation().referencedDeclaration))
2877
1.18k
      return variableDeclaration->isStateVariable() ? variableDeclaration : nullptr;
2878
2.92k
  return nullptr;
2879
4.11k
}
2880
2881
1.79k
bool SMTEncoder::isExternalCallToThis(Expression const* _expr) {
2882
1.79k
  auto memberAccess = dynamic_cast<MemberAccess const*>(_expr);
2883
1.79k
  if (!memberAccess)
2884
82
    return false;
2885
2886
1.70k
  auto identifier = dynamic_cast<Identifier const*>(&memberAccess->expression());
2887
1.70k
  return identifier &&
2888
1.40k
    identifier->name() == "this" &&
2889
1.16k
    identifier->annotation().referencedDeclaration &&
2890
1.16k
    dynamic_cast<MagicVariableDeclaration const*>(identifier->annotation().referencedDeclaration)
2891
1.79k
  ;
2892
1.79k
}
2893
2894
std::string SMTEncoder::extraComment()
2895
3.04k
{
2896
3.04k
  std::string extra;
2897
3.04k
  if (m_arrayAssignmentHappened)
2898
46
    extra +=
2899
46
      "\nNote that array aliasing is not supported,"
2900
46
      " therefore all mapping information is erased after"
2901
46
      " a mapping local variable/parameter is assigned.\n"
2902
46
      "You can re-introduce information using require().";
2903
3.04k
  return extra;
2904
3.04k
}
2905
2906
FunctionDefinition const* SMTEncoder::functionCallToDefinition(
2907
  FunctionCall const& _funCall,
2908
  ContractDefinition const* _scopeContract,
2909
  ContractDefinition const* _contextContract
2910
)
2911
21.7k
{
2912
21.7k
  if (*_funCall.annotation().kind != FunctionCallKind::FunctionCall)
2913
0
    return {};
2914
2915
21.7k
  auto [calledExpr, callOptions] = functionCallExpression(_funCall);
2916
2917
21.7k
  if (TupleExpression const* fun = dynamic_cast<TupleExpression const*>(calledExpr))
2918
4
  {
2919
4
    solAssert(fun->components().size() == 1, "");
2920
4
    calledExpr = &innermostTuple(*calledExpr);
2921
4
  }
2922
2923
21.7k
  auto resolveVirtual = [&](auto const* _ref) -> FunctionDefinition const* {
2924
20.0k
    VirtualLookup lookup = *_ref->annotation().requiredLookup;
2925
20.0k
    solAssert(_contextContract || lookup == VirtualLookup::Static, "No contract context provided for function lookup resolution!");
2926
20.0k
    auto funDef = dynamic_cast<FunctionDefinition const*>(_ref->annotation().referencedDeclaration);
2927
20.0k
    if (!funDef)
2928
8.01k
      return funDef;
2929
12.0k
    switch (lookup)
2930
12.0k
    {
2931
6.75k
    case VirtualLookup::Virtual:
2932
6.75k
      return &(funDef->resolveVirtual(*_contextContract));
2933
462
    case VirtualLookup::Super:
2934
462
    {
2935
462
      solAssert(_scopeContract, "");
2936
462
      auto super = _scopeContract->superContract(*_contextContract);
2937
462
      solAssert(super, "Super contract not available.");
2938
462
      return &funDef->resolveVirtual(*_contextContract, super);
2939
0
    }
2940
4.83k
    case VirtualLookup::Static:
2941
4.83k
      return funDef;
2942
12.0k
    }
2943
0
    solAssert(false, "");
2944
0
  };
SMTEncoder.cpp:solidity::frontend::FunctionDefinition const* solidity::frontend::SMTEncoder::functionCallToDefinition(solidity::frontend::FunctionCall const&, solidity::frontend::ContractDefinition const*, solidity::frontend::ContractDefinition const*)::$_0::operator()<solidity::frontend::Identifier>(solidity::frontend::Identifier const*) const
Line
Count
Source
2923
11.1k
  auto resolveVirtual = [&](auto const* _ref) -> FunctionDefinition const* {
2924
11.1k
    VirtualLookup lookup = *_ref->annotation().requiredLookup;
2925
11.1k
    solAssert(_contextContract || lookup == VirtualLookup::Static, "No contract context provided for function lookup resolution!");
2926
11.1k
    auto funDef = dynamic_cast<FunctionDefinition const*>(_ref->annotation().referencedDeclaration);
2927
11.1k
    if (!funDef)
2928
4.43k
      return funDef;
2929
6.75k
    switch (lookup)
2930
6.75k
    {
2931
6.75k
    case VirtualLookup::Virtual:
2932
6.75k
      return &(funDef->resolveVirtual(*_contextContract));
2933
0
    case VirtualLookup::Super:
2934
0
    {
2935
0
      solAssert(_scopeContract, "");
2936
0
      auto super = _scopeContract->superContract(*_contextContract);
2937
0
      solAssert(super, "Super contract not available.");
2938
0
      return &funDef->resolveVirtual(*_contextContract, super);
2939
0
    }
2940
0
    case VirtualLookup::Static:
2941
0
      return funDef;
2942
6.75k
    }
2943
0
    solAssert(false, "");
2944
0
  };
SMTEncoder.cpp:solidity::frontend::FunctionDefinition const* solidity::frontend::SMTEncoder::functionCallToDefinition(solidity::frontend::FunctionCall const&, solidity::frontend::ContractDefinition const*, solidity::frontend::ContractDefinition const*)::$_0::operator()<solidity::frontend::MemberAccess>(solidity::frontend::MemberAccess const*) const
Line
Count
Source
2923
8.87k
  auto resolveVirtual = [&](auto const* _ref) -> FunctionDefinition const* {
2924
8.87k
    VirtualLookup lookup = *_ref->annotation().requiredLookup;
2925
8.87k
    solAssert(_contextContract || lookup == VirtualLookup::Static, "No contract context provided for function lookup resolution!");
2926
8.87k
    auto funDef = dynamic_cast<FunctionDefinition const*>(_ref->annotation().referencedDeclaration);
2927
8.87k
    if (!funDef)
2928
3.58k
      return funDef;
2929
5.29k
    switch (lookup)
2930
5.29k
    {
2931
0
    case VirtualLookup::Virtual:
2932
0
      return &(funDef->resolveVirtual(*_contextContract));
2933
462
    case VirtualLookup::Super:
2934
462
    {
2935
462
      solAssert(_scopeContract, "");
2936
462
      auto super = _scopeContract->superContract(*_contextContract);
2937
462
      solAssert(super, "Super contract not available.");
2938
462
      return &funDef->resolveVirtual(*_contextContract, super);
2939
0
    }
2940
4.83k
    case VirtualLookup::Static:
2941
4.83k
      return funDef;
2942
5.29k
    }
2943
0
    solAssert(false, "");
2944
0
  };
2945
2946
21.7k
  if (Identifier const* fun = dynamic_cast<Identifier const*>(calledExpr))
2947
11.1k
    return resolveVirtual(fun);
2948
10.5k
  else if (MemberAccess const* fun = dynamic_cast<MemberAccess const*>(calledExpr))
2949
8.87k
    return resolveVirtual(fun);
2950
2951
1.67k
  return {};
2952
21.7k
}
2953
2954
std::vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(ContractDefinition const& _contract)
2955
1.54M
{
2956
1.54M
  return fold(
2957
1.54M
    _contract.annotation().linearizedBaseContracts,
2958
1.54M
    std::vector<VariableDeclaration const*>{},
2959
1.79M
    [](auto&& _acc, auto _contract) { return _acc + _contract->stateVariables(); }
2960
1.54M
  );
2961
1.54M
}
2962
2963
std::vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(FunctionDefinition const& _function)
2964
80
{
2965
80
  if (auto contract = dynamic_cast<ContractDefinition const*>(_function.scope()))
2966
78
    return stateVariablesIncludingInheritedAndPrivate(*contract);
2967
2
  return {};
2968
80
}
2969
2970
std::vector<VariableDeclaration const*> SMTEncoder::localVariablesIncludingModifiers(FunctionDefinition const& _function, ContractDefinition const* _contract)
2971
501k
{
2972
501k
  return _function.localVariables() + tryCatchVariables(_function) + modifiersVariables(_function, _contract);
2973
501k
}
2974
2975
std::vector<VariableDeclaration const*> SMTEncoder::tryCatchVariables(FunctionDefinition const& _function)
2976
501k
{
2977
501k
  struct TryCatchVarsVisitor : public ASTConstVisitor
2978
501k
  {
2979
501k
    bool visit(TryCatchClause const& _catchClause) override
2980
501k
    {
2981
19.4k
      if (_catchClause.parameters())
2982
3.80k
      {
2983
3.80k
        auto const& params = _catchClause.parameters()->parameters();
2984
3.80k
        for (auto param: params)
2985
4.52k
          vars.push_back(param.get());
2986
3.80k
      }
2987
2988
19.4k
      return true;
2989
19.4k
    }
2990
2991
501k
    std::vector<VariableDeclaration const*> vars;
2992
501k
  } tryCatchVarsVisitor;
2993
501k
  _function.accept(tryCatchVarsVisitor);
2994
501k
  return tryCatchVarsVisitor.vars;
2995
501k
}
2996
2997
std::vector<VariableDeclaration const*> SMTEncoder::modifiersVariables(FunctionDefinition const& _function, ContractDefinition const* _contract)
2998
501k
{
2999
501k
  struct BlockVars: ASTConstVisitor
3000
501k
  {
3001
501k
    BlockVars(Block const& _block) { _block.accept(*this); }
3002
501k
    void endVisit(VariableDeclaration const& _var) { vars.push_back(&_var); }
3003
501k
    std::vector<VariableDeclaration const*> vars;
3004
501k
  };
3005
3006
501k
  std::vector<VariableDeclaration const*> vars;
3007
501k
  std::set<ModifierDefinition const*> visited;
3008
501k
  for (auto invok: _function.modifiers())
3009
40.3k
  {
3010
40.3k
    if (!invok)
3011
0
      continue;
3012
40.3k
    auto const* modifier = resolveModifierInvocation(*invok, _contract);
3013
40.3k
    if (!modifier || visited.count(modifier))
3014
21.6k
      continue;
3015
3016
18.7k
    visited.insert(modifier);
3017
18.7k
    if (modifier->isImplemented())
3018
18.6k
    {
3019
18.6k
      vars += applyMap(modifier->parameters(), [](auto _var) { return _var.get(); });
3020
18.6k
      vars += BlockVars(modifier->body()).vars;
3021
18.6k
    }
3022
18.7k
  }
3023
501k
  return vars;
3024
501k
}
3025
3026
ModifierDefinition const* SMTEncoder::resolveModifierInvocation(ModifierInvocation const& _invocation, ContractDefinition const* _contract)
3027
41.3k
{
3028
41.3k
  auto const* modifier = dynamic_cast<ModifierDefinition const*>(_invocation.name().annotation().referencedDeclaration);
3029
41.3k
  if (modifier)
3030
35.1k
  {
3031
35.1k
    VirtualLookup lookup = *_invocation.name().annotation().requiredLookup;
3032
35.1k
    solAssert(lookup == VirtualLookup::Virtual || lookup == VirtualLookup::Static, "");
3033
35.1k
    solAssert(_contract || lookup == VirtualLookup::Static, "No contract context provided for modifier lookup resolution!");
3034
35.1k
    if (lookup == VirtualLookup::Virtual)
3035
34.9k
      modifier = &modifier->resolveVirtual(*_contract);
3036
35.1k
  }
3037
41.3k
  return modifier;
3038
41.3k
}
3039
3040
std::set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctions(ContractDefinition const& _contract)
3041
54.5k
{
3042
54.5k
  if (!m_contractFunctions.count(&_contract))
3043
28.0k
  {
3044
28.0k
    auto const& functions = _contract.definedFunctions();
3045
28.0k
    std::set<FunctionDefinition const*, ASTNode::CompareByID> resolvedFunctions(begin(functions), end(functions));
3046
28.0k
    for (auto const* base: _contract.annotation().linearizedBaseContracts)
3047
31.7k
    {
3048
31.7k
      if (base == &_contract)
3049
28.0k
        continue;
3050
3.65k
      for (auto const* baseFunction: base->definedFunctions())
3051
3.27k
      {
3052
3.27k
        if (baseFunction->isConstructor()) // We don't want to include constructors of parent contracts
3053
1.01k
          continue;
3054
2.25k
        bool overridden = false;
3055
2.25k
        for (auto const* function: resolvedFunctions)
3056
2.46k
          if (
3057
2.46k
            function->name() == baseFunction->name() &&
3058
1.10k
            function->kind() == baseFunction->kind() &&
3059
1.09k
            FunctionType(*function).asExternallyCallableFunction(false)->
3060
1.09k
              hasEqualParameterTypes(*FunctionType(*baseFunction).asExternallyCallableFunction(false))
3061
2.46k
            )
3062
1.00k
          {
3063
1.00k
            overridden = true;
3064
1.00k
            break;
3065
1.00k
          }
3066
2.25k
        if (!overridden)
3067
1.24k
          resolvedFunctions.insert(baseFunction);
3068
2.25k
      }
3069
3.65k
    }
3070
28.0k
    m_contractFunctions.emplace(&_contract, std::move(resolvedFunctions));
3071
28.0k
  }
3072
54.5k
  return m_contractFunctions.at(&_contract);
3073
54.5k
}
3074
3075
std::set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctionsWithoutVirtual(ContractDefinition const& _contract)
3076
42.2k
{
3077
42.2k
  if (!m_contractFunctionsWithoutVirtual.count(&_contract))
3078
28.0k
  {
3079
28.0k
    auto allFunctions = contractFunctions(_contract);
3080
28.0k
    for (auto const* base: _contract.annotation().linearizedBaseContracts)
3081
31.7k
      for (auto const* baseFun: base->definedFunctions())
3082
30.1k
        allFunctions.insert(baseFun);
3083
3084
28.0k
    m_contractFunctionsWithoutVirtual.emplace(&_contract, std::move(allFunctions));
3085
3086
28.0k
  }
3087
42.2k
  return m_contractFunctionsWithoutVirtual.at(&_contract);
3088
42.2k
}
3089
3090
std::map<ContractDefinition const*, std::vector<ASTPointer<frontend::Expression>>> SMTEncoder::baseArguments(ContractDefinition const& _contract)
3091
13.8k
{
3092
13.8k
  std::map<ContractDefinition const*, std::vector<ASTPointer<Expression>>> baseArgs;
3093
3094
13.8k
  for (auto contract: _contract.annotation().linearizedBaseContracts)
3095
15.4k
  {
3096
    /// Collect base contracts and potential constructor arguments.
3097
15.4k
    for (auto specifier: contract->baseContracts())
3098
1.75k
    {
3099
1.75k
      solAssert(specifier, "");
3100
1.75k
      auto const& base = dynamic_cast<ContractDefinition const&>(*specifier->name().annotation().referencedDeclaration);
3101
1.75k
      if (auto args = specifier->arguments())
3102
50
        baseArgs[&base] = *args;
3103
1.75k
    }
3104
    /// Collect base constructor arguments given as constructor modifiers.
3105
15.4k
    if (auto constructor = contract->constructor())
3106
2.03k
      for (auto mod: constructor->modifiers())
3107
362
      {
3108
362
        auto decl = mod->name().annotation().referencedDeclaration;
3109
362
        if (auto base = dynamic_cast<ContractDefinition const*>(decl))
3110
261
        {
3111
261
          solAssert(!baseArgs.count(base), "");
3112
261
          if (auto args = mod->arguments())
3113
261
            baseArgs[base] = *args;
3114
261
        }
3115
362
      }
3116
15.4k
  }
3117
3118
13.8k
  return baseArgs;
3119
13.8k
}
3120
3121
RationalNumberType const* SMTEncoder::isConstant(Expression const& _expr)
3122
83.1k
{
3123
83.1k
  if (auto type = dynamic_cast<RationalNumberType const*>(_expr.annotation().type))
3124
11.8k
    return type;
3125
3126
71.3k
  if (
3127
71.3k
    auto typedValue = ConstantEvaluator::tryEvaluate(_expr);
3128
71.3k
    std::holds_alternative<rational>(typedValue.value)
3129
71.3k
  )
3130
1.26k
    return TypeProvider::rationalNumber(std::get<rational>(typedValue.value));
3131
3132
70.0k
  return nullptr;
3133
71.3k
}
3134
3135
std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> SMTEncoder::collectABICalls(ASTNode const* _node)
3136
28.0k
{
3137
28.0k
  struct ABIFunctions: public ASTConstVisitor
3138
28.0k
  {
3139
28.0k
    ABIFunctions(ASTNode const* _node) { _node->accept(*this); }
3140
28.0k
    void endVisit(FunctionCall const& _funCall)
3141
28.0k
    {
3142
26.3k
      if (*_funCall.annotation().kind == FunctionCallKind::FunctionCall)
3143
20.9k
        switch (dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type).kind())
3144
20.9k
        {
3145
322
        case FunctionType::Kind::ABIEncode:
3146
472
        case FunctionType::Kind::ABIEncodePacked:
3147
516
        case FunctionType::Kind::ABIEncodeWithSelector:
3148
554
        case FunctionType::Kind::ABIEncodeCall:
3149
594
        case FunctionType::Kind::ABIEncodeWithSignature:
3150
842
        case FunctionType::Kind::ABIDecode:
3151
842
          abiCalls.insert(&_funCall);
3152
842
          break;
3153
20.0k
        default: {}
3154
20.9k
        }
3155
26.3k
    }
3156
3157
28.0k
    std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> abiCalls;
3158
28.0k
  };
3159
3160
28.0k
  return ABIFunctions(_node).abiCalls;
3161
28.0k
}
3162
3163
std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> SMTEncoder::collectBytesConcatCalls(ASTNode const* _node)
3164
28.0k
{
3165
28.0k
  struct BytesConcatFunctions: public ASTConstVisitor
3166
28.0k
  {
3167
28.0k
    BytesConcatFunctions(ASTNode const* _node) { _node->accept(*this); }
3168
28.0k
    void endVisit(FunctionCall const& _funCall)
3169
28.0k
    {
3170
26.3k
      if (*_funCall.annotation().kind == FunctionCallKind::FunctionCall)
3171
20.9k
        switch (dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type).kind())
3172
20.9k
        {
3173
134
        case FunctionType::Kind::BytesConcat:
3174
134
          bytesConcatCalls.insert(&_funCall);
3175
134
          break;
3176
20.7k
        default: {}
3177
20.9k
        }
3178
26.3k
    }
3179
3180
28.0k
    std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> bytesConcatCalls;
3181
28.0k
  };
3182
3183
28.0k
  return BytesConcatFunctions(_node).bytesConcatCalls;
3184
28.0k
}
3185
3186
std::set<SourceUnit const*, ASTNode::CompareByID> SMTEncoder::sourceDependencies(SourceUnit const& _source)
3187
26.8k
{
3188
26.8k
  std::set<SourceUnit const*, ASTNode::CompareByID> sources;
3189
26.8k
  sources.insert(&_source);
3190
26.8k
  for (auto const& source: _source.referencedSourceUnits(true))
3191
1.33k
    sources.insert(source);
3192
26.8k
  return sources;
3193
26.8k
}
3194
3195
void SMTEncoder::createReturnedExpressions(FunctionDefinition const* _funDef, Expression const& _callStackExpr)
3196
12.6k
{
3197
12.6k
  if (!_funDef)
3198
8.02k
    return;
3199
3200
4.62k
  auto const& returnParams = _funDef->returnParameters();
3201
4.62k
  for (auto param: returnParams)
3202
3.71k
    createVariable(*param);
3203
4.62k
  auto returnValues = applyMap(returnParams, [this](auto const& param) -> std::optional<smtutil::Expression> {
3204
3.71k
    solAssert(param && m_context.knownVariable(*param), "");
3205
3.71k
    return currentValue(*param);
3206
3.71k
  });
3207
4.62k
  defineExpr(_callStackExpr, returnValues);
3208
4.62k
}
3209
3210
std::vector<smtutil::Expression> SMTEncoder::symbolicArguments(
3211
  std::vector<ASTPointer<VariableDeclaration>> const& _funParameters,
3212
  std::vector<Expression const*> const& _arguments,
3213
  std::optional<Expression const*> _boundArgumentCall
3214
)
3215
3.89k
{
3216
3.89k
  std::vector<smtutil::Expression> args;
3217
3.89k
  unsigned firstParam = 0;
3218
3.89k
  if (_boundArgumentCall)
3219
228
  {
3220
228
    Expression const& calledExpr = innermostTuple(*_boundArgumentCall.value());
3221
228
    auto const& attachedFunction = dynamic_cast<MemberAccess const*>(&calledExpr);
3222
228
    solAssert(attachedFunction, "");
3223
228
    args.push_back(expr(attachedFunction->expression(), _funParameters.front()->type()));
3224
228
    firstParam = 1;
3225
228
  }
3226
3227
3.89k
  solAssert((_arguments.size() + firstParam) == _funParameters.size(), "");
3228
3229
5.94k
  for (unsigned i = 0; i < _arguments.size(); ++i)
3230
2.05k
    args.push_back(expr(*_arguments.at(i), _funParameters.at(i + firstParam)->type()));
3231
3232
3.89k
  return args;
3233
3.89k
}
3234
3235
smtutil::Expression SMTEncoder::constantExpr(Expression const& _expr, VariableDeclaration const& _var)
3236
1.04k
{
3237
1.04k
  if (RationalNumberType const* rationalType = isConstant(_expr))
3238
856
  {
3239
856
    if (rationalType->isNegative())
3240
2
      return smtutil::Expression(u2s(rationalType->literalValue(nullptr)));
3241
854
    else
3242
854
      return smtutil::Expression(rationalType->literalValue(nullptr));
3243
856
  }
3244
188
  else
3245
188
  {
3246
188
    solAssert(_var.value(), "");
3247
188
    _var.value()->accept(*this);
3248
188
    return expr(*_var.value(), _expr.annotation().type);
3249
188
  }
3250
0
  solAssert(false, "");
3251
0
}
3252
3253
void SMTEncoder::collectFreeFunctions(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources)
3254
13.4k
{
3255
13.4k
  for (auto source: _sources)
3256
14.0k
    for (auto node: source->nodes())
3257
34.2k
      if (auto function = dynamic_cast<FunctionDefinition const*>(node.get()))
3258
1.17k
        m_freeFunctions.insert(function);
3259
33.0k
      else if (
3260
33.0k
        auto contract = dynamic_cast<ContractDefinition const*>(node.get());
3261
33.0k
        contract && contract->isLibrary()
3262
33.0k
      )
3263
468
        for (auto function: contract->definedFunctions())
3264
          // We need to add public library functions too because they can be called
3265
          // internally by internal library functions that are considered free functions.
3266
440
          m_freeFunctions.insert(function);
3267
13.4k
}
3268
3269
void SMTEncoder::createFreeConstants(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources)
3270
26.8k
{
3271
26.8k
  for (auto source: _sources)
3272
28.0k
    for (auto node: source->nodes())
3273
68.5k
      if (auto var = dynamic_cast<VariableDeclaration const*>(node.get()))
3274
394
        createVariable(*var);
3275
68.1k
      else if (
3276
68.1k
        auto contract = dynamic_cast<ContractDefinition const*>(node.get());
3277
68.1k
        contract && contract->isLibrary()
3278
68.1k
      )
3279
936
        for (auto var: contract->stateVariables())
3280
72
        {
3281
72
          solAssert(var->isConstant(), "");
3282
72
          createVariable(*var);
3283
72
        }
3284
26.8k
}
3285
3286
void SMTEncoder::createStateVariables(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources)
3287
13.4k
{
3288
13.4k
  for (auto const& source: _sources)
3289
14.0k
    for (auto const& node: source->nodes())
3290
34.2k
      if (auto contract = dynamic_cast<ContractDefinition const*>(node.get()))
3291
14.3k
        createStateVariables(*contract);
3292
13.4k
}
3293
3294
smt::SymbolicState& SMTEncoder::state()
3295
1.32M
{
3296
1.32M
  return m_context.state();
3297
1.32M
}
3298
3299
smtutil::Expression SMTEncoder::createSelectExpressionForFunction(
3300
  smtutil::Expression symbFunction,
3301
  std::vector<frontend::ASTPointer<frontend::Expression const>> const& args,
3302
  frontend::TypePointers const& inTypes,
3303
  unsigned long argsActualLength
3304
)
3305
1.00k
{
3306
1.00k
  solAssert(argsActualLength <= args.size() && inTypes.size() == argsActualLength);
3307
1.00k
  if (inTypes.size() == 1)
3308
595
  {
3309
595
    smtutil::Expression arg = expr(*args.at(0), inTypes.at(0));
3310
595
    return smtutil::Expression::select(symbFunction, arg);
3311
595
  }
3312
3313
405
  std::vector<smtutil::Expression> symbArgs;
3314
1.36k
  for (unsigned i = 0; i < argsActualLength; ++i)
3315
962
    if (args.at(i))
3316
962
      symbArgs.emplace_back(expr(*args.at(i), inTypes.at(i)));
3317
3318
405
  auto inputSort = dynamic_cast<smtutil::ArraySort&>(*symbFunction.sort).domain;
3319
405
  smtutil::Expression arg = smtutil::Expression::tuple_constructor(
3320
405
    smtutil::Expression(std::make_shared<smtutil::SortSort>(inputSort), ""),
3321
405
    symbArgs
3322
405
  );
3323
405
  return smtutil::Expression::select(symbFunction, arg);
3324
1.00k
}