Merge pull request #12437 from ethereum/encodeCallForDeclarations

abi.encodeCall for declarations.
This commit is contained in:
chriseth
2021-12-29 18:40:18 +01:00
committed by GitHub
8 changed files with 241 additions and 72 deletions
+22 -3
View File
@@ -2122,16 +2122,35 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
return;
}
if (functionPointerType->kind() != FunctionType::Kind::External)
if (
functionPointerType->kind() != FunctionType::Kind::External &&
functionPointerType->kind() != FunctionType::Kind::Declaration
)
{
string msg = "Function must be \"public\" or \"external\".";
string msg = "Expected regular external function type, or external view on public function.";
if (functionPointerType->kind() == FunctionType::Kind::Internal)
msg += " Provided internal function.";
else if (functionPointerType->kind() == FunctionType::Kind::DelegateCall)
msg += " Cannot use library functions for abi.encodeCall.";
else if (functionPointerType->kind() == FunctionType::Kind::Creation)
msg += " Provided creation function.";
else
msg += " Cannot use special function.";
SecondarySourceLocation ssl{};
if (functionPointerType->hasDeclaration())
{
ssl.append("Function is declared here:", functionPointerType->declaration().location());
if (functionPointerType->declaration().scope() == m_currentContract)
if (
functionPointerType->declaration().visibility() == Visibility::Public &&
functionPointerType->declaration().scope() == m_currentContract
)
msg += " Did you forget to prefix \"this.\"?";
else if (contains(
m_currentContract->annotation().linearizedBaseContracts,
functionPointerType->declaration().scope()
) && functionPointerType->declaration().scope() != m_currentContract)
msg += " Functions from base contracts have to be external.";
}
m_errorReporter.typeError(3509_error, arguments[0]->location(), ssl, msg);
+14 -4
View File
@@ -1255,7 +1255,6 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
auto const functionPtr = dynamic_cast<FunctionTypePointer>(arguments[0]->annotation().type);
solAssert(functionPtr);
solAssert(functionPtr->sizeOnStack() == 2);
// Account for tuples with one component which become that component
if (auto const tupleType = dynamic_cast<TupleType const*>(arguments[1]->annotation().type))
@@ -1330,9 +1329,20 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
}
else if (function.kind() == FunctionType::Kind::ABIEncodeCall)
{
// stack: <memory pointer> <functionPointer>
// Extract selector from the stack
m_context << Instruction::SWAP1 << Instruction::POP;
auto const& funType = dynamic_cast<FunctionType const&>(*selectorType);
if (funType.kind() == FunctionType::Kind::Declaration)
{
solAssert(funType.hasDeclaration());
solAssert(selectorType->sizeOnStack() == 0);
m_context << funType.externalIdentifier();
}
else
{
solAssert(selectorType->sizeOnStack() == 2);
// stack: <memory pointer> <functionPointer>
// Extract selector from the stack
m_context << Instruction::SWAP1 << Instruction::POP;
}
// Conversion will be done below
dataOnStack = TypeProvider::uint(32);
}
@@ -1150,10 +1150,21 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
}
if (functionType->kind() == FunctionType::Kind::ABIEncodeCall)
selector = convert(
IRVariable(*arguments[0]).part("functionSelector"),
*TypeProvider::fixedBytes(4)
).name();
{
auto const& selectorType = dynamic_cast<FunctionType const&>(type(*arguments.front()));
if (selectorType.kind() == FunctionType::Kind::Declaration)
{
solAssert(selectorType.hasDeclaration());
selector = formatNumber(selectorType.externalIdentifier() << (256 - 32));
}
else
{
selector = convert(
IRVariable(*arguments[0]).part("functionSelector"),
*TypeProvider::fixedBytes(4)
).name();
}
}
else if (functionType->kind() == FunctionType::Kind::ABIEncodeWithSignature)
{
// hash the signature