diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index d18121f81..22b506291 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -795,7 +795,7 @@ string IRGenerator::deployCode(ContractDefinition const& _contract) string IRGenerator::callValueCheck() { - return "if callvalue() { revert(0, 0) }"; + return "if callvalue() { " + m_context.revertReasonIfDebug("Ether sent to non-payable function") + " }"; } string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) @@ -839,8 +839,10 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) if (type->stateMutability() > StateMutability::View) // If the function is not a view function and is called without DELEGATECALL, // we revert. - // TODO add revert message. - delegatecallCheck = "if iszero(called_via_delegatecall) { revert(0, 0) }"; + delegatecallCheck = + "if iszero(called_via_delegatecall) { " + + m_context.revertReasonIfDebug("Non-view function of library called without DELEGATECALL") + + " }"; } templ["delegatecallCheck"] = delegatecallCheck; templ["callValueCheck"] = (type->isPayable() || _contract.isLibrary()) ? "" : callValueCheck(); @@ -864,7 +866,8 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) templ["abiEncode"] = abiFunctions.tupleEncoder(type->returnParameterTypes(), type->returnParameterTypes(), _contract.isLibrary()); } t("cases", functions); - if (FunctionDefinition const* etherReceiver = _contract.receiveFunction()) + FunctionDefinition const* etherReceiver = _contract.receiveFunction(); + if (etherReceiver) { solAssert(!_contract.isLibrary(), ""); t("receiveEther", m_context.enqueueFunctionForCodeGeneration(*etherReceiver) + "() stop()"); @@ -888,9 +891,15 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) } t("fallback", fallbackCode); + t("revertNoSignature", ""); } else - t("fallback", "revert(0, 0)"); + t( + "fallback", + etherReceiver ? + m_context.revertReasonIfDebug("Unknown signature and no fallback defined") : + m_context.revertReasonIfDebug("Contract does not have fallback nor receive functions") + ); return t.render(); } diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 2960992b1..7ad962473 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2364,7 +2364,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } Whiskers templ(R"( - if iszero(extcodesize(
)) { revert(0, 0) } + if iszero(extcodesize(
)) { } // storage for arguments and returned data let := @@ -2389,6 +2389,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( := (, add(, )) } )"); + templ("revertNoCode", m_context.revertReasonIfDebug("Target contract does not contain code")); templ("pos", m_context.newYulVariable()); templ("end", m_context.newYulVariable()); if (_functionCall.annotation().tryCall) diff --git a/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol b/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol index 110b1e50c..356a3f1d4 100644 --- a/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol +++ b/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol @@ -7,6 +7,7 @@ contract C { } // ==== // EVMVersion: >=byzantium +// compileViaYul: also // revertStrings: debug // ---- // g() -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/revertStrings/ether_non_payable_function.sol b/test/libsolidity/semanticTests/revertStrings/ether_non_payable_function.sol index ffaea6878..a5c6cefe7 100644 --- a/test/libsolidity/semanticTests/revertStrings/ether_non_payable_function.sol +++ b/test/libsolidity/semanticTests/revertStrings/ether_non_payable_function.sol @@ -4,6 +4,7 @@ contract C { // ==== // EVMVersion: >=byzantium // revertStrings: debug +// compileViaYul: also // ---- // f(), 1 ether -> FAILURE, hex"08c379a0", 0x20, 34, "Ether sent to non-payable functi", "on" // () -> FAILURE, hex"08c379a0", 0x20, 53, "Contract does not have fallback ", "nor receive functions" diff --git a/test/libsolidity/semanticTests/revertStrings/library_non_view_call.sol b/test/libsolidity/semanticTests/revertStrings/library_non_view_call.sol index 1a079a04a..1439acfbf 100644 --- a/test/libsolidity/semanticTests/revertStrings/library_non_view_call.sol +++ b/test/libsolidity/semanticTests/revertStrings/library_non_view_call.sol @@ -9,6 +9,7 @@ contract C { } } // ==== +// compileViaYul: also // EVMVersion: >=byzantium // revertStrings: debug // ---- diff --git a/test/libsolidity/semanticTests/revertStrings/unknown_sig_no_fallback.sol b/test/libsolidity/semanticTests/revertStrings/unknown_sig_no_fallback.sol index 62b245885..6fab690a0 100644 --- a/test/libsolidity/semanticTests/revertStrings/unknown_sig_no_fallback.sol +++ b/test/libsolidity/semanticTests/revertStrings/unknown_sig_no_fallback.sol @@ -4,5 +4,6 @@ contract A { // ==== // EVMVersion: >=byzantium // revertStrings: debug +// compileViaYul: also // ---- // (): hex"00" -> FAILURE, hex"08c379a0", 0x20, 41, "Unknown signature and no fallbac", "k defined"