diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 252ddffa7..755110c27 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -730,6 +730,16 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) break; } + case FunctionType::Kind::Revert: + { + solAssert(arguments.size() == parameterTypes.size(), ""); + if (arguments.empty()) + m_code << "revert(0, 0)\n"; + else + solUnimplementedAssert(false, ""); + + break; + } // Array creation using new case FunctionType::Kind::ObjectCreation: { @@ -908,6 +918,34 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) break; } + case FunctionType::Kind::Send: + case FunctionType::Kind::Transfer: + { + solAssert(arguments.size() == 1 && parameterTypes.size() == 1, ""); + string address{IRVariable(_functionCall.expression()).part("address").name()}; + string value{expressionAsType(*arguments[0], *(parameterTypes[0]))}; + Whiskers templ(R"( + let := 0 + if iszero() { := } + let := call(,
, , 0, 0, 0, 0) + + if iszero() { () } + + )"); + templ("gas", m_context.newYulVariable()); + templ("callStipend", toString(evmasm::GasCosts::callStipend)); + templ("address", address); + templ("value", value); + if (functionType->kind() == FunctionType::Kind::Transfer) + templ("success", m_context.newYulVariable()); + else + templ("success", IRVariable(_functionCall).commaSeparatedList()); + templ("isTransfer", functionType->kind() == FunctionType::Kind::Transfer); + templ("forwardingRevert", m_utils.forwardingRevertFunction()); + m_code << templ.render(); + + break; + } default: solUnimplemented("FunctionKind " + toString(static_cast(functionType->kind())) + " not yet implemented"); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 153d6a8f4..83e7ef95d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -50,6 +50,7 @@ using namespace solidity::langutil; #define ALSO_VIA_YUL(CODE) \ { \ { CODE } \ + reset(); \ m_compileViaYul = true; \ { CODE } \ } @@ -1058,11 +1059,13 @@ BOOST_AUTO_TEST_CASE(send_ether) } } )"; - u256 amount(130); - compileAndRun(sourceCode, amount + 1); - u160 address(23); - ABI_CHECK(callContractFunction("a(address,uint256)", address, amount), encodeArgs(1)); - BOOST_CHECK_EQUAL(balanceAt(address), amount); + ALSO_VIA_YUL( + u256 amount(250); + compileAndRun(sourceCode, amount + 1); + u160 address(23); + ABI_CHECK(callContractFunction("a(address,uint256)", address, amount), encodeArgs(1)); + BOOST_CHECK_EQUAL(balanceAt(address), amount); + ) } BOOST_AUTO_TEST_CASE(transfer_ether) @@ -1088,17 +1091,19 @@ BOOST_AUTO_TEST_CASE(transfer_ether) } } )"; - compileAndRun(sourceCode, 0, "B"); - u160 const nonPayableRecipient = m_contractAddress; - compileAndRun(sourceCode, 0, "C"); - u160 const oogRecipient = m_contractAddress; - compileAndRun(sourceCode, 20, "A"); - u160 payableRecipient(23); - ABI_CHECK(callContractFunction("a(address,uint256)", payableRecipient, 10), encodeArgs(10)); - BOOST_CHECK_EQUAL(balanceAt(payableRecipient), 10); - BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); - ABI_CHECK(callContractFunction("b(address,uint256)", nonPayableRecipient, 10), encodeArgs()); - ABI_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10), encodeArgs()); + ALSO_VIA_YUL( + compileAndRun(sourceCode, 0, "B"); + u160 const nonPayableRecipient = m_contractAddress; + compileAndRun(sourceCode, 0, "C"); + u160 const oogRecipient = m_contractAddress; + compileAndRun(sourceCode, 20, "A"); + u160 payableRecipient(23); + ABI_CHECK(callContractFunction("a(address,uint256)", payableRecipient, 10), encodeArgs(10)); + BOOST_CHECK_EQUAL(balanceAt(payableRecipient), 10); + BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); + ABI_CHECK(callContractFunction("b(address,uint256)", nonPayableRecipient, 10), encodeArgs()); + ABI_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10), encodeArgs()); + ) } BOOST_AUTO_TEST_CASE(uncalled_blockhash)