|
|
@ -174,6 +174,16 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) |
|
|
|
map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.getInterfaceFunctions(); |
|
|
|
map<FixedHash<4>, const eth::AssemblyItem> callDataUnpackerEntryPoints; |
|
|
|
|
|
|
|
FunctionDefinition const* fallback = _contract.getFallbackFunction(); |
|
|
|
eth::AssemblyItem notFound = m_context.newTag(); |
|
|
|
// shortcut messages without data if we have many functions in order to be able to receive
|
|
|
|
// ether with constant gas
|
|
|
|
if (interfaceFunctions.size() > 5 || fallback) |
|
|
|
{ |
|
|
|
m_context << eth::Instruction::CALLDATASIZE << eth::Instruction::ISZERO; |
|
|
|
m_context.appendConditionalJumpTo(notFound); |
|
|
|
} |
|
|
|
|
|
|
|
// retrieve the function signature hash from the calldata
|
|
|
|
if (!interfaceFunctions.empty()) |
|
|
|
CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true); |
|
|
@ -185,7 +195,10 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) |
|
|
|
m_context << eth::dupInstruction(1) << u256(FixedHash<4>::Arith(it.first)) << eth::Instruction::EQ; |
|
|
|
m_context.appendConditionalJumpTo(callDataUnpackerEntryPoints.at(it.first)); |
|
|
|
} |
|
|
|
if (FunctionDefinition const* fallback = _contract.getFallbackFunction()) |
|
|
|
m_context.appendJumpTo(notFound); |
|
|
|
|
|
|
|
m_context << notFound; |
|
|
|
if (fallback) |
|
|
|
{ |
|
|
|
eth::AssemblyItem returnTag = m_context.pushNewTag(); |
|
|
|
fallback->accept(*this); |
|
|
@ -194,6 +207,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) |
|
|
|
} |
|
|
|
else |
|
|
|
m_context << eth::Instruction::STOP; // function not found
|
|
|
|
|
|
|
|
for (auto const& it: interfaceFunctions) |
|
|
|
{ |
|
|
|
FunctionTypePointer const& functionType = it.second; |
|
|
|