Merge pull request #3950 from ethereum/develop

Merge develop into release for 0.4.23
This commit is contained in:
chriseth 2018-04-19 19:24:01 +02:00 committed by GitHub
commit 124ca40dc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 874 additions and 519 deletions

View File

@ -159,7 +159,8 @@ cache:
install:
- test $SOLC_INSTALL_DEPS_TRAVIS != On || (scripts/install_deps.sh)
- test "$TRAVIS_OS_NAME" != "linux" || (scripts/install_cmake.sh)
# - if [ "$TRAVIS_BRANCH" != release -a -z "$TRAVIS_TAG" ]; then SOLC_TESTS=Off; fi
# Disable tests unless run on the release branch, on tags or with daily cron
#- if [ "$TRAVIS_BRANCH" != release -a -z "$TRAVIS_TAG" -a "$TRAVIS_EVENT_TYPE" != cron ]; then SOLC_TESTS=Off; fi
- SOLC_TESTS=Off
- if [ "$TRAVIS_BRANCH" = release -o -n "$TRAVIS_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
- echo -n "$TRAVIS_COMMIT" > commit_hash.txt

View File

@ -8,7 +8,7 @@ include(EthPolicy)
eth_policy()
# project name and version should be set after cmake_policy CMP0048
set(PROJECT_VERSION "0.4.22")
set(PROJECT_VERSION "0.4.23")
project(solidity VERSION ${PROJECT_VERSION})
option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF)

View File

