@@ -543,6 +543,35 @@ void CHC::endVisit(ForStatement const& _for)
543
543
m_scopes.pop_back ();
544
544
}
545
545
546
+ void CHC::endVisit (UnaryOperation const & _op)
547
+ {
548
+ SMTEncoder::endVisit (_op);
549
+
550
+ if (auto funDef = *_op.annotation ().userDefinedFunction )
551
+ {
552
+ std::vector<Expression const *> arguments;
553
+ arguments.push_back (&_op.subExpression ());
554
+ internalFunctionCall (funDef, std::nullopt, _op.userDefinedFunctionType (), arguments, state ().thisAddress ());
555
+
556
+ createReturnedExpressions (funDef, _op);
557
+ }
558
+ }
559
+
560
+ void CHC::endVisit (BinaryOperation const & _op)
561
+ {
562
+ SMTEncoder::endVisit (_op);
563
+
564
+ if (auto funDef = *_op.annotation ().userDefinedFunction )
565
+ {
566
+ std::vector<Expression const *> arguments;
567
+ arguments.push_back (&_op.leftExpression ());
568
+ arguments.push_back (&_op.rightExpression ());
569
+ internalFunctionCall (funDef, std::nullopt, _op.userDefinedFunctionType (), arguments, state ().thisAddress ());
570
+
571
+ createReturnedExpressions (funDef, _op);
572
+ }
573
+ }
574
+
546
575
void CHC::endVisit (FunctionCall const & _funCall)
547
576
{
548
577
auto functionCallKind = *_funCall.annotation ().kind ;
@@ -593,8 +622,8 @@ void CHC::endVisit(FunctionCall const& _funCall)
593
622
break ;
594
623
}
595
624
596
-
597
- createReturnedExpressions (_funCall, m_currentContract );
625
+ auto funDef = functionCallToDefinition (_funCall, currentScopeContract (), m_currentContract);
626
+ createReturnedExpressions (funDef, _funCall );
598
627
}
599
628
600
629
void CHC::endVisit (Break const & _break)
@@ -820,20 +849,26 @@ void CHC::visitDeployment(FunctionCall const& _funCall)
820
849
defineExpr (_funCall, newAddr);
821
850
}
822
851
823
- void CHC::internalFunctionCall (FunctionCall const & _funCall)
852
+ void CHC::internalFunctionCall (
853
+ FunctionDefinition const * _funDef,
854
+ std::optional<Expression const *> _boundArgumentCall,
855
+ FunctionType const * _funType,
856
+ std::vector<Expression const *> const & _arguments,
857
+ smtutil::Expression _contractAddressValue
858
+ )
824
859
{
825
860
solAssert (m_currentContract, " " );
861
+ solAssert (_funType, " " );
826
862
827
- auto function = functionCallToDefinition (_funCall, currentScopeContract (), m_currentContract);
828
- if (function)
863
+ if (_funDef)
829
864
{
830
865
if (m_currentFunction && !m_currentFunction->isConstructor ())
831
- m_callGraph[m_currentFunction].insert (function );
866
+ m_callGraph[m_currentFunction].insert (_funDef );
832
867
else
833
- m_callGraph[m_currentContract].insert (function );
868
+ m_callGraph[m_currentContract].insert (_funDef );
834
869
}
835
870
836
- m_context.addAssertion (predicate (_funCall ));
871
+ m_context.addAssertion (predicate (_funDef, _boundArgumentCall, _funType, _arguments, _contractAddressValue ));
837
872
838
873
solAssert (m_errorDest, " " );
839
874
connectBlocks (
@@ -845,6 +880,42 @@ void CHC::internalFunctionCall(FunctionCall const& _funCall)
845
880
m_context.addAssertion (errorFlag ().increaseIndex () == 0 );
846
881
}
847
882
883
+ void CHC::internalFunctionCall (FunctionCall const & _funCall)
884
+ {
885
+ solAssert (m_currentContract, " " );
886
+
887
+ auto funDef = functionCallToDefinition (_funCall, currentScopeContract (), m_currentContract);
888
+ if (funDef)
889
+ {
890
+ if (m_currentFunction && !m_currentFunction->isConstructor ())
891
+ m_callGraph[m_currentFunction].insert (funDef);
892
+ else
893
+ m_callGraph[m_currentContract].insert (funDef);
894
+ }
895
+
896
+ Expression const * calledExpr = &_funCall.expression ();
897
+ auto funType = dynamic_cast <FunctionType const *>(calledExpr->annotation ().type );
898
+
899
+ auto contractAddressValue = [this ](FunctionCall const & _f) {
900
+ auto [callExpr, callOptions] = functionCallExpression (_f);
901
+
902
+ FunctionType const & funType = dynamic_cast <FunctionType const &>(*callExpr->annotation ().type );
903
+ if (funType.kind () == FunctionType::Kind::Internal)
904
+ return state ().thisAddress ();
905
+ if (MemberAccess const * callBase = dynamic_cast <MemberAccess const *>(callExpr))
906
+ return expr (callBase->expression ());
907
+ solAssert (false , " Unreachable!" );
908
+ };
909
+
910
+ std::vector<Expression const *> arguments;
911
+ for (auto & arg: _funCall.sortedArguments ())
912
+ arguments.push_back (&(*arg));
913
+
914
+ std::optional<Expression const *> boundArgumentCall =
915
+ funType->hasBoundFirstArgument () ? std::make_optional (calledExpr) : std::nullopt;
916
+ internalFunctionCall (funDef, boundArgumentCall, funType, arguments, contractAddressValue (_funCall));
917
+ }
918
+
848
919
void CHC::addNondetCalls (ContractDefinition const & _contract)
849
920
{
850
921
for (auto var: _contract.stateVariables ())
@@ -1028,7 +1099,10 @@ void CHC::externalFunctionCallToTrustedCode(FunctionCall const& _funCall)
1028
1099
state ().readStateVars (*function->annotation ().contract , contractAddressValue (_funCall));
1029
1100
}
1030
1101
1031
- smtutil::Expression pred = predicate (_funCall);
1102
+ std::vector<Expression const *> arguments;
1103
+ for (auto & arg: _funCall.sortedArguments ())
1104
+ arguments.push_back (&(*arg));
1105
+ smtutil::Expression pred = predicate (function, std::nullopt, &funType, arguments, calledAddress);
1032
1106
1033
1107
auto txConstraints = state ().txTypeConstraints () && state ().txFunctionConstraints (*function);
1034
1108
m_context.addAssertion (pred && txConstraints);
@@ -1264,6 +1338,12 @@ std::set<unsigned> CHC::transactionVerificationTargetsIds(ASTNode const* _txRoot
1264
1338
return verificationTargetsIds;
1265
1339
}
1266
1340
1341
+ bool CHC::usesStaticCall (FunctionDefinition const * _funDef, FunctionType const * _funType)
1342
+ {
1343
+ auto kind = _funType->kind ();
1344
+ return (_funDef && (_funDef->stateMutability () == StateMutability::Pure || _funDef->stateMutability () == StateMutability::View)) || kind == FunctionType::Kind::BareStaticCall;
1345
+ }
1346
+
1267
1347
bool CHC::usesStaticCall (FunctionCall const & _funCall)
1268
1348
{
1269
1349
FunctionType const & funType = dynamic_cast <FunctionType const &>(*_funCall.expression ().annotation ().type );
@@ -1733,40 +1813,34 @@ smtutil::Expression CHC::predicate(Predicate const& _block)
1733
1813
solAssert (false , " " );
1734
1814
}
1735
1815
1736
- smtutil::Expression CHC::predicate (FunctionCall const & _funCall)
1816
+ smtutil::Expression CHC::predicate (
1817
+ FunctionDefinition const * _funDef,
1818
+ std::optional<Expression const *> _boundArgumentCall,
1819
+ FunctionType const * _funType,
1820
+ std::vector<Expression const *> _arguments,
1821
+ smtutil::Expression _contractAddressValue
1822
+ )
1737
1823
{
1738
- FunctionType const & funType = dynamic_cast <FunctionType const &>(*_funCall. expression (). annotation (). type );
1739
- auto kind = funType. kind ();
1824
+ solAssert (_funType, " " );
1825
+ auto kind = _funType-> kind ();
1740
1826
solAssert (kind == FunctionType::Kind::Internal || kind == FunctionType::Kind::External || kind == FunctionType::Kind::BareStaticCall, " " );
1741
-
1742
- solAssert (m_currentContract, " " );
1743
- auto function = functionCallToDefinition (_funCall, currentScopeContract (), m_currentContract);
1744
- if (!function)
1827
+ if (!_funDef)
1745
1828
return smtutil::Expression (true );
1746
1829
1747
- auto contractAddressValue = [this ](FunctionCall const & _f) {
1748
- auto [callExpr, callOptions] = functionCallExpression (_f);
1749
-
1750
- FunctionType const & funType = dynamic_cast <FunctionType const &>(*callExpr->annotation ().type );
1751
- if (funType.kind () == FunctionType::Kind::Internal)
1752
- return state ().thisAddress ();
1753
- if (MemberAccess const * callBase = dynamic_cast <MemberAccess const *>(callExpr))
1754
- return expr (callBase->expression ());
1755
- solAssert (false , " Unreachable!" );
1756
- };
1757
1830
errorFlag ().increaseIndex ();
1758
- std::vector<smtutil::Expression> args{errorFlag ().currentValue (), contractAddressValue (_funCall), state ().abi (), state ().crypto (), state ().tx (), state ().state ()};
1759
1831
1760
- auto const * contract = function->annotation ().contract ;
1832
+ std::vector<smtutil::Expression> args{errorFlag ().currentValue (), _contractAddressValue, state ().abi (), state ().crypto (), state ().tx (), state ().state ()};
1833
+
1834
+ auto const * contract = _funDef->annotation ().contract ;
1761
1835
auto const & hierarchy = m_currentContract->annotation ().linearizedBaseContracts ;
1762
- solAssert (kind != FunctionType::Kind::Internal || function ->isFree () || (contract && contract->isLibrary ()) || util::contains (hierarchy, contract), " " );
1836
+ solAssert (kind != FunctionType::Kind::Internal || _funDef ->isFree () || (contract && contract->isLibrary ()) || util::contains (hierarchy, contract), " " );
1763
1837
1764
1838
if (kind == FunctionType::Kind::Internal)
1765
1839
contract = m_currentContract;
1766
1840
1767
1841
args += currentStateVariables (*contract);
1768
- args += symbolicArguments (_funCall, contract );
1769
- if (!usesStaticCall (_funCall ))
1842
+ args += symbolicArguments (_funDef-> parameters (), _arguments, _boundArgumentCall );
1843
+ if (!usesStaticCall (_funDef, _funType ))
1770
1844
{
1771
1845
state ().newState ();
1772
1846
for (auto const & var: stateVariablesIncludingInheritedAndPrivate (*contract))
@@ -1775,7 +1849,7 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
1775
1849
args += std::vector<smtutil::Expression>{state ().state ()};
1776
1850
args += currentStateVariables (*contract);
1777
1851
1778
- for (auto var: function ->parameters () + function ->returnParameters ())
1852
+ for (auto var: _funDef ->parameters () + _funDef ->returnParameters ())
1779
1853
{
1780
1854
if (m_context.knownVariable (*var))
1781
1855
m_context.variable (*var)->increaseIndex ();
@@ -1784,10 +1858,10 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
1784
1858
args.push_back (currentValue (*var));
1785
1859
}
1786
1860
1787
- Predicate const & summary = *m_summaries.at (contract).at (function );
1861
+ Predicate const & summary = *m_summaries.at (contract).at (_funDef );
1788
1862
auto from = smt::function (summary, contract, m_context);
1789
1863
Predicate const & callPredicate = *createSummaryBlock (
1790
- *function ,
1864
+ *_funDef ,
1791
1865
*contract,
1792
1866
kind == FunctionType::Kind::Internal ? PredicateType::InternalCall : PredicateType::ExternalCallTrusted
1793
1867
);
0 commit comments