From 12f3257e7d0e23502eb01a28c857ed56d9d2dbdc Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 17 Jul 2017 11:38:29 +0200 Subject: Add statemutability field to the ABI --- Changelog.md | 1 + docs/abi-spec.rst | 3 ++- libsolidity/interface/ABI.cpp | 3 +++ test/libsolidity/SolidityABIJSON.cpp | 23 +++++++++++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 256198f9..9bc0b354 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.16 (unreleased) Features: + * ABI JSON: Include new field ``statemutability`` with values ``view``, ``nonpayable`` and ``payable``. * Parser: Display previous visibility specifier in error if multiple are found. * Syntax Checker: Support ``pragma experimental ;`` to turn on experimental features. * Static Analyzer: Warn about large storage structures. diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 2cf57427..7a1a9af0 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -294,7 +294,8 @@ The JSON format for a contract's interface is given by an array of function and/ * `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 `); -- `payable`: `true` if function accepts ether, defaults to `false`. +- `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). `type` can be omitted, defaulting to `"function"`. diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index 12f958fc..9fc2f4e8 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -38,6 +38,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) method["name"] = it.second->declaration().name(); method["constant"] = it.second->isConstant(); method["payable"] = it.second->isPayable(); + method["statemutability"] = stateMutabilityToString(it.second->stateMutability()); method["inputs"] = formatTypeList( externalFunctionType->parameterNames(), externalFunctionType->parameterTypes(), @@ -57,6 +58,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) auto externalFunction = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType(); solAssert(!!externalFunction, ""); method["payable"] = externalFunction->isPayable(); + method["statemutability"] = stateMutabilityToString(externalFunction->stateMutability()); method["inputs"] = formatTypeList( externalFunction->parameterNames(), externalFunction->parameterTypes(), @@ -71,6 +73,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) Json::Value method; method["type"] = "fallback"; method["payable"] = externalFunctionType->isPayable(); + method["statemutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); abi.append(method); } for (auto const& it: _contractDef.interfaceEvents()) diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 452a2662..b06dcfe5 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -76,6 +76,7 @@ BOOST_AUTO_TEST_CASE(basic_test) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -119,6 +120,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -137,6 +139,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) "name": "g", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -169,6 +172,7 @@ BOOST_AUTO_TEST_CASE(multiple_params) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -207,6 +211,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) "name": "c", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -225,6 +230,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -258,6 +264,7 @@ BOOST_AUTO_TEST_CASE(const_function) "name": "foo", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -280,6 +287,7 @@ BOOST_AUTO_TEST_CASE(const_function) "name": "boo", "constant": true, "payable" : false, + "statemutability": "view", "type": "function", "inputs": [{ "name": "a", @@ -311,6 +319,7 @@ BOOST_AUTO_TEST_CASE(events) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -392,6 +401,7 @@ BOOST_AUTO_TEST_CASE(inherited) "name": "baseFunction", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [{ @@ -408,6 +418,7 @@ BOOST_AUTO_TEST_CASE(inherited) "name": "derivedFunction", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [{ @@ -463,6 +474,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -505,6 +517,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -548,6 +561,7 @@ BOOST_AUTO_TEST_CASE(constructor_abi) } ], "payable": false, + "statemutability": "nonpayable", "type": "constructor" } ])"; @@ -574,6 +588,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) { "constant" : false, "payable" : false, + "statemutability": "nonpayable", "inputs" : [], "name" : "ret", "outputs" : [ @@ -592,6 +607,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) } ], "payable": false, + "statemutability": "nonpayable", "type": "constructor" } ] @@ -613,6 +629,7 @@ BOOST_AUTO_TEST_CASE(strings_and_arrays) { "constant" : false, "payable" : false, + "statemutability": "nonpayable", "name": "f", "inputs": [ { "name": "a", "type": "string" }, @@ -641,6 +658,7 @@ BOOST_AUTO_TEST_CASE(library_function) { "constant" : false, "payable" : false, + "statemutability": "nonpayable", "name": "f", "inputs": [ { "name": "b", "type": "test.StructType storage" }, @@ -670,6 +688,7 @@ BOOST_AUTO_TEST_CASE(include_fallback_function) [ { "payable": false, + "statemutability": "nonpayable", "type" : "fallback" } ] @@ -691,6 +710,7 @@ BOOST_AUTO_TEST_CASE(payable_function) { "constant" : false, "payable": false, + "statemutability": "nonpayable", "inputs": [], "name": "f", "outputs": [], @@ -699,6 +719,7 @@ BOOST_AUTO_TEST_CASE(payable_function) { "constant" : false, "payable": true, + "statemutability": "payable", "inputs": [], "name": "g", "outputs": [], @@ -721,6 +742,7 @@ BOOST_AUTO_TEST_CASE(payable_fallback_function) [ { "payable": true, + "statemutability": "payable", "type" : "fallback" } ] @@ -741,6 +763,7 @@ BOOST_AUTO_TEST_CASE(function_type) { "constant" : false, "payable": false, + "statemutability": "nonpayable", "inputs": [{ "name": "x", "type": "function" -- cgit From 1f5ab603a74ded4058d3c7103e436112852b45ba Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 15 Aug 2017 01:40:53 +0100 Subject: Add test for payable constructor in ABI --- test/libsolidity/SolidityABIJSON.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index b06dcfe5..80b4b6ad 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -568,6 +568,37 @@ BOOST_AUTO_TEST_CASE(constructor_abi) checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(payable_constructor_abi) +{ + char const* sourceCode = R"( + contract test { + function test(uint param1, test param2, bool param3) payable {} + } + )"; + + char const* interface = R"([ + { + "inputs": [ + { + "name": "param1", + "type": "uint256" + }, + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bool" + } + ], + "payable": true, + "statemutability": "payable", + "type": "constructor" + } + ])"; + checkInterface(sourceCode, interface); +} BOOST_AUTO_TEST_CASE(return_param_in_abi) { -- cgit