@ -1,35 +1,24 @@
0. Formatting
## 0. Formatting
GOLDEN RULE: Follow the style of the existing code when you make changes.
**GOLDEN RULE**: Follow the style of the existing code when you make changes.
a. Use tabs for leading indentation
- tab stops are every 4 characters (only relevant for line length).
- One indentation level -> exactly one byte (i.e. a tab character) in the source file.
b. Line widths:
- Lines should be at most 99 characters wide to make diff views readable and reduce merge conflicts.
- Lines of comments should be formatted according to ease of viewing, but simplicity is to be preferred over beauty.
c. Single-statement blocks should not have braces, unless required for clarity.
d. Never place condition bodies on same line as condition.
e. Space between keyword and opening parenthesis, but not following opening parenthesis or before final parenthesis.
f. No spaces for unary operators, `->` or `.`.
g. No space before ':' but one after it, except in the ternary operator: one on both sides.
h. Add spaces around all other operators.
i. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
j. If lines are broken, a list of elements enclosed with parentheses (of any kind) and separated by a
separator (of any kind) are formatted such that there is exactly one element per line, followed by
the separator, the opening parenthesis is on the first line, followed by a line break and the closing
parenthesis is on a line of its own (unindented). See example below.
1. Use tabs for leading indentation:
- tab stops are every 4 characters (only relevant for line length).
- one indentation level -> exactly one byte (i.e. a tab character) in the source file.
2. Line widths:
- Lines should be at most 99 characters wide to make diff views readable and reduce merge conflicts.
- Lines of comments should be formatted according to ease of viewing, but simplicity is to be preferred over beauty.
3. Single-statement blocks should not have braces, unless required for clarity.
4. Never place condition bodies on same line as condition.
5. Space between keyword and opening parenthesis, but not following opening parenthesis or before final parenthesis.
6. No spaces for unary operators, `->` or `.`.
7. No space before `:` but one after it, except in the ternary operator: one on both sides.
8. Add spaces around all other operators.
9. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
10. If lines are broken, a list of elements enclosed with parentheses (of any kind) and separated by a separator (of any kind) are formatted such that there is exactly one element per line, followed by the separator, the opening parenthesis is on the first line, followed by a line break and the closing parenthesis is on a line of its own unindented). See example below.
(WRONG)
if( a==b[ i ] ) { printf ("Hello\n"); }
foo->bar(someLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName);
cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl;
(RIGHT)
Yes:
```cpp
if (a == b[i])
printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'.
foo->bar(
@ -44,99 +33,92 @@ cout <<
"text that talks about this and that and contains the words " <<
"\"lorem\" and \"ipsum\"" <<
endl;
```
No:
```cpp
if( a==b[ i ] ) { printf ("Hello\n"); }
foo->bar(someLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName);
cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl;
```
## 1. Namespaces
1. Namespaces;
1. No `using namespace` declarations in header files.
2. All symbols should be declared in a namespace except for final applications.
3. Use anonymous namespaces for helpers whose scope is a cpp file only.
4. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
a. No "using namespace" declarations in header files.
b. All symbols should be declared in a namespace except for final applications.
c. Use anonymous namespaces for helpers whose scope is a cpp file only.
d. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
Yes:
```cpp
#include <cassert>
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
```
(WRONG)
No:
```cpp
#include <cassert>
using namespace std;
tuple<float, float> meanAndSigma(vector<float> const& _v);
```
(CORRECT)
#include <cassert>
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
## 2. Preprocessor
1. File comment is always at top, and includes:
- Copyright
- License (e.g. see COPYING)
2. Never use `#ifdef`/`#define`/`#endif` file guards. Prefer `#pragma` once as first line below file comment.
3. Prefer static const variable to value macros.
4. Prefer inline constexpr functions to function macros.
5. Split complex macro on multiple lines with `\`.
## 3. Capitalization
2. Preprocessor;
a. File comment is always at top, and includes:
- Copyright.
- License (e.g. see COPYING).
b. Never use #ifdef/#define/#endif file guards. Prefer #pragma once as first line below file comment.
c. Prefer static const variable to value macros.
d. Prefer inline constexpr functions to function macros.
e. Split complex macro on multiple lines with '\'.
3. Capitalization;
GOLDEN RULE: Preprocessor: ALL_CAPS; C++: camelCase.
a. Use camelCase for splitting words in names, except where obviously extending STL/boost functionality in which case follow those naming conventions.
b. The following entities' first alpha is upper case:
- Type names.
- Template parameters.
- Enum members.
- static const variables that form an external API.
c. All preprocessor symbols (macros, macro arguments) in full uppercase with underscore word separation.
**GOLDEN RULE**: Preprocessor: `ALL_CAPS`; C++: `camelCase`.
1. Use camelCase for splitting words in names, except where obviously extending STL/boost functionality in which case follow those naming conventions.
2. The following entities' first alpha is upper case:
- Type names
- Template parameters
- Enum members
- static const variables that form an external API.
3. All preprocessor symbols (macros, macro arguments) in full uppercase with underscore word separation.
All other entities' first alpha is lower case.
## 4. Variable prefixes
1. Leading underscore "_" to parameter names:
- Exception: "o_parameterName" when it is used exclusively for output. See 6(f).
- Exception: "io_parameterName" when it is used for both input and output. See 6(f).
2. Leading "g_" to global (non-const) variables.
3. Leading "s_" to static (non-const, non-global) variables.
4. Variable prefixes:
## 5. Assertions
a. Leading underscore "_" to parameter names.
- Exception: "o_parameterName" when it is used exclusively for output. See 6(f).
- Exception: "io_parameterName" when it is used for both input and output. See 6(f).
b. Leading "g_" to global (non-const) variables.
c. Leading "s_" to static (non-const, non-global) variables.
Use `solAssert` and `solUnimplementedAssert` generously to check assumptions that span across different parts of the code base, for example before dereferencing a pointer.
## 6. Declarations
1. {Typename} + {qualifiers} + {name}.
2. Only one per line.
3. Associate */& with type, not variable (at ends with parser, but more readable, and safe if in conjunction with (b)).
4. Favour declarations close to use; don't habitually declare at top of scope ala C.
5. Pass non-trivial parameters as const reference, unless the data is to be copied into the function, then either pass by const reference or by value and use std::move.
6. If a function returns multiple values, use std::tuple (std::pair acceptable) or better introduce a struct type. Do not use */& arguments.
7. Use parameters of pointer type only if ``nullptr`` is a valid argument, use references otherwise. Often, ``boost::optional`` is better suited than a raw pointer.
8. Never use a macro where adequate non-preprocessor C++ can be written.
9. Only use ``auto`` if the type is very long and rather irrelevant.
10. Do not pass bools: prefer enumerations instead.
11. Prefer enum class to straight enum.
12. Always initialize POD variables, even if their value is overwritten later.
5. Assertions:
- use `solAssert` and `solUnimplementedAssert` generously to check assumptions
that span across different parts of the code base, for example before dereferencing
a pointer.
6. Declarations:
a. {Typename} + {qualifiers} + {name}.
b. Only one per line.
c. Associate */& with type, not variable (at ends with parser, but more readable, and safe if in conjunction with (b)).
d. Favour declarations close to use; don't habitually declare at top of scope ala C.
e. Pass non-trivial parameters as const reference, unless the data is to be copied into the function, then either pass by const reference or by value and use std::move.
f. If a function returns multiple values, use std::tuple (std::pair acceptable) or better introduce a struct type. Do not use */& arguments.
g. Use parameters of pointer type only if ``nullptr`` is a valid argument, use references otherwise. Often, ``boost::optional`` is better suited than a raw pointer.
h. Never use a macro where adequate non-preprocessor C++ can be written.
i. Only use ``auto`` if the type is very long and rather irrelevant.
j. Do not pass bools: prefer enumerations instead.
k. Prefer enum class to straight enum.
l. Always initialize POD variables, even if their value is overwritten later.
(WRONG)
const double d = 0;
int i, j;
char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
(CORRECT)
Yes:
```cpp
enum class Accuracy
{
Approximate,
@ -154,78 +136,78 @@ char* s;
MeanAndSigma ms meanAndSigma(std::vector<float> const& _v, Accuracy _a);
Derived* x = dynamic_cast<Derived*>(base);
for (auto i = x->begin(); i != x->end(); ++i) {}
```
No:
```cp
const double d = 0;
int i, j;
char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
```
7. Structs & classes
## 7. Structs & classes
a. Structs to be used when all members public and no virtual functions.
- In this case, members should be named naturally and not prefixed with 'm_'
b. Classes to be used in all other circumstances.
1. Structs to be used when all members public and no virtual functions:
- In this case, members should be named naturally and not prefixed with `m_`.
2. Classes to be used in all other circumstances.
## 8. Members
1. One member per line only.
2. Private, non-static, non-const fields prefixed with `m_`.
3. Avoid public fields, except in structs.
4. Use override, final and const as much as possible.
5. No implementations with the class declaration, except:
- template or force-inline method (though prefer implementation at bottom of header file).
- one-line implementation (in which case include it in same line as declaration).
6. For a property `foo`
- Member: `m_foo`
- Getter: `foo()` [ also: for booleans, `isFoo()` ]
- Setter: `setFoo()`
8. Members:
## 9. Naming
a. One member per line only.
b. Private, non-static, non-const fields prefixed with m_.
c. Avoid public fields, except in structs.
d. Use override, final and const as much as possible.
e. No implementations with the class declaration, except:
- template or force-inline method (though prefer implementation at bottom of header file).
- one-line implementation (in which case include it in same line as declaration).
f. For a property 'foo'
- Member: m_foo;
- Getter: foo() [ also: for booleans, isFoo() ];
- Setter: setFoo();
1. Avoid unpronouncable names.
2. Names should be shortened only if they are extremely common, but shortening should be generally avoided
3. Avoid prefixes of initials (e.g. do not use `IMyInterface`, `CMyImplementation`)
4. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments:
- A dictionary and thesaurus are your friends;
- Spell correctly;
- Think carefully about the class's purpose;
- Imagine it as an isolated component to try to decontextualise it when considering its name;
- Don't be trapped into naming it (purely) in terms of its implementation.
## 10. Type definitions
1. Prefer `using` to `typedef`. e.g. `using ints = std::vector<int>;` rather than typedef `std::vector<int> ints;`
2. Generally avoid shortening a standard form that already includes all important information:
- e.g. stick to `shared_ptr<X>` rather than shortening to `ptr<X>`.
3. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently:
- e.g. `using Guard = std::lock_guard<std::mutex>;` ///< Guard is used throughout the codebase since it is clear in meaning and used commonly.
4. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
5. Avoid introducing aliases for types unless they are very complicated. Consider the number of items a brain can keep track of at the same time.
9. Naming
## 11. Commenting
a. Avoid unpronouncable names
b. Names should be shortened only if they are extremely common, but shortening should be generally avoided
c. Avoid prefixes of initials (e.g. do not use IMyInterface, CMyImplementation)
c. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
- A dictionary and thesaurus are your friends.
- Spell correctly.
- Think carefully about the class's purpose.
- Imagine it as an isolated component to try to decontextualise it when considering its name.
- Don't be trapped into naming it (purely) in terms of its implementation.
1. Comments should be doxygen-compilable, using @notation rather than \notation.
2. Document the interface, not the implementation:
- Documentation should be able to remain completely unchanged, even if the method is reimplemented;
- Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports);
- Be careful to scrutinise documentation that extends only to intended purpose and usage;
- Reject documentation that is simply an English transaction of the implementation.
3. Avoid in-code comments. Instead, try to extract blocks of functionality into functions. This often already eliminates the need for an in-code comment.
## 12. Include Headers
10. Type-definitions
a. Prefer 'using' to 'typedef'. e.g. using ints = std::vector<int>; rather than typedef std::vector<int> ints;
b. Generally avoid shortening a standard form that already includes all important information:
- e.g. stick to shared_ptr<X> rather than shortening to ptr<X>.
c. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently.
- e.g. using Guard = std::lock_guard<std::mutex>; ///< Guard is used throughout the codebase since it is clear in meaning and used commonly.
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
e. Avoid introducing aliases for types unless they are very complicated. Consider the number of items a brain can keep track of at the same time.
11. Commenting
a. Comments should be doxygen-compilable, using @notation rather than \notation.
b. Document the interface, not the implementation.
- Documentation should be able to remain completely unchanged, even if the method is reimplemented.
- Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports).
- Be careful to scrutinise documentation that extends only to intended purpose and usage.
- Reject documentation that is simply an English transaction of the implementation.
c. Avoid in-code comments. Instead, try to extract blocks of functionality into functions. This often already eliminates the need for an in-code comment.
12. Include Headers
Includes should go in increasing order of generality (libsolidity -> libevmasm -> libdevcore -> boost -> STL).
The corresponding .h file should be the first include in the respective .cpp file.
Insert empty lines between blocks of include files.
1. Includes should go in increasing order of generality (`libsolidity` -> `libevmasm` -> `libdevcore` -> `boost` -> `STL`).
2. The corresponding `.h` file should be the first include in the respective `.cpp` file.
3. Insert empty lines between blocks of include files.
Example:
```
```cpp
#include <libsolidity/codegen/ExpressionCompiler.h>
#include <libsolidity/ast/AST.h>
@ -245,18 +227,17 @@ Example:
#include <numeric>
```
See http://stackoverflow.com/questions/614302/c-header-order/614333#614333 for the reason: this makes it easier to find missing includes in header files.
See [this issue](http://stackoverflow.com/questions/614302/c-header-order/614333#614333 "C header order") for the reason: this makes it easier to find missing includes in header files.
## 13. Recommended reading
13. Recommended reading
- Herb Sutter and Bjarne Stroustrup:
- [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
Herb Sutter and Bjarne Stroustrup
- "C++ Core Guidelines" (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
- Herb Sutter and Andrei Alexandrescu:
- "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices"
Herb Sutter and Andrei Alexandrescu
- "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices"
Scott Meyers
- "Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition)"
- "More Effective C++: 35 New Ways to Improve Your Programs and Designs"
- "Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14"
- Scott Meyers:
- "Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition)"
- "More Effective C++: 35 New Ways to Improve Your Programs and Designs"
- "Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14"

View File

@ -1,3 +1,16 @@
### 0.4.23 (2018-04-19)
Features:
* Build system: Support Ubuntu Bionic.
* SMTChecker: Integration with CVC4 SMT solver
* Syntax Checker: Warn about functions named "constructor".
Bugfixes:
* Type Checker: Improve error message for failed function overload resolution.
* Type Checker: Do not complain about new-style constructor and fallback function to have the same name.
* Type Checker: Detect multiple constructor declarations in the new syntax and old syntax.
* Type Checker: Explicit conversion of ``bytesXX`` to ``contract`` is properly disallowed.
### 0.4.22 (2018-04-16)
Features:
@ -25,7 +38,6 @@ Features:
* Syntax Tests: Add source locations to syntax test expectations.
* Type Checker: Improve documentation and warnings for accessing contract members inherited from ``address``.
Bugfixes:
* Code Generator: Allow ``block.blockhash`` without being called.
* Code Generator: Do not include internal functions in the runtime bytecode which are only referenced in the constructor.

View File

@ -14,6 +14,6 @@ Solidity is still under development. So please do not hesitate and open an [issu
See the [Solidity documentation](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source) for build instructions.
## How to Contribute
Please see our contribution guidelines in [the Solidity documentation](https://solidity.readthedocs.io/en/latest/contributing.html).
Please see our [contribution guidelines](https://solidity.readthedocs.io/en/latest/contributing.html) in the Solidity documentation.
Any contributions are welcome!

View File

@ -1,7 +1,8 @@
Checklist for making a release:
- [ ] Check that all "nextrelease" issues and pull requests are merged to ``develop``.
- [ ] Create a commit in ``develop`` that updates the ``Changelog`` to include a release date (run the tests locally to update the bug list).
- [ ] Ensure that a Github project exists for the release.
- [ ] Check that all issues and pull requests from the Github project to be released are merged to ``develop``.
- [ ] Create a commit in ``develop`` that updates the ``Changelog`` to include a release date (run ``./scripts/tests.sh`` to update the bug list). Sort the changelog entries alphabetically and correct any errors you notice.
- [ ] Create a pull request and wait for the tests, merge it.
- [ ] Create a pull request from ``develop`` to ``release``, wait for the tests, then merge it.
- [ ] Make a final check that there are no platform-dependency issues in the ``solc-test-bytecode`` repository.
@ -9,7 +10,7 @@ Checklist for making a release:
- [ ] Thank voluntary contributors in the Github release page (use ``git shortlog -s -n -e origin/release..origin/develop``).
- [ ] Wait for the CI runs on the tag itself (they should push artefacts onto the Github release page).
- [ ] Run ``scripts/release_ppa.sh release`` to create the PPA release (you need the relevant openssl key).
- [ ] Check that the Docker release was pushed to Docker Hub (this still seems to have problems).
- [ ] Check that the Docker release was pushed to Docker Hub (this still seems to have problems, run ``./scripts/docker_deploy_manual.sh release``).
- [ ] Update the homebrew realease in https://github.com/ethereum/homebrew-ethereum/blob/master/solidity.rb (version and hash)
- [ ] Update the default version on readthedocs.
- [ ] Make a release of ``solc-js``: Increment the version number, create a pull request for that, merge it after tests succeeded.

View File

@ -43,27 +43,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
# TODO - Track down what breaks if we do NOT do this.
add_compile_options(-Wno-unknown-pragmas)
# To get the code building on FreeBSD and Arch Linux we seem to need the following
# warning suppression to work around some issues in Boost headers.
#
# See the following reports:
# https://github.com/ethereum/webthree-umbrella/issues/384
# https://github.com/ethereum/webthree-helpers/pull/170
#
# The issue manifest as warnings-as-errors like the following:
#
# /usr/local/include/boost/multiprecision/cpp_int.hpp:181:4: error:
# right operand of shift expression '(1u << 63u)' is >= than the precision of the left operand
#
# -fpermissive is a pretty nasty way to address this. It is described as follows:
#
# Downgrade some diagnostics about nonconformant code from errors to warnings.
# Thus, using -fpermissive will allow some nonconforming code to compile.
#
# NB: Have to use this form for the setting, so that it only applies to C++ builds.
# Applying -fpermissive to a C command-line (ie. secp256k1) gives a build error.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
# Configuration-specific compiler settings.
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
@ -82,18 +61,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
# Additional Clang-specific compiler settings.
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# A couple of extra warnings suppressions which we seemingly
# need when building with Clang.
#
# TODO - Nail down exactly where these warnings are manifesting and
# try to suppress them in a more localized way. Notes in this file
# indicate that the first is needed for sepc256k1 and that the
# second is needed for the (clog, cwarn) macros. These will need
# testing on at least OS X and Ubuntu.
add_compile_options(-Wno-unused-function)
add_compile_options(-Wno-dangling-else)
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
# Set stack size to 16MB - by default Apple's clang defines a stack size of 8MB, some tests require more.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size -Wl,0x1000000")

4
cmake/FindCVC4.cmake Normal file
View File

@ -0,0 +1,4 @@
find_path(CVC4_INCLUDE_DIR cvc4/cvc4.h)
find_library(CVC4_LIBRARY NAMES cvc4 )
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CVC4 DEFAULT_MSG CVC4_LIBRARY CVC4_INCLUDE_DIR)

3
cmake/FindGMP.cmake Normal file
View File

@ -0,0 +1,3 @@
find_library(GMP_LIBRARY NAMES gmp )
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GMP DEFAULT_MSG GMP_LIBRARY)

View File

@ -1,4 +1,12 @@
[
{
"name": "OneOfTwoConstructorsSkipped",
"summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.",
"description": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored. There will be a compiler warning about the old-style constructor, so contracts only using new-style constructors are fine.",
"introduced": "0.4.22",
"fixed": "0.4.23",
"severity": "very low"
},
{
"name": "ZeroFunctionSelector",
"summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.",

View File

@ -423,9 +423,15 @@
"released": "2018-03-07"
},
"0.4.22": {
"bugs": [],
"bugs": [
"OneOfTwoConstructorsSkipped"
],
"released": "2018-04-16"
},
"0.4.23": {
"bugs": [],
"released": "2018-04-19"
},
"0.4.3": {
"bugs": [
"ZeroFunctionSelector",

View File

@ -225,9 +225,6 @@ Minor Details
=============
- In ``for (var i = 0; i < arrayName.length; i++) { ... }``, the type of ``i`` will be ``uint8``, because this is the smallest type that is required to hold the value ``0``. If the array has more than 255 elements, the loop will not terminate.
- The ``constant`` keyword for functions is currently not enforced by the compiler.
Furthermore, it is not enforced by the EVM, so a contract function that "claims"
to be constant might still cause changes to the state.
- Types that do not occupy the full 32 bytes might contain "dirty higher order bits".
This is especially important if you access ``msg.data`` - it poses a malleability risk:
You can craft transactions that call a function ``f(uint8 x)`` with a raw byte argument
@ -239,6 +236,22 @@ Minor Details
Recommendations
***************
Take Warnings Seriously
=======================
If the compiler warns you about something, you should better change it.
Even if you do not think that this particular warning has security
implications, there might be another issue buried beneath it.
Any compiler warning we issue can be silenced by slight changes to the
code.
Also try to enable the "0.5.0" safety features as early as possible
by adding ``pragma experimental "v0.5.0";``. Note that in this case,
the word ``experimental`` does not mean that the safety features are in any
way risky, it is just a way to enable some features that are
not yet part of the latest version of Solidity due to backwards
compatibility.
Restrict the Amount of Ether
============================

View File

@ -27,6 +27,11 @@
using namespace std;
static_assert(
(JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 7) && (JSONCPP_VERSION_PATCH == 7),
"Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.7.7."
);
namespace dev
{

View File

@ -6,10 +6,25 @@ find_package(Z3 QUIET)
if (${Z3_FOUND})
include_directories(${Z3_INCLUDE_DIR})
add_definitions(-DHAVE_Z3)
message("Z3 SMT solver found. This enables optional SMT checking.")
message("Z3 SMT solver found. This enables optional SMT checking with Z3.")
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
else()
message("Z3 SMT solver NOT found. Optional SMT checking will not be available. Please install Z3 if it is desired.")
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp")
find_package(GMP QUIET)
find_package(CVC4 QUIET)
if (${CVC4_FOUND})
if (${GMP_FOUND})
include_directories(${CVC4_INCLUDE_DIR})
add_definitions(-DHAVE_CVC4)
message("CVC4 SMT solver and GMP found. This enables optional SMT checking with CVC4.")
else()
message("CVC4 SMT solver found but its dependency GMP was NOT found. Optional SMT checking with CVC4 will not be available. Please install GMP if it is desired.")
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
endif()
else()
message("No SMT solver found (Z3 or CVC4). Optional SMT checking will not be available. Please install Z3 or CVC4 if it is desired.")
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
endif()
endif()
add_library(solidity ${sources} ${headers})
@ -17,4 +32,9 @@ target_link_libraries(solidity PUBLIC evmasm devcore)
if (${Z3_FOUND})
target_link_libraries(solidity PUBLIC ${Z3_LIBRARY})
endif()
endif()
if (${CVC4_FOUND} AND ${GMP_FOUND})
target_link_libraries(solidity PUBLIC ${CVC4_LIBRARY})
target_link_libraries(solidity PUBLIC ${GMP_LIBRARY})
endif()

View File

@ -237,8 +237,13 @@ bool SyntaxChecker::visit(FunctionDefinition const& _function)
if (v050)
m_errorReporter.syntaxError(_function.location(), "Functions without implementation cannot have modifiers.");
else
m_errorReporter.warning( _function.location(), "Modifiers of functions without implementation are ignored." );
m_errorReporter.warning(_function.location(), "Modifiers of functions without implementation are ignored." );
}
if (_function.name() == "constructor")
m_errorReporter.warning(_function.location(),
"This function is named \"constructor\" but is not the constructor of the contract. "
"If you intend this to be a constructor, use \"constructor(...) { ... }\" without the \"function\" keyword to define it."
);
return true;
}

View File

@ -109,39 +109,28 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
m_errorReporter.typeError(function->location(), "Constructor must be public or internal.");
}
FunctionDefinition const* fallbackFunction = nullptr;
for (FunctionDefinition const* function: _contract.definedFunctions())
{
if (function->isFallback())
{
if (fallbackFunction)
{
m_errorReporter.declarationError(function->location(), "Only one fallback function is allowed.");
}
else
{
fallbackFunction = function;
if (_contract.isLibrary())
m_errorReporter.typeError(fallbackFunction->location(), "Libraries cannot have fallback functions.");
if (function->stateMutability() != StateMutability::NonPayable && function->stateMutability() != StateMutability::Payable)
m_errorReporter.typeError(
function->location(),
"Fallback function must be payable or non-payable, but is \"" +
stateMutabilityToString(function->stateMutability()) +
"\"."
);
if (!fallbackFunction->parameters().empty())
m_errorReporter.typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
if (!fallbackFunction->returnParameters().empty())
m_errorReporter.typeError(fallbackFunction->returnParameterList()->location(), "Fallback function cannot return values.");
if (
_contract.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050) &&
fallbackFunction->visibility() != FunctionDefinition::Visibility::External
)
m_errorReporter.typeError(fallbackFunction->location(), "Fallback function must be defined as \"external\".");
}
if (_contract.isLibrary())
m_errorReporter.typeError(function->location(), "Libraries cannot have fallback functions.");
if (function->stateMutability() != StateMutability::NonPayable && function->stateMutability() != StateMutability::Payable)
m_errorReporter.typeError(
function->location(),
"Fallback function must be payable or non-payable, but is \"" +
stateMutabilityToString(function->stateMutability()) +
"\"."
);
if (!function->parameters().empty())
m_errorReporter.typeError(function->parameterList().location(), "Fallback function cannot take parameters.");
if (!function->returnParameters().empty())
m_errorReporter.typeError(function->returnParameterList()->location(), "Fallback function cannot return values.");
if (
_contract.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050) &&
function->visibility() != FunctionDefinition::Visibility::External
)
m_errorReporter.typeError(function->location(), "Fallback function must be defined as \"external\".");
}
}
for (auto const& n: _contract.subNodes())
if (!visited.count(n.get()))
@ -172,25 +161,34 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
/// Checks that two functions with the same name defined in this contract have different
/// argument types and that there is at most one constructor.
map<string, vector<FunctionDefinition const*>> functions;
FunctionDefinition const* constructor = nullptr;
FunctionDefinition const* fallback = nullptr;
for (FunctionDefinition const* function: _contract.definedFunctions())
functions[function->name()].push_back(function);
// Constructor
if (functions[_contract.name()].size() > 1)
{
SecondarySourceLocation ssl;
auto it = ++functions[_contract.name()].begin();
for (; it != functions[_contract.name()].end(); ++it)
ssl.append("Another declaration is here:", (*it)->location());
string msg = "More than one constructor defined.";
ssl.limitSize(msg);
m_errorReporter.declarationError(
functions[_contract.name()].front()->location(),
ssl,
msg
);
}
if (function->isConstructor())
{
if (constructor)
m_errorReporter.declarationError(
function->location(),
SecondarySourceLocation().append("Another declaration is here:", constructor->location()),
"More than one constructor defined."
);
constructor = function;
}
else if (function->isFallback())
{
if (fallback)
m_errorReporter.declarationError(
function->location(),
SecondarySourceLocation().append("Another declaration is here:", fallback->location()),
"Only one fallback function is allowed."
);
fallback = function;
}
else
{
solAssert(!function->name().empty(), "");
functions[function->name()].push_back(function);
}
findDuplicateDefinitions(functions, "Function with same name and arguments defined twice.");
}
@ -1906,7 +1904,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
// Retrieve the types of the arguments if this is used to call a function.
auto const& argumentTypes = _memberAccess.annotation().argumentTypes;
MemberList::MemberMap possibleMembers = exprType->members(m_scope).membersByName(memberName);
if (possibleMembers.size() > 1 && argumentTypes)
size_t const initialMemberCount = possibleMembers.size();
if (initialMemberCount > 1 && argumentTypes)
{
// do overload resolution
for (auto it = possibleMembers.begin(); it != possibleMembers.end();)
@ -1920,17 +1919,21 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
}
if (possibleMembers.size() == 0)
{
auto storageType = ReferenceType::copyForLocationIfReference(
DataLocation::Storage,
exprType
);
if (!storageType->members(m_scope).membersByName(memberName).empty())
m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" is not available in " +
exprType->toString() +
" outside of storage."
if (initialMemberCount == 0)
{
// Try to see if the member was removed because it is only available for storage types.
auto storageType = ReferenceType::copyForLocationIfReference(
DataLocation::Storage,
exprType
);
if (!storageType->members(m_scope).membersByName(memberName).empty())
m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" is not available in " +
exprType->toString() +
" outside of storage."
);
}
m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" not found or not visible "

View File

@ -1299,7 +1299,6 @@ bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo.category() == Category::Integer ||
_convertTo.category() == Category::FixedPoint ||
_convertTo.category() == Category::Contract ||
_convertTo.category() == category();
}

View File

@ -0,0 +1,200 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libsolidity/formal/CVC4Interface.h>
#include <libsolidity/interface/Exceptions.h>
#include <libdevcore/CommonIO.h>
using namespace std;
using namespace dev;
using namespace dev::solidity::smt;
CVC4Interface::CVC4Interface():
m_solver(&m_context)
{
reset();
}
void CVC4Interface::reset()
{
m_constants.clear();
m_functions.clear();
m_solver.reset();
m_solver.setOption("produce-models", true);
}
void CVC4Interface::push()
{
m_solver.push();
}
void CVC4Interface::pop()
{
m_solver.pop();
}
Expression CVC4Interface::newFunction(string _name, Sort _domain, Sort _codomain)
{
CVC4::Type fType = m_context.mkFunctionType(cvc4Sort(_domain), cvc4Sort(_codomain));
m_functions.insert({_name, m_context.mkVar(_name.c_str(), fType)});
return SolverInterface::newFunction(move(_name), _domain, _codomain);
}
Expression CVC4Interface::newInteger(string _name)
{
m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.integerType())});
return SolverInterface::newInteger(move(_name));
}
Expression CVC4Interface::newBool(string _name)
{
m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.booleanType())});
return SolverInterface::newBool(std::move(_name));
}
void CVC4Interface::addAssertion(Expression const& _expr)
{
try
{
m_solver.assertFormula(toCVC4Expr(_expr));
}
catch (CVC4::TypeCheckingException const&)
{
solAssert(false, "");
}
catch (CVC4::LogicException const&)
{
solAssert(false, "");
}
catch (CVC4::UnsafeInterruptException const&)
{
solAssert(false, "");
}
}
pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const& _expressionsToEvaluate)
{
CheckResult result;
vector<string> values;
try
{
switch (m_solver.checkSat().isSat())
{
case CVC4::Result::SAT:
result = CheckResult::SATISFIABLE;
break;
case CVC4::Result::UNSAT:
result = CheckResult::UNSATISFIABLE;
break;
case CVC4::Result::SAT_UNKNOWN:
result = CheckResult::UNKNOWN;
break;
default:
solAssert(false, "");
}
if (result != CheckResult::UNSATISFIABLE && !_expressionsToEvaluate.empty())
{
for (Expression const& e: _expressionsToEvaluate)
values.push_back(toString(m_solver.getValue(toCVC4Expr(e))));
}
}
catch (CVC4::Exception & e)
{
result = CheckResult::ERROR;
values.clear();
}
return make_pair(result, values);
}
CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
{
if (_expr.arguments.empty() && m_constants.count(_expr.name))
return m_constants.at(_expr.name);
vector<CVC4::Expr> arguments;
for (auto const& arg: _expr.arguments)
arguments.push_back(toCVC4Expr(arg));
string const& n = _expr.name;
if (m_functions.count(n))
return m_context.mkExpr(CVC4::kind::APPLY_UF, m_functions[n], arguments);
else if (m_constants.count(n))
{
solAssert(arguments.empty(), "");
return m_constants.at(n);
}
else if (arguments.empty())
{
if (n == "true")
return m_context.mkConst(true);
else if (n == "false")
return m_context.mkConst(false);
else
// We assume it is an integer...
return m_context.mkConst(CVC4::Rational(n));
}
solAssert(_expr.hasCorrectArity(), "");
if (n == "ite")
return arguments[0].iteExpr(arguments[1], arguments[2]);
else if (n == "not")
return arguments[0].notExpr();
else if (n == "and")
return arguments[0].andExpr(arguments[1]);
else if (n == "or")
return arguments[0].orExpr(arguments[1]);
else if (n == "=")
return m_context.mkExpr(CVC4::kind::EQUAL, arguments[0], arguments[1]);
else if (n == "<")
return m_context.mkExpr(CVC4::kind::LT, arguments[0], arguments[1]);
else if (n == "<=")
return m_context.mkExpr(CVC4::kind::LEQ, arguments[0], arguments[1]);
else if (n == ">")
return m_context.mkExpr(CVC4::kind::GT, arguments[0], arguments[1]);
else if (n == ">=")
return m_context.mkExpr(CVC4::kind::GEQ, arguments[0], arguments[1]);
else if (n == "+")
return m_context.mkExpr(CVC4::kind::PLUS, arguments[0], arguments[1]);
else if (n == "-")
return m_context.mkExpr(CVC4::kind::MINUS, arguments[0], arguments[1]);
else if (n == "*")
return m_context.mkExpr(CVC4::kind::MULT, arguments[0], arguments[1]);
else if (n == "/")
return m_context.mkExpr(CVC4::kind::INTS_DIVISION_TOTAL, arguments[0], arguments[1]);
// Cannot reach here.
solAssert(false, "");
return arguments[0];
}
CVC4::Type CVC4Interface::cvc4Sort(Sort _sort)
{
switch (_sort)
{
case Sort::Bool:
return m_context.booleanType();
case Sort::Int:
return m_context.integerType();
default:
break;
}
solAssert(false, "");
// Cannot be reached.
return m_context.integerType();
}

