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:
* 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.

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.
// 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:

View File

@ -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)