MCPcopy Create free account
hub / github.com/argotorg/solidity / defineExternalFunctionInterface

Method defineExternalFunctionInterface

libsolidity/formal/CHC.cpp:1492–1575  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1490}
1491
1492void CHC::defineExternalFunctionInterface(FunctionDefinition const& _function, ContractDefinition const& _contract)
1493{
1494 // Create a rule that represents an external call to this function.
1495 // This contains more things than the function body itself,
1496 // such as balance updates because of ``msg.value``.
1497 auto functionEntryBlock = createBlock(&_function, PredicateType::FunctionBlock);
1498 auto functionPred = predicate(*functionEntryBlock);
1499 addRule(functionPred, functionPred.name);
1500 setCurrentBlock(*functionEntryBlock);
1501
1502 m_context.addAssertion(initialConstraints(_contract, &_function));
1503 m_context.addAssertion(state().txTypeConstraints() && state().txFunctionConstraints(_function));
1504
1505 // The contract may have received funds through a selfdestruct or
1506 // block.coinbase, which do not trigger calls into the contract.
1507 // So the only constraint we can add here is that the balance of
1508 // the contract grows by at least `msg.value`.
1509 SymbolicIntVariable k{TypeProvider::uint256(), TypeProvider::uint256(), "funds_" + std::to_string(m_context.newUniqueId()), m_context};
1510 m_context.addAssertion(k.currentValue() >= state().txMember("msg.value"));
1511 // Assume that address(this).balance cannot overflow.
1512 m_context.addAssertion(smt::symbolicUnknownConstraints(state().balance(state().thisAddress()) + k.currentValue(), TypeProvider::uint256()));
1513 state().addBalance(state().thisAddress(), k.currentValue());
1514
1515 if (encodeExternalCallsAsTrusted())
1516 {
1517 // If the contract has state variables that are addresses to other contracts,
1518 // we need to encode the fact that those contracts may have been called in between
1519 // transactions to _contract.
1520 //
1521 // We do that by adding nondet_interface constraints for those contracts,
1522 // in the last line of this if block.
1523 //
1524 // If there are state variables of container types like structs or arrays
1525 // that indirectly contain contract types, we havoc the state for simplicity,
1526 // in the first part of this block.
1527 // TODO: This could actually be supported.
1528 // For structs: simply collect the SMT expressions of all the indirect contract type members.
1529 // For arrays: more involved, needs to traverse the array symbolically and do the same for each contract.
1530 // For mappings: way more complicated if the element type is a contract.
1531 auto hasContractOrAddressSubType = [&](VariableDeclaration const* _var) -> bool {
1532 bool foundContract = false;
1533 solidity::util::BreadthFirstSearch<Type const*> bfs{{_var->type()}};
1534 bfs.run([&](auto _type, auto&& _addChild) {
1535 if (
1536 _type->category() == Type::Category::Address ||
1537 _type->category() == Type::Category::Contract
1538 )
1539 {
1540 foundContract = true;
1541 bfs.abort();
1542 }
1543 if (auto const* mapType = dynamic_cast<MappingType const*>(_type))
1544 _addChild(mapType->valueType());
1545 else if (auto const* arrayType = dynamic_cast<ArrayType const*>(_type))
1546 _addChild(arrayType->baseType());
1547 else if (auto const* structType = dynamic_cast<StructType const*>(_type))
1548 for (auto const& member: structType->nativeMembers(nullptr))
1549 _addChild(member.type);

Callers

nothing calls this directly

Calls 15

txTypeConstraintsMethod · 0.80
txFunctionConstraintsMethod · 0.80
newUniqueIdMethod · 0.80
txMemberMethod · 0.80
thisAddressMethod · 0.80
addBalanceMethod · 0.80
abortMethod · 0.80
valueTypeMethod · 0.80
newStorageMethod · 0.80
to_stringFunction · 0.50
addAssertionMethod · 0.45

Tested by

no test coverage detected