View File

@ -0,0 +1,62 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <libsolidity/formal/SolverInterface.h>
#include <boost/noncopyable.hpp>
#include <cvc4/cvc4.h>
namespace dev
{
namespace solidity
{
namespace smt
{
class CVC4Interface: public SolverInterface, public boost::noncopyable
{
public:
CVC4Interface();
void reset() override;
void push() override;
void pop() override;
Expression newFunction(std::string _name, Sort _domain, Sort _codomain) override;
Expression newInteger(std::string _name) override;
Expression newBool(std::string _name) override;
void addAssertion(Expression const& _expr) override;
std::pair<CheckResult, std::vector<std::string>> check(std::vector<Expression> const& _expressionsToEvaluate) override;
private:
CVC4::Expr toCVC4Expr(Expression const& _expr);
CVC4::Type cvc4Sort(smt::Sort _sort);
CVC4::ExprManager m_context;
CVC4::SmtEngine m_solver;
std::map<std::string, CVC4::Expr> m_constants;
std::map<std::string, CVC4::Expr> m_functions;
};
}
}
}

View File

@ -19,6 +19,8 @@
#ifdef HAVE_Z3
#include <libsolidity/formal/Z3Interface.h>
#elif HAVE_CVC4
#include <libsolidity/formal/CVC4Interface.h>
#else
#include <libsolidity/formal/SMTLib2Interface.h>
#endif
@ -39,6 +41,8 @@ using namespace dev::solidity;
SMTChecker::SMTChecker(ErrorReporter& _errorReporter, ReadCallback::Callback const& _readFileCallback):
#ifdef HAVE_Z3
m_interface(make_shared<smt::Z3Interface>()),
#elif HAVE_CVC4
m_interface(make_shared<smt::CVC4Interface>()),
#else
m_interface(make_shared<smt::SMTLib2Interface>(_readFileCallback)),
#endif
@ -464,7 +468,7 @@ void SMTChecker::compareOperation(BinaryOperation const& _op)
}
else // Bool
{
solAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "");
solUnimplementedAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "Operation not yet supported");
value = make_shared<smt::Expression>(
op == Token::Equal ? (left == right) :
op == Token::NotEqual ? (left != right) :
@ -835,7 +839,7 @@ void SMTChecker::createExpr(Expression const& _e)
m_expressions.emplace(&_e, m_interface->newBool(uniqueSymbol(_e)));
break;
default:
solAssert(false, "Type not implemented.");
solUnimplementedAssert(false, "Type not implemented.");
}
}
}

