Include revert strings in IR

This commit is contained in:
Alex Beregszaszi 2020-11-27 20:26:13 +00:00 committed by chriseth
parent f9bfceccd1
commit 7c7fd22062
6 changed files with 20 additions and 6 deletions

View File

@ -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();
}

View File

@ -2364,7 +2364,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
}
Whiskers templ(R"(
if iszero(extcodesize(<address>)) { revert(0, 0) }
if iszero(extcodesize(<address>)) { <revertNoCode> }
// storage for arguments and returned data
let <pos> := <freeMemory>
@ -2389,6 +2389,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
<?+retVars> <retVars> := </+retVars> <abiDecode>(<pos>, add(<pos>, <returnSize>))
}
)");
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)

View File

@ -7,6 +7,7 @@ contract C {
}
// ====
// EVMVersion: >=byzantium
// compileViaYul: also
// revertStrings: debug
// ----
// g() -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code"

View File

@ -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"

View File

@ -9,6 +9,7 @@ contract C {
}
}
// ====
// compileViaYul: also
// EVMVersion: >=byzantium
// revertStrings: debug
// ----

View File

@ -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"