diff options
40 files changed, 580 insertions, 233 deletions
diff --git a/.travis.yml b/.travis.yml index d787c795..da9bd2f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,13 @@ matrix: env: - ZIP_SUFFIX=ubuntu-trusty + - os: linux + dist: trusty + sudo: required + compiler: clang + env: + - ZIP_SUFFIX=ubuntu-trusty-clang + # Documentation target, which generates documentation using Phoenix / ReadTheDocs. - os: linux dist: trusty @@ -85,41 +92,42 @@ matrix: # OS X Yosemite (10.10) # https://en.wikipedia.org/wiki/OS_X_Yosemite # - - os: osx - osx_image: xcode7.1 - env: - # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" - # https://github.com/ethereum/solidity/issues/894 - - TRAVIS_TESTS=Off - - ZIP_SUFFIX=osx-yosemite +# - os: osx +# osx_image: xcode7.1 +# env: +# # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" +# # https://github.com/ethereum/solidity/issues/894 +# - TRAVIS_TESTS=Off +# - ZIP_SUFFIX=osx-yosemite # OS X El Capitan (10.11) # https://en.wikipedia.org/wiki/OS_X_El_Capitan # - - os: osx - osx_image: xcode7.3 - env: - # The use of Debug config here ONLY for El Capitan is a workaround for "The Heisenbug" - # See https://github.com/ethereum/webthree-umbrella/issues/565 - - TRAVIS_BUILD_TYPE=Debug - # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" - # https://github.com/ethereum/solidity/issues/894 - - TRAVIS_TESTS=Off - - ZIP_SUFFIX=osx-elcapitan +# - os: osx +# osx_image: xcode7.3 +# env: +# # The use of Debug config here ONLY for El Capitan is a workaround for "The Heisenbug" +# # See https://github.com/ethereum/webthree-umbrella/issues/565 +# - TRAVIS_BUILD_TYPE=Debug +# # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" +# # https://github.com/ethereum/solidity/issues/894 +# - TRAVIS_TESTS=Off +# - ZIP_SUFFIX=osx-elcapitan # macOS Sierra (10.12) # https://en.wikipedia.org/wiki/MacOS_Sierra # - - os: osx - osx_image: xcode8 - env: - # Look like "The Heisenbug" is occurring here too, so we'll do the same workaround. - # See https://travis-ci.org/ethereum/solidity/jobs/150240930 - - TRAVIS_BUILD_TYPE=Debug - # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" - # https://github.com/ethereum/solidity/issues/894 - - TRAVIS_TESTS=Off - - ZIP_SUFFIX=macos-sierra +# - os: osx +# osx_image: xcode8 +# env: +# # Look like "The Heisenbug" is occurring here too, so we'll do the same workaround. +# # See https://travis-ci.org/ethereum/solidity/jobs/150240930 +# - TRAVIS_BUILD_TYPE=Debug +# # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" +# # https://github.com/ethereum/solidity/issues/894 +# - TRAVIS_TESTS=Off +# - ZIP_SUFFIX=macos-sierra + git: depth: 2 @@ -133,6 +141,8 @@ cache: install: - test $TRAVIS_INSTALL_DEPS != On || ./scripts/install_deps.sh + - echo -n "$TRAVIS_COMMIT" > commit_hash.txt + - test "$TRAVIS_PULL_REQUESTS" != "false" || test "$TRAVIS_BRANCH" != release || echo -n > prerelease.txt # this is a proper release before_script: - test $TRAVIS_EMSCRIPTEN != On || ./scripts/build_emscripten.sh - test $TRAVIS_RELEASE != On || (mkdir -p build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..2b591f4e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,5 @@ +# Contribution Guidelines + +Please see our contribution guidelines in [the Solidity documentation](http://solidity.readthedocs.io/en/latest/contributing.html). + +Thank you for your help! diff --git a/Changelog.md b/Changelog.md index 8805498e..5cf2898b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,9 +1,44 @@ +### 0.4.0 (unreleased) + +This release deliberately breaks backwards compatibility mostly to +enforce some safety features. The most important change is +... + +Breaking Changes: + + * Contracts that want to receive Ether have to implement a fallback + function (contracts now throw if no fallback function is defined + and no function matches the signature). + * Failing contract creation through "new" throws now. + * Throw on division / modulus by zero + * Function call throws if target contract does not have code + * Modifiers are required to contain ``_`` (use ``if (false) _`` as a workaround if needed). + * Modifiers: return does not skip part in modifier after ``_`` + * ``ecrecover`` now returns zero if the input is malformed (it previously returned garbage) + * Removed ``--interface`` (Solidity interface) output option + * JSON AST: General cleanup, renamed many nodes to match their C++ names. + * Json Output: srcmap-runtime renamed to srcmapRuntime + * Moved (and reworked) standard library contracts from inside the compiler to github.com/ethereum/solidity/std + (``import "std";`` or ``import owned;`` do not work anymore). + * Confusing and undocumented keyword "after" was removed. + * New reserved words: hex, payable, abstract, static, interface + Features: - * Fixed point types (in progress) + * Hexadecimal string literals: ``hex"ab1248fe"`` + * Internal: Inline assembly usable by the code generator. + * Commandline interface: Using ``-`` as filename allows reading from stdin. + * Interface Json: Fallback function is now part of the ABI. + * Interface: Version string now semver compatible. Bugfixes: + * JSON AST: nodes were added at wrong parent + * Why3 translator: crash fix for exponentiation + * Type Checker: Fallback function cannot return data anymore. + +Lots of changes to the documentation mainly by voluntary external contributors. + ### 0.3.6 (2016-08-10) Features: @@ -14,7 +14,6 @@ Solidity is still under development. So please do not hesitate and open an [issu See the [Solidity documentation](http://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source) for build instructions. ## How to Contribute -This repository uses the same [coding style](https://github.com/ethereum/webthree-umbrella/blob/develop/CodingStandards.txt) as -all of the cpp-ethereum projects. Please try to align with us in the gitter channel before making larger changes. +Please see our contribution guidelines in [the Solidity documentation](http://solidity.readthedocs.io/en/latest/contributing.html). Any contributions are welcome! diff --git a/cmake/EthBuildInfo.cmake b/cmake/EthBuildInfo.cmake index cbb9dd24..1f70d371 100644 --- a/cmake/EthBuildInfo.cmake +++ b/cmake/EthBuildInfo.cmake @@ -19,7 +19,7 @@ function(create_build_info NAME) set(ETH_BUILD_COMPILER "unknown") endif () - set(ETH_BUILD_PLATFORM "${ETH_BUILD_OS}/${ETH_BUILD_COMPILER}") + set(ETH_BUILD_PLATFORM "${ETH_BUILD_OS}.${ETH_BUILD_COMPILER}") #cmake build type may be not speCified when using msvc if (CMAKE_BUILD_TYPE) @@ -36,8 +36,6 @@ function(create_build_info NAME) -DETH_BUILD_OS="${ETH_BUILD_OS}" -DETH_BUILD_COMPILER="${ETH_BUILD_COMPILER}" -DETH_BUILD_PLATFORM="${ETH_BUILD_PLATFORM}" - -DETH_BUILD_NUMBER="${BUILD_NUMBER}" - -DETH_VERSION_SUFFIX="${VERSION_SUFFIX}" -DPROJECT_VERSION="${PROJECT_VERSION}" -P "${ETH_SCRIPTS_DIR}/buildinfo.cmake" ) diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index 39359486..ad23ca86 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -5,11 +5,11 @@ # ETH_DST_DIR - main CMAKE_BINARY_DIR # ETH_BUILD_TYPE # ETH_BUILD_PLATFORM -# ETH_BUILD_NUMBER -# ETH_VERSION_SUFFIX # # example usage: -# cmake -DETH_SOURCE_DIR=. -DETH_DST_DIR=build -DETH_BUILD_TYPE=Debug -DETH_BUILD_PLATFORM=Darwin/appleclang -P scripts/buildinfo.cmake +# cmake -DETH_SOURCE_DIR=. -DETH_DST_DIR=build -DETH_BUILD_TYPE=Debug -DETH_BUILD_PLATFORM=Darwin.appleclang -P scripts/buildinfo.cmake +# +# Its main output variables are SOL_VERSION_BUILDINFO and SOL_VERSION_PRERELEASE if (NOT ETH_BUILD_TYPE) set(ETH_BUILD_TYPE "unknown") @@ -19,26 +19,45 @@ if (NOT ETH_BUILD_PLATFORM) set(ETH_BUILD_PLATFORM "unknown") endif() -execute_process( - COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse HEAD - OUTPUT_VARIABLE ETH_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET -) +# Logic here: If prereleases.txt exists but is empty, it is a non-pre release. +# If it does not exist, create our own prerelease string +if (EXISTS ${ETH_SOURCE_DIR}/prerelease.txt) + file(READ ${ETH_SOURCE_DIR}/prerelease.txt SOL_VERSION_PRERELEASE) + string(STRIP ${SOL_VERSION_PRERELEASE} SOL_VERSION_PRERELEASE) +else() + string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC) +endif() -if (NOT ETH_COMMIT_HASH) - set(ETH_COMMIT_HASH 0) +if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt) + file(READ ${ETH_SOURCE_DIR}/commit_hash.txt SOL_COMMIT_HASH) + string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH) +else() + execute_process( + COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse HEAD + OUTPUT_VARIABLE SOL_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET + ) + execute_process( + COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} diff HEAD --shortstat + OUTPUT_VARIABLE SOL_LOCAL_CHANGES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET + ) endif() -execute_process( - COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} diff HEAD --shortstat - OUTPUT_VARIABLE ETH_LOCAL_CHANGES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET -) +if (SOL_COMMIT_HASH) + string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH) + string(SUBSTRING ${SOL_COMMIT_HASH} 0 8 SOL_COMMIT_HASH) +endif() -if (ETH_LOCAL_CHANGES) - set(ETH_CLEAN_REPO 0) -else() - set(ETH_CLEAN_REPO 1) +if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES) + set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}-mod") +endif() + +if (NOT SOL_COMMIT_HASH) + message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or " + "supply a file called commit_hash.txt") endif() +set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}") + set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp") set(OUTFILE "${ETH_DST_DIR}/BuildInfo.h") diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index 6f9baf50..6c16e4ac 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -1,11 +1,10 @@ #pragma once #define ETH_PROJECT_VERSION "@PROJECT_VERSION@" -#define ETH_COMMIT_HASH @ETH_COMMIT_HASH@ -#define ETH_CLEAN_REPO @ETH_CLEAN_REPO@ -#define ETH_BUILD_TYPE @ETH_BUILD_TYPE@ -#define ETH_BUILD_OS @ETH_BUILD_OS@ -#define ETH_BUILD_COMPILER @ETH_BUILD_COMPILER@ -#define ETH_BUILD_PLATFORM @ETH_BUILD_PLATFORM@ -#define ETH_BUILD_NUMBER @ETH_BUILD_NUMBER@ -#define ETH_VERSION_SUFFIX "@ETH_VERSION_SUFFIX@" +#define SOL_COMMIT_HASH "@SOL_COMMIT_HASH@" +#define ETH_BUILD_TYPE "@ETH_BUILD_TYPE@" +#define ETH_BUILD_OS "@ETH_BUILD_OS@" +#define ETH_BUILD_COMPILER "@ETH_BUILD_COMPILER@" +#define ETH_BUILD_PLATFORM "@ETH_BUILD_PLATFORM@" +#define SOL_VERSION_PRERELEASE "@SOL_VERSION_PRERELEASE@" +#define SOL_VERSION_BUILDINFO "@SOL_VERSION_BUILDINFO@" diff --git a/docs/contracts.rst b/docs/contracts.rst index 911bfc0d..a22a3544 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -179,7 +179,7 @@ and the default is ``internal``. .. note:: Everything that is inside a contract is visible to all external observers. Making something ``private`` - only prevents other contract from accessing and modifying + only prevents other contracts from accessing and modifying the information, but it will still be visible to the whole world outside of the blockchain. @@ -195,9 +195,39 @@ return parameter list for functions. uint public data; } -Other contracts can call ``c.data()`` to retrieve the value of data in state -storage, but are not able to call ``f``. Contracts derived from ``c`` can call -``setData`` to alter the value of ``data`` (but only in their own state). +In the following example, ``D``, can call ``c.getData()`` to retrieve the value of +``data`` in state storage, but is not able to call ``f``. Contract ``E`` is derived from +``C`` and, thus, can call ``compute``. + +:: + + contract C { + uint private data; + + function f(uint a) private returns(uint b) { return a + 1; } + function setData(uint a) { data = a; } + function getData() public returns(uint) { return data; } + function compute(uint a, uint b) internal returns (uint) { return a+b; } + } + + + contract D { + function readData() { + C c = new C(); + uint local = c.f(7); // error: member "f" is not visible + c.setData(3); + local = c.getData(); + local = c.compute(3, 5); // error: member "compute" is not visible + } + } + + + contract E is C { + function g() { + C c = new C(); + uint val = compute(3, 5); // acces to internal member (from derivated to parent contract) + } + } .. index:: ! accessor;function, ! function;accessor @@ -205,21 +235,39 @@ Accessor Functions ================== The compiler automatically creates accessor functions for -all public state variables. The contract given below will -have a function called ``data`` that does not take any -arguments and returns a uint, the value of the state +all public state variables. For the contract given below, the compiler will +generate a function called ``data`` that does not take any +arguments and returns a ``uint``, the value of the state variable ``data``. The initialization of state variables can be done at declaration. +:: + + contract C { + uint public data = 42; + } + + + contract Caller { + C c = new C(); + function f() { + uint local = c.data(); + } + } + The accessor functions have external visibility. If the symbol is accessed internally (i.e. without ``this.``), -it is a state variable and if it is accessed externally -(i.e. with ``this.``), it is a function. +it is evaluated as a state variable and if it is accessed externally +(i.e. with ``this.``), it is evaluated as a function. :: - contract Test { - uint public data = 42; + contract C { + uint public data; + function x() { + data = 3; // internal access + uint val = this.data(); // external access + } } The next example is a bit more complex: @@ -380,7 +428,8 @@ Fallback Function ***************** A contract can have exactly one unnamed function. This function cannot have -arguments and is executed on a call to the contract if none of the other +arguments and cannot return anything. +It is executed on a call to the contract if none of the other functions matches the given function identifier (or if no data was supplied at all). @@ -389,6 +438,21 @@ Ether (without data). In such a context, there is very little gas available to the function call (to be precise, 2300 gas), so it is important to make fallback functions as cheap as possible. +In particular, the following operations will consume more gas than the stipend provided to a fallback function: + +- Writing to storage +- Creating a contract +- Calling an external function which consumes a large amount of gas +- Sending Ether + +Please ensure you test your fallback function thoroughly to ensure the execution cost is less than 2300 gas before deploying a contract. + +.. warning:: + Contracts that receive Ether but do not define a fallback function + throw an exception, sending back the Ether (this was different + before Solidity v0.4.0). So if you want your contract to receive Ether, + you have to implement a fallback function. + :: contract Test { diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 00000000..cef6dfd2 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,55 @@ +############ +Contributing +############ + +Help is always appreciated! + +To get started, you can try :ref:`building-from-source` in order to familiarize +yourself with the components of Solidity and the build process. Also, it may be +useful to become well-versed at writing smart-contracts in Solidity. + +In particular, we need help in the following areas: + +* Improving the documentation +* Responding to questions from other users on `StackExchange + <http://ethereum.stackexchange.com/>`_ and the `Solidity Gitter + <https://gitter.im/ethereum/solidity>`_ +* Fixing and responding to `Solidity's GitHub issues + <https://github.com/ethereum/solidity/issues>`_ + +How to Report Issues +==================== + +To report an issue, please use the +`GitHub issues tracker <https://github.com/ethereum/solidity/issues>`_. When +reporting issues, please mention the following details: + +* Which version of Solidity you are using +* Which platform are you running on +* How to reproduce the issue +* What was the result of the issue +* What the expected behaviour is + +Workflow for Pull Requests +========================== + +In order to contribute, please fork off of the ``develop`` branch and make your +changes there. Your commit messages should detail *why* you made your change, as +opposed to *what* you did. + +If you need to pull in any changes from ``develop`` after making your fork (for +example, to resolve potential merge conflicts), please avoid using ``git merge`` +and instead, ``git rebase`` your branch. + +Additionally, if you are writing a new feature, please ensure you write appropriate +Boost test cases and place them under ``test/``. + +However, if you are making a larger change, please consult with the Gitter +channel, first. + +Finally, please make sure you respect the `coding standards +<https://raw.githubusercontent.com/ethereum/cpp-ethereum/develop/CodingStandards.txt>`_ +for this project. Also, even though we do CI testing, please test your code and +ensure that it builds locally before submitting a pull request. + +Thank you for your help! diff --git a/docs/index.rst b/docs/index.rst index a330172e..a5ab3f86 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -66,7 +66,7 @@ Discontinued: Solidity Tools -------------------------------- +-------------- * `Solidity REPL <https://github.com/raineorshine/solidity-repl>`_ Try Solidity instantly with a command-line Solidity console. @@ -113,4 +113,5 @@ Contents security-considerations.rst style-guide.rst common-patterns.rst + contributing.rst frequently-asked-questions.rst diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index ba40c99f..ad27e528 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -1,3 +1,7 @@ +.. index:: ! installing + +.. _installing-solidity: + ################### Installing Solidity ################### @@ -8,8 +12,10 @@ Browser-Solidity If you just want to try Solidity for small contracts, you can try `browser-solidity <https://ethereum.github.io/browser-solidity>`_ which does not need any installation. If you want to use it -without connection to the Internet, you can also just save the page -locally or clone http://github.com/ethereum/browser-solidity. +without connection to the Internet, you can go to +https://github.com/ethereum/browser-solidity/tree/gh-pages and +download the .ZIP file as explained on that page. + npm / Node.js ============= @@ -22,7 +28,7 @@ package available. To install it, simply use -:: +.. code:: bash npm install solc @@ -32,102 +38,151 @@ Details about the usage of the Node.js package can be found in the Binary Packages =============== -Binary packages of Solidity together with its IDE Mix are available through -the `C++ bundle <https://github.com/ethereum/webthree-umbrella/releases>`_ of -Ethereum. +Binary packages of Solidity available at +`solidity/releases <https://github.com/ethereum/solidity/releases>`_. -Building from Source -==================== +We also have PPAs for Ubuntu. For the latest stable version. -Building Solidity is quite similar on MacOS X, Ubuntu and probably other Unices. -This guide starts explaining how to install the dependencies for each platform -and then shows how to build Solidity itself. +.. code:: bash -MacOS X -------- + sudo add-apt-repository ppa:ethereum/ethereum + sudo apt-get update + sudo apt-get install solc +If you want to use the cutting edge developer version: -Requirements: +.. code:: bash -- OS X Yosemite (10.10.5) -- Homebrew -- Xcode + sudo add-apt-repository ppa:ethereum/ethereum + sudo add-apt-repository ppa:ethereum/ethereum-dev + sudo apt-get update + sudo apt-get install solc -Set up Homebrew: +Homebrew is missing pre-built bottles at the time of writing, +following a Jenkins to TravisCI migration, but Homebrew +should still work just fine as a means to build-from-source. +We will re-add the pre-built bottles soon. -.. code-block:: bash +.. code:: bash brew update brew upgrade + brew tap ethereum/ethereum + brew install solidity + brew linkapps solidity + + +.. _building-from-source: + +Building from Source +==================== + +Clone the Repository +-------------------- + +To clone the source code, execute the following command: + +.. code:: bash + + git clone --recursive https://github.com/ethereum/solidity.git + cd solidity + +If you want to help developing Solidity, +you should fork Solidity and add your personal fork as a second remote: + +.. code:: bash + + cd solidity + git remote add personal git@github.com:[username]/solidity.git - brew install boost --c++11 # this takes a while - brew install cmake cryptopp gmp jsoncpp -Ubuntu Trusty (14.04) +Prerequisites - macOS --------------------- -Below are the instructions to install the minimal dependencies required -to compile Solidity on Ubuntu 14.04 (Trusty Tahr). +For macOS, ensure that you have the latest version of +`Xcode installed <https://developer.apple.com/xcode/download/>`_. +This contains the `Clang C++ compiler <https://en.wikipedia.org/wiki/Clang>`_, the +`Xcode IDE <https://en.wikipedia.org/wiki/Xcode>`_ and other Apple development +tools which are required for building C++ applications on OS X. +If you are installing Xcode for the first time, or have just installed a new +version then you will need to agree to the license before you can do +command-line builds: + +.. code:: bash + + sudo xcodebuild -license accept + +Our OS X builds require you to `install the Homebrew <http://brew.sh>`_ +package manager for installing external dependencies. +Here's how to `uninstall Homebrew +<https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/FAQ.md#how-do-i-uninstall-homebrew>`_, +if you ever want to start again from scratch. -.. code-block:: bash - sudo apt-get -y install build-essential git cmake libgmp-dev libboost-all-dev \ - libjsoncpp-dev +Prerequisites - Windows +----------------------- - sudo add-apt-repository -y ppa:ethereum/ethereum - sudo add-apt-repository -y ppa:ethereum/ethereum-dev - sudo apt-get -y update - sudo apt-get -y upgrade # this will update cmake to version 3.x - sudo apt-get -y install libcryptopp-dev libjsoncpp-dev +You will need to install the following dependencies for Windows builds of Solidity: -Ubuntu Xenial (16.04) ++------------------------------+-------------------------------------------------------+ +| Software | Notes | ++==============================+=======================================================+ +| `Git for Windows`_ | Command-line tool for retrieving source from Github. | ++------------------------------+-------------------------------------------------------+ +| `CMake`_ | Cross-platform build file generator. | ++------------------------------+-------------------------------------------------------+ +| `Visual Studio 2015`_ | C++ compiler and dev environment. | ++------------------------------+-------------------------------------------------------+ + +.. _Git for Windows: https://git-scm.com/download/win +.. _CMake: https://cmake.org/download/ +.. _Visual Studio 2015: https://www.visualstudio.com/products/vs-2015-product-editions + + +External Dependencies --------------------- -Below are the instructions to install the minimal dependencies required -to compile Solidity on Ubuntu 16.04 (Xenial Xerus). +We now have a "one button" script which installs all required external dependencies +on macOS, Windows and on numerous Linux distros. This used to be a multi-step +manual process, but is now a one-liner: -One of the dependencies (Crypto++ Library, with version >= 5.6.2) can be -installed either by adding the Ethereum PPA (Option 1) or by backporting -``libcrypto++`` from Ubuntu Development to Ubuntu Xenial (Option 2). +.. code:: bash -.. code-block:: bash + ./scripts/install_deps.sh - sudo apt-get -y install build-essential git cmake libgmp-dev libboost-all-dev \ - libjsoncpp-dev +Or, on Windows: - # (Option 1) For those willing to add the Ethereum PPA: - sudo add-apt-repository -y ppa:ethereum/ethereum - sudo add-apt-repository -y ppa:ethereum/ethereum-dev - sudo apt-get -y update - sudo apt-get -y upgrade - sudo apt-get -y install libcryptopp-dev +.. code:: bat - ## (Option 2) For those willing to backport libcrypto++: - #sudo apt-get -y install ubuntu-dev-tools - #sudo pbuilder create - #mkdir ubuntu - #cd ubuntu - #backportpackage --workdir=. --build --dont-sign libcrypto++ - #sudo dpkg -i buildresult/libcrypto++6_*.deb buildresult/libcrypto++-dev_*.deb - #cd .. + scripts\install_deps.bat -Building --------- -Run this if you plan on installing Solidity only: +Command-Line Build +------------------ -.. code-block:: bash +Building Solidity is quite similar on Linux, macOS and other Unices: + +.. code:: bash - git clone --recursive https://github.com/ethereum/solidity.git - cd solidity mkdir build cd build cmake .. && make -If you want to help developing Solidity, -you should fork Solidity and add your personal fork as a second remote: +And even on Windows: -.. code-block:: bash +.. code:: bash - cd solidity - git remote add personal git@github.com:username/solidity.git + mkdir build + cd build + cmake -G "Visual Studio 14 2015 Win64" .. + +This latter set of instructions should result in the creation of +**solidity.sln** in that build directory. Double-clicking on that file +should result in Visual Studio firing up. We suggest building +**RelWithDebugInfo** configuration, but all others work. + +Alternatively, you can build for Windows on the command-line, like so: + +.. code:: bash + + cmake --build . --config RelWithDebInfo diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index fbce4244..6fcd4854 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -220,7 +220,7 @@ only the person holding the keys to the account can transfer money from it. Blocks ====== -One major obstacle to overcome is what, in Bitcoin terms, is called "double-spend attack": +One major obstacle to overcome is what, in Bitcoin terms, is called a "double-spend attack": What happens if two transactions exist in the network that both want to empty an account, a so-called conflict? @@ -444,13 +444,13 @@ receives the address of the new contract on the stack. .. index:: selfdestruct -Selfdestruct -============ +``selfdestruct`` +================ The only possibility that code is removed from the blockchain is -when a contract at that address performs the ``SELFDESTRUCT`` operation. +when a contract at that address performs the ``selfdestruct`` operation. The remaining Ether stored at that address is sent to a designated target and then the storage and code is removed. -Note that even if a contract's code does not contain the ``SELFDESTRUCT`` -opcode, it can still perform that operation using delegatecall or callcode. +Note that even if a contract's code does not contain a call to ``selfdestruct``, +it can still perform that operation using ``delegatecall`` or ``callcode``. diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index f8d099e4..7e846674 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -103,7 +103,9 @@ and stall those. Please be explicit about such cases in the documentation of you Sending and Receiving Ether =========================== -- If a contract receives Ether (without a function being called), the fallback function is executed. The contract can only rely +- If a contract receives Ether (without a function being called), the fallback function is executed. + If it does not have a fallback function, the Ether will be rejected (by throwing an exception). + During the execution of the fallback function, the contract can only rely on the "gas stipend" (2300 gas) being available to it at that time. This stipend is not enough to access storage in any way. To be sure that your contract can receive Ether in that way, check the gas requirements of the fallback function (for example in the "details" section in browser-solidity). diff --git a/docs/types.rst b/docs/types.rst index d6445ed9..737fbe7d 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -661,13 +661,18 @@ Explicit Conversions -------------------- If the compiler does not allow implicit conversion but you know what you are -doing, an explicit type conversion is sometimes possible:: +doing, an explicit type conversion is sometimes possible. Note that this may +give you some unexpected behaviour so be sure to test to ensure that the +result is what you want! Take the following example where you are converting +a negative ``int8`` to a ``uint``: + +:: int8 y = -3; uint x = uint(y); At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex -characters), which is -3 in two's complement representation of 256 bits. +characters), which is -3 in the two's complement representation of 256 bits. If a type is explicitly converted to a smaller type, higher-order bits are cut off:: diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index d1d578ed..9ee334cf 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -18,7 +18,7 @@ Suffixes like ``seconds``, ``minutes``, ``hours``, ``days``, ``weeks`` and ``years`` after literal numbers can be used to convert between units of time where seconds are the base unit and units are considered naively in the following way: - * ``1 == 1 second`` + * ``1 == 1 seconds`` * ``1 minutes == 60 seconds`` * ``1 hours == 60 minutes`` * ``1 days == 24 hours`` @@ -109,6 +109,10 @@ This means that the following are all identical:: If padding is needed, explicit type conversions can be used: ``sha3("\x00\x12")`` is the same as ``sha3(uint16(0x12))``. +Note that constants will be packed using the minimum number of bytes required to store them. +This means that, for example, ``sha3(0) == sha3(uint8(0))`` and +``sha3(0x12345678) == sha3(uint32(0x12345678))``. + It might be that you run into Out-of-Gas for ``sha256``, ``ripemd160`` or ``ecrecover`` on a *private blockchain*. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net. .. _address_related: diff --git a/docs/utils/SolidityLexer.py b/docs/utils/SolidityLexer.py index d05c7b0c..779147f4 100644 --- a/docs/utils/SolidityLexer.py +++ b/docs/utils/SolidityLexer.py @@ -58,12 +58,14 @@ class SolidityLexer(RegexLexer): r'throw|try|catch|finally|new|delete|typeof|instanceof|void|' r'this|import|mapping|returns|private|public|external|internal|' r'constant|memory|storage)\b', Keyword, 'slashstartsregex'), - (r'(var|let|with|function|event|modifier|struct|enum|contract)\b', Keyword.Declaration, 'slashstartsregex'), + (r'(var|let|with|function|event|modifier|struct|enum|contract|library)\b', Keyword.Declaration, 'slashstartsregex'), (r'(bytes|string|address|uint|int|bool|byte|' + '|'.join( ['uint%d' % (i + 8) for i in range(0, 256, 8)] + ['int%d' % (i + 8) for i in range(0, 256, 8)] + - ['bytes%d' % (i + 1) for i in range(0, 32)] + ['bytes%d' % (i + 1) for i in range(0, 32)] + + ['ufixed%dx%d' % ((i), (j + 8)) for i in range(0, 256, 8) for j in range(0, 256 - i, 8)] + + ['fixed%dx%d' % ((i), (j + 8)) for i in range(0, 256, 8) for j in range(0, 256 - i, 8)] ) + r')\b', Keyword.Type, 'slashstartsregex'), (r'(abstract|boolean|byte|char|class|const|debugger|double|enum|export|' r'extends|final|float|goto|implements|int|interface|long|native|' diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 6b2c1cb8..bc03da01 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -92,8 +92,12 @@ bool TypeChecker::visit(ContractDefinition const& _contract) else { fallbackFunction = function; + if (_contract.isLibrary()) + typeError(fallbackFunction->location(), "Libraries cannot have fallback functions."); if (!fallbackFunction->parameters().empty()) typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters."); + if (!fallbackFunction->returnParameters().empty()) + typeError(fallbackFunction->returnParameterList()->location(), "Fallback function cannot return values."); } } if (!function->isImplemented()) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 715852be..9d77ccdc 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -247,11 +247,8 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac m_context << returnTag; appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes(), _contract.isLibrary()); } - else if (_contract.isLibrary()) - // Reject invalid library calls and ether sent to a library. - m_context.appendJumpTo(m_context.errorTag()); else - m_context << Instruction::STOP; // function not found + m_context.appendJumpTo(m_context.errorTag()); for (auto const& it: interfaceFunctions) { diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 0e5ead2b..bd79bb73 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -42,26 +42,8 @@ using namespace std; using namespace dev; using namespace dev::solidity; -const map<string, string> StandardSources = map<string, string>{ - {"coin", R"(import "CoinReg";import "Config";import "configUser";contract coin is configUser{function coin(bytes3 name, uint denom) {CoinReg(Config(configAddr()).lookup(3)).register(name, denom);}})"}, - {"Coin", R"(contract Coin{function isApprovedFor(address _target,address _proxy)constant returns(bool _r){}function isApproved(address _proxy)constant returns(bool _r){}function sendCoinFrom(address _from,uint256 _val,address _to){}function coinBalanceOf(address _a)constant returns(uint256 _r){}function sendCoin(uint256 _val,address _to){}function coinBalance()constant returns(uint256 _r){}function approve(address _a){}})"}, - {"CoinReg", R"(contract CoinReg{function count()constant returns(uint256 r){}function info(uint256 i)constant returns(address addr,bytes3 name,uint256 denom){}function register(bytes3 name,uint256 denom){}function unregister(){}})"}, - {"configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xc6d9d2cd449a754c494264e1809c50e34d64562b;}})"}, - {"Config", R"(contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}})"}, - {"mortal", R"(import "owned";contract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }})"}, - {"named", R"(import "Config";import "NameReg";import "configUser";contract named is configUser {function named(bytes32 name) {NameReg(Config(configAddr()).lookup(1)).register(name);}})"}, - {"NameReg", R"(contract NameReg{function register(bytes32 name){}function addressOf(bytes32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(bytes32 name){}})"}, - {"owned", R"(contract owned{function owned(){owner = msg.sender;}modifier onlyowner(){if(msg.sender==owner)_}address owner;})"}, - {"service", R"(import "Config";import "configUser";contract service is configUser{function service(uint _n){Config(configAddr()).register(_n, this);}})"}, - {"std", R"(import "owned";import "mortal";import "Config";import "configUser";import "NameReg";import "named";)"} -}; - -CompilerStack::CompilerStack(bool _addStandardSources, ReadFileCallback const& _readFile): - m_readFile(_readFile), m_parseSuccessful(false) -{ - if (_addStandardSources) - addSources(StandardSources, true); // add them as libraries -} +CompilerStack::CompilerStack(ReadFileCallback const& _readFile): + m_readFile(_readFile), m_parseSuccessful(false) {} void CompilerStack::setRemappings(vector<string> const& _remappings) { @@ -81,7 +63,7 @@ void CompilerStack::setRemappings(vector<string> const& _remappings) swap(m_remappings, remappings); } -void CompilerStack::reset(bool _keepSources, bool _addStandardSources) +void CompilerStack::reset(bool _keepSources) { m_parseSuccessful = false; if (_keepSources) @@ -90,8 +72,6 @@ void CompilerStack::reset(bool _keepSources, bool _addStandardSources) else { m_sources.clear(); - if (_addStandardSources) - addSources(StandardSources, true); } m_globalContext.reset(); m_sourceOrder.clear(); @@ -616,10 +596,9 @@ CompilerStack::Contract const& CompilerStack::contract(string const& _contractNa if (_contractName.empty()) // try to find some user-supplied contract for (auto const& it: m_sources) - if (!StandardSources.count(it.first)) - for (ASTPointer<ASTNode> const& node: it.second.ast->nodes()) - if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) - contractName = contract->name(); + for (ASTPointer<ASTNode> const& node: it.second.ast->nodes()) + if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) + contractName = contract->name(); auto it = m_contracts.find(contractName); if (it == m_contracts.end()) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract " + _contractName + " not found.")); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index b3c4450c..da479638 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -85,14 +85,13 @@ public: /// Creates a new compiler stack. /// @param _readFile callback to used to read files for import statements. Should return - /// @param _addStandardSources Adds standard sources if @a _addStandardSources. - explicit CompilerStack(bool _addStandardSources = true, ReadFileCallback const& _readFile = ReadFileCallback()); + explicit CompilerStack(ReadFileCallback const& _readFile = ReadFileCallback()); /// Sets path remappings in the format "context:prefix=target" void setRemappings(std::vector<std::string> const& _remappings); /// Resets the compiler to a state where the sources are not parsed or even removed. - void reset(bool _keepSources = false, bool _addStandardSources = true); + void reset(bool _keepSources = false); /// Adds a source object (e.g. file) to the parser. After this, parse has to be called again. /// @returns true if a source object by the name already existed and was replaced. diff --git a/libsolidity/interface/InterfaceHandler.cpp b/libsolidity/interface/InterfaceHandler.cpp index f5c10356..5d24e1bf 100644 --- a/libsolidity/interface/InterfaceHandler.cpp +++ b/libsolidity/interface/InterfaceHandler.cpp @@ -74,7 +74,15 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef) ); abi.append(method); } - + if (_contractDef.fallbackFunction()) + { + auto externalFunctionType = FunctionType(*_contractDef.fallbackFunction()).interfaceFunctionType(); + solAssert(!!externalFunctionType, ""); + Json::Value method; + method["type"] = "fallback"; + method["constant"] = externalFunctionType->isConstant(); + abi.append(method); + } for (auto const& it: _contractDef.interfaceEvents()) { Json::Value event; diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp index a846efea..31ba4afc 100644 --- a/libsolidity/interface/Version.cpp +++ b/libsolidity/interface/Version.cpp @@ -35,10 +35,8 @@ char const* dev::solidity::VersionNumber = ETH_PROJECT_VERSION; string const dev::solidity::VersionString = string(dev::solidity::VersionNumber) + - "-" + - string(DEV_QUOTED(ETH_COMMIT_HASH)).substr(0, 8) + - (ETH_CLEAN_REPO ? "" : "*") + - "/" DEV_QUOTED(ETH_BUILD_TYPE) "-" DEV_QUOTED(ETH_BUILD_PLATFORM); + (string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + string(SOL_VERSION_PRERELEASE)) + + (string(SOL_VERSION_BUILDINFO).empty() ? "" : "+" + string(SOL_VERSION_BUILDINFO)); bytes dev::solidity::binaryVersion() diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index 6046978e..da2c7df3 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -29,6 +29,7 @@ set -e if [[ "$OSTYPE" != "darwin"* ]]; then + date -u +"nightly.%Y.%m.%d" > prerelease.txt ./scripts/travis-emscripten/install_deps.sh docker run -v $(pwd):/src trzeci/emscripten:sdk-tag-1.35.4-64bit ./scripts/travis-emscripten/build_emscripten.sh fi diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 2fd286fd..8e9dc282 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -56,13 +56,13 @@ commithash=`git rev-parse --short HEAD` committimestamp=`git show --format=%ci HEAD | head -n 1` commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10` -# TODO store the commit hash in a file so that the build info mechanism can pick it up even without git - +echo "$commithash" > commit_hash.txt if [ $branch = develop ] then debversion="$version-nightly-$commitdate-$commithash" else debversion="$version" + echo -n > prerelease.txt # proper release fi # gzip will create different tars all the time and we are not allowed diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 08c08797..fbef56f0 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -560,7 +560,7 @@ bool CommandLineInterface::processInput() } }; - m_compiler.reset(new CompilerStack(m_args.count(g_argAddStandard) > 0, fileReader)); + m_compiler.reset(new CompilerStack(fileReader)); auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compiler->scanner(_sourceName); }; try { diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index 896a5922..5cdee2e2 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -159,7 +159,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback return result; }; } - CompilerStack compiler(true, readCallback); + CompilerStack compiler(readCallback); auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return compiler.scanner(_sourceName); }; bool success = false; try diff --git a/std/StandardToken.sol b/std/StandardToken.sol new file mode 100644 index 00000000..db453492 --- /dev/null +++ b/std/StandardToken.sol @@ -0,0 +1,43 @@ +import "./Token.sol"; + +contract StandardToken is Token { + uint256 public totalSupply; + mapping (address => uint256) public balanceOf; + mapping (address => + mapping (address => uint256)) public allowance; + + function StandardToken(address _initialOwner, uint256 _supply) { + totalSupply = _supply; + balanceOf[_initialOwner] = _supply; + } + + function transfer(address _to, uint256 _value) returns (bool success) { + if (balanceOf[msg.sender] >= _value && balanceOf[_to] + _value >= balanceOf[_to]) { + balanceOf[msg.sender] -= _value; + balanceOf[_to] += _value; + Transfer(msg.sender, _to, _value); + return true; + } + else { + return false; + } + } + + function transferFrom(address _from, address _to, uint256 _value) returns (bool success) { + if (allowance[_from][msg.sender] >= _value && balanceOf[_to] + _value >= balanceOf[_to]) { + allowance[_from][msg.sender] -= _value; + balanceOf[_to] += _value; + Transfer(_from, _to, _value); + return true; + } + else { + return false; + } + } + + function approve(address _spender, uint256 _value) returns (bool success) { + allowance[msg.sender][_spender] = _value; + Approval(msg.sender, _spender, _value); + return true; + } +} diff --git a/std/Token.sol b/std/Token.sol new file mode 100644 index 00000000..50d9ab7a --- /dev/null +++ b/std/Token.sol @@ -0,0 +1,11 @@ +contract Token { + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); + + function totalSupply() constant returns (uint256 supply) {} + function balanceOf(address _owner) constant returns (uint256 balance) {} + function transfer(address _to, uint256 _value) returns (bool success) {} + function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {} + function approve(address _spender, uint256 _value) returns (bool success) {} + function allowance(address _owner, address _spender) constant returns (uint256 remaining) {} +} diff --git a/std/mortal.sol b/std/mortal.sol new file mode 100644 index 00000000..8de019ab --- /dev/null +++ b/std/mortal.sol @@ -0,0 +1,8 @@ +import "./owned.sol"; + +contract mortal is owned { + function kill() { + if (msg.sender == owner) + selfdestruct(owner); + } +} diff --git a/std/owned.sol b/std/owned.sol new file mode 100644 index 00000000..37f0ecb9 --- /dev/null +++ b/std/owned.sol @@ -0,0 +1,13 @@ +contract owned { + address owner; + + modifier onlyowner() { + if (msg.sender == owner) { + _ + } + } + + function owned() { + owner = msg.sender; + } +} diff --git a/std/std.sol b/std/std.sol new file mode 100644 index 00000000..c3f66b1b --- /dev/null +++ b/std/std.sol @@ -0,0 +1,4 @@ +import "./owned.sol"; +import "./mortal.sol"; +import "./Token.sol"; +import "./StandardToken.sol"; diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index bb2e5663..3b1d1165 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -230,7 +230,7 @@ protected: if (!s_compiledRegistrar) { m_optimize = true; - m_compiler.reset(false, m_addStandardSources); + m_compiler.reset(false); m_compiler.addSource("", registrarCode); ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed"); s_compiledRegistrar.reset(new bytes(m_compiler.object("GlobalRegistrar").bytecode)); diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index 6d79bec6..3acfba62 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -131,7 +131,7 @@ protected: if (!s_compiledRegistrar) { m_optimize = true; - m_compiler.reset(false, m_addStandardSources); + m_compiler.reset(false); m_compiler.addSource("", registrarCode); ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed"); s_compiledRegistrar.reset(new bytes(m_compiler.object("FixedFeeRegistrar").bytecode)); diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 7a9b0b17..9e797af4 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -445,7 +445,7 @@ protected: if (!s_compiledWallet) { m_optimize = true; - m_compiler.reset(false, m_addStandardSources); + m_compiler.reset(false); m_compiler.addSource("", walletCode); ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed"); s_compiledWallet.reset(new bytes(m_compiler.object("Wallet").bytecode)); diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 557d496a..81332f4f 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -114,7 +114,7 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr<string const> n = make_shared<string>("source"); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(17, SourceLocation(2, 75, n)) + + vector<SourceLocation>(18, SourceLocation(2, 75, n)) + vector<SourceLocation>(28, SourceLocation(20, 72, n)) + vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector<SourceLocation>(4, SourceLocation(58, 67, n)) + diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 77b39978..cfc7b9bd 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -35,7 +35,7 @@ namespace test class JSONInterfaceChecker { public: - JSONInterfaceChecker(): m_compilerStack(false) {} + JSONInterfaceChecker(): m_compilerStack() {} void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) { @@ -273,15 +273,6 @@ BOOST_AUTO_TEST_CASE(const_function) checkInterface(sourceCode, interface); } -BOOST_AUTO_TEST_CASE(exclude_fallback_function) -{ - char const* sourceCode = "contract test { function() {} }"; - - char const* interface = "[]"; - - checkInterface(sourceCode, interface); -} - BOOST_AUTO_TEST_CASE(events) { char const* sourceCode = "contract test {\n" @@ -626,6 +617,25 @@ BOOST_AUTO_TEST_CASE(library_function) checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(include_fallback_function) +{ + char const* sourceCode = R"( + contract test { + function() {} + } + )"; + + char const* interface = R"( + [ + { + "constant" : false, + "type" : "fallback" + } + ] + )"; + checkInterface(sourceCode, interface); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 45f6aec5..a370aafa 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2053,6 +2053,7 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses) { char const* sourceCode = R"( contract helper { + function() { } // can receive ether } contract test { helper h; @@ -2469,21 +2470,6 @@ BOOST_AUTO_TEST_CASE(function_modifier_for_constructor) BOOST_CHECK(callContractFunction("getData()") == encodeArgs(4 | 2)); } -BOOST_AUTO_TEST_CASE(use_std_lib) -{ - char const* sourceCode = R"( - import "mortal"; - contract Icarus is mortal { } - )"; - m_addStandardSources = true; - u256 amount(130 * ether); - compileAndRun(sourceCode, amount, "Icarus"); - u256 balanceBefore = balanceAt(m_sender); - BOOST_CHECK(callContractFunction("kill()") == bytes()); - BOOST_CHECK(!addressHasCode(m_contractAddress)); - BOOST_CHECK(balanceAt(m_sender) > balanceBefore); -} - BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) { char const* sourceCode = R"( @@ -2529,13 +2515,13 @@ BOOST_AUTO_TEST_CASE(fallback_function) char const* sourceCode = R"( contract A { uint data; - function() returns (uint r) { data = 1; return 2; } + function() { data = 1; } function getData() returns (uint r) { return data; } } )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("") == encodeArgs(2)); + BOOST_CHECK(callContractFunction("") == encodeArgs()); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); } @@ -2544,17 +2530,30 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function) char const* sourceCode = R"( contract A { uint data; - function() returns (uint r) { data = 1; return 2; } + function() { data = 1; } function getData() returns (uint r) { return data; } } contract B is A {} )"; compileAndRun(sourceCode, 0, "B"); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("") == encodeArgs(2)); + BOOST_CHECK(callContractFunction("") == encodeArgs()); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); } +BOOST_AUTO_TEST_CASE(default_fallback_throws) +{ + char const* sourceCode = R"( + contract A { + function f() returns (bool) { + return this.call(); + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(0)); +} + BOOST_AUTO_TEST_CASE(event) { char const* sourceCode = R"( @@ -3002,13 +3001,13 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) { char const* sourceCode = R"( contract C { - function() returns (bytes32) { + function f() returns (bytes32) { return sha3("abc", msg.data); } } )"; compileAndRun(sourceCode); - bytes calldata1 = bytes(61, 0x22) + bytes(12, 0x12); + bytes calldata1 = FixedHash<4>(dev::sha3("f()")).asBytes() + bytes(61, 0x22) + bytes(12, 0x12); sendMessage(calldata1, false); BOOST_CHECK(m_output == encodeArgs(dev::sha3(bytes{'a', 'b', 'c'} + calldata1))); } @@ -3024,7 +3023,7 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes) contract sender { function sender() { rec = new receiver(); } function() { savedData = msg.data; } - function forward() returns (bool) { rec.call(savedData); return true; } + function forward() returns (bool) { !rec.call(savedData); return true; } function clear() returns (bool) { delete savedData; return true; } function val() returns (uint) { return rec.received(); } receiver rec; @@ -4342,12 +4341,12 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls) y = this.t1(C1(7)); } function t1(C1 a) returns (C1) { return a; } - function() returns (C1) { return C1(9); } + function t2() returns (C1) { return C1(9); } } )"; compileAndRun(sourceCode, 0, "C"); BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(9), u256(7))); - BOOST_CHECK(callContractFunction("nonexisting") == encodeArgs(u256(9))); + BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(9))); } BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) @@ -5958,6 +5957,7 @@ BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library) function f(address x) returns (bool) { return x.send(1); } + function () {} } )"; compileAndRun(sourceCode, 0, "lib"); diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index c34b00ec..f4bdc657 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -67,7 +67,7 @@ public: std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>() ) { - m_compiler.reset(false, m_addStandardSources); + m_compiler.reset(false); m_compiler.addSource("", _sourceCode); if (!m_compiler.compile(m_optimize, m_optimizeRuns)) { @@ -290,7 +290,6 @@ protected: size_t m_optimizeRuns = 200; bool m_optimize = false; - bool m_addStandardSources = false; dev::solidity::CompilerStack m_compiler; Address m_sender; Address m_contractAddress; diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index e9da390c..fdd8d7f4 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1102,6 +1102,26 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments) BOOST_CHECK(expectError(text) == Error::Type::TypeError); } +BOOST_AUTO_TEST_CASE(fallback_function_in_library) +{ + char const* text = R"( + library C { + function() {} + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) +{ + char const* text = R"( + contract C { + function() returns (uint) { } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + BOOST_AUTO_TEST_CASE(fallback_function_twice) { char const* text = R"( diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 8c0c2098..56572b43 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -37,7 +37,7 @@ namespace test class DocumentationChecker { public: - DocumentationChecker(): m_compilerStack(false) {} + DocumentationChecker(): m_compilerStack() {} void checkNatspec( std::string const& _code, |