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(
+retVars> := +retVars> (, 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"