diff options
-rw-r--r-- | docs/frequently-asked-questions.rst | 28 | ||||
-rw-r--r-- | docs/metadata.rst | 15 | ||||
-rw-r--r-- | docs/types.rst | 7 | ||||
-rw-r--r-- | libsolidity/interface/StandardCompiler.cpp | 23 | ||||
-rw-r--r-- | test/libsolidity/StandardCompiler.cpp | 65 |
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"( |