View File

@ -65,6 +65,26 @@ public:
Expression& operator=(Expression const&) = default;
Expression& operator=(Expression&&) = default;
bool hasCorrectArity() const
{
static std::map<std::string, unsigned> const operatorsArity{
{"ite", 3},
{"not", 1},
{"and", 2},
{"or", 2},
{"=", 2},
{"<", 2},
{"<=", 2},
{">", 2},
{">=", 2},
{"+", 2},
{"-", 2},
{"*", 2},
{"/", 2}
};
return operatorsArity.count(name) && operatorsArity.at(name) == arguments.size();
}
static Expression ite(Expression _condition, Expression _trueValue, Expression _falseValue)
{
solAssert(_trueValue.sort == _falseValue.sort, "");

View File

@ -116,21 +116,6 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
for (auto const& arg: _expr.arguments)
arguments.push_back(toZ3Expr(arg));
static map<string, unsigned> arity{
{"ite", 3},
{"not", 1},
{"and", 2},
{"or", 2},
{"=", 2},
{"<", 2},
{"<=", 2},
{">", 2},
{">=", 2},
{"+", 2},
{"-", 2},
{"*", 2},
{"/", 2}
};
string const& n = _expr.name;
if (m_functions.count(n))
return m_functions.at(n)(arguments);
@ -150,7 +135,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
return m_context.int_val(n.c_str());
}
solAssert(arity.count(n) && arity.at(n) == arguments.size(), "");
solAssert(_expr.hasCorrectArity(), "");
if (n == "ite")
return z3::ite(arguments[0], arguments[1], arguments[2]);
else if (n == "not")

