mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Only generate sort/search code when interface functions exist
This commit is contained in:
committed by
chriseth
parent
7d3727bbf7
commit
1b8570f829
@@ -331,6 +331,25 @@ void ContractCompiler::appendInternalSelector(
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Helper function to check if any function is payable
|
||||
bool hasPayableFunctions(ContractDefinition const& _contract)
|
||||
{
|
||||
FunctionDefinition const* fallback = _contract.fallbackFunction();
|
||||
if (fallback && fallback->isPayable())
|
||||
return true;
|
||||
|
||||
for (auto const& it: _contract.interfaceFunctions())
|
||||
if (it.second->isPayable())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contract)
|
||||
{
|
||||
map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions();
|
||||
@@ -342,6 +361,15 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
||||
}
|
||||
|
||||
FunctionDefinition const* fallback = _contract.fallbackFunction();
|
||||
solAssert(!_contract.isLibrary() || !fallback, "Libraries can't have fallback functions");
|
||||
|
||||
bool needToAddCallvalueCheck = true;
|
||||
if (!hasPayableFunctions(_contract) && !interfaceFunctions.empty() && !_contract.isLibrary())
|
||||
{
|
||||
appendCallValueCheck();
|
||||
needToAddCallvalueCheck = false;
|
||||
}
|
||||
|
||||
eth::AssemblyItem notFound = m_context.newTag();
|
||||
// directly jump to fallback if the data is too short to contain a function selector
|
||||
// also guards against short data
|
||||
@@ -350,23 +378,26 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
||||
|
||||
// retrieve the function signature hash from the calldata
|
||||
if (!interfaceFunctions.empty())
|
||||
{
|
||||
CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true);
|
||||
|
||||
// stack now is: <can-call-non-view-functions>? <funhash>
|
||||
vector<FixedHash<4>> sortedIDs;
|
||||
for (auto const& it: interfaceFunctions)
|
||||
{
|
||||
callDataUnpackerEntryPoints.insert(std::make_pair(it.first, m_context.newTag()));
|
||||
sortedIDs.emplace_back(it.first);
|
||||
// stack now is: <can-call-non-view-functions>? <funhash>
|
||||
vector<FixedHash<4>> sortedIDs;
|
||||
for (auto const& it: interfaceFunctions)
|
||||
{
|
||||
callDataUnpackerEntryPoints.emplace(it.first, m_context.newTag());
|
||||
sortedIDs.emplace_back(it.first);
|
||||
}
|
||||
std::sort(sortedIDs.begin(), sortedIDs.end());
|
||||
appendInternalSelector(callDataUnpackerEntryPoints, sortedIDs, notFound, m_optimise_runs);
|
||||
}
|
||||
std::sort(sortedIDs.begin(), sortedIDs.end());
|
||||
appendInternalSelector(callDataUnpackerEntryPoints, sortedIDs, notFound, m_optimise_runs);
|
||||
|
||||
m_context << notFound;
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
solAssert(!_contract.isLibrary(), "");
|
||||
if (!fallback->isPayable())
|
||||
if (!fallback->isPayable() && needToAddCallvalueCheck)
|
||||
appendCallValueCheck();
|
||||
|
||||
solAssert(fallback->isFallback(), "");
|
||||
@@ -396,7 +427,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
||||
m_context.setStackOffset(0);
|
||||
// We have to allow this for libraries, because value of the previous
|
||||
// call is still visible in the delegatecall.
|
||||
if (!functionType->isPayable() && !_contract.isLibrary())
|
||||
if (!functionType->isPayable() && !_contract.isLibrary() && needToAddCallvalueCheck)
|
||||
appendCallValueCheck();
|
||||
|
||||
// Return tag is used to jump out of the function.
|
||||
|
||||
Reference in New Issue
Block a user