aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/frequently-asked-questions.rst28
-rw-r--r--docs/metadata.rst15
-rw-r--r--docs/types.rst7
-rw-r--r--libsolidity/interface/StandardCompiler.cpp23
-rw-r--r--test/libsolidity/StandardCompiler.cpp65
5 files changed, 116 insertions, 22 deletions
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index 7b7dd0b0..a474f905 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -43,17 +43,11 @@ Can you return an array or a ``string`` from a solidity function call?
Yes. See `array_receiver_and_returner.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/60_array_receiver_and_returner.sol>`_.
-What is problematic, though, is returning any variably-sized data (e.g. a
-variably-sized array like ``uint[]``) from a function **called from within Solidity**.
-This is a limitation of the EVM and will be solved with the next protocol update.
-
-Returning variably-sized data as part of an external transaction or call is fine.
-
Is it possible to in-line initialize an array like so: ``string[] myarray = ["a", "b"];``
=========================================================================================
Yes. However it should be noted that this currently only works with statically sized memory arrays. You can even create an inline memory
-array in the return statement. Pretty cool, huh?
+array in the return statement.
Example::
@@ -70,7 +64,7 @@ Example::
Can a contract function return a ``struct``?
============================================
-Yes, but only in ``internal`` function calls.
+Yes, but only in ``internal`` function calls or if ``pragma experimental "ABIEncoderV2";`` is used.
If I return an ``enum``, I only get integer values in web3.js. How to get the named values?
===========================================================================================
@@ -145,7 +139,17 @@ you should always convert it to a ``bytes`` first::
Can I concatenate two strings?
==============================
-You have to do it manually for now.
+Yes, you can use ``abi.encodePacked``::
+
+ pragma solidity >=0.4.0 <0.6.0;
+
+ library ConcatHelper {
+ function concat(bytes memory a, bytes memory b)
+ internal pure returns (bytes memory) {
+ return abi.encodePacked(a, b);
+ }
+ }
+
Why is the low-level function ``.call()`` less favorable than instantiating a contract with a variable (``ContractB b;``) and executing its functions (``b.doSomething();``)?
=============================================================================================================================================================================
@@ -299,8 +303,8 @@ In this example::
Can a contract function accept a two-dimensional array?
=======================================================
-This is not yet implemented for external calls and dynamic arrays -
-you can only use one level of dynamic arrays.
+If you want to pass two-dimensional arrays across non-internal functions,
+you most likely need to use ``pragma experimental "ABIEncoderV2";``.
What is the relationship between ``bytes32`` and ``string``? Why is it that ``bytes32 somevar = "stringliteral";`` works and what does the saved 32-byte hex value mean?
========================================================================================================================================================================
@@ -401,7 +405,7 @@ case in C or Java).
Is it possible to return an array of strings (``string[]``) from a Solidity function?
=====================================================================================
-Not yet, as this requires two levels of dynamic arrays (``string`` is a dynamic array itself).
+Only when ``pragma experimental "ABIEncoderV2";`` is used.
What does the following strange check do in the Custom Token contract?
======================================================================
diff --git a/docs/metadata.rst b/docs/metadata.rst
index 180b0647..c0613809 100644
--- a/docs/metadata.rst
+++ b/docs/metadata.rst
@@ -118,19 +118,28 @@ to the end of the deployed bytecode::
So in order to retrieve the data, the end of the deployed bytecode can be checked
to match that pattern and use the Swarm hash to retrieve the file.
+.. note::
+ The compiler currently uses the "swarm version 0" hash of the metadata,
+ but this might change in the future, so do not rely on this sequence
+ to start with ``0xa1 0x65 'b' 'z' 'z' 'r' '0'``. We might also
+ add additional data to this CBOR structure, so the
+ best option is to use a proper CBOR parser.
+
+
Usage for Automatic Interface Generation and NatSpec
====================================================
The metadata is used in the following way: A component that wants to interact
-with a contract (e.g. Mist) retrieves the code of the contract, from that
+with a contract (e.g. Mist or any wallet) retrieves the code of the contract, from that
the Swarm hash of a file which is then retrieved.
That file is JSON-decoded into a structure like above.
The component can then use the ABI to automatically generate a rudimentary
user interface for the contract.
-Furthermore, Mist can use the userdoc to display a confirmation message to the user
-whenever they interact with the contract.
+Furthermore, the wallet can use the NatSpec user documentation to display a confirmation message to the user
+whenever they interact with the contract, together with requesting
+authorization for the transaction signature.
Additional information about Ethereum Natural Specification (NatSpec) can be found `here <https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format>`_.
diff --git a/docs/types.rst b/docs/types.rst
index 3dc95ac2..43291af8 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -51,7 +51,7 @@ Operators:
* Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``)
* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation)
* Shift operators: ``<<`` (left shift), ``>>`` (right shift)
-* Arithmetic operators: ``+``, ``-``, unary ``-``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation)
+* Arithmetic operators: ``+``, ``-``, unary ``-``, ``*``, ``/``, ``%`` (modulo), ``**`` (exponentiation)
Comparisons
@@ -120,7 +120,8 @@ Exponentiation
Exponentiation is only available for unsigned types. Please take care that the types
you are using are large enough to hold the result and prepare for potential wrapping behaviour.
-Note that ``0**0`` is defined by the EVM as ``1``.
+.. note::
+ Note that ``0**0`` is defined by the EVM as ``1``.
.. index:: ! ufixed, ! fixed, ! fixed point number
@@ -138,7 +139,7 @@ the type and ``N`` represents how many decimal points are available. ``M`` must
Operators:
* Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``)
-* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder)
+* Arithmetic operators: ``+``, ``-``, unary ``-``, ``*``, ``/``, ``%`` (modulo)
.. note::
The main difference between floating point (``float`` and ``double`` in many languages, more precisely IEEE 754 numbers) and fixed point numbers is
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index e7b1553f..2305da13 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -342,10 +342,25 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
}
m_compilerStack.setRemappings(remappings);
- Json::Value optimizerSettings = settings.get("optimizer", Json::Value());
- bool const optimize = optimizerSettings.get("enabled", Json::Value(false)).asBool();
- unsigned const optimizeRuns = optimizerSettings.get("runs", Json::Value(200u)).asUInt();
- m_compilerStack.setOptimiserSettings(optimize, optimizeRuns);
+ if (settings.isMember("optimizer"))
+ {
+ Json::Value optimizerSettings = settings["optimizer"];
+ if (optimizerSettings.isMember("enabled"))
+ {
+ if (!optimizerSettings["enabled"].isBool())
+ return formatFatalError("JSONError", "The \"enabled\" setting must be a boolean.");
+
+ bool const optimize = optimizerSettings["enabled"].asBool();
+ unsigned optimizeRuns = 200;
+ if (optimizerSettings.isMember("runs"))
+ {
+ if (!optimizerSettings["runs"].isUInt())
+ return formatFatalError("JSONError", "The \"runs\" setting must be an unsigned number.");
+ optimizeRuns = optimizerSettings["runs"].asUInt();
+ }
+ m_compilerStack.setOptimiserSettings(optimize, optimizeRuns);
+ }
+ }
map<string, h160> libraries;
Json::Value jsonLibraries = settings.get("libraries", Json::Value(Json::objectValue));
diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp
index d34bacda..1570a9d2 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -225,6 +225,71 @@ BOOST_AUTO_TEST_CASE(smoke_test)
BOOST_CHECK(containsAtMostWarnings(result));
}
+BOOST_AUTO_TEST_CASE(optimizer_enabled_not_boolean)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "optimizer": {
+ "enabled": "wrong"
+ }
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "The \"enabled\" setting must be a boolean."));
+}
+
+BOOST_AUTO_TEST_CASE(optimizer_runs_not_a_number)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": "not a number"
+ }
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number."));
+}
+
+BOOST_AUTO_TEST_CASE(optimizer_runs_not_an_unsigned_number)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": -1
+ }
+ },
+ "sources": {
+ "empty": {
+ "content": ""
+ }
+ }
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number."));
+}
+
BOOST_AUTO_TEST_CASE(basic_compilation)
{
char const* input = R"(