View File

@ -51,9 +51,6 @@ private:
z3::expr toZ3Expr(Expression const& _expr);
z3::sort z3Sort(smt::Sort _sort);
std::string checkSatAndGetValuesCommand(std::vector<Expression> const& _expressionsToEvaluate);
std::vector<std::string> parseValues(std::string::const_iterator _start, std::string::const_iterator _end);
z3::context m_context;
z3::solver m_solver;
std::map<std::string, z3::expr> m_constants;

View File

@ -268,43 +268,39 @@ case $(uname -s) in
install_z3=""
case $(lsb_release -cs) in
trusty|qiana|rebecca|rafaela|rosa)
#trusty
echo "Installing solidity dependencies on Ubuntu Trusty Tahr (14.04)."
echo "Or, you may also be running Linux Mint Qiana / Rebecca / Rafaela / Rosa (base: Ubuntu Trusty Tahr (14.04).)"
;;
utopic)
#utopic
echo "Installing solidity dependencies on Ubuntu Utopic Unicorn (14.10)."
;;
vivid)
#vivid
echo "Installing solidity dependencies on Ubuntu Vivid Vervet (15.04)."
;;
wily)
#wily
echo "Installing solidity dependencies on Ubuntu Wily Werewolf (15.10)."
;;
xenial|sarah|serena|sonya|sylvia)
#xenial
echo "Installing solidity dependencies on Ubuntu Xenial Xerus (16.04)."
echo "Or, you may also be running Linux Mint Sarah / Serena / Sonya / Sylvia (base: Ubuntu Xenial Xerus (16.04).)"
install_z3="libz3-dev"
;;
yakkety)
#yakkety
echo "Installing solidity dependencies on Ubuntu Yakkety Yak (16.10)."
install_z3="libz3-dev"
;;
zesty)
#zesty
echo "Installing solidity dependencies on Ubuntu Zesty (17.04)."
install_z3="libz3-dev"
;;
artful)
#artful
echo "Installing solidity dependencies on Ubuntu Artful (17.10)."
install_z3="libz3-dev"
;;
bionic)
echo "Installing solidity dependencies on Ubuntu Bionic (18.04)."
install_z3="libz3-dev"
;;
betsy)
#do not try anything for betsy.
echo "Linux Mint Betsy is not supported at the moment as it runs off of Debian."
@ -319,7 +315,7 @@ case $(uname -s) in
echo "ERROR - Unknown or unsupported Ubuntu version (" $(lsb_release -cs) ")"
echo "ERROR - This might not work, but we are trying anyway."
echo "Please drop us a message at https://gitter.im/ethereum/solidity-dev."
echo "We only support Trusty, Utopic, Vivid, Wily, Xenial, Yakkety, Zesty and Artful."
echo "We only support Trusty, Utopic, Vivid, Wily, Xenial, Yakkety, Zesty, Artful and Bionic."
install_z3="libz3-dev"
;;
esac

