Fix combination of delegatecall and ABIEncoderV2.

We can set the flag to false for bare delegatecall, because we always
send a memory string and never a storage reference.
This commit is contained in:
chriseth 2019-02-18 18:30:19 +01:00
parent 55c4131a03
commit d5791fef41
3 changed files with 26 additions and 18 deletions

View File

@ -8,6 +8,7 @@ Compiler Features:
Bugfixes: Bugfixes:
* ABIEncoderV2: Fix internal error related to bare delegatecall.
* ABIEncoderV2: Fix internal error related to mappings as library parameters. * ABIEncoderV2: Fix internal error related to mappings as library parameters.
* Yul: Properly detect name clashes with functions before their declaration. * Yul: Properly detect name clashes with functions before their declaration.

View File

@ -1967,12 +1967,13 @@ void ExpressionCompiler::appendExternalFunctionCall(
// If the function takes arbitrary parameters or is a bare call, copy dynamic length data in place. // 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 // Move arguments to memory, will not update the free memory pointer (but will update the memory
// pointer on the stack). // pointer on the stack).
bool encodeForLibraryCall = funKind == FunctionType::Kind::DelegateCall;
utils().encodeToMemory( utils().encodeToMemory(
argumentTypes, argumentTypes,
parameterTypes, parameterTypes,
_functionType.padArguments(), _functionType.padArguments(),
_functionType.takesArbitraryParameters() || _functionType.isBareCall(), _functionType.takesArbitraryParameters() || _functionType.isBareCall(),
isDelegateCall encodeForLibraryCall
); );
// Stack now: // Stack now:

View File

@ -4440,23 +4440,29 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall)
} }
} }
)**"; )**";
compileAndRun(sourceCode, 0, "Receiver");
u160 const c_receiverAddress = m_contractAddress; for (auto v2: {false, true})
compileAndRun(sourceCode, 50, "Sender"); {
u160 const c_senderAddress = m_contractAddress; string source = (v2 ? "pragma experimental ABIEncoderV2;\n" : "") + string(sourceCode);
BOOST_CHECK(m_sender != c_senderAddress); // just for sanity
ABI_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress), encodeArgs()); compileAndRun(source, 0, "Receiver");
ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(23))); u160 const c_receiverAddress = m_contractAddress;
ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender))); compileAndRun(source, 50, "Sender");
ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(11))); u160 const c_senderAddress = m_contractAddress;
m_contractAddress = c_receiverAddress; BOOST_CHECK(m_sender != c_senderAddress); // just for sanity
ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(0))); ABI_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress), encodeArgs());
ABI_CHECK(callContractFunction("sender()"), encodeArgs(u256(0))); ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(23)));
ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(0))); ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender)));
BOOST_CHECK(storageEmpty(c_receiverAddress)); ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(11)));
BOOST_CHECK(!storageEmpty(c_senderAddress)); m_contractAddress = c_receiverAddress;
BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(0)));
BOOST_CHECK_EQUAL(balanceAt(c_senderAddress), 50 + 11); 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) BOOST_AUTO_TEST_CASE(generic_staticcall)