| 1068 | } |
| 1069 | |
| 1070 | void CHC::externalFunctionCallToTrustedCode(FunctionCall const& _funCall) |
| 1071 | { |
| 1072 | if (publicGetter(_funCall.expression())) |
| 1073 | visitPublicGetter(_funCall); |
| 1074 | |
| 1075 | solAssert(m_currentContract, ""); |
| 1076 | |
| 1077 | auto [callExpr, callOptions] = functionCallExpression(_funCall); |
| 1078 | FunctionType const& funType = dynamic_cast<FunctionType const&>(*callExpr->annotation().type); |
| 1079 | |
| 1080 | auto kind = funType.kind(); |
| 1081 | solAssert(kind == FunctionType::Kind::External || kind == FunctionType::Kind::BareStaticCall, ""); |
| 1082 | |
| 1083 | auto function = functionCallToDefinition(_funCall, currentScopeContract(), m_currentContract); |
| 1084 | if (!function) |
| 1085 | return; |
| 1086 | |
| 1087 | // Remember the external call in the call graph to properly detect verification targets for the current function |
| 1088 | if (m_currentFunction && !m_currentFunction->isConstructor()) |
| 1089 | m_callGraph[m_currentFunction].insert(function); |
| 1090 | else |
| 1091 | m_callGraph[m_currentContract].insert(function); |
| 1092 | |
| 1093 | // External call creates a new transaction. |
| 1094 | auto originalTx = state().tx(); |
| 1095 | Expression const* value = valueOption(callOptions); |
| 1096 | newTxConstraints(value); |
| 1097 | |
| 1098 | auto calledAddress = contractAddressValue(_funCall); |
| 1099 | if (value) |
| 1100 | { |
| 1101 | decreaseBalanceFromOptionsValue(*value); |
| 1102 | state().addBalance(calledAddress, expr(*value)); |
| 1103 | } |
| 1104 | |
| 1105 | if (encodeExternalCallsAsTrusted()) |
| 1106 | { |
| 1107 | // The order here is important!! Write should go first. |
| 1108 | |
| 1109 | // Load the caller contract's state variables into the global state. |
| 1110 | state().writeStateVars(*m_currentContract, state().thisAddress()); |
| 1111 | // Load the called contract's state variables from the global state. |
| 1112 | state().readStateVars(*function->annotation().contract, contractAddressValue(_funCall)); |
| 1113 | } |
| 1114 | |
| 1115 | std::vector<Expression const*> arguments; |
| 1116 | for (auto& arg: _funCall.sortedArguments()) |
| 1117 | arguments.push_back(&(*arg)); |
| 1118 | smtutil::Expression pred = predicate(function, std::nullopt, &funType, arguments, calledAddress); |
| 1119 | |
| 1120 | auto txConstraints = state().txTypeConstraints() && state().txFunctionConstraints(*function); |
| 1121 | m_context.addAssertion(pred && txConstraints); |
| 1122 | // restore the original transaction data |
| 1123 | state().newTx(); |
| 1124 | m_context.addAssertion(originalTx == state().tx()); |
| 1125 | |
| 1126 | solAssert(m_errorDest, ""); |
| 1127 | connectBlocks( |
nothing calls this directly
no test coverage detected