Merge pull request #10424 from ethereum/ir-modifiers

Add unimplemented assert for modifiers in the IR
This commit is contained in:
Kamil Śliwak 2020-11-27 20:06:54 +01:00 committed by GitHub
commit fb01884e69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 43 deletions

View File

@ -249,6 +249,7 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
{ {
string functionName = IRNames::function(_function); string functionName = IRNames::function(_function);
return m_context.functionCollector().createFunction(functionName, [&]() { return m_context.functionCollector().createFunction(functionName, [&]() {
solUnimplementedAssert(_function.modifiers().empty(), "Modifiers not implemented yet.");
Whiskers t(R"( Whiskers t(R"(
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> { function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
<initReturnVariables> <initReturnVariables>
@ -521,8 +522,16 @@ void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contra
)"); )");
vector<string> params; vector<string> params;
if (contract->constructor()) if (contract->constructor())
{
for (auto const& modifierInvocation: contract->constructor()->modifiers())
// This can be ContractDefinition too for super arguments. That is supported.
solUnimplementedAssert(
!dynamic_cast<ModifierDefinition const*>(modifierInvocation->name()->annotation().referencedDeclaration),
"Modifiers not implemented yet."
);
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters()) for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
params += m_context.addLocalVariable(*varDecl).stackSlots(); params += m_context.addLocalVariable(*varDecl).stackSlots();
}
t("params", joinHumanReadable(params)); t("params", joinHumanReadable(params));
vector<string> baseParams = listAllParams(baseConstructorParams); vector<string> baseParams = listAllParams(baseConstructorParams);
t("baseParams", joinHumanReadable(baseParams)); t("baseParams", joinHumanReadable(baseParams));

View File

@ -4481,30 +4481,6 @@ BOOST_AUTO_TEST_CASE(non_payable_throw)
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
} }
BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier)
{
char const* sourceCode = R"(
contract C {
modifier tryCircumvent {
if (false) _; // avoid the function, we should still not accept ether
}
function f() tryCircumvent public returns (uint) {
return msgvalue();
}
function msgvalue() internal returns (uint) {
return msg.value;
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs());
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
)
}
BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
{ {
// This tests that memory resize for return values is not paid during the call, which would // This tests that memory resize for return values is not paid during the call, which would

View File

@ -11,10 +11,23 @@ contract C {
function f() public m returns (bool) { function f() public m returns (bool) {
return true; return true;
} }
modifier n {
uint256 a = 1;
assembly {
a := 2
}
if (a != 2)
_;
revert();
}
function g() public n returns (bool) {
// This statement should never execute.
return true;
}
} }
// ====
// compileViaYul: also
// compileToEwasm: also
// ---- // ----
// f() -> true // f() -> true
// g() -> FAILURE

View File

@ -3,7 +3,8 @@ contract C {
modifier run() { modifier run() {
for (uint256 i = 0; i < 10; i++) { for (uint256 i = 0; i < 10; i++) {
_; _;
break; if (i == 1)
break;
} }
} }
@ -13,10 +14,7 @@ contract C {
x = t; x = t;
} }
} }
// ====
// compileViaYul: also
// compileToEwasm: also
// ---- // ----
// x() -> 0 // x() -> 0
// f() -> // f() ->
// x() -> 1 // x() -> 2

View File

@ -1,22 +1,21 @@
contract C { contract C {
uint256 public x; uint256 public x;
modifier run() { modifier m() {
for (uint256 i = 0; i < 10; i++) { for (uint256 i = 0; i < 10; i++) {
_; _;
break; ++x;
return;
} }
} }
function f() public run { function f() public m m m returns (uint) {
uint256 k = x; for (uint256 i = 0; i < 10; i++) {
uint256 t = k + 1; ++x;
x = t; return 42;
}
} }
} }
// ====
// compileViaYul: also
// compileToEwasm: also
// ---- // ----
// x() -> 0 // x() -> 0
// f() -> // f() -> 42
// x() -> 1 // x() -> 4

View File

@ -0,0 +1,18 @@
contract C {
modifier tryCircumvent {
if (false) _; // avoid the function, we should still not accept ether
}
function f() tryCircumvent public returns (uint) {
return msgvalue();
}
function msgvalue() internal returns (uint) {
return msg.value;
}
// TODO: remove this helper function once isoltest supports balance checking
function balance() external returns (uint) {
return address(this).balance;
}
}
// ----
// f(), 27 wei -> FAILURE
// balance() -> 0