mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add `staticcall to address`.
This commit is contained in:
committed by
chriseth
parent
2ed793c4d3
commit
7ca0aaaf6f
@@ -1359,7 +1359,8 @@ void TypeChecker::endVisit(ExpressionStatement const& _statement)
|
||||
if (
|
||||
kind == FunctionType::Kind::BareCall ||
|
||||
kind == FunctionType::Kind::BareCallCode ||
|
||||
kind == FunctionType::Kind::BareDelegateCall
|
||||
kind == FunctionType::Kind::BareDelegateCall ||
|
||||
kind == FunctionType::Kind::BareStaticCall
|
||||
)
|
||||
m_errorReporter.warning(_statement.location(), "Return value of low-level calls not used.");
|
||||
else if (kind == FunctionType::Kind::Send)
|
||||
@@ -1754,6 +1755,9 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (functionType->kind() == FunctionType::Kind::BareStaticCall && !m_evmVersion.hasStaticCall())
|
||||
m_errorReporter.typeError(_functionCall.location(), "\"staticcall\" is not supported by the VM version.");
|
||||
|
||||
auto returnTypes =
|
||||
allowDynamicTypes ?
|
||||
functionType->returnParameterTypes() :
|
||||
@@ -1834,7 +1838,8 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
else if (
|
||||
functionType->kind() == FunctionType::Kind::BareCall ||
|
||||
functionType->kind() == FunctionType::Kind::BareCallCode ||
|
||||
functionType->kind() == FunctionType::Kind::BareDelegateCall
|
||||
functionType->kind() == FunctionType::Kind::BareDelegateCall ||
|
||||
functionType->kind() == FunctionType::Kind::BareStaticCall
|
||||
)
|
||||
{
|
||||
if (arguments.empty())
|
||||
@@ -1882,7 +1887,8 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
if (
|
||||
functionType->kind() == FunctionType::Kind::BareCall ||
|
||||
functionType->kind() == FunctionType::Kind::BareCallCode ||
|
||||
functionType->kind() == FunctionType::Kind::BareDelegateCall
|
||||
functionType->kind() == FunctionType::Kind::BareDelegateCall ||
|
||||
functionType->kind() == FunctionType::Kind::BareStaticCall
|
||||
)
|
||||
msg += " This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it.";
|
||||
else if (
|
||||
|
||||
@@ -621,6 +621,7 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons
|
||||
{"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)},
|
||||
{"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)},
|
||||
{"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)}
|
||||
};
|
||||
else
|
||||
@@ -2522,6 +2523,7 @@ string FunctionType::richIdentifier() const
|
||||
case Kind::BareCall: id += "barecall"; break;
|
||||
case Kind::BareCallCode: id += "barecallcode"; break;
|
||||
case Kind::BareDelegateCall: id += "baredelegatecall"; break;
|
||||
case Kind::BareStaticCall: id += "barestaticcall"; break;
|
||||
case Kind::Creation: id += "creation"; break;
|
||||
case Kind::Send: id += "send"; break;
|
||||
case Kind::Transfer: id += "transfer"; break;
|
||||
@@ -2705,6 +2707,7 @@ unsigned FunctionType::sizeOnStack() const
|
||||
case Kind::BareCall:
|
||||
case Kind::BareCallCode:
|
||||
case Kind::BareDelegateCall:
|
||||
case Kind::BareStaticCall:
|
||||
case Kind::Internal:
|
||||
case Kind::ArrayPush:
|
||||
case Kind::ArrayPop:
|
||||
@@ -2772,6 +2775,7 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
|
||||
case Kind::BareCall:
|
||||
case Kind::BareCallCode:
|
||||
case Kind::BareDelegateCall:
|
||||
case Kind::BareStaticCall:
|
||||
{
|
||||
MemberList::MemberMap members;
|
||||
if (m_kind == Kind::External)
|
||||
@@ -2911,6 +2915,7 @@ bool FunctionType::isBareCall() const
|
||||
case Kind::BareCall:
|
||||
case Kind::BareCallCode:
|
||||
case Kind::BareDelegateCall:
|
||||
case Kind::BareStaticCall:
|
||||
case Kind::ECRecover:
|
||||
case Kind::SHA256:
|
||||
case Kind::RIPEMD160:
|
||||
@@ -3054,6 +3059,7 @@ bool FunctionType::padArguments() const
|
||||
case Kind::BareCall:
|
||||
case Kind::BareCallCode:
|
||||
case Kind::BareDelegateCall:
|
||||
case Kind::BareStaticCall:
|
||||
case Kind::SHA256:
|
||||
case Kind::RIPEMD160:
|
||||
case Kind::KECCAK256:
|
||||
|
||||
@@ -904,6 +904,7 @@ public:
|
||||
BareCall, ///< CALL without function hash
|
||||
BareCallCode, ///< CALLCODE without function hash
|
||||
BareDelegateCall, ///< DELEGATECALL without function hash
|
||||
BareStaticCall, ///< STATICCALL without function hash
|
||||
Creation, ///< external call using CREATE
|
||||
Send, ///< CALL, but without data and gas
|
||||
Transfer, ///< CALL, but without data and throws on error
|
||||
@@ -935,7 +936,7 @@ public:
|
||||
ABIEncodeWithSelector,
|
||||
ABIEncodeWithSignature,
|
||||
ABIDecode,
|
||||
GasLeft ///< gasleft()
|
||||
GasLeft, ///< gasleft()
|
||||
};
|
||||
|
||||
virtual Category category() const override { return Category::Function; }
|
||||
@@ -1051,7 +1052,7 @@ public:
|
||||
/// @returns true iff the function type is equal to the given type, ignoring state mutability differences.
|
||||
bool equalExcludingStateMutability(FunctionType const& _other) const;
|
||||
|
||||
/// @returns true if the ABI is used for this call (only meaningful for external calls)
|
||||
/// @returns true if the ABI is NOT used for this call (only meaningful for external calls)
|
||||
bool isBareCall() const;
|
||||
Kind const& kind() const { return m_kind; }
|
||||
StateMutability stateMutability() const { return m_stateMutability; }
|
||||
@@ -1090,6 +1091,7 @@ public:
|
||||
case FunctionType::Kind::BareCall:
|
||||
case FunctionType::Kind::BareCallCode:
|
||||
case FunctionType::Kind::BareDelegateCall:
|
||||
case FunctionType::Kind::BareStaticCall:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -571,6 +571,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::BareCall:
|
||||
case FunctionType::Kind::BareCallCode:
|
||||
case FunctionType::Kind::BareDelegateCall:
|
||||
case FunctionType::Kind::BareStaticCall:
|
||||
_functionCall.expression().accept(*this);
|
||||
appendExternalFunctionCall(function, arguments);
|
||||
break;
|
||||
@@ -1172,6 +1173,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
case FunctionType::Kind::BareCall:
|
||||
case FunctionType::Kind::BareCallCode:
|
||||
case FunctionType::Kind::BareDelegateCall:
|
||||
case FunctionType::Kind::BareStaticCall:
|
||||
case FunctionType::Kind::Transfer:
|
||||
_memberAccess.expression().accept(*this);
|
||||
m_context << funType->externalIdentifier();
|
||||
@@ -1273,7 +1275,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
);
|
||||
m_context << Instruction::BALANCE;
|
||||
}
|
||||
else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member))
|
||||
else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall", "staticcall"}).count(member))
|
||||
utils().convertType(
|
||||
*_memberAccess.expression().annotation().type,
|
||||
IntegerType(160, IntegerType::Modifier::Address),
|
||||
@@ -1825,10 +1827,13 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
||||
utils().moveToStackTop(gasValueSize, _functionType.selfType()->sizeOnStack());
|
||||
|
||||
auto funKind = _functionType.kind();
|
||||
bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall;
|
||||
|
||||
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 isCallCode = funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::CallCode;
|
||||
bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
|
||||
bool useStaticCall = _functionType.stateMutability() <= StateMutability::View && m_context.evmVersion().hasStaticCall();
|
||||
bool useStaticCall = funKind == FunctionType::Kind::BareStaticCall || (_functionType.stateMutability() <= StateMutability::View && m_context.evmVersion().hasStaticCall());
|
||||
|
||||
bool haveReturndatacopy = m_context.evmVersion().supportsReturndata();
|
||||
unsigned retSize = 0;
|
||||
|
||||
Reference in New Issue
Block a user