| 1049 | } |
| 1050 | |
| 1051 | std::string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) |
| 1052 | { |
| 1053 | Whiskers t(R"X( |
| 1054 | <?+cases>if iszero(lt(calldatasize(), 4)) |
| 1055 | { |
| 1056 | let selector := <shr224>(calldataload(0)) |
| 1057 | switch selector |
| 1058 | <#cases> |
| 1059 | case <functionSelector> |
| 1060 | { |
| 1061 | // <functionName> |
| 1062 | <delegatecallCheck> |
| 1063 | <externalFunction>() |
| 1064 | } |
| 1065 | </cases> |
| 1066 | default {} |
| 1067 | }</+cases> |
| 1068 | <?+receiveEther>if iszero(calldatasize()) { <receiveEther> }</+receiveEther> |
| 1069 | <fallback> |
| 1070 | )X"); |
| 1071 | t("shr224", m_utils.shiftRightFunction(224)); |
| 1072 | std::vector<std::map<std::string, std::string>> functions; |
| 1073 | for (auto const& function: _contract.interfaceFunctions()) |
| 1074 | { |
| 1075 | functions.emplace_back(); |
| 1076 | std::map<std::string, std::string>& templ = functions.back(); |
| 1077 | templ["functionSelector"] = "0x" + function.first.hex(); |
| 1078 | FunctionTypePointer const& type = function.second; |
| 1079 | templ["functionName"] = type->externalSignature(); |
| 1080 | std::string delegatecallCheck; |
| 1081 | if (_contract.isLibrary()) |
| 1082 | { |
| 1083 | solAssert(!type->isPayable(), ""); |
| 1084 | if (type->stateMutability() > StateMutability::View) |
| 1085 | // If the function is not a view function and is called without DELEGATECALL, |
| 1086 | // we revert. |
| 1087 | delegatecallCheck = |
| 1088 | "if iszero(called_via_delegatecall) { " + |
| 1089 | m_utils.revertReasonIfDebugFunction("Non-view function of library called without DELEGATECALL") + |
| 1090 | "() }"; |
| 1091 | } |
| 1092 | templ["delegatecallCheck"] = delegatecallCheck; |
| 1093 | |
| 1094 | templ["externalFunction"] = generateExternalFunction(_contract, *type); |
| 1095 | } |
| 1096 | t("cases", functions); |
| 1097 | FunctionDefinition const* etherReceiver = _contract.receiveFunction(); |
| 1098 | if (etherReceiver) |
| 1099 | { |
| 1100 | solAssert(!_contract.isLibrary(), ""); |
| 1101 | t("receiveEther", m_context.enqueueFunctionForCodeGeneration(*etherReceiver) + "() stop()"); |
| 1102 | } |
| 1103 | else |
| 1104 | t("receiveEther", ""); |
| 1105 | if (FunctionDefinition const* fallback = _contract.fallbackFunction()) |
| 1106 | { |
| 1107 | solAssert(!_contract.isLibrary(), ""); |
| 1108 | std::string fallbackCode; |
nothing calls this directly
no test coverage detected