mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add return data to bare calls.
This commit is contained in:
@@ -617,11 +617,11 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons
|
||||
if (isAddress())
|
||||
return {
|
||||
{"balance", make_shared<IntegerType>(256)},
|
||||
{"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)},
|
||||
{"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)},
|
||||
{"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareDelegateCall, false)},
|
||||
{"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)},
|
||||
{"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)},
|
||||
{"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false)},
|
||||
{"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)},
|
||||
{"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)},
|
||||
{"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)},
|
||||
{"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)}
|
||||
};
|
||||
else
|
||||
@@ -2492,7 +2492,14 @@ TypePointers FunctionType::returnParameterTypesWithoutDynamicTypes() const
|
||||
{
|
||||
TypePointers returnParameterTypes = m_returnParameterTypes;
|
||||
|
||||
if (m_kind == Kind::External || m_kind == Kind::DelegateCall)
|
||||
if (
|
||||
m_kind == Kind::External ||
|
||||
m_kind == Kind::DelegateCall ||
|
||||
m_kind == Kind::BareCall ||
|
||||
m_kind == Kind::BareCallCode ||
|
||||
m_kind == Kind::BareDelegateCall ||
|
||||
m_kind == Kind::BareStaticCall
|
||||
)
|
||||
for (auto& param: returnParameterTypes)
|
||||
if (param->isDynamicallySized() && !param->dataStoredIn(DataLocation::Storage))
|
||||
param = make_shared<InaccessibleDynamicType>();
|
||||
|
||||
@@ -1827,33 +1827,34 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
||||
auto funKind = _functionType.kind();
|
||||
|
||||
solAssert(funKind != FunctionType::Kind::BareStaticCall || m_context.evmVersion().hasStaticCall(), "");
|
||||
|
||||
bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall;
|
||||
|
||||
bool returnSuccessConditionAndReturndata = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall;
|
||||
bool isCallCode = funKind == FunctionType::Kind::BareCallCode;
|
||||
bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
|
||||
bool useStaticCall = funKind == FunctionType::Kind::BareStaticCall || (_functionType.stateMutability() <= StateMutability::View && m_context.evmVersion().hasStaticCall());
|
||||
|
||||
bool haveReturndatacopy = m_context.evmVersion().supportsReturndata();
|
||||
unsigned retSize = 0;
|
||||
TypePointers returnTypes;
|
||||
if (returnSuccessCondition)
|
||||
retSize = 0; // return value actually is success condition
|
||||
else if (haveReturndatacopy)
|
||||
returnTypes = _functionType.returnParameterTypes();
|
||||
else
|
||||
returnTypes = _functionType.returnParameterTypesWithoutDynamicTypes();
|
||||
|
||||
bool dynamicReturnSize = false;
|
||||
for (auto const& retType: returnTypes)
|
||||
if (retType->isDynamicallyEncoded())
|
||||
{
|
||||
solAssert(haveReturndatacopy, "");
|
||||
dynamicReturnSize = true;
|
||||
retSize = 0;
|
||||
break;
|
||||
}
|
||||
TypePointers returnTypes;
|
||||
if (!returnSuccessConditionAndReturndata)
|
||||
{
|
||||
if (haveReturndatacopy)
|
||||
returnTypes = _functionType.returnParameterTypes();
|
||||
else
|
||||
retSize += retType->calldataEncodedSize();
|
||||
returnTypes = _functionType.returnParameterTypesWithoutDynamicTypes();
|
||||
|
||||
for (auto const& retType: returnTypes)
|
||||
if (retType->isDynamicallyEncoded())
|
||||
{
|
||||
solAssert(haveReturndatacopy, "");
|
||||
dynamicReturnSize = true;
|
||||
retSize = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
retSize += retType->calldataEncodedSize();
|
||||
}
|
||||
|
||||
// Evaluate arguments.
|
||||
TypePointers argumentTypes;
|
||||
@@ -1997,7 +1998,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
||||
(_functionType.gasSet() ? 1 : 0) +
|
||||
(!_functionType.isBareCall() ? 1 : 0);
|
||||
|
||||
if (returnSuccessCondition)
|
||||
if (returnSuccessConditionAndReturndata)
|
||||
m_context << swapInstruction(remainsSize);
|
||||
else
|
||||
{
|
||||
@@ -2008,9 +2009,31 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
||||
|
||||
utils().popStackSlots(remainsSize);
|
||||
|
||||
if (returnSuccessCondition)
|
||||
if (returnSuccessConditionAndReturndata)
|
||||
{
|
||||
// already there
|
||||
// success condition is already there
|
||||
// The return parameter types can be empty, when this function is used as
|
||||
// an internal helper function e.g. for ``send`` and ``transfer``. In that
|
||||
// case we're only interested in the success condition, not the return data.
|
||||
if (!_functionType.returnParameterTypes().empty())
|
||||
{
|
||||
if (haveReturndatacopy)
|
||||
{
|
||||
m_context << Instruction::RETURNDATASIZE;
|
||||
m_context.appendInlineAssembly(R"({
|
||||
switch v case 0 {
|
||||
v := 0x60
|
||||
} default {
|
||||
v := mload(0x40)
|
||||
mstore(0x40, add(v, and(add(returndatasize(), 0x3f), not(0x1f))))
|
||||
mstore(v, returndatasize())
|
||||
returndatacopy(add(v, 0x20), 0, returndatasize())
|
||||
}
|
||||
})", {"v"});
|
||||
}
|
||||
else
|
||||
utils().pushZeroPointer();
|
||||
}
|
||||
}
|
||||
else if (funKind == FunctionType::Kind::RIPEMD160)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user