View File

@ -54,7 +54,7 @@ keyid=703F83D0
email=builds@ethereum.org
packagename=solc
for distribution in trusty vivid xenial zesty artful
for distribution in trusty vivid xenial zesty artful bionic
do
cd /tmp/
rm -rf $distribution

View File

@ -42,13 +42,21 @@ else
log_directory=""
fi
echo "Running commandline tests..."
function printError() { echo "$(tput setaf 1)$1$(tput sgr0)"; }
function printTask() { echo "$(tput bold)$(tput setaf 2)$1$(tput sgr0)"; }
printTask "Running commandline tests..."
"$REPO_ROOT/test/cmdlineTests.sh" &
CMDLINE_PID=$!
# Only run in parallel if this is run on CI infrastructure
if [ -z "$CI" ]
then
wait $CMDLINE_PID
if ! wait $CMDLINE_PID
then
printError "Commandline tests FAILED"
exit 1
fi
fi
function download_eth()
@ -112,7 +120,7 @@ for optimize in "" "--optimize"
do
for vm in $EVM_VERSIONS
do
echo "--> Running tests using "$optimize" --evm-version "$vm"..."
printTask "--> Running tests using "$optimize" --evm-version "$vm"..."
log=""
if [ -n "$log_directory" ]
then
@ -127,7 +135,11 @@ do
done
done
wait $CMDLINE_PID
if ! wait $CMDLINE_PID
then
printError "Commandline tests FAILED"
exit 1
fi
pkill "$ETH_PID" || true
sleep 4

View File

@ -35,9 +35,9 @@ for v in versions:
continue
versions[v]['bugs'] += [bug['name']]
with open(path + '/../docs/bugs_by_version.json', 'r+') as bugs_by_version:
new_contents = json.dumps(versions, sort_keys=True, indent=4)
with open(path + '/../docs/bugs_by_version.json', 'r') as bugs_by_version:
old_contents = bugs_by_version.read()
new_contents = json.dumps(versions, sort_keys=True, indent=4)
bugs_by_version.seek(0)
with open(path + '/../docs/bugs_by_version.json', 'w') as bugs_by_version:
bugs_by_version.write(new_contents)
sys.exit(old_contents != new_contents)
sys.exit(old_contents != new_contents)

View File

