aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
authorDaniel Kirchner <daniel@ekpyron.org>2018-08-15 20:40:20 +0800
committerchriseth <chris@ethereum.org>2018-08-15 22:06:48 +0800
commit7ca0aaaf6f62aafd0fe36ae6b7dc777361ae40e3 (patch)
tree95019017cb653af8109ca7ac0b5f4216103eae3f /libsolidity
parent2ed793c4d345de909332651145265a21a04e92d1 (diff)
downloaddexon-solidity-7ca0aaaf6f62aafd0fe36ae6b7dc777361ae40e3.tar.gz
dexon-solidity-7ca0aaaf6f62aafd0fe36ae6b7dc777361ae40e3.tar.zst
dexon-solidity-7ca0aaaf6f62aafd0fe36ae6b7dc777361ae40e3.zip
Add ``staticcall`` to ``address``.
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/TypeChecker.cpp12
-rw-r--r--libsolidity/ast/Types.cpp6
-rw-r--r--libsolidity/ast/Types.h6
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp11
4 files changed, 27 insertions, 8 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 43e894e5..8d6da28b 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -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 (
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index c9dca126..ccf31543 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -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:
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index d8e73ab9..0b1b5d6d 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -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;
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 7a4548f5..9baad7d1 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -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;