diff --git a/Changelog.md b/Changelog.md index c1fa23cdf..fbaddb36f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: + * ABIEncoderV2: Fix internal error related to bare delegatecall. * ABIEncoderV2: Fix internal error related to mappings as library parameters. * Yul: Properly detect name clashes with functions before their declaration. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 45c9d63ac..23522a203 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1967,12 +1967,13 @@ void ExpressionCompiler::appendExternalFunctionCall( // If the function takes arbitrary parameters or is a bare call, copy dynamic length data in place. // Move arguments to memory, will not update the free memory pointer (but will update the memory // pointer on the stack). + bool encodeForLibraryCall = funKind == FunctionType::Kind::DelegateCall; utils().encodeToMemory( argumentTypes, parameterTypes, _functionType.padArguments(), _functionType.takesArbitraryParameters() || _functionType.isBareCall(), - isDelegateCall + encodeForLibraryCall ); // Stack now: diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index c8fbbff7b..416990adf 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4440,23 +4440,29 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall) } } )**"; - compileAndRun(sourceCode, 0, "Receiver"); - u160 const c_receiverAddress = m_contractAddress; - compileAndRun(sourceCode, 50, "Sender"); - u160 const c_senderAddress = m_contractAddress; - BOOST_CHECK(m_sender != c_senderAddress); // just for sanity - ABI_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress), encodeArgs()); - ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(23))); - ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender))); - ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(11))); - m_contractAddress = c_receiverAddress; - ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("sender()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(0))); - BOOST_CHECK(storageEmpty(c_receiverAddress)); - BOOST_CHECK(!storageEmpty(c_senderAddress)); - BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); - BOOST_CHECK_EQUAL(balanceAt(c_senderAddress), 50 + 11); + + for (auto v2: {false, true}) + { + string source = (v2 ? "pragma experimental ABIEncoderV2;\n" : "") + string(sourceCode); + + compileAndRun(source, 0, "Receiver"); + u160 const c_receiverAddress = m_contractAddress; + compileAndRun(source, 50, "Sender"); + u160 const c_senderAddress = m_contractAddress; + BOOST_CHECK(m_sender != c_senderAddress); // just for sanity + ABI_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress), encodeArgs()); + ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(23))); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender))); + ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(11))); + m_contractAddress = c_receiverAddress; + ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(0))); + BOOST_CHECK(storageEmpty(c_receiverAddress)); + BOOST_CHECK(!storageEmpty(c_senderAddress)); + BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); + BOOST_CHECK_EQUAL(balanceAt(c_senderAddress), 50 + 11); + } } BOOST_AUTO_TEST_CASE(generic_staticcall)