@ -47,13 +47,6 @@ function test_truffle
cd "$DIR"
npm install
find . -name soljson.js -exec cp "$SOLJSON" {} \;
if [ "$name" == "Zeppelin" ]; then
# Fix some things that look like bugs (only seemed to fail on Node 6 and not Node 8)
# FIXME: report upstream or to web3.js?
sed -i -e 's/let token = await ERC827TokenMock.new();//;' test/token/ERC827/ERC827Token.js
sed -i -e 's/CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0)/CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, this.token.address)/' test/crowdsale/CappedCrowdsale.test.js
sed -i -e 's/RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, { from: owner })/RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, this.token.address, { from: owner })/' test/crowdsale/RefundableCrowdsale.test.js
fi
if [ "$name" == "Gnosis" ]; then
# Replace fixed-version pragmas in Gnosis (part of Consensys best practice)
find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity 0/pragma solidity ^0/'

View File

@ -243,16 +243,6 @@ BOOST_AUTO_TEST_CASE(assignment_to_struct)
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(returns_in_constructor)
{
char const* text = R"(
contract test {
function test() public returns (uint a) { }
}
)";
CHECK_ERROR(text, TypeError, "Non-empty \"returns\" directive for constructor.");
}
BOOST_AUTO_TEST_CASE(forward_function_reference)
{
char const* text = R"(
@ -869,26 +859,6 @@ BOOST_AUTO_TEST_CASE(complex_inheritance)
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(constructor_visibility)
{
// The constructor of a base class should not be visible in the derived class
char const* text = R"(
contract A { function A() public { } }
contract B is A { function f() public { A x = A(0); } }
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(overriding_constructor)
{
// It is fine to "override" constructor of a base class since it is invisible
char const* text = R"(
contract A { function A() public { } }
contract B is A { function A() public returns (uint8 r) {} }
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments)
{
char const* text = R"(
@ -907,35 +877,6 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments_override)
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(new_constructor_syntax)
{
char const* text = R"(
contract A { constructor() public {} }
)";
CHECK_SUCCESS_NO_WARNINGS(text);
}
BOOST_AUTO_TEST_CASE(old_constructor_syntax)
{
char const* text = R"(
contract A { function A() public {} }
)";
CHECK_WARNING(
text,
"Defining constructors as functions with the same name as the contract is deprecated."
);
text = R"(
pragma experimental "v0.5.0";
contract A { function A() public {} }
)";
CHECK_ERROR(
text,
SyntaxError,
"Functions are not allowed to have the same name as the contract."
);
}
BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion)
{
char const* text = R"(
@ -1199,7 +1140,6 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice)
}
)";
CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, (vector<string>{
"Function with same name and arguments defined twice.",
"Only one fallback function is"
}));
}
@ -2588,17 +2528,6 @@ BOOST_AUTO_TEST_CASE(override_changes_return_types)
CHECK_ERROR(sourceCode, TypeError, "Overriding function return types differ");
}
BOOST_AUTO_TEST_CASE(multiple_constructors)
{
char const* sourceCode = R"(
contract test {
function test(uint a) public { }
function test() public {}
}
)";
CHECK_ERROR(sourceCode, DeclarationError, "More than one constructor defined");
}
BOOST_AUTO_TEST_CASE(equal_overload)
{
char const* sourceCode = R"(
@ -3064,21 +2993,6 @@ BOOST_AUTO_TEST_CASE(literal_strings)
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
{
char const* text = R"(
contract Test {
struct S { uint8 a; mapping(uint => uint) b; uint8 c; }
S s;
function f() public {
S memory x;
x.b[1];
}
}
)";
CHECK_ERROR(text, TypeError, "Member \"b\" is not available in struct Test.S memory outside of storage.");
}
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
{
char const* text = R"(
@ -3122,19 +3036,6 @@ BOOST_AUTO_TEST_CASE(library_having_variables)
CHECK_ERROR(text, TypeError, "Library cannot have non-constant state variables");
}
BOOST_AUTO_TEST_CASE(library_constructor)
{
char const* text = R"(
library Lib {
function Lib();
}
)";
CHECK_ERROR_ALLOW_MULTI(text, TypeError, (vector<std::string>{
"Constructor cannot be defined in libraries.",
"Constructor must be implemented if declared."
}));
}
BOOST_AUTO_TEST_CASE(valid_library)
{
char const* text = R"(
@ -5030,38 +4931,6 @@ BOOST_AUTO_TEST_CASE(unsatisfied_version)
BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file requires different compiler version"));
}
BOOST_AUTO_TEST_CASE(invalid_constructor_statemutability)
{
char const* text = R"(
contract test {
function test() constant {}
}
)";
CHECK_ERROR(text, TypeError, "Constructor must be payable or non-payable");
text = R"(
contract test {
function test() view {}
}
)";
CHECK_ERROR(text, TypeError, "Constructor must be payable or non-payable");
text = R"(
contract test {
function test() pure {}
}
)";
CHECK_ERROR(text, TypeError, "Constructor must be payable or non-payable");
}
BOOST_AUTO_TEST_CASE(external_constructor)
{
char const* text = R"(
contract test {
function test() external {}
}
)";
CHECK_ERROR(text, TypeError, "Constructor must be public or internal.");
}
BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
{
char const* text = R"(
@ -5608,50 +5477,6 @@ BOOST_AUTO_TEST_CASE(assignment_to_constant)
CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable.");
}
BOOST_AUTO_TEST_CASE(inconstructible_internal_constructor)
{
char const* text = R"(
contract C {
function C() internal {}
}
contract D {
function f() public { var x = new C(); }
}
)";
CHECK_ERROR(text, TypeError, "Contract with internal constructor cannot be created directly.");
}
BOOST_AUTO_TEST_CASE(inconstructible_internal_constructor_inverted)
{
// Previously, the type information for A was not yet available at the point of
// "new A".
char const* text = R"(
contract B {
A a;
function B() public {
a = new A(this);
}
}
contract A {
function A(address a) internal {}
}
)";
CHECK_ERROR(text, TypeError, "Contract with internal constructor cannot be created directly.");
}
BOOST_AUTO_TEST_CASE(constructible_internal_constructor)
{
char const* text = R"(
contract C {
function C() internal {}
}
contract D is C {
function D() public { }
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(return_structs)
{
char const* text = R"(
@ -5813,19 +5638,6 @@ BOOST_AUTO_TEST_CASE(interface)
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(interface_constructor)
{
char const* text = R"(
interface I {
function I();
}
)";
CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector<std::string>{
"Constructor cannot be defined in interfaces",
"Constructor must be implemented if declared.",
}));
}
BOOST_AUTO_TEST_CASE(interface_functions)
{
char const* text = R"(
@ -6907,16 +6719,6 @@ BOOST_AUTO_TEST_CASE(builtin_reject_value)
CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup");
}
BOOST_AUTO_TEST_CASE(constructor_without_implementation)
{
char const* text = R"(
contract C {
function C();
}
)";
CHECK_ERROR(text, TypeError, "Constructor must be implemented if declared.");
}
BOOST_AUTO_TEST_CASE(large_storage_array_fine)
{
char const* text = R"(

View File

@ -0,0 +1,6 @@
contract C {
constructor() internal {}
}
contract D is C {
constructor() public { }
}

View File

@ -0,0 +1,9 @@
contract C {
function C() internal {}
}
contract D is C {
function D() public {}
}
// ----
// Warning: (14-38): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// Warning: (60-82): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.

View File

@ -0,0 +1 @@
contract A { constructor() public {} }

View File

@ -0,0 +1,3 @@
contract A { function A() public {} }
// ----
// Warning: (13-35): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.

View File

@ -0,0 +1,4 @@
pragma experimental "v0.5.0";
contract A { function A() public {} }
// ----
// SyntaxError: (43-65): Functions are not allowed to have the same name as the contract. If you intend this to be a constructor, use "constructor(...) { ... }" to define it.

View File

@ -0,0 +1,13 @@
contract test1 {
constructor() constant {}
}
contract test2 {
constructor() view {}
}
contract test3 {
constructor() pure {}
}
// ----
// TypeError: (19-44): Constructor must be payable or non-payable, but is "view".
// TypeError: (66-87): Constructor must be payable or non-payable, but is "view".
// TypeError: (109-130): Constructor must be payable or non-payable, but is "pure".

View File

@ -0,0 +1,16 @@
contract test1 {
function test1() constant {}
}
contract test2 {
function test2() view {}
}
contract test3 {
function test3() pure {}
}
// ----
// Warning: (21-49): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// Warning: (73-97): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// Warning: (121-145): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (21-49): Constructor must be payable or non-payable, but is "view".
// TypeError: (73-97): Constructor must be payable or non-payable, but is "view".
// TypeError: (121-145): Constructor must be payable or non-payable, but is "pure".

View File

@ -0,0 +1,12 @@
// The constructor of a base class should not be visible in the derived class
contract A { constructor(string) public { } }
contract B is A {
function f() pure public {
A x = A(0); // convert from address
string memory y = "ab";
A(y); // call as a function is invalid
x;
}
}
// ----
// TypeError: (243-247): Explicit type conversion not allowed from "string memory" to "contract A".

View File

@ -0,0 +1,13 @@
// The constructor of a base class should not be visible in the derived class
contract A { function A(string s) public { } }
contract B is A {
function f() pure public {
A x = A(0); // convert from address
string memory y = "ab";
A(y); // call as a function is invalid
x;
}
}
// ----
// Warning: (91-122): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (244-248): Explicit type conversion not allowed from "string memory" to "contract A".

View File

@ -0,0 +1,5 @@
contract C {
constructor();
}
// ----
// TypeError: (14-28): Constructor must be implemented if declared.

View File

@ -0,0 +1,6 @@
contract C {
function C();
}
// ----
// Warning: (14-27): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (14-27): Constructor must be implemented if declared.

View File

@ -0,0 +1,5 @@
contract test {
constructor() external {}
}
// ----
// TypeError: (17-42): Constructor must be public or internal.

View File

@ -0,0 +1,6 @@
contract test {
function test() external {}
}
// ----
// Warning: (17-44): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (17-44): Constructor must be public or internal.

View File

@ -0,0 +1,5 @@
contract C {
function constructor() public;
}
// ----
// Warning: (17-47): This function is named "constructor" but is not the constructor of the contract. If you intend this to be a constructor, use "constructor(...) { ... }" without the "function" keyword to define it.

View File

@ -0,0 +1,13 @@
// Previously, the type information for A was not yet available at the point of
// "new A".
contract B {
A a;
constructor() public {
a = new A(this);
}
}
contract A {
constructor(address a) internal {}
}
// ----
// TypeError: (141-146): Contract with internal constructor cannot be created directly.

View File

@ -0,0 +1,15 @@
// Previously, the type information for A was not yet available at the point of
// "new A".
contract B {
A a;
function B() public {
a = new A(this);
}
}
contract A {
function A(address a) internal {}
}
// ----
// Warning: (112-155): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// Warning: (172-205): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (140-145): Contract with internal constructor cannot be created directly.

View File

@ -0,0 +1,8 @@
contract C {
constructor() internal {}
}
contract D {
function f() public { C c = new C(); c; }
}
// ----
// TypeError: (84-89): Contract with internal constructor cannot be created directly.

View File

@ -0,0 +1,9 @@
contract C {
function C() internal {}
}
contract D {
function f() public { C x = new C(); x; }
}
// ----
// Warning: (14-38): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (83-88): Contract with internal constructor cannot be created directly.

View File

@ -0,0 +1,7 @@
interface I {
constructor();
}
// ----
// Warning: (15-29): Functions in interfaces should be declared external.
// TypeError: (15-29): Constructor cannot be defined in interfaces.
// TypeError: (15-29): Constructor must be implemented if declared.

View File

@ -0,0 +1,8 @@
interface I {
function I();
}
// ----
// Warning: (15-28): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// Warning: (15-28): Functions in interfaces should be declared external.
// TypeError: (15-28): Constructor cannot be defined in interfaces.
// TypeError: (15-28): Constructor must be implemented if declared.

View File

@ -0,0 +1,6 @@
library Lib {
constructor();
}
// ----
// TypeError: (15-29): Constructor cannot be defined in libraries.
// TypeError: (15-29): Constructor must be implemented if declared.

View File

@ -0,0 +1,7 @@
library Lib {
function Lib();
}
// ----
// Warning: (15-30): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (15-30): Constructor cannot be defined in libraries.
// TypeError: (15-30): Constructor must be implemented if declared.

View File

@ -0,0 +1,6 @@
// It is fine to "override" constructor of a base class since it is invisible
contract A { function A() public { } }
contract B is A { function A() public pure returns (uint8) {} }
// ----
// Warning: (91-114): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// Warning: (135-178): This declaration shadows an existing declaration.

View File

@ -0,0 +1,5 @@
contract test {
constructor() public returns (uint a) { }
}
// ----
// TypeError: (46-54): Non-empty "returns" directive for constructor.

View File

@ -0,0 +1,6 @@
contract test {
function test() public returns (uint a) { }
}
// ----
// Warning: (17-60): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// TypeError: (48-56): Non-empty "returns" directive for constructor.

View File

@ -0,0 +1,7 @@
contract test {
function test(uint) public { }
constructor() public {}
}
// ----
// Warning: (17-47): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// DeclarationError: (49-72): More than one constructor defined.

View File

@ -0,0 +1,6 @@
contract test {
constructor(uint) public { }
constructor() public {}
}
// ----
// DeclarationError: (47-70): More than one constructor defined.

View File

@ -0,0 +1,8 @@
contract test {
function test(uint a) public { }
function test() public {}
}
// ----
// Warning: (17-49): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// Warning: (51-76): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
// DeclarationError: (51-76): More than one constructor defined.

View File

@ -0,0 +1,7 @@
contract C {
function f(uint, uint) {}
function f(uint) {}
function g() { f(1, 2, 3); }
}
// ----
// TypeError: (80-81): No matching declaration found after argument-dependent lookup.

View File

@ -0,0 +1,9 @@
library L {
function f(uint, uint) {}
function f(uint) {}
}
contract C {
function g() { L.f(1, 2, 3); }
}
// ----
// TypeError: (94-97): Member "f" not found or not visible after argument-dependent lookup in type(library L)

View File

@ -0,0 +1,10 @@
contract Test {
struct S { uint8 a; mapping(uint => uint) b; uint8 c; }
S s;
function f() public {
S memory x;
x.b[1];
}
}
// ----
// TypeError: (118-121): Member "b" is not available in struct Test.S memory outside of storage.

View File

@ -0,0 +1,8 @@
contract Test {
function f() public pure {
uint[] memory x;
x.push(1);
}
}
// ----
// TypeError: (77-83): Member "push" is not available in uint256[] memory outside of storage.

View File

@ -0,0 +1,7 @@
contract C {
function f() public pure {
C(bytes20(0x1234));
}
}
// ----
// TypeError: (64-82): Explicit type conversion not allowed from "bytes20" to "contract C".