diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libsolidity/codegen/ContractCompiler.cpp | 4 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 17 |
3 files changed, 21 insertions, 1 deletions
diff --git a/Changelog.md b/Changelog.md index d61ac7c8..e18d8507 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,6 @@ ### 0.4.2 + * Code Generator: Fix library functions being called from payable functions. * Type Checker: Fixed a crash about invalid array types. ### 0.4.1 (2016-09-09) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 33571bc0..18b42fce 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -263,7 +263,9 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration()); m_context << callDataUnpackerEntryPoints.at(it.first); - if (!functionType->isPayable()) + // We have to allow this for libraries, because value of the previous + // call is still visible in the delegatecall. + if (!functionType->isPayable() && !_contract.isLibrary()) { // Throw if function is not payable but call contained ether. m_context << Instruction::CALLVALUE; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 7ee5700c..3c949e9a 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7144,6 +7144,23 @@ BOOST_AUTO_TEST_CASE(payable_function) BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27); } +BOOST_AUTO_TEST_CASE(payable_function_calls_library) +{ + char const* sourceCode = R"( + library L { + function f() returns (uint) { return 7; } + } + contract C { + function f() payable returns (uint) { + return L.f(); + } + } + )"; + compileAndRun(sourceCode, 0, "L"); + compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}}); + BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7))); +} + BOOST_AUTO_TEST_CASE(non_payable_throw) { char const* sourceCode = R"( |