aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2017-08-23 02:09:35 +0800
committerGitHub <noreply@github.com>2017-08-23 02:09:35 +0800
commit0ffc5db82b24b4897d5d09cebbaadba37fa63b45 (patch)
tree023cefa5a9f00b0e6a5bf84d02745ab8e6666121
parent210b4870a805620329793c8ba2177a3ff6e7b477 (diff)
parentb1cdf81506de39502db0fb4a4b55ba8155f853ab (diff)
downloaddexon-solidity-0ffc5db82b24b4897d5d09cebbaadba37fa63b45.tar.gz
dexon-solidity-0ffc5db82b24b4897d5d09cebbaadba37fa63b45.tar.zst
dexon-solidity-0ffc5db82b24b4897d5d09cebbaadba37fa63b45.zip
Merge pull request #2762 from ethereum/statemutability-view
Introduce view state-mutability (keep constant as alias)
-rw-r--r--Changelog.md1
-rw-r--r--docs/abi-spec.rst2
-rw-r--r--docs/contracts.rst19
-rw-r--r--docs/grammar.txt2
-rw-r--r--docs/miscellaneous.rst5
-rw-r--r--docs/types.rst2
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp2
-rw-r--r--libsolidity/ast/Types.h1
-rw-r--r--libsolidity/interface/ABI.cpp3
-rw-r--r--libsolidity/parsing/Parser.cpp3
-rw-r--r--libsolidity/parsing/Token.h4
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp58
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp6
-rw-r--r--test/libsolidity/SolidityParser.cpp5
14 files changed, 91 insertions, 22 deletions
diff --git a/Changelog.md b/Changelog.md
index 39cbd44b..efcea03f 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -3,6 +3,7 @@
Features:
* ABI JSON: Include new field ``statemutability`` with values ``view``, ``nonpayable`` and ``payable``.
* Parser: Display previous visibility specifier in error if multiple are found.
+ * Parser: Introduce ``view`` keyword on functions (``constant`` remains an alias for ``view``).
* Syntax Checker: Support ``pragma experimental <feature>;`` to turn on experimental features.
* Static Analyzer: Warn about large storage structures.
* Metadata: Store experimental flag in metadata CBOR.
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index a9110a0a..159bd6c7 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -293,7 +293,7 @@ The JSON format for a contract's interface is given by an array of function and/
* `name`: the name of the parameter;
* `type`: the canonical type of the parameter.
- `outputs`: an array of objects similar to `inputs`, can be omitted if function doesn't return anything;
-- `constant`: `true` if function is :ref:`specified to not modify blockchain state <constant-functions>`);
+- `constant`: `true` if function is :ref:`specified to not modify blockchain state <view-functions>`);
- `payable`: `true` if function accepts ether, defaults to `false`;
- `statemutability`: a string with one of the following values: `view` (same as `constant` above), `nonpayable` and `payable` (same as `payable` above).
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 7b972e17..0f1a882c 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -461,29 +461,32 @@ value types and strings.
}
-.. _constant-functions:
+.. _view-functions:
-******************
-Constant Functions
-******************
+**************
+View Functions
+**************
-Functions can be declared constant in which case they promise not to modify the state.
+Functions can be declared ``view`` in which case they promise not to modify the state.
::
pragma solidity ^0.4.0;
contract C {
- function f(uint a, uint b) constant returns (uint) {
+ function f(uint a, uint b) view returns (uint) {
return a * (b + 42);
}
}
.. note::
- Getter methods are marked constant.
+ ``constant`` is an alias to ``view``.
+
+.. note::
+ Getter methods are marked ``view``.
.. warning::
- The compiler does not enforce yet that a constant method is not modifying state.
+ The compiler does not enforce yet that a ``view`` method is not modifying state.
.. index:: ! fallback function, function;fallback
diff --git a/docs/grammar.txt b/docs/grammar.txt
index 76827a77..36ba36f0 100644
--- a/docs/grammar.txt
+++ b/docs/grammar.txt
@@ -53,7 +53,7 @@ ArrayTypeName = TypeName '[' Expression? ']'
FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | StateMutability )*
( 'returns' TypeNameList )?
StorageLocation = 'memory' | 'storage'
-StateMutability = 'constant' | 'payable'
+StateMutability = 'constant' | 'view' | 'payable'
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement |
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 199182d3..7889fff2 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -505,11 +505,12 @@ Function Visibility Specifiers
Modifiers
=========
+- ``view`` for functions: Disallow modification of state - this is not enforced yet.
+- ``payable`` for functions: Allows them to receive Ether together with a call.
- ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot.
-- ``constant`` for functions: Disallows modification of state - this is not enforced yet.
+- ``constant`` for functions: Same as ``view``.
- ``anonymous`` for events: Does not store event signature as topic.
- ``indexed`` for event parameters: Stores the parameter as topic.
-- ``payable`` for functions: Allows them to receive Ether together with a call.
Reserved Keywords
=================
diff --git a/docs/types.rst b/docs/types.rst
index 13c848c2..9c1c73c6 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -337,7 +337,7 @@ be passed via and returned from external function calls.
Function types are notated as follows::
- function (<parameter types>) {internal|external} [constant|payable] [returns (<return types>)]
+ function (<parameter types>) {internal|external} [constant|view|payable] [returns (<return types>)]
In contrast to the parameter types, the return types cannot be empty - if the
function type should not return anything, the whole ``returns (<return types>)``
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index f7661357..cb74ea39 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -323,6 +323,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
{
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
+ // FIXME: remove with next breaking release
make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() == StateMutability::View),
make_pair("payable", _node.isPayable()),
make_pair("statemutability", stateMutabilityToString(_node.stateMutability())),
@@ -415,6 +416,7 @@ bool ASTJsonConverter::visit(FunctionTypeName const& _node)
make_pair("payable", _node.isPayable()),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("statemutability", stateMutabilityToString(_node.stateMutability())),
+ // FIXME: remove with next breaking release
make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() == StateMutability::View),
make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 56546a82..ce2d3bf8 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -993,7 +993,6 @@ public:
return *m_declaration;
}
bool hasDeclaration() const { return !!m_declaration; }
- bool isConstant() const { return m_stateMutability == StateMutability::View; }
/// @returns true if the the result of this function only depends on its arguments
/// and it does not modify the state.
/// Currently, this will only return true for internal functions like keccak and ecrecover.
diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp
index a7224e86..6e8563f7 100644
--- a/libsolidity/interface/ABI.cpp
+++ b/libsolidity/interface/ABI.cpp
@@ -35,7 +35,8 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
Json::Value method;
method["type"] = "function";
method["name"] = it.second->declaration().name();
- method["constant"] = it.second->isConstant();
+ // TODO: deprecate constant in a future release
+ method["constant"] = it.second->stateMutability() == StateMutability::View;
method["payable"] = it.second->isPayable();
method["statemutability"] = stateMutabilityToString(it.second->stateMutability());
method["inputs"] = formatTypeList(
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 7455cbca..92a614e0 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -337,7 +337,8 @@ StateMutability Parser::parseStateMutability(Token::Value _token)
StateMutability stateMutability(StateMutability::NonPayable);
if (_token == Token::Payable)
stateMutability = StateMutability::Payable;
- else if (_token == Token::Constant)
+ // FIXME: constant should be removed at the next breaking release
+ else if (_token == Token::View || _token == Token::Constant)
stateMutability = StateMutability::View;
else
solAssert(false, "Invalid state mutability specifier.");
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index efbe5e9e..3bc52f1d 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -176,6 +176,7 @@ namespace solidity
K(Throw, "throw", 0) \
K(Using, "using", 0) \
K(Var, "var", 0) \
+ K(View, "view", 0) \
K(While, "while", 0) \
\
/* Ether subdenominations */ \
@@ -236,7 +237,6 @@ namespace solidity
K(Try, "try", 0) \
K(Type, "type", 0) \
K(TypeOf, "typeof", 0) \
- K(View, "view", 0) \
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
\
@@ -290,7 +290,7 @@ public:
static bool isVisibilitySpecifier(Value op) { return isVariableVisibilitySpecifier(op) || op == External; }
static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Internal; }
static bool isLocationSpecifier(Value op) { return op == Memory || op == Storage; }
- static bool isStateMutabilitySpecifier(Value op) { return op == Constant || op == Payable; }
+ static bool isStateMutabilitySpecifier(Value op) { return op == Constant || op == View || op == Payable; }
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; }
static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; }
static bool isReservedKeyword(Value op) { return (Abstract <= op && op <= TypeOf); }
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index 80b4b6ad..12fb1f9c 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -250,7 +250,63 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order)
checkInterface(sourceCode, interface);
}
-BOOST_AUTO_TEST_CASE(const_function)
+BOOST_AUTO_TEST_CASE(view_function)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function foo(uint a, uint b) returns(uint d) { return a + b; }
+ function boo(uint32 a) view returns(uint b) { return a * 4; }
+ }
+ )";
+
+ char const* interface = R"([
+ {
+ "name": "foo",
+ "constant": false,
+ "payable" : false,
+ "statemutability": "nonpayable",
+ "type": "function",
+ "inputs": [
+ {
+ "name": "a",
+ "type": "uint256"
+ },
+ {
+ "name": "b",
+ "type": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "d",
+ "type": "uint256"
+ }
+ ]
+ },
+ {
+ "name": "boo",
+ "constant": true,
+ "payable" : false,
+ "statemutability": "view",
+ "type": "function",
+ "inputs": [{
+ "name": "a",
+ "type": "uint32"
+ }],
+ "outputs": [
+ {
+ "name": "b",
+ "type": "uint256"
+ }
+ ]
+ }
+ ])";
+
+ checkInterface(sourceCode, interface);
+}
+
+// constant is an alias to view above
+BOOST_AUTO_TEST_CASE(constant_function)
{
char const* sourceCode = R"(
contract test {
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index f5f607ca..380978e8 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -1172,7 +1172,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_REQUIRE(function && function->hasDeclaration());
auto returnParams = function->returnParameterTypes();
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(false), "uint256");
- BOOST_CHECK(function->isConstant());
+ BOOST_CHECK(function->stateMutability() == StateMutability::View);
function = retrieveFunctionBySignature(*contract, "map(uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
@@ -1180,7 +1180,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_EQUAL(params.at(0)->canonicalName(false), "uint256");
returnParams = function->returnParameterTypes();
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(false), "bytes4");
- BOOST_CHECK(function->isConstant());
+ BOOST_CHECK(function->stateMutability() == StateMutability::View);
function = retrieveFunctionBySignature(*contract, "multiple_map(uint256,uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
@@ -1189,7 +1189,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_EQUAL(params.at(1)->canonicalName(false), "uint256");
returnParams = function->returnParameterTypes();
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(false), "bytes4");
- BOOST_CHECK(function->isConstant());
+ BOOST_CHECK(function->stateMutability() == StateMutability::View);
}
BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor)
diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp
index 30dc80d9..8e84ead1 100644
--- a/test/libsolidity/SolidityParser.cpp
+++ b/test/libsolidity/SolidityParser.cpp
@@ -920,6 +920,11 @@ BOOST_AUTO_TEST_CASE(multiple_statemutability_specifiers)
CHECK_PARSE_ERROR(text, "State mutability already specified as \"view\".");
text = R"(
contract c {
+ function f() constant view {}
+ })";
+ CHECK_PARSE_ERROR(text, "State mutability already specified as \"view\".");
+ text = R"(
+ contract c {
function f() payable constant {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"payable\".");