diff --git a/.circleci/README.md b/.circleci/README.md
new file mode 100644
index 000000000..8c411c7b1
--- /dev/null
+++ b/.circleci/README.md
@@ -0,0 +1,21 @@
+## CircleCI integration
+
+### Docker images
+
+The docker images are build locally on the developer machine:
+
+```!sh
+cd .circleci/docker/
+
+docker build -t ethereum/solc-buildpack-deps:ubuntu1904 -f Dockerfile.ubuntu1904 .
+docker push solidity/solc-buildpack-deps:ubuntu1904
+
+docker build -t ethereum/solc-buildpack-deps:archlinux -f Dockerfile.archlinux .
+docker push solidity/solc-buildpack-deps:archlinux
+```
+
+which you can find on Dockerhub after the push at:
+
+ https://hub.docker.com/r/ethereum/solidity-buildpack-deps
+
+where the image tag reflects the target OS to build Solidity and run its test on.
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3ea21ff0d..d88cb0269 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,48 +1,72 @@
+# vim:ts=2:sw=2:et
+# --------------------------------------------------------------------------
+# Prefixes used in order to keep CircleCI workflow overview more readable:
+# - b: build
+# - t: test
+# - ubu: ubuntu
+# - ems: Emscripten
+version: 2
+
defaults:
- # The default for tags is to not run, so we have to explicitly match a filter.
- - build_on_tags: &build_on_tags
- filters:
- tags:
- only: /.*/
+
+ # --------------------------------------------------------------------------
+ # Build Templates
+
- setup_prerelease_commit_hash: &setup_prerelease_commit_hash
name: Store commit hash and prerelease
command: |
if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
echo -n "$CIRCLE_SHA1" > commit_hash.txt
+
- run_build: &run_build
name: Build
command: |
+ set -ex
+ if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
+ echo -n "$CIRCLE_SHA1" > commit_hash.txt
mkdir -p build
cd build
[ -n "$COVERAGE" -a "$CIRCLE_BRANCH" != release -a -z "$CIRCLE_TAG" ] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON"
- cmake .. -DCMAKE_BUILD_TYPE=Release $CMAKE_OPTIONS
+ cmake .. -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release} $CMAKE_OPTIONS -G "Unix Makefiles"
make -j4
+
- run_build_ossfuzz: &run_build_ossfuzz
name: Build_ossfuzz
command: |
mkdir -p build
cd build
- /src/LPM/external.protobuf/bin/protoc --proto_path=../test/tools/ossfuzz yulProto.proto --cpp_out=../test/tools/ossfuzz
- cmake .. -DCMAKE_BUILD_TYPE=Release $CMAKE_OPTIONS
+ protoc --proto_path=../test/tools/ossfuzz yulProto.proto --cpp_out=../test/tools/ossfuzz
+ cmake .. -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release} $CMAKE_OPTIONS
make ossfuzz ossfuzz_proto -j4
- - run_tests: &run_tests
- name: Tests
- command: scripts/tests.sh --junit_report test_results
- - run_regressions: &run_regressions
- name: Regression tests
- command: |
- export ASAN_OPTIONS="check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2"
- scripts/regressions.py -o test_results
- - solc_artifact: &solc_artifact
+
+ - run_proofs: &run_proofs
+ name: Correctness proofs for optimization rules
+ command: scripts/run_proofs.sh
+
+ # --------------------------------------------------------------------------
+ # Artifacts Templates
+
+ # the whole build directory
+ - artifacts_build_dir: &artifacts_build_dir
+ root: build
+ paths:
+ - "*"
+
+ # compiled solc executable target
+ - artifacts_solc: &artifacts_solc
path: build/solc/solc
destination: solc
- - all_artifacts: &all_artifacts
+
+ # compiled executable targets
+ - artifacts_executables: &artifacts_executables
root: build
paths:
- solc/solc
- test/soltest
- test/tools/solfuzzer
- - ossfuzz_artifacts: &ossfuzz_artifacts
+
+ # compiled OSSFUZZ targets
+ - artifacts_executables_ossfuzz: &artifacts_executables_ossfuzz
root: build
paths:
- test/tools/ossfuzz/const_opt_ossfuzz
@@ -54,9 +78,280 @@ defaults:
- test/tools/ossfuzz/yul_proto_diff_ossfuzz
- test/tools/ossfuzz/yul_proto_ossfuzz
-version: 2
+ # test result output directory
+ - artifacts_test_results: &artifacts_test_results
+ path: test_results/
+ destination: test_results/
+
+ # --------------------------------------------------------------------------
+ # Tests Templates
+
+ # store_test_results helper
+ - store_test_results: &store_test_results
+ path: test_results/
+
+ - run_soltest: &run_soltest
+ name: soltest
+ command: ./.circleci/soltest.sh
+
+ - run_cmdline_tests: &run_cmdline_tests
+ name: command line tests
+ command: ./test/cmdlineTests.sh
+
+ - test_steps: &test_steps
+ - checkout
+ - attach_workspace:
+ at: build
+ - run: *run_soltest
+ - store_test_results: *store_test_results
+ - store_artifacts: *artifacts_test_results
+
+ - test_ubuntu1904: &test_ubuntu1904
+ docker:
+ - image: ethereum/solidity-buildpack-deps:ubuntu1904
+ steps: *test_steps
+
+ - test_asan: &test_asan
+ <<: *test_ubuntu1904
+ steps:
+ - checkout
+ - attach_workspace:
+ at: build
+ - run:
+ <<: *run_soltest
+ no_output_timeout: 30m
+ - store_test_results: *store_test_results
+ - store_artifacts: *artifacts_test_results
+
+ # --------------------------------------------------------------------------
+ # Workflow Templates
+
+ - workflow_trigger_on_tags: &workflow_trigger_on_tags
+ filters:
+ tags:
+ only: /.*/
+
+ - workflow_ubuntu1904: &workflow_ubuntu1904
+ <<: *workflow_trigger_on_tags
+ requires:
+ - b_ubu
+
+ - workflow_ubuntu1904_codecov: &workflow_ubuntu1904_codecov
+ <<: *workflow_trigger_on_tags
+ requires:
+ - b_ubu_codecov
+
+ - workflow_osx: &workflow_osx
+ <<: *workflow_trigger_on_tags
+ requires:
+ - b_osx
+
+ - workflow_ubuntu1904_asan: &workflow_ubuntu1904_asan
+ <<: *workflow_trigger_on_tags
+ requires:
+ - b_ubu_asan
+
+ - workflow_emscripten: &workflow_emscripten
+ <<: *workflow_trigger_on_tags
+ requires:
+ - b_ems
+
+ - workflow_ubuntu1904_ossfuzz: &workflow_ubuntu1904_ossfuzz
+ <<: *workflow_trigger_on_tags
+ requires:
+ - b_ubu_ossfuzz
+
+# -----------------------------------------------------------------------------------------------
jobs:
- build_emscripten:
+
+ chk_spelling:
+ docker:
+ - image: circleci/python:3.6
+ environment:
+ TERM: xterm
+ steps:
+ - checkout
+ - attach_workspace:
+ at: build
+ - run:
+ name: Install dependencies
+ command: |
+ pip install --user codespell
+ - run:
+ name: Check spelling
+ command: ~/.local/bin/codespell -S "*.enc,.git" -I ./scripts/codespell_whitelist.txt
+
+ chk_coding_style:
+ docker:
+ - image: buildpack-deps:disco
+ steps:
+ - checkout
+ - run:
+ name: Check for C++ coding style
+ command: ./scripts/check_style.sh
+
+ chk_buglist:
+ docker:
+ - image: circleci/node
+ environment:
+ TERM: xterm
+ steps:
+ - checkout
+ - run:
+ name: JS deps
+ command: |
+ npm install download
+ npm install JSONPath
+ npm install mktemp
+ - run:
+ name: Test buglist
+ command: ./test/buglistTests.js
+
+ chk_proofs:
+ docker:
+ - image: buildpack-deps:disco
+ environment:
+ TERM: xterm
+ steps:
+ - checkout
+ - run:
+ name: Z3 python deps
+ command: |
+ apt-get -qq update
+ apt-get -qy install python-pip
+ pip install --user z3-solver
+ - run: *run_proofs
+
+ b_ubu: &build_ubuntu1904
+ docker:
+ - image: ethereum/solidity-buildpack-deps:ubuntu1904
+ steps:
+ - checkout
+ - run: *run_build
+ - store_artifacts: *artifacts_solc
+ - persist_to_workspace: *artifacts_executables
+
+ b_ubu_codecov:
+ <<: *build_ubuntu1904
+ environment:
+ COVERAGE: ON
+ CMAKE_BUILD_TYPE: Debug
+ steps:
+ - checkout
+ - run: *run_build
+ - persist_to_workspace: *artifacts_build_dir
+
+ t_ubu_codecov:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: constantinople
+ OPTIMIZE: 1
+ steps:
+ - checkout
+ - attach_workspace:
+ at: build
+ - run:
+ name: "soltest: Syntax Tests"
+ command: build/test/soltest -t 'syntaxTest*' -- --no-ipc --testpath test
+ - run:
+ name: "Code Coverage: Syntax Tests"
+ command: codecov --flags syntax --gcov-root build
+ - run: *run_soltest
+ - run:
+ name: "Coverage: All"
+ command: codecov --flags all --gcov-root build
+ - store_artifacts: *artifacts_test_results
+
+ # Builds in C++17 mode and uses debug build in order to speed up.
+ # Do *NOT* store any artifacts or workspace as we don't run tests on this build.
+ b_ubu_cxx17:
+ <<: *build_ubuntu1904
+ environment:
+ CMAKE_BUILD_TYPE: Debug
+ CMAKE_OPTIONS: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/cxx17.cmake -DUSE_CVC4=OFF
+ steps:
+ - checkout
+ - run: *run_build
+
+ b_ubu_ossfuzz:
+ <<: *build_ubuntu1904
+ environment:
+ TERM: xterm
+ CC: /usr/bin/clang-8
+ CXX: /usr/bin/clang++-8
+ CMAKE_OPTIONS: -DOSSFUZZ=1 -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/libfuzzer.cmake
+ steps:
+ - checkout
+ - run: *setup_prerelease_commit_hash
+ - run: *run_build_ossfuzz
+ - persist_to_workspace: *artifacts_executables_ossfuzz
+
+ t_ubu_ossfuzz: &t_ubu_ossfuzz
+ <<: *test_ubuntu1904
+ steps:
+ - checkout
+ - attach_workspace:
+ at: build
+ - run:
+ name: Regression tests
+ command: |
+ mkdir -p test_results
+ export ASAN_OPTIONS="check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2"
+ scripts/regressions.py -o test_results
+ - store_test_results: *store_test_results
+ - store_artifacts: *artifacts_test_results
+
+ b_archlinux:
+ docker:
+ - image: ethereum/solidity-buildpack-deps:archlinux
+ environment:
+ TERM: xterm
+ steps:
+ - checkout
+ - run: *run_build
+ - store_artifacts: *artifacts_solc
+ - persist_to_workspace: *artifacts_executables
+
+ b_osx:
+ macos:
+ xcode: "10.0.0"
+ environment:
+ TERM: xterm
+ CMAKE_BUILD_TYPE: Debug
+ CMAKE_OPTIONS: -DLLL=ON
+ steps:
+ - checkout
+ - run:
+ name: Install build dependencies
+ command: |
+ brew unlink python
+ brew install z3
+ brew install boost
+ brew install cmake
+ brew install wget
+ ./scripts/install_obsolete_jsoncpp_1_7_4.sh
+ - run: *run_build
+ - store_artifacts: *artifacts_solc
+ - persist_to_workspace: *artifacts_executables
+
+ t_osx_cli:
+ macos:
+ xcode: "10.0.0"
+ environment:
+ TERM: xterm
+ steps:
+ - checkout
+ - attach_workspace:
+ at: build
+ - run:
+ name: Install dependencies
+ command: |
+ brew unlink python
+ brew install z3
+ - run: *run_cmdline_tests
+ - store_artifacts: *artifacts_test_results
+
+ b_ems:
docker:
- image: trzeci/emscripten:sdk-tag-1.38.22-64bit
environment:
@@ -78,7 +373,7 @@ jobs:
name: Save Boost build
key: *boost-cache-key
paths:
- - boost_1_68_0
+ - boost_1_70_0_install
- store_artifacts:
path: emscripten_build/libsolc/soljson.js
destination: soljson.js
@@ -91,7 +386,123 @@ jobs:
- soljson.js
- version.txt
- test_emscripten_solcjs:
+ # x64 ASAN build, for testing for memory related bugs
+ b_ubu_asan: &b_ubu_asan
+ <<: *build_ubuntu1904
+ environment:
+ CMAKE_OPTIONS: -DSANITIZE=address
+ CMAKE_BUILD_TYPE: Release
+ steps:
+ - checkout
+ - run: *run_build
+ - store_artifacts: *artifacts_solc
+ - persist_to_workspace: *artifacts_executables
+
+ b_docs:
+ docker:
+ - image: ethereum/solidity-buildpack-deps:ubuntu1904
+ steps:
+ - checkout
+ - run: *setup_prerelease_commit_hash
+ - run:
+ name: Build documentation
+ command: ./scripts/docs.sh
+ - store_artifacts:
+ path: docs/_build/html/
+ destination: docs-html
+
+ t_ubu_cli: &t_ubu_cli
+ docker:
+ - image: ethereum/solidity-buildpack-deps:ubuntu1904
+ environment:
+ TERM: xterm
+ steps:
+ - checkout
+ - attach_workspace:
+ at: build
+ - run: *run_cmdline_tests
+ - store_test_results: *store_test_results
+ - store_artifacts: *artifacts_test_results
+
+ t_ubu_asan_cli:
+ <<: *t_ubu_cli
+ environment:
+ TERM: xterm
+ ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2
+ steps:
+ - checkout
+ - attach_workspace:
+ at: build
+ - run:
+ <<: *run_cmdline_tests
+ no_output_timeout: 30m
+ - store_test_results: *store_test_results
+ - store_artifacts: *artifacts_test_results
+
+ t_ubu_asan_constantinople:
+ <<: *test_asan
+ environment:
+ EVM: constantinople
+ OPTIMIZE: 0
+ SOLTEST_IPC: 0
+ ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2
+
+ t_ubu_homestead:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: homestead
+ OPTIMIZE: 0
+
+ t_ubu_homestead_opt:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: homestead
+ OPTIMIZE: 1
+
+ t_ubu_byzantium:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: byzantium
+ OPTIMIZE: 0
+
+ t_ubu_byzantium_opt:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: byzantium
+ OPTIMIZE: 1
+
+ t_ubu_constantinople:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: constantinople
+ OPTIMIZE: 0
+
+ t_ubu_constantinople_opt:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: constantinople
+ OPTIMIZE: 1
+
+ t_ubu_constantinople_opt_abiv2:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: constantinople
+ OPTIMIZE: 1
+ ABI_ENCODER_V2: 1
+
+ t_ubu_petersburg:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: petersburg
+ OPTIMIZE: 0
+
+ t_ubu_petersburg_opt:
+ <<: *test_ubuntu1904
+ environment:
+ EVM: petersburg
+ OPTIMIZE: 1
+
+ t_ems_solcjs:
docker:
- image: circleci/node:10
environment:
@@ -101,16 +512,13 @@ jobs:
- attach_workspace:
at: /tmp/workspace
- run:
- name: Install external tests deps
+ name: Test solcjs
command: |
node --version
npm --version
- - run:
- name: Test solcjs
- command: |
test/solcjsTests.sh /tmp/workspace/soljson.js $(cat /tmp/workspace/version.txt)
- test_emscripten_external_gnosis:
+ t_ems_external_gnosis:
docker:
- image: circleci/node:10
environment:
@@ -124,7 +532,7 @@ jobs:
command: |
test/externalTests/gnosis.sh /tmp/workspace/soljson.js || test/externalTests/gnosis.sh /tmp/workspace/soljson.js
- test_emscripten_external_zeppelin:
+ t_ems_external_zeppelin:
docker:
- image: circleci/node:10
environment:
@@ -138,7 +546,7 @@ jobs:
command: |
test/externalTests/zeppelin.sh /tmp/workspace/soljson.js || test/externalTests/zeppelin.sh /tmp/workspace/soljson.js
- test_emscripten_external_colony:
+ t_ems_external_colony:
docker:
- image: circleci/node:10
environment:
@@ -156,370 +564,51 @@ jobs:
command: |
test/externalTests/colony.sh /tmp/workspace/soljson.js || test/externalTests/colony.sh /tmp/workspace/soljson.js
- build_x86_linux:
- docker:
- - image: buildpack-deps:bionic
- environment:
- TERM: xterm
- COVERAGE: "ON"
- steps:
- - checkout
- - run:
- name: Install build dependencies
- command: |
- apt-get -qq update
- apt-get -qy install cmake libboost-regex-dev libboost-filesystem-dev libboost-test-dev libboost-system-dev libboost-program-options-dev libcvc4-dev libjsoncpp-dev=1.7.4-\*
- - run: *setup_prerelease_commit_hash
- - run: *run_build
- - store_artifacts: *solc_artifact
- - persist_to_workspace:
- root: build
- paths:
- - "*"
-
- build_x86_linux_cxx17:
- docker:
- - image: buildpack-deps:disco
- environment:
- TERM: xterm
- CMAKE_OPTIONS: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/cxx17.cmake
- steps:
- - checkout
- - run:
- name: Install build dependencies
- command: |
- apt-get -qq update
- apt-get -qy install cmake libboost-regex-dev libboost-filesystem-dev libboost-test-dev libboost-system-dev libboost-program-options-dev libcvc4-dev libjsoncpp-dev=1.7.4-\*
- - run: *setup_prerelease_commit_hash
- - run: *run_build
-
- build_x86_archlinux:
- docker:
- - image: archlinux/base
- environment:
- TERM: xterm
- steps:
- - run:
- name: Install build dependencies
- command: |
- pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar
- - checkout
- - run: *setup_prerelease_commit_hash
- - run: *run_build
- - store_artifacts: *solc_artifact
- - persist_to_workspace:
- root: build
- paths:
- - solc/solc
- - test/soltest
- - test/tools/solfuzzer
-
- build_x86_clang7_asan:
- docker:
- - image: buildpack-deps:cosmic
- environment:
- TERM: xterm
- CC: /usr/bin/clang-7
- CXX: /usr/bin/clang++-7
- CMAKE_OPTIONS: -DSANITIZE=address -DCMAKE_BUILD_TYPE=Debug
- steps:
- - checkout
- - run:
- name: Install build dependencies
- command: |
- apt-get -qq update
- apt-get -qy install clang-7 cmake libboost-regex-dev libboost-filesystem-dev libboost-test-dev libboost-system-dev libboost-program-options-dev libcvc4-dev libjsoncpp-dev=1.7.4-\*
- - run: *setup_prerelease_commit_hash
- - run: *run_build
- - store_artifacts: *solc_artifact
- - persist_to_workspace:
- root: build
- paths:
- - solc/solc
- - test/soltest
- - test/tools/solfuzzer
-
- build_x86_mac:
- macos:
- xcode: "10.0.0"
- environment:
- TERM: xterm
- CMAKE_OPTIONS: -DLLL=ON
- steps:
- - checkout
- - run:
- name: Install build dependencies
- command: |
- brew unlink python
- brew install z3
- brew install boost
- brew install cmake
- brew install wget
- ./scripts/install_obsolete_jsoncpp_1_7_4.sh
- - run: *setup_prerelease_commit_hash
- - run: *run_build
- - store_artifacts: *solc_artifact
- - persist_to_workspace: *all_artifacts
-
- test_check_spelling:
- docker:
- - image: circleci/python:3.6
- environment:
- TERM: xterm
- steps:
- - checkout
- - attach_workspace:
- at: build
- - run:
- name: Install dependencies
- command: |
- pip install --user codespell
- - run:
- name: Check spelling
- command: ~/.local/bin/codespell -S "*.enc,.git" -I ./scripts/codespell_whitelist.txt
-
- test_check_style:
- docker:
- - image: buildpack-deps:bionic
- steps:
- - checkout
- - run:
- name: Check for trailing whitespace
- command: ./scripts/check_style.sh
-
- test_buglist:
- docker:
- - image: circleci/node
- environment:
- TERM: xterm
- steps:
- - checkout
- - run:
- name: JS deps
- command: |
- npm install download
- npm install JSONPath
- npm install mktemp
- - run:
- name: Test buglist
- command: ./test/buglistTests.js
-
- test_x86_linux:
- docker:
- - image: buildpack-deps:bionic
- environment:
- TERM: xterm
- steps:
- - checkout
- - attach_workspace:
- at: build
- - run:
- name: Install dependencies
- command: |
- apt-get -qq update
- apt-get -qy install libcvc4-dev libleveldb1v5 python-pip
- pip install codecov
- - run: mkdir -p test_results
- - run:
- name: Test type checker
- command: build/test/soltest -t 'syntaxTest*' -- --no-ipc --testpath test
- - run:
- name: Coverage of type checker
- command: codecov --flags syntax --gcov-root build
- - run: *run_tests
- - run:
- name: Coverage of all
- command: codecov --flags all --gcov-root build
- - store_test_results:
- path: test_results/
- - store_artifacts:
- path: test_results/
- destination: test_results/
-
- test_x86_clang7_asan:
- docker:
- - image: buildpack-deps:cosmic
- environment:
- TERM: xterm
- steps:
- - checkout
- - attach_workspace:
- at: build
- - run:
- name: Install dependencies
- command: |
- apt-get -qq update
- apt-get -qy install llvm-7-dev libcvc4-dev libleveldb1v5 python-pip
- # This is needed to resolve the symbols. Since we're using clang7 in the build, we must use the appropriate symbolizer.
- update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-7 1
- - run: mkdir -p test_results
- - run:
- name: Run soltest with ASAN
- command: |
- ulimit -a
- # Increase stack size because ASan makes stack frames bigger and that breaks our assumptions (in tests).
- ulimit -s 16384
- export ASAN_OPTIONS="check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2"
- build/test/soltest --logger=JUNIT,test_suite,test_results/result.xml -- --no-ipc --testpath test
- - run:
- name: Run commandline tests with ASAN
- command: |
- ulimit -a
- # Increase stack size because ASan makes stack frames bigger and that breaks our assumptions (in tests).
- ulimit -s 16384
- export ASAN_OPTIONS="check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2"
- test/cmdlineTests.sh
- - store_test_results:
- path: test_results/
- - store_artifacts:
- path: test_results/
- destination: test_results/
-
- test_x86_archlinux:
- docker:
- - image: archlinux/base
- environment:
- TERM: xterm
- steps:
- - run:
- name: Install dependencies
- command: |
- pacman --noconfirm -Syu --noprogressbar --needed boost z3 cvc4 git openssh tar
- - checkout
- - attach_workspace:
- at: build
- - run: mkdir -p test_results
- - run: build/test/soltest --logger=JUNIT,test_suite,test_results/result.xml -- --no-ipc --testpath test
- - store_test_results:
- path: test_results/
- - store_artifacts:
- path: test_results/
- destination: test_results/
-
- test_x86_mac:
- macos:
- xcode: "10.0.0"
- environment:
- TERM: xterm
- steps:
- - checkout
- - attach_workspace:
- at: build
- - run:
- name: Install dependencies
- command: |
- brew unlink python
- brew install z3
- - run: mkdir -p test_results
- - run: *run_tests
- - store_test_results:
- path: test_results/
- - store_artifacts:
- path: test_results/
- destination: test_results/
-
- docs:
- docker:
- - image: buildpack-deps:bionic
- environment:
- DEBIAN_FRONTEND: noninteractive
- steps:
- - checkout
- - run:
- name: Install build dependencies
- command: |
- apt-get -qq update
- apt-get -qy install python-sphinx python-pip
- - run: *setup_prerelease_commit_hash
- - run:
- name: Build documentation
- command: ./scripts/docs.sh
- - store_artifacts:
- path: docs/_build/html/
- destination: docs-html
-
- build_x86_linux_ossfuzz:
- docker:
- - image: buildpack-deps:disco
- environment:
- TERM: xterm
- CC: /usr/bin/clang-8
- CXX: /usr/bin/clang++-8
- CMAKE_OPTIONS: -DOSSFUZZ=1 -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/libfuzzer.cmake
- steps:
- - checkout
- - run:
- name: Install build dependencies
- command: |
- apt-get -qq update
- apt-get -qy install wget clang-8 cmake libboost-regex-dev libboost-filesystem-dev libboost-test-dev libboost-system-dev libboost-program-options-dev libcvc4-dev libbz2-dev ninja-build zlib1g-dev libjsoncpp-dev=1.7.4-\*
- ./scripts/install_lpm.sh
- ./scripts/install_libfuzzer.sh
- # Install evmone and dependencies (intx and ethash)
- ./scripts/install_evmone.sh
- - run: *setup_prerelease_commit_hash
- - run: *run_build_ossfuzz
- - persist_to_workspace: *ossfuzz_artifacts
-
- test_x86_ossfuzz_regression:
- docker:
- - image: buildpack-deps:disco
- environment:
- TERM: xterm
- steps:
- - checkout
- - attach_workspace:
- at: build
- - run:
- name: Install dependencies
- command: |
- apt-get -qq update
- apt-get -qy install libcvc4-dev llvm-8-dev
- ./scripts/download_ossfuzz_corpus.sh
- update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-8 1
- - run: mkdir -p test_results
- - run: *run_regressions
- - store_artifacts:
- path: test_results/
- destination: test_results/
-
workflows:
version: 2
- build_all:
- jobs:
- - test_check_spelling: *build_on_tags
- - test_check_style: *build_on_tags
- - test_buglist: *build_on_tags
- - build_emscripten: *build_on_tags
- - test_emscripten_solcjs:
- <<: *build_on_tags
- requires:
- - build_emscripten
- - build_x86_linux: *build_on_tags
- - build_x86_linux_cxx17: *build_on_tags
- - build_x86_clang7_asan: *build_on_tags
- - build_x86_mac: *build_on_tags
- - test_x86_linux:
- <<: *build_on_tags
- requires:
- - build_x86_linux
- - test_x86_clang7_asan:
- <<: *build_on_tags
- requires:
- - build_x86_clang7_asan
- - test_x86_mac:
- <<: *build_on_tags
- requires:
- - build_x86_mac
- - docs: *build_on_tags
- - build_x86_archlinux: *build_on_tags
- - test_x86_archlinux:
- <<: *build_on_tags
- requires:
- - build_x86_archlinux
- - build_x86_linux_ossfuzz: *build_on_tags
- test_nightly:
+ main:
+ jobs:
+ # basic checks
+ - chk_spelling: *workflow_trigger_on_tags
+ - chk_coding_style: *workflow_trigger_on_tags
+ - chk_buglist: *workflow_trigger_on_tags
+ - chk_proofs: *workflow_trigger_on_tags
+
+ # build-only
+ - b_docs: *workflow_trigger_on_tags
+ - b_archlinux: *workflow_trigger_on_tags
+ - b_ubu_cxx17: *workflow_trigger_on_tags
+ - b_ubu_ossfuzz: *workflow_trigger_on_tags
+
+ # OS/X build and tests
+ - b_osx: *workflow_trigger_on_tags
+ - t_osx_cli: *workflow_osx
+
+ # Ubuntu 18.10 build and tests
+ - b_ubu: *workflow_trigger_on_tags
+ - t_ubu_cli: *workflow_ubuntu1904
+ - t_ubu_homestead: *workflow_ubuntu1904
+ - t_ubu_homestead_opt: *workflow_ubuntu1904
+ - t_ubu_byzantium: *workflow_ubuntu1904
+ - t_ubu_byzantium_opt: *workflow_ubuntu1904
+ - t_ubu_constantinople: *workflow_ubuntu1904
+ - t_ubu_constantinople_opt: *workflow_ubuntu1904
+ - t_ubu_constantinople_opt_abiv2: *workflow_ubuntu1904
+ - t_ubu_petersburg: *workflow_ubuntu1904
+ - t_ubu_petersburg_opt: *workflow_ubuntu1904
+
+ # ASan build and tests
+ - b_ubu_asan: *workflow_trigger_on_tags
+ - t_ubu_asan_constantinople: *workflow_ubuntu1904_asan
+ - t_ubu_asan_cli: *workflow_ubuntu1904_asan
+
+ # Emscripten build and selected tests
+ - b_ems: *workflow_trigger_on_tags
+ - t_ems_solcjs: *workflow_emscripten
+
+ nightly:
+
triggers:
- schedule:
cron: "0 0 * * *"
@@ -527,23 +616,19 @@ workflows:
branches:
only:
- develop
- jobs:
- - build_emscripten: *build_on_tags
- - test_emscripten_external_zeppelin:
- <<: *build_on_tags
- requires:
- - build_emscripten
- - test_emscripten_external_gnosis:
- <<: *build_on_tags
- requires:
- - build_emscripten
- - test_emscripten_external_colony:
- <<: *build_on_tags
- requires:
- - build_emscripten
- - build_x86_linux_ossfuzz: *build_on_tags
- - test_x86_ossfuzz_regression:
- <<: *build_on_tags
- requires:
- - build_x86_linux_ossfuzz
+
+ jobs:
+ # Emscripten builds and external tests
+ - b_ems: *workflow_trigger_on_tags
+ - t_ems_external_zeppelin: *workflow_emscripten
+ - t_ems_external_gnosis: *workflow_emscripten
+ - t_ems_external_colony: *workflow_emscripten
+
+ # OSSFUZZ builds and (regression) tests
+ - b_ubu_ossfuzz: *workflow_trigger_on_tags
+ - t_ubu_ossfuzz: *workflow_ubuntu1904_ossfuzz
+
+ # Code Coverage enabled build and tests
+ - b_ubu_codecov: *workflow_trigger_on_tags
+ - t_ubu_codecov: *workflow_ubuntu1904_codecov
diff --git a/.circleci/docker/Dockerfile.archlinux b/.circleci/docker/Dockerfile.archlinux
new file mode 100644
index 000000000..cd956c9cd
--- /dev/null
+++ b/.circleci/docker/Dockerfile.archlinux
@@ -0,0 +1,28 @@
+# vim:syntax=dockerfile
+#------------------------------------------------------------------------------
+# Dockerfile for building and testing Solidity Compiler on CI
+# Target: Arch Linux
+# URL: https://hub.docker.com/r/ethereum/solidity-buildpack-deps
+#
+# 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
+#
+# (c) 2016-2019 solidity contributors.
+#------------------------------------------------------------------------------
+FROM archlinux/base
+
+RUN pacman --noconfirm -Syu --noprogressbar --needed \
+ base-devel boost cmake z3 cvc4 git openssh tar
+
diff --git a/.circleci/docker/Dockerfile.ubuntu1904 b/.circleci/docker/Dockerfile.ubuntu1904
new file mode 100644
index 000000000..bad21f664
--- /dev/null
+++ b/.circleci/docker/Dockerfile.ubuntu1904
@@ -0,0 +1,124 @@
+# vim:syntax=dockerfile
+#------------------------------------------------------------------------------
+# Dockerfile for building and testing Solidity Compiler on CI
+# Target: Ubuntu 19.04 (Disco Dingo)
+# URL: https://hub.docker.com/r/ethereum/solidity-buildpack-deps
+#
+# 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
+#
+# (c) 2016-2019 solidity contributors.
+#------------------------------------------------------------------------------
+FROM buildpack-deps:disco
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+RUN set -ex; \
+ apt-get update; \
+ apt-get install -qqy --no-install-recommends \
+ build-essential \
+ software-properties-common \
+ cmake ninja-build clang++-8 \
+ libboost-regex-dev libboost-filesystem-dev libboost-test-dev libboost-system-dev \
+ libboost-program-options-dev \
+ libjsoncpp-dev \
+ llvm-8-dev libcvc4-dev libleveldb1d \
+ ; \
+ apt-get install -qy python-pip python-sphinx; \
+ update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-8 1; \
+ pip install codecov; \
+ rm -rf /var/lib/apt/lists/*
+
+# Aleth for end-to-end tests
+ARG ALETH_VERSION="1.6.0"
+ARG ALETH_HASH="7f7004e1563299bc57882e32b32e4a195747dfb6"
+ARG ALETH_URL="https://github.com/ethereum/aleth/releases/download/v${ALETH_VERSION}/aleth-${ALETH_VERSION}-linux-x86_64.tar.gz"
+RUN set -ex; \
+ wget -q -O /tmp/aleth.tar.gz "${ALETH_URL}"; \
+ test "$(shasum /tmp/aleth.tar.gz)" = "$ALETH_HASH /tmp/aleth.tar.gz"; \
+ tar -xf /tmp/aleth.tar.gz -C /usr
+
+# Z3
+RUN set -ex; \
+ git clone --depth=1 --branch="Z3-4.8.5" https://github.com/Z3Prover/z3.git /usr/src/z3; \
+ mkdir /usr/src/z3/build; \
+ cd /usr/src/z3/build; \
+ cmake -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="/usr" -G "Ninja" ..; \
+ ninja; \
+ ninja install/strip; \
+ rm -rf /usr/src/z3
+
+# OSSFUZZ: LPM package (do not remove build dirs as solidity compiles/links against that dir)
+RUN set -ex; \
+ mkdir /src; \
+ cd /src; \
+ git clone https://github.com/google/libprotobuf-mutator.git; \
+ cd libprotobuf-mutator; \
+ git checkout d1fe8a7d8ae18f3d454f055eba5213c291986f21; \
+ mkdir ../LPM; \
+ cd ../LPM; \
+ cmake ../libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release; \
+ ninja; \
+ cp -vpr external.protobuf/bin/* /usr/bin/; \
+ cp -vpr external.protobuf/include/* /usr/include/; \
+ cp -vpr external.protobuf/lib/* /usr/lib/; \
+ ninja install/strip
+
+# OSSFUZZ: libfuzzer
+RUN set -ex; \
+ cd /var/tmp; \
+ svn co https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer libfuzzer; \
+ mkdir -p build-libfuzzer; \
+ cd build-libfuzzer; \
+ clang++-8 -O1 -stdlib=libstdc++ -std=c++11 -O2 -fPIC -c ../libfuzzer/*.cpp -I../libfuzzer; \
+ ar r /usr/lib/libFuzzingEngine.a *.o; \
+ rm -rf /var/lib/libfuzzer
+
+# ETHASH
+RUN set -ex; \
+ cd /usr/src; \
+ git clone --branch="v0.4.4" https://github.com/chfast/ethash.git; \
+ cd ethash; \
+ mkdir build; \
+ cd build; \
+ cmake .. -G Ninja -DBUILD_SHARED_LIBS=OFF -DETHASH_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX="/usr"; \
+ ninja; \
+ ninja install/strip; \
+ rm -rf /usr/src/ethash
+
+# INTX
+RUN set -ex; \
+ cd /usr/src; \
+ git clone --branch="v0.2.0" https://github.com/chfast/intx.git; \
+ cd intx; \
+ mkdir build; \
+ cd build; \
+ cmake .. -G Ninja -DBUILD_SHARED_LIBS=OFF -DINTX_TESTING=OFF -DINTX_BENCHMARKING=OFF -DCMAKE_INSTALL_PREFIX="/usr"; \
+ ninja; \
+ ninja install/strip; \
+ rm -rf /usr/src/intx;
+
+# EVMONE
+RUN set -ex; \
+ cd /usr/src; \
+ git clone --branch="v0.1.0" --recurse-submodules https://github.com/chfast/evmone.git; \
+ cd evmone; \
+ mkdir build; \
+ cd build; \
+ cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr" ..; \
+ ninja; \
+ ninja install/strip; \
+ rm -rf /usr/src/evmone
+
diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh
new file mode 100755
index 000000000..673540b3c
--- /dev/null
+++ b/.circleci/soltest.sh
@@ -0,0 +1,65 @@
+#! /bin/bash
+#------------------------------------------------------------------------------
+# Bash script to execute the Solidity tests by CircleCI.
+#
+# The documentation for solidity is hosted at:
+#
+# https://solidity.readthedocs.org
+#
+# ------------------------------------------------------------------------------
+# Configuration Environment Variables:
+#
+# EVM=version_string Specifies EVM version to compile for (such as homestead, etc)
+# OPTIMIZE=1 Enables backend optimizer
+# ABI_ENCODER_V2=1 Enables ABI encoder version 2
+#
+# ------------------------------------------------------------------------------
+# 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
+#
+# (c) 2016-2019 solidity contributors.
+# ------------------------------------------------------------------------------
+set -e
+
+OPTIMIZE=${OPTIMIZE:-"0"}
+EVM=${EVM:-"invalid"}
+WORKDIR=${CIRCLE_WORKING_DIRECTORY:-.}
+SOLTEST_IPC=${SOLTEST_IPC:-1}
+REPODIR="$(realpath $(dirname $0)/..)"
+ALETH_PATH="/usr/bin/aleth"
+
+source "${REPODIR}/scripts/common.sh"
+# Test result output directory (CircleCI is reading test results from here)
+mkdir -p test_results
+
+ALETH_PID=$(run_aleth)
+
+function cleanup() {
+ safe_kill $ALETH_PID $ALETH_PATH
+}
+trap cleanup INT TERM
+
+# in case we run with ASAN enabled, we must increase stck size.
+ulimit -s 16384
+
+BOOST_TEST_ARGS="--color_output=no --show_progress=yes --logger=JUNIT,error,test_results/$EVM.xml"
+SOLTEST_ARGS="--evm-version=$EVM --ipcpath "${WORKDIR}/geth.ipc" $flags"
+test "${SOLTEST_IPC}" = "1" || SOLTEST_ARGS="$SOLTEST_ARGS --no-ipc"
+test "${OPTIMIZE}" = "1" && SOLTEST_ARGS="${SOLTEST_ARGS} --optimize"
+test "${ABI_ENCODER_V2}" = "1" && SOLTEST_ARGS="${SOLTEST_ARGS} --abiencoderv2 --optimize-yul"
+
+echo "Running ${REPODIR}/build/test/soltest ${BOOST_TEST_ARGS} -- ${SOLTEST_ARGS}"
+
+${REPODIR}/build/test/soltest ${BOOST_TEST_ARGS} -- ${SOLTEST_ARGS}
diff --git a/.travis.yml b/.travis.yml
index c91daada1..7e1114974 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -183,7 +183,7 @@ git:
cache:
ccache: true
directories:
- - boost_1_68_0
+ - boost_1_70_0_install
- $HOME/.local
install:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bfe35fcf5..40a81c03a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.0.0)
+cmake_minimum_required(VERSION 3.5.0)
set(ETH_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake" CACHE PATH "The the path to the cmake directory")
list(APPEND CMAKE_MODULE_PATH ${ETH_CMAKE_DIR})
@@ -10,9 +10,20 @@ include(EthPolicy)
eth_policy()
# project name and version should be set after cmake_policy CMP0048
-set(PROJECT_VERSION "0.5.9")
+set(PROJECT_VERSION "0.5.10")
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES CXX)
+if (${CMAKE_VERSION} VERSION_LESS "3.9.0")
+ # needed for the big endian test for older cmake versions
+ enable_language(C)
+endif()
+
+include(TestBigEndian)
+TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
+if (IS_BIG_ENDIAN)
+ message(FATAL_ERROR "${PROJECT_NAME} currently does not support big endian systems.")
+endif()
+
option(LLL "Build LLL" OFF)
option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF)
option(LLLC_LINK_STATIC "Link lllc executable statically on supported platforms" OFF)
diff --git a/Changelog.md b/Changelog.md
index 4ccefe18d..63879d665 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,29 @@
+### 0.5.10 (2019-06-25)
+
+Important Bugfixes:
+ * ABIEncoderV2: Fix incorrect abi encoding of storage array of data type that occupy multiple storage slots
+ * Code Generator: Properly zero out higher order bits in elements of an array of negative numbers when assigning to storage and converting the type at the same time.
+
+
+Compiler Features:
+ * Commandline Interface: Experimental parser error recovery via the ``--error-recovery`` commandline switch.
+ * Optimizer: Add rule to simplify ``SUB(~0, X)`` to ``NOT(X)``.
+ * Yul Optimizer: Make the optimizer work for all dialects of Yul including eWasm.
+
+
+Bugfixes:
+ * Type Checker: Set state mutability of the function type members ``gas`` and ``value`` to pure (while their return type inherits state mutability from the function type).
+ * Yul / Inline Assembly Parser: Disallow trailing commas in function call arguments.
+
+
+Build System:
+ * Attempt to use stock Z3 cmake files to find Z3 and only fall back to manual discovery.
+ * CMake: use imported targets for boost.
+ * Emscripten build: upgrade to boost 1.70.
+ * Generate a cmake error for gcc versions older than 5.0.
+
+
+
### 0.5.9 (2019-05-28)
Language Features:
@@ -21,7 +47,6 @@ Compiler Features:
* Yul Optimizer: Do not inline recursive functions.
* Yul Optimizer: Do not remove instructions that affect ``msize()`` if ``msize()`` is used.
-
Bugfixes:
* Code Generator: Explicitly turn uninitialized internal function pointers into invalid functions when loaded from storage.
* Code Generator: Fix assertion failure when assigning structs containing array of mapping.
@@ -61,6 +86,7 @@ Compiler Features:
* Yul: Adds break and continue keywords to for-loop syntax.
* Yul: Support ``.`` as part of identifiers.
* Yul Optimizer: Adds steps for detecting and removing of dead code.
+ * Yul Code Generator: Directly jump over a series of function definitions (instead of jumping over each one)
Bugfixes:
diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake
index 3fe98188d..7ffb45964 100644
--- a/cmake/EthCompilerSettings.cmake
+++ b/cmake/EthCompilerSettings.cmake
@@ -41,11 +41,11 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
# Additional GCC-specific compiler settings.
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
- # Check that we've got GCC 4.7 or newer.
+ # Check that we've got GCC 5.0 or newer.
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
- if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7))
- message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.")
+ if (NOT (GCC_VERSION VERSION_GREATER 5.0 OR GCC_VERSION VERSION_EQUAL 5.0))
+ message(FATAL_ERROR "${PROJECT_NAME} requires g++ 5.0 or greater.")
endif ()
# Additional Clang-specific compiler settings.
diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake
index 477a604d6..53319e6c8 100644
--- a/cmake/EthDependencies.cmake
+++ b/cmake/EthDependencies.cmake
@@ -1,21 +1,6 @@
# all dependencies that are not directly included in the cpp-ethereum distribution are defined here
# for this to work, download the dependency via the cmake script in extdep or install them manually!
-function(eth_show_dependency DEP NAME)
- get_property(DISPLAYED GLOBAL PROPERTY ETH_${DEP}_DISPLAYED)
- if (NOT DISPLAYED)
- set_property(GLOBAL PROPERTY ETH_${DEP}_DISPLAYED TRUE)
- if (NOT("${${DEP}_VERSION}" STREQUAL ""))
- message(STATUS "${NAME} version: ${${DEP}_VERSION}")
- endif()
- message(STATUS "${NAME} headers: ${${DEP}_INCLUDE_DIRS}")
- message(STATUS "${NAME} lib : ${${DEP}_LIBRARIES}")
- if (NOT("${${DEP}_DLLS}" STREQUAL ""))
- message(STATUS "${NAME} dll : ${${DEP}_DLLS}")
- endif()
- endif()
-endfunction()
-
if (DEFINED MSVC)
# by defining CMAKE_PREFIX_PATH variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ...
# this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory
@@ -41,6 +26,29 @@ set(ETH_SCRIPTS_DIR ${ETH_CMAKE_DIR}/scripts)
set(Boost_USE_MULTITHREADED ON)
option(Boost_USE_STATIC_LIBS "Link Boost statically" ON)
-find_package(Boost 1.65.0 QUIET REQUIRED COMPONENTS regex filesystem unit_test_framework program_options system)
+set(BOOST_COMPONENTS "regex;filesystem;unit_test_framework;program_options;system")
-eth_show_dependency(Boost boost)
+find_package(Boost 1.65.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS})
+
+# If cmake is older than boost and boost is older than 1.70,
+# find_package does not define imported targets, so we have to
+# define them manually.
+
+if (NOT TARGET Boost::boost) # header only target
+ add_library(Boost::boost INTERFACE IMPORTED)
+ set_property(TARGET Boost::boost APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS})
+endif()
+get_property(LOCATION TARGET Boost::boost PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+message(STATUS "Found Boost headers in ${LOCATION}")
+
+foreach (BOOST_COMPONENT IN LISTS BOOST_COMPONENTS)
+ if (NOT TARGET Boost::${BOOST_COMPONENT})
+ add_library(Boost::${BOOST_COMPONENT} UNKNOWN IMPORTED)
+ string(TOUPPER ${BOOST_COMPONENT} BOOST_COMPONENT_UPPER)
+ set_property(TARGET Boost::${BOOST_COMPONENT} PROPERTY IMPORTED_LOCATION ${Boost_${BOOST_COMPONENT_UPPER}_LIBRARY})
+ set_property(TARGET Boost::${BOOST_COMPONENT} PROPERTY INTERFACE_LINK_LIBRARIES ${Boost_${BOOST_COMPONENT_UPPER}_LIBRARIES})
+ set_property(TARGET Boost::${BOOST_COMPONENT} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS})
+ endif()
+ get_property(LOCATION TARGET Boost::${BOOST_COMPONENT} PROPERTY IMPORTED_LOCATION)
+ message(STATUS "Found Boost::${BOOST_COMPONENT} at ${LOCATION}")
+endforeach()
diff --git a/cmake/FindZ3.cmake b/cmake/FindZ3.cmake
index bdd8ce72f..4b63ed4cb 100644
--- a/cmake/FindZ3.cmake
+++ b/cmake/FindZ3.cmake
@@ -1,29 +1,45 @@
if (USE_Z3)
- find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3)
- find_library(Z3_LIBRARY NAMES z3)
- find_program(Z3_EXECUTABLE z3 PATH_SUFFIXES bin)
-
- if(Z3_INCLUDE_DIR AND Z3_LIBRARY AND Z3_EXECUTABLE)
- execute_process (COMMAND ${Z3_EXECUTABLE} -version
- OUTPUT_VARIABLE libz3_version_str
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- string(REGEX REPLACE "^Z3 version ([0-9.]+).*" "\\1"
- Z3_VERSION_STRING "${libz3_version_str}")
- unset(libz3_version_str)
- endif()
- mark_as_advanced(Z3_VERSION_STRING z3_DIR)
+ # Save and clear Z3_FIND_VERSION, since the
+ # Z3 config module cannot handle version requirements.
+ set(Z3_FIND_VERSION_ORIG ${Z3_FIND_VERSION})
+ set(Z3_FIND_VERSION)
+ # Try to find Z3 using its stock cmake files.
+ find_package(Z3 QUIET CONFIG)
+ # Restore Z3_FIND_VERSION for find_package_handle_standard_args.
+ set(Z3_FIND_VERSION ${Z3_FIND_VERSION_ORIG})
+ set(Z3_FIND_VERSION_ORIG)
include(FindPackageHandleStandardArgs)
- find_package_handle_standard_args(Z3
- REQUIRED_VARS Z3_LIBRARY Z3_INCLUDE_DIR
- VERSION_VAR Z3_VERSION_STRING)
- if (NOT TARGET Z3::Z3)
- add_library(Z3::Z3 UNKNOWN IMPORTED)
- set_property(TARGET Z3::Z3 PROPERTY IMPORTED_LOCATION ${Z3_LIBRARY})
- set_property(TARGET Z3::Z3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR})
+ if (Z3_FOUND)
+ set(Z3_VERSION ${Z3_VERSION_STRING})
+ find_package_handle_standard_args(Z3 CONFIG_MODE)
+ else()
+ find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3)
+ find_library(Z3_LIBRARY NAMES z3)
+ find_program(Z3_EXECUTABLE z3 PATH_SUFFIXES bin)
+
+ if(Z3_INCLUDE_DIR AND Z3_LIBRARY AND Z3_EXECUTABLE)
+ execute_process (COMMAND ${Z3_EXECUTABLE} -version
+ OUTPUT_VARIABLE libz3_version_str
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ string(REGEX REPLACE "^Z3 version ([0-9.]+).*" "\\1"
+ Z3_VERSION_STRING "${libz3_version_str}")
+ unset(libz3_version_str)
+ endif()
+ mark_as_advanced(Z3_VERSION_STRING z3_DIR)
+
+ find_package_handle_standard_args(Z3
+ REQUIRED_VARS Z3_LIBRARY Z3_INCLUDE_DIR
+ VERSION_VAR Z3_VERSION_STRING)
+
+ if (NOT TARGET z3::libz3)
+ add_library(z3::libz3 UNKNOWN IMPORTED)
+ set_property(TARGET z3::libz3 PROPERTY IMPORTED_LOCATION ${Z3_LIBRARY})
+ set_property(TARGET z3::libz3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR})
+ endif()
endif()
else()
set(Z3_FOUND FALSE)
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 355286d49..5015a18bb 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -415,7 +415,8 @@ Local Solidity variables are available for assignments, for example:
To be safe, always clear the data properly before you use it
in a context where this is important:
``uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ }``
- To clean signed types, you can use the ``signextend`` opcode.
+ To clean signed types, you can use the ``signextend`` opcode:
+ ``assembly { signextend(, x) }``
Labels
------
@@ -595,21 +596,21 @@ of their block is reached.
Conventions in Solidity
-----------------------
-In contrast to EVM assembly, Solidity knows types which are narrower than 256 bits,
-e.g. ``uint24``. In order to make them more efficient, most arithmetic operations just
-treat them as 256-bit numbers and the higher-order bits are only cleaned at the
-point where it is necessary, i.e. just shortly before they are written to memory
-or before comparisons are performed. This means that if you access such a variable
-from within inline assembly, you might have to manually clean the higher order bits
+In contrast to EVM assembly, Solidity has types which are narrower than 256 bits,
+e.g. ``uint24``. For efficiency, most arithmetic operations ignore the fact that types can be shorter than 256
+bits, and the higher-order bits are cleaned when necessary,
+i.e., shortly before they are written to memory or before comparisons are performed.
+This means that if you access such a variable
+from within inline assembly, you might have to manually clean the higher-order bits
first.
-Solidity manages memory in a very simple way: There is a "free memory pointer"
-at position ``0x40`` in memory. If you want to allocate memory, just use the memory
-starting from where this pointer points at and update it accordingly.
+Solidity manages memory in the following way. There is a "free memory pointer"
+at position ``0x40`` in memory. If you want to allocate memory, use the memory
+starting from where this pointer points at and update it.
There is no guarantee that the memory has not been used before and thus
you cannot assume that its contents are zero bytes.
There is no built-in mechanism to release or free allocated memory.
-Here is an assembly snippet that can be used for allocating memory::
+Here is an assembly snippet you can use for allocating memory that follows the process outlined above::
function allocate(length) -> pos {
pos := mload(0x40)
@@ -617,13 +618,13 @@ Here is an assembly snippet that can be used for allocating memory::
}
The first 64 bytes of memory can be used as "scratch space" for short-term
-allocation. The 32 bytes after the free memory pointer (i.e. starting at ``0x60``)
-is meant to be zero permanently and is used as the initial value for
+allocation. The 32 bytes after the free memory pointer (i.e., starting at ``0x60``)
+are meant to be zero permanently and is used as the initial value for
empty dynamic memory arrays.
This means that the allocatable memory starts at ``0x80``, which is the initial value
of the free memory pointer.
-Elements in memory arrays in Solidity always occupy multiples of 32 bytes (yes, this is
+Elements in memory arrays in Solidity always occupy multiples of 32 bytes (this is
even true for ``byte[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory
arrays are pointers to memory arrays. The length of a dynamic array is stored at the
first slot of the array and followed by the array elements.
@@ -631,7 +632,7 @@ first slot of the array and followed by the array elements.
.. warning::
Statically-sized memory arrays do not have a length field, but it might be added later
to allow better convertibility between statically- and dynamically-sized arrays, so
- please do not rely on that.
+ do not rely on this.
Standalone Assembly
diff --git a/docs/bugs.json b/docs/bugs.json
index 3eb5d1807..e4c3bbcc1 100644
--- a/docs/bugs.json
+++ b/docs/bugs.json
@@ -1,4 +1,23 @@
[
+ {
+ "name": "SignedArrayStorageCopy",
+ "summary": "Assigning an array of signed integers to a storage array of different type can lead to data corruption in that array.",
+ "description": "In two's complement, negative integers have their higher order bits set. In order to fit into a shared storage slot, these have to be set to zero. When a conversion is done at the same time, the bits to set to zero were incorrectly determined from the source and not the target type. This means that such copy operations can lead to incorrect values being stored.",
+ "introduced": "0.4.7",
+ "fixed": "0.5.10",
+ "severity": "low/medium"
+ },
+ {
+ "name": "ABIEncoderV2StorageArrayWithMultiSlotElement",
+ "summary": "Storage arrays containing structs or other statically-sized arrays are not read properly when directly encoded in external function calls or in abi.encode*.",
+ "description": "When storage arrays whose elements occupy more than a single storage slot are directly encoded in external function calls or using abi.encode*, their elements are read in an overlapping manner, i.e. the element pointer is not properly advanced between reads. This is not a problem when the storage data is first copied to a memory variable or if the storage array only contains value types or dynamically-sized arrays.",
+ "introduced": "0.4.16",
+ "fixed": "0.5.10",
+ "severity": "low",
+ "conditions": {
+ "ABIEncoderV2": true
+ }
+ },
{
"name": "DynamicConstructorArgumentsClippedABIV2",
"summary": "A contract's constructor that takes structs or arrays that contain dynamically-sized arrays reverts or decodes to invalid data.",
diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json
index 16c949f65..247f1230f 100644
--- a/docs/bugs_by_version.json
+++ b/docs/bugs_by_version.json
@@ -380,6 +380,7 @@
},
"0.4.10": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -394,6 +395,7 @@
},
"0.4.11": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -407,6 +409,7 @@
},
"0.4.12": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -419,6 +422,7 @@
},
"0.4.13": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -431,6 +435,7 @@
},
"0.4.14": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -442,6 +447,7 @@
},
"0.4.15": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -452,6 +458,8 @@
},
"0.4.16": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -463,6 +471,8 @@
},
"0.4.17": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -475,6 +485,8 @@
},
"0.4.18": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -486,6 +498,8 @@
},
"0.4.19": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -514,6 +528,8 @@
},
"0.4.20": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -526,6 +542,8 @@
},
"0.4.21": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -538,6 +556,8 @@
},
"0.4.22": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -550,6 +570,8 @@
},
"0.4.23": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -561,6 +583,8 @@
},
"0.4.24": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -572,6 +596,8 @@
},
"0.4.25": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@@ -581,6 +607,8 @@
},
"0.4.26": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2"
],
"released": "2019-04-29"
@@ -647,6 +675,7 @@
},
"0.4.7": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -661,6 +690,7 @@
},
"0.4.8": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -675,6 +705,7 @@
},
"0.4.9": {
"bugs": [
+ "SignedArrayStorageCopy",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
"ExpExponentCleanup",
@@ -689,6 +720,8 @@
},
"0.5.0": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@@ -698,6 +731,8 @@
},
"0.5.1": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@@ -705,8 +740,14 @@
],
"released": "2018-12-03"
},
+ "0.5.10": {
+ "bugs": [],
+ "released": "2019-06-25"
+ },
"0.5.2": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@@ -716,6 +757,8 @@
},
"0.5.3": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@@ -725,6 +768,8 @@
},
"0.5.4": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@@ -734,6 +779,8 @@
},
"0.5.5": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@@ -745,6 +792,8 @@
},
"0.5.6": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@@ -755,6 +804,8 @@
},
"0.5.7": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries"
@@ -763,12 +814,17 @@
},
"0.5.8": {
"bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2"
],
"released": "2019-04-30"
},
"0.5.9": {
- "bugs": [],
+ "bugs": [
+ "SignedArrayStorageCopy",
+ "ABIEncoderV2StorageArrayWithMultiSlotElement"
+ ],
"released": "2019-05-28"
}
}
\ No newline at end of file
diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst
index 4e5a52c0f..e8d9961e7 100644
--- a/docs/contracts/functions.rst
+++ b/docs/contracts/functions.rst
@@ -252,10 +252,6 @@ will consume more gas than the 2300 gas stipend:
Like any function, the fallback function can execute complex operations as long as there is enough gas passed on to it.
-.. note::
- Even though the fallback function cannot have arguments, one can still use ``msg.data`` to retrieve
- any payload supplied with the call.
-
.. warning::
The fallback function is also executed if the caller meant to call
a function that is not available. If you want to implement the fallback
@@ -273,6 +269,10 @@ Like any function, the fallback function can execute complex operations as long
A contract without a payable fallback function can receive Ether as a recipient of a `coinbase transaction` (aka `miner block reward`)
or as a destination of a ``selfdestruct``.
+.. note::
+ Even though the fallback function cannot have arguments, one can still use ``msg.data`` to retrieve
+ any payload supplied with the call.
+
A contract cannot react to such Ether transfers and thus also cannot reject them. This is a design choice of the EVM and Solidity cannot work around it.
It also means that ``address(this).balance`` can be higher than the sum of some manual accounting implemented in a contract (i.e. having a counter updated in the fallback function).
diff --git a/docs/contracts/interfaces.rst b/docs/contracts/interfaces.rst
index 43c8637ee..91e7d5947 100644
--- a/docs/contracts/interfaces.rst
+++ b/docs/contracts/interfaces.rst
@@ -34,3 +34,8 @@ Contracts can inherit interfaces as they would inherit other contracts.
Types defined inside interfaces and other contract-like structures
can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``.
+
+.. warning:
+
+ Interfaces have supported ``enum`` types since :doc:`Solidity version 0.5.0 <050-breaking-changes>`, make
+ sure the pragma version specifies this version as a minimum.
\ No newline at end of file
diff --git a/docs/contracts/using-for.rst b/docs/contracts/using-for.rst
index 12fc976d5..ed19dd046 100644
--- a/docs/contracts/using-for.rst
+++ b/docs/contracts/using-for.rst
@@ -33,39 +33,41 @@ Let us rewrite the set example from the
pragma solidity >=0.4.16 <0.7.0;
+
// This is the same code as before, just without comments
library Set {
- struct Data { mapping(uint => bool) flags; }
+ struct Data { mapping(uint => bool) flags; }
- function insert(Data storage self, uint value)
- public
- returns (bool)
- {
- if (self.flags[value])
- return false; // already there
- self.flags[value] = true;
- return true;
- }
+ function insert(Data storage self, uint value)
+ public
+ returns (bool)
+ {
+ if (self.flags[value])
+ return false; // already there
+ self.flags[value] = true;
+ return true;
+ }
- function remove(Data storage self, uint value)
- public
- returns (bool)
- {
- if (!self.flags[value])
- return false; // not there
- self.flags[value] = false;
- return true;
- }
+ function remove(Data storage self, uint value)
+ public
+ returns (bool)
+ {
+ if (!self.flags[value])
+ return false; // not there
+ self.flags[value] = false;
+ return true;
+ }
- function contains(Data storage self, uint value)
- public
- view
- returns (bool)
- {
- return self.flags[value];
- }
+ function contains(Data storage self, uint value)
+ public
+ view
+ returns (bool)
+ {
+ return self.flags[value];
+ }
}
+
contract C {
using Set for Set.Data; // this is the crucial change
Set.Data knownValues;
diff --git a/docs/contributing.rst b/docs/contributing.rst
index 0e0a58905..fd488d56d 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -130,7 +130,7 @@ The CI runs additional tests (including ``solc-js`` and testing third party Soli
Some versions of ``aleth`` can not be used for testing. We suggest using
the same version that the Solidity continuous integration tests use.
- Currently the CI uses version ``1.5.0-alpha.7`` of ``aleth``.
+ Currently the CI uses version ``1.6.0`` of ``aleth``.
Writing and running syntax tests
--------------------------------
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index c8be772f4..bd04ce58b 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -298,8 +298,8 @@ Scoping and Declarations
A variable which is declared will have an initial default value whose byte-representation is all zeros.
The "default values" of variables are the typical "zero-state" of whatever the type is. For example, the default value for a ``bool``
is ``false``. The default value for the ``uint`` or ``int`` types is ``0``. For statically-sized arrays and ``bytes1`` to ``bytes32``, each individual
-element will be initialized to the default value corresponding to its type. Finally, for dynamically-sized arrays, ``bytes``
-and ``string``, the default value is an empty array or string.
+element will be initialized to the default value corresponding to its type. For dynamically-sized arrays, ``bytes``
+and ``string``, the default value is an empty array or string. For the ``enum`` type, the default value is its first member.
Scoping in Solidity follows the widespread scoping rules of C99
(and many other languages): Variables are visible from the point right after their declaration
@@ -373,33 +373,53 @@ In any case, you will get a warning about the outer variable being shadowed.
Error handling: Assert, Require, Revert and Exceptions
======================================================
-Solidity uses state-reverting exceptions to handle errors. Such an exception will undo all changes made to the
-state in the current call (and all its sub-calls) and also flag an error to the caller.
-The convenience functions ``assert`` and ``require`` can be used to check for conditions and throw an exception
-if the condition is not met. The ``assert`` function should only be used to test for internal errors, and to check invariants.
-The ``require`` function should be used to ensure valid conditions, such as inputs, or contract state variables are met, or to validate return values from calls to external contracts.
-If used properly, analysis tools can evaluate your contract to identify the conditions and function calls which will reach a failing ``assert``. Properly functioning code should never reach a failing assert statement; if this happens there is a bug in your contract which you should fix.
+Solidity uses state-reverting exceptions to handle errors. Such an exception undoes all changes made to the
+state in the current call (and all its sub-calls) and flags an error to the caller.
-There are two other ways to trigger exceptions: The ``revert`` function can be used to flag an error and
-revert the current call. It is possible to provide a string message containing details about the error
-that will be passed back to the caller.
-
-.. note::
- There used to be a keyword called ``throw`` with the same semantics as ``revert()`` which
- was deprecated in version 0.4.13 and removed in version 0.5.0.
-
-When exceptions happen in a sub-call, they "bubble up" (i.e. exceptions are rethrown) automatically. Exceptions to this rule are ``send``
-and the low-level functions ``call``, ``delegatecall`` and ``staticcall`` -- those return ``false`` as their first return value in case
+When exceptions happen in a sub-call, they "bubble up" (i.e., exceptions are rethrown) automatically. Exceptions to this rule are ``send``
+and the low-level functions ``call``, ``delegatecall`` and ``staticcall``, they return ``false`` as their first return value in case
of an exception instead of "bubbling up".
.. warning::
- The low-level functions ``call``, ``delegatecall`` and ``staticcall`` return ``true`` as their first return value if the called account is non-existent, as part of the design of EVM. Existence must be checked prior to calling if desired.
+ The low-level functions ``call``, ``delegatecall`` and ``staticcall`` return ``true`` as their first return value if the account called is non-existent, as part of the design of EVM. Existence must be checked prior to calling if needed.
-Catching exceptions is not yet possible.
+It is not yet possible to catch exceptions with Solidity.
-In the following example, you can see how ``require`` can be used to easily check conditions on inputs
-and how ``assert`` can be used for internal error checking. Note that you can optionally provide
-a message string for ``require``, but not for ``assert``.
+``assert`` and ``require``
+--------------------------
+
+The convenience functions ``assert`` and ``require`` can be used to check for conditions and throw an exception
+if the condition is not met.
+
+The ``assert`` function should only be used to test for internal errors, and to check invariants. Properly functioning code should never reach a failing ``assert`` statement; if this happens there is a bug in your contract which you should fix. Language analysis tools can evaluate your contract to identify the conditions and function calls which will reach a failing ``assert``.
+
+An ``assert``-style exception is generated in the following situations:
+
+#. If you access an array at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``).
+#. If you access a fixed-length ``bytesN`` at a too large or negative index.
+#. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
+#. If you shift by a negative amount.
+#. If you convert a value too big or negative into an enum type.
+#. If you call a zero-initialized variable of internal function type.
+#. If you call ``assert`` with an argument that evaluates to false.
+
+The ``require`` function should be used to ensure valid conditions that cannot be detected until execution time.
+These conditions include inputs, or contract state variables are met, or to validate return values from calls to external contracts.
+
+A ``require``-style exception is generated in the following situations:
+
+#. Calling ``require`` with an argument that evaluates to ``false``.
+#. If you call a function via a message call but it does not finish properly (i.e., it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall``, ``callcode`` or ``staticcall`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``.
+#. If you create a contract using the ``new`` keyword but the contract creation :ref:`does not finish properly`.
+#. If you perform an external function call targeting a contract that contains no code.
+#. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function).
+#. If your contract receives Ether via a public getter function.
+#. If a ``.transfer()`` fails.
+
+You can optionally provide a message string for ``require``, but not for ``assert``.
+
+The following example shows how you can use ``require`` to check conditions on inputs
+and ``assert`` for internal error checking.
::
@@ -418,34 +438,23 @@ a message string for ``require``, but not for ``assert``.
}
}
-An ``assert``-style exception is generated in the following situations:
-
-#. If you access an array at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``).
-#. If you access a fixed-length ``bytesN`` at a too large or negative index.
-#. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
-#. If you shift by a negative amount.
-#. If you convert a value too big or negative into an enum type.
-#. If you call a zero-initialized variable of internal function type.
-#. If you call ``assert`` with an argument that evaluates to false.
-
-A ``require``-style exception is generated in the following situations:
-
-#. Calling ``require`` with an argument that evaluates to ``false``.
-#. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall``, ``callcode`` or ``staticcall`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``.
-#. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly").
-#. If you perform an external function call targeting a contract that contains no code.
-#. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function).
-#. If your contract receives Ether via a public getter function.
-#. If a ``.transfer()`` fails.
-
Internally, Solidity performs a revert operation (instruction ``0xfd``) for a ``require``-style exception and executes an invalid operation
(instruction ``0xfe``) to throw an ``assert``-style exception. In both cases, this causes
the EVM to revert all changes made to the state. The reason for reverting is that there is no safe way to continue execution, because an expected effect
-did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction
-(or at least call) without effect. Note that ``assert``-style exceptions consume all gas available to the call, while
-``require``-style exceptions will not consume any gas starting from the Metropolis release.
+did not occur. Because we want to keep the atomicity of transactions, the safest action is to revert all changes and make the whole transaction
+(or at least call) without effect.
-The following example shows how an error string can be used together with revert and require:
+.. note::
+
+ ``assert``-style exceptions consume all gas available to the call, while ``require``-style exceptions do not consume any gas starting from the Metropolis release.
+
+``revert``
+----------
+
+The ``revert`` function is another way to trigger exceptions from within other code blocks to flag an error and
+revert the current call. The function takes an optional string message containing details about the error that is passed back to the caller.
+
+The following example shows how to use an error string together with ``revert`` and the equivalent ``require``:
::
@@ -464,9 +473,10 @@ The following example shows how an error string can be used together with revert
}
}
-The provided string will be :ref:`abi-encoded ` as if it were a call to a function ``Error(string)``.
-In the above example, ``revert("Not enough Ether provided.");`` will cause the following hexadecimal data be
-set as error return data:
+The two syntax options are equivalent, it's developer preference which to use.
+
+The provided string is :ref:`abi-encoded ` as if it were a call to a function ``Error(string)``.
+In the above example, ``revert("Not enough Ether provided.");`` returns the following hexadecimal as error return data:
.. code::
@@ -474,3 +484,7 @@ set as error return data:
0x0000000000000000000000000000000000000000000000000000000000000020 // Data offset
0x000000000000000000000000000000000000000000000000000000000000001a // String length
0x4e6f7420656e6f7567682045746865722070726f76696465642e000000000000 // String data
+
+.. note::
+ There used to be a keyword called ``throw`` with the same semantics as ``revert()`` which
+ was deprecated in version 0.4.13 and removed in version 0.5.0.
diff --git a/docs/examples/safe-remote.rst b/docs/examples/safe-remote.rst
index 765bdfc35..c4e684ce1 100644
--- a/docs/examples/safe-remote.rst
+++ b/docs/examples/safe-remote.rst
@@ -13,6 +13,7 @@ Safe Remote Purchase
address payable public seller;
address payable public buyer;
enum State { Created, Locked, Inactive }
+ // The state variable has a default value of the first member, `State.created`
State public state;
// Ensure that `msg.value` is an even number.
diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst
index 71073e29c..b19532d39 100644
--- a/docs/installing-solidity.rst
+++ b/docs/installing-solidity.rst
@@ -184,7 +184,7 @@ The following are dependencies for all builds of Solidity:
+-----------------------------------+-------------------------------------------------------+
| Software | Notes |
+===================================+=======================================================+
-| `CMake`_ | Cross-platform build file generator. |
+| `CMake`_ (version 3.5+) | Cross-platform build file generator. |
+-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.65+) | C++ libraries. |
+-----------------------------------+-------------------------------------------------------+
@@ -201,6 +201,13 @@ The following are dependencies for all builds of Solidity:
.. _CMake: https://cmake.org/download/
.. _z3: https://github.com/Z3Prover/z3
+.. note::
+ Solidity versions prior to 0.5.10 can fail to correctly link against Boost versions 1.70+.
+ A possible workaround is to temporarily rename ``/lib/cmake/Boost-1.70.0``
+ prior to running the cmake command to configure solidity.
+
+ Starting from 0.5.10 linking against Boost 1.70+ should work without manual intervention.
+
Prerequisites - macOS
---------------------
@@ -304,10 +311,6 @@ Building Solidity is quite similar on Linux, macOS and other Unices:
cd build
cmake .. && make
-.. warning::
-
- BSD builds should work, but are untested by the Solidity team.
-
or even easier on Linux and macOS, you can run:
.. code-block:: bash
@@ -315,6 +318,10 @@ or even easier on Linux and macOS, you can run:
#note: this will install binaries solc and soltest at usr/local/bin
./scripts/build.sh
+.. warning::
+
+ BSD builds should work, but are untested by the Solidity team.
+
And for Windows:
.. code-block:: bash
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index 5d5649837..f59200b24 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -42,8 +42,7 @@ data (its *state*) that resides at a specific address on the Ethereum
blockchain. The line ``uint storedData;`` declares a state variable called ``storedData`` of
type ``uint`` (*u*\nsigned *int*\eger of *256* bits). You can think of it as a single slot
in a database that you can query and alter by calling functions of the
-code that manages the database. In the case of Ethereum, this is always the owning
-contract. In this case, the functions ``set`` and ``get`` can be used to modify
+code that manages the database. In this example, the contract defines the functions ``set`` and ``get`` that can be used to modify
or retrieve the value of the variable.
To access a state variable, you do not need the prefix ``this.`` as is common in
@@ -57,53 +56,54 @@ and overwrite your number, but the number is still stored in the history
of the blockchain. Later, you will see how you can impose access restrictions
so that only you can alter the number.
-.. note::
- All identifiers (contract names, function names and variable names) are restricted to
- the ASCII character set. It is possible to store UTF-8 encoded data in string variables.
-
.. warning::
Be careful with using Unicode text, as similar looking (or even identical) characters can
have different code points and as such are encoded as a different byte array.
+.. note::
+ All identifiers (contract names, function names and variable names) are restricted to
+ the ASCII character set. It is possible to store UTF-8 encoded data in string variables.
+
.. index:: ! subcurrency
Subcurrency Example
===================
-The following contract will implement the simplest form of a
-cryptocurrency. It is possible to generate coins out of thin air, but
-only the person that created the contract will be able to do that (it is easy
-to implement a different issuance scheme).
-Furthermore, anyone can send coins to each other without a need for
-registering with username and password — all you need is an Ethereum keypair.
-
+The following contract implements the simplest form of a
+cryptocurrency. The contract allows only its creator to create new coins (different issuance scheme are possible).
+Anyone can send coins to each other without a need for
+registering with a username and password, all you need is an Ethereum keypair.
::
pragma solidity >=0.5.0 <0.7.0;
contract Coin {
- // The keyword "public" makes those variables
- // easily readable from outside.
+ // The keyword "public" makes variables
+ // accessible from other contracts
address public minter;
mapping (address => uint) public balances;
- // Events allow light clients to react to
- // changes efficiently.
+ // Events allow clients to react to specific
+ // contract changes you declare
event Sent(address from, address to, uint amount);
- // This is the constructor whose code is
- // run only when the contract is created.
+ // Constructor code is only run when the contract
+ // is created
constructor() public {
minter = msg.sender;
}
+ // Sends an amount of newly created coins to an address
+ // Can only be called by the contract creator
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
require(amount < 1e60);
balances[receiver] += amount;
}
+ // Sends an amount of existing coins
+ // from any caller to an address
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
@@ -114,58 +114,56 @@ registering with username and password — all you need is an Ethereum keypair.
This contract introduces some new concepts, let us go through them one by one.
-The line ``address public minter;`` declares a state variable of type address
-that is publicly accessible. The ``address`` type is a 160-bit value
-that does not allow any arithmetic operations. It is suitable for
-storing addresses of contracts or of keypairs belonging to external
-persons. The keyword ``public`` automatically generates a function that
-allows you to access the current value of the state variable
-from outside of the contract.
-Without this keyword, other contracts have no way to access the variable.
-The code of the function generated by the compiler is roughly equivalent
+The line ``address public minter;`` declares a state variable of type :ref:`address`.
+The ``address`` type is a 160-bit value that does not allow any arithmetic operations.
+It is suitable for storing addresses of contracts, or a hash of the public half of a keypair belonging to :ref:`external accounts`.
+
+The keyword ``public`` automatically generates a function that allows you to access the current value of the state
+variable from outside of the contract. Without this keyword, other contracts have no way to access the variable.
+The code of the function generated by the compiler is equivalent
to the following (ignore ``external`` and ``view`` for now)::
function minter() external view returns (address) { return minter; }
-Of course, adding a function exactly like that will not work
-because we would have a
-function and a state variable with the same name, but hopefully, you
-get the idea - the compiler figures that out for you.
+You could add a function like the above yourself, but you would have a function and state variable with the same name.
+You do not need to do this, the compiler figures it out for you.
.. index:: mapping
The next line, ``mapping (address => uint) public balances;`` also
creates a public state variable, but it is a more complex datatype.
-The type maps addresses to unsigned integers.
+The :ref:`mapping ` type maps addresses to :ref:`unsigned integers `.
+
Mappings can be seen as `hash tables `_ which are
-virtually initialized such that every possible key exists from the start and is mapped to a
-value whose byte-representation is all zeros. This analogy does not go
-too far, though, as it is neither possible to obtain a list of all keys of
-a mapping, nor a list of all values. So either keep in mind (or
-better, keep a list or use a more advanced data type) what you
-added to the mapping or use it in a context where this is not needed.
+virtually initialised such that every possible key exists from the start and is mapped to a
+value whose byte-representation is all zeros. However, it is neither possible to obtain a list of all keys of
+a mapping, nor a list of all values. Record what you
+added to the mapping, or use it in a context where this is not needed. Or
+even better, keep a list, or use a more suitable data type.
+
The :ref:`getter function` created by the ``public`` keyword
-is a bit more complex in this case. It roughly looks like the
+is more complex in the case of a mapping. It looks like the
following::
function balances(address _account) external view returns (uint) {
return balances[_account];
}
-As you see, you can use this function to easily query the balance of a
-single account.
+You can use this function to query the balance of a single account.
.. index:: event
The line ``event Sent(address from, address to, uint amount);`` declares
-a so-called "event" which is emitted in the last line of the function
-``send``. User interfaces (as well as server applications of course) can
-listen for those events being emitted on the blockchain without much
-cost. As soon as it is emitted, the listener will also receive the
-arguments ``from``, ``to`` and ``amount``, which makes it easy to track
-transactions. In order to listen for this event, you would use the following
-JavaScript code (which assumes that ``Coin`` is a contract object created via
-web3.js or a similar module)::
+an :ref:`"event" `, which is emitted in the last line of the function
+``send``. Ethereum clients such as web applications can
+listen for these events emitted on the blockchain without much
+cost. As soon as it is emitted, the listener receives the
+arguments ``from``, ``to`` and ``amount``, which makes it possible to track
+transactions.
+
+To listen for this event, you could use the following
+JavaScript code, which uses `web3.js `_ to create the ``Coin`` contract object,
+and any user interface calls the automatically generated ``balances`` function from above::
Coin.Sent().watch({}, '', function(error, result) {
if (!error) {
@@ -178,36 +176,33 @@ web3.js or a similar module)::
}
})
-Note how the automatically generated function ``balances`` is called from
-the user interface.
-
.. index:: coin
-The constructor is a special function which is run during creation of the contract and
-cannot be called afterwards. It permanently stores the address of the person creating the
-contract: ``msg`` (together with ``tx`` and ``block``) is a special global variable that
-contains some properties which allow access to the blockchain. ``msg.sender`` is
+The :ref:`constructor` is a special function run during the creation of the contract and
+cannot be called afterwards. In this case, it permanently stores the address of the person creating the
+contract. The ``msg`` variable (together with ``tx`` and ``block``) is a
+:ref:`special global variable ` that
+contains properties which allow access to the blockchain. ``msg.sender`` is
always the address where the current (external) function call came from.
-Finally, the functions that will actually end up with the contract and can be called
-by users and contracts alike are ``mint`` and ``send``.
-If ``mint`` is called by anyone except the account that created the contract,
-nothing will happen. This is ensured by the special function ``require`` which
-causes all changes to be reverted if its argument evaluates to false.
-The second call to ``require`` ensures that there will not be too many coins,
-which could cause overflow errors later.
+The functions that make up the contract, and that users and contracts can call are ``mint`` and ``send``.
-On the other hand, ``send`` can be used by anyone (who already
-has some of these coins) to send coins to anyone else. If you do not have
-enough coins to send, the ``require`` call will fail and also provide the
-user with an appropriate error message string.
+The ``mint`` function sends an amount of newly created coins to another address.
+The :ref:`require ` function call defines conditions that reverts all changes if not met.
+In this example, ``require(msg.sender == minter);`` ensures that only the creator of the contract can call ``mint``,
+and ``require(amount < 1e60);`` ensures a maximum amount of tokens, without which could cause overflow errors in the future.
+
+The ``send`` function can be used by anyone (who already
+has some of these coins) to send coins to anyone else. If the sender does not have
+enough coins to send, the ``require`` call fails and provides the
+sender with an appropriate error message string.
.. note::
If you use
this contract to send coins to an address, you will not see anything when you
- look at that address on a blockchain explorer, because the fact that you sent
+ look at that address on a blockchain explorer, because the record that you sent
coins and the changed balances are only stored in the data storage of this
- particular coin contract. By the use of events it is relatively easy to create
+ particular coin contract. By using events, you can create
a "blockchain explorer" that tracks transactions and balances of your new coin,
but you have to inspect the coin contract address and not the addresses of the
coin owners.
@@ -301,6 +296,8 @@ Smart contracts even have limited access to other smart contracts.
.. index:: ! account, address, storage, balance
+.. _accounts:
+
Accounts
========
@@ -513,10 +510,10 @@ Deactivate and Self-destruct
The only way to remove code from the blockchain is 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 from the state. Removing the contract in theory sounds like a good idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost.
+.. warning::
+ Even if a contract is removed by "selfdestruct", it is still part of the history of the blockchain and probably retained by most Ethereum nodes. So using "selfdestruct" is not the same as deleting data from a hard disk.
+
.. note::
Even if a contract's code does not contain a call to ``selfdestruct``, it can still perform that operation using ``delegatecall`` or ``callcode``.
If you want to deactivate your contracts, you should instead **disable** them by changing some internal state which causes all functions to revert. This makes it impossible to use the contract, as it returns Ether immediately.
-
-.. warning::
- Even if a contract is removed by "selfdestruct", it is still part of the history of the blockchain and probably retained by most Ethereum nodes. So using "selfdestruct" is not the same as deleting data from a hard disk.
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index ff80b01ae..137513b83 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -11,7 +11,7 @@ Layout of State Variables in Storage
Statically-sized variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position ``0``. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible, according to the following rules:
- The first item in a storage slot is stored lower-order aligned.
-- Elementary types use only that many bytes that are necessary to store them.
+- Elementary types use only as many bytes as are necessary to store them.
- If an elementary type does not fit the remaining part of a storage slot, it is moved to the next storage slot.
- Structs and array data always start a new slot and occupy whole slots (but items inside a struct or array are packed tightly according to these rules).
@@ -64,10 +64,11 @@ So for the following contract snippet::
pragma solidity >=0.4.0 <0.7.0;
+
contract C {
- struct s { uint a; uint b; }
- uint x;
- mapping(uint => mapping(uint => s)) data;
+ struct S { uint a; uint b; }
+ uint x;
+ mapping(uint => mapping(uint => S)) data;
}
The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``.
@@ -268,7 +269,7 @@ Tips and Tricks
* Use ``delete`` on arrays to delete all its elements.
* Use shorter types for struct elements and sort them such that short types are grouped together. This can lower the gas costs as multiple ``SSTORE`` operations might be combined into a single (``SSTORE`` costs 5000 or 20000 gas, so this is what you want to optimise). Use the gas price estimator (with optimiser enabled) to check!
-* Make your state variables public - the compiler will create :ref:`getters ` for you automatically.
+* Make your state variables public - the compiler creates :ref:`getters ` for you automatically.
* If you end up checking conditions on input or state a lot at the beginning of your functions, try using :ref:`modifiers`.
* Initialize storage structs with a single assignment: ``x = MyStruct({a: 1, b: 2});``
diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst
index d55547050..2ba6d2188 100644
--- a/docs/natspec-format.rst
+++ b/docs/natspec-format.rst
@@ -36,12 +36,16 @@ Documentation is inserted above each ``class``, ``interface`` and
documentation `__.
The following example shows a contract and a function using all available tags.
-Note: NatSpec currently does NOT apply to public state variables (see
-`solidity#3418 `__),
-even if they are declared public and therefore do affect the ABI. Note:
-The Solidity compiler only interprets tags if they are external or
-public. You are welcome to use similar comments for your internal and
-private functions, but those will not be parsed.
+
+.. note::
+
+ NatSpec currently does NOT apply to public state variables (see
+ `solidity#3418 `__),
+ even if they are declared public and therefore do affect the ABI.
+
+ The Solidity compiler only interprets tags if they are external or
+ public. You are welcome to use similar comments for your internal and
+ private functions, but those will not be parsed.
.. code:: solidity
@@ -108,7 +112,7 @@ to the end-user as:
This function will multiply 10 by 7
-if a function is being called and the input ``a`` is assigned a value of 7.
+if a function is being called and the input ``a`` is assigned a value of 10.
Specifying these dynamic expressions is outside the scope of the Solidity
documentation and you may read more at
@@ -196,4 +200,3 @@ file should also be produced and should look like this:
},
"title" : "A simulator for trees"
}
-
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index 7bc75a306..fb38f2d93 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -757,20 +757,26 @@ No::
pragma solidity >=0.4.0 <0.7.0;
+
// Base contracts just to make this compile
contract B {
constructor(uint) public {
}
}
+
+
contract C {
constructor(uint, uint) public {
}
}
+
+
contract D {
constructor(uint) public {
}
}
+
contract A is B, C, D {
uint x;
@@ -778,12 +784,12 @@ No::
B(param1)
C(param2, param3)
D(param4)
- public
- {
+ public {
x = param5;
}
}
+
contract X is B, C, D {
uint x;
@@ -792,10 +798,11 @@ No::
C(param2, param3)
D(param4)
public {
- x = param5;
- }
+ x = param5;
+ }
}
+
When declaring short functions with a single statement, it is permissible to do it on a single line.
Permissible::
@@ -973,27 +980,32 @@ Yes::
pragma solidity >=0.4.0 <0.7.0;
+
// Owned.sol
contract Owned {
- address public owner;
+ address public owner;
- constructor() public {
- owner = msg.sender;
- }
+ constructor() public {
+ owner = msg.sender;
+ }
- modifier onlyOwner {
- require(msg.sender == owner);
- _;
- }
+ modifier onlyOwner {
+ require(msg.sender == owner);
+ _;
+ }
- function transferOwnership(address newOwner) public onlyOwner {
- owner = newOwner;
- }
+ function transferOwnership(address newOwner) public onlyOwner {
+ owner = newOwner;
+ }
}
- // Congress.sol
+and in ``Congress.sol``::
+
+ pragma solidity >=0.4.0 <0.7.0;
+
import "./Owned.sol";
+
contract Congress is Owned, TokenRecipient {
//...
}
@@ -1002,32 +1014,34 @@ No::
pragma solidity >=0.4.0 <0.7.0;
+
// owned.sol
contract owned {
- address public owner;
+ address public owner;
- constructor() public {
- owner = msg.sender;
- }
+ constructor() public {
+ owner = msg.sender;
+ }
- modifier onlyOwner {
- require(msg.sender == owner);
- _;
- }
+ modifier onlyOwner {
+ require(msg.sender == owner);
+ _;
+ }
- function transferOwnership(address newOwner) public onlyOwner {
- owner = newOwner;
- }
+ function transferOwnership(address newOwner) public onlyOwner {
+ owner = newOwner;
+ }
}
- // Congress.sol
+and in ``Congress.sol``::
+
import "./owned.sol";
+
contract Congress is owned, tokenRecipient {
//...
}
-
Struct Names
==========================
@@ -1104,6 +1118,7 @@ added looks like the one below::
pragma solidity >=0.4.0 <0.7.0;
+
/// @author The Solidity Team
/// @title A simple storage example
contract SimpleStorage {
@@ -1126,4 +1141,4 @@ added looks like the one below::
It is recommended that Solidity contracts are fully annontated using `NatSpec `_ for all public interfaces (everything in the ABI).
-Please see the sectian about `NatSpec `_ for a detailed explanation.
\ No newline at end of file
+Please see the section about `NatSpec `_ for a detailed explanation.
\ No newline at end of file
diff --git a/docs/types/conversion.rst b/docs/types/conversion.rst
index 49a3f0100..51e373405 100644
--- a/docs/types/conversion.rst
+++ b/docs/types/conversion.rst
@@ -8,25 +8,28 @@ Conversions between Elementary Types
Implicit Conversions
--------------------
-If an operator is applied to different types, the compiler tries to
-implicitly convert one of the operands to the type of the other (the same is
-true for assignments). In general, an implicit conversion between value-types
-is possible if it
-makes sense semantically and no information is lost: ``uint8`` is convertible to
-``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256``
-(because ``uint256`` cannot hold e.g. ``-1``).
+If an operator is applied to different types, the compiler tries to implicitly
+convert one of the operands to the type of the other (the same is true for assignments).
+This means that operations are always performed in the type of one of the operands.
+In general, an implicit conversion between value-types is possible if it makes
+sense semantically and no information is lost.
+
+For example, ``uint8`` is convertible to
+``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256``,
+because ``uint256`` cannot hold values such as ``-1``.
For more details, please consult the sections about the types themselves.
Explicit Conversions
--------------------
-If the compiler does not allow implicit conversion but you know what you are
-doing, an explicit type conversion is sometimes possible. Note that this may
-give you some unexpected behaviour and allows you to bypass some security
+If the compiler does not allow implicit conversion but you are confident a conversion will work,
+an explicit type conversion is sometimes possible. This may
+result in unexpected behaviour and allows you to bypass some security
features of the compiler, so be sure to test that the
-result is what you want! Take the following example where you are converting
-a negative ``int`` to a ``uint``:
+result is what you want and expect!
+
+Take the following example that converts a negative ``int`` to a ``uint``:
::
@@ -42,7 +45,7 @@ cut off::
uint32 a = 0x12345678;
uint16 b = uint16(a); // b will be 0x5678 now
-If an integer is explicitly converted to a larger type, it is padded on the left (i.e. at the higher order end).
+If an integer is explicitly converted to a larger type, it is padded on the left (i.e., at the higher order end).
The result of the conversion will compare equal to the original integer::
uint16 a = 0x1234;
diff --git a/docs/types/mapping-types.rst b/docs/types/mapping-types.rst
index 2414687c5..afee61202 100644
--- a/docs/types/mapping-types.rst
+++ b/docs/types/mapping-types.rst
@@ -25,7 +25,7 @@ in functions, or as parameters for library functions.
They cannot be used as parameters or return parameters
of contract functions that are publicly visible.
-You can mark variables of mapping type as ``public`` and Solidity creates a
+You can mark state variables of mapping type as ``public`` and Solidity creates a
:ref:`getter ` for you. The ``_KeyType`` becomes a
parameter for the getter. If ``_ValueType`` is a value type or a struct,
the getter returns ``_ValueType``.
diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst
index 9c082f9b4..f970a2e2c 100644
--- a/docs/types/value-types.rst
+++ b/docs/types/value-types.rst
@@ -26,6 +26,7 @@ Operators:
The operators ``||`` and ``&&`` apply the common short-circuiting rules. This means that in the expression ``f(x) || g(y)``, if ``f(x)`` evaluates to ``true``, ``g(y)`` will not be evaluated even if it may have side-effects.
.. index:: ! uint, ! int, ! integer
+.. _integers:
Integers
--------
@@ -332,7 +333,7 @@ type and this type is also used in the :ref:`ABI`.
Contracts do not support any operators.
The members of contract types are the external functions of the contract
-including public state variables.
+including any state variables marked as ``public``.
For a contract ``C`` you can use ``type(C)`` to access
:ref:`type information` about the contract.
@@ -427,6 +428,9 @@ long as the operands are integers. If any of the two is fractional, bit operatio
and exponentiation is disallowed if the exponent is fractional (because that might result in
a non-rational number).
+.. warning::
+ Division on integer literals used to truncate in Solidity prior to version 0.4.0, but it now converts into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``.
+
.. note::
Solidity has a number literal type for each rational number.
Integer literals and rational number literals belong to number literal types.
@@ -435,8 +439,6 @@ a non-rational number).
types. So the number literal expressions ``1 + 2`` and ``2 + 1`` both
belong to the same number literal type for the rational number three.
-.. warning::
- Division on integer literals used to truncate in Solidity prior to version 0.4.0, but it now converts into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``.
.. note::
Number literal expressions are converted into a non-literal type as soon as they are used with non-literal
@@ -510,7 +512,7 @@ Enums
Enums are one way to create a user-defined type in Solidity. They are explicitly convertible
to and from all integer types but implicit conversion is not allowed. The explicit conversion
from integer checks at runtime that the value lies inside the range of the enum and causes a failing assert otherwise.
-Enums needs at least one member.
+Enums require at least one member, and its default value when declared is the first member.
The data representation is the same as for enums in C: The options are represented by
subsequent unsigned integer values starting from ``0``.
@@ -624,100 +626,116 @@ Example that shows how to use the members::
pragma solidity >=0.4.16 <0.7.0;
+
contract Example {
- function f() public payable returns (bytes4) {
- return this.f.selector;
- }
- function g() public {
- this.f.gas(10).value(800)();
- }
+ function f() public payable returns (bytes4) {
+ return this.f.selector;
+ }
+
+ function g() public {
+ this.f.gas(10).value(800)();
+ }
}
Example that shows how to use internal function types::
pragma solidity >=0.4.16 <0.7.0;
+
library ArrayUtils {
- // internal functions can be used in internal library functions because
- // they will be part of the same code context
- function map(uint[] memory self, function (uint) pure returns (uint) f)
- internal
- pure
- returns (uint[] memory r)
- {
- r = new uint[](self.length);
- for (uint i = 0; i < self.length; i++) {
- r[i] = f(self[i]);
+ // internal functions can be used in internal library functions because
+ // they will be part of the same code context
+ function map(uint[] memory self, function (uint) pure returns (uint) f)
+ internal
+ pure
+ returns (uint[] memory r)
+ {
+ r = new uint[](self.length);
+ for (uint i = 0; i < self.length; i++) {
+ r[i] = f(self[i]);
+ }
}
- }
- function reduce(
- uint[] memory self,
- function (uint, uint) pure returns (uint) f
- )
- internal
- pure
- returns (uint r)
- {
- r = self[0];
- for (uint i = 1; i < self.length; i++) {
- r = f(r, self[i]);
+
+ function reduce(
+ uint[] memory self,
+ function (uint, uint) pure returns (uint) f
+ )
+ internal
+ pure
+ returns (uint r)
+ {
+ r = self[0];
+ for (uint i = 1; i < self.length; i++) {
+ r = f(r, self[i]);
+ }
}
- }
- function range(uint length) internal pure returns (uint[] memory r) {
- r = new uint[](length);
- for (uint i = 0; i < r.length; i++) {
- r[i] = i;
+
+ function range(uint length) internal pure returns (uint[] memory r) {
+ r = new uint[](length);
+ for (uint i = 0; i < r.length; i++) {
+ r[i] = i;
+ }
}
- }
}
+
contract Pyramid {
- using ArrayUtils for *;
- function pyramid(uint l) public pure returns (uint) {
- return ArrayUtils.range(l).map(square).reduce(sum);
- }
- function square(uint x) internal pure returns (uint) {
- return x * x;
- }
- function sum(uint x, uint y) internal pure returns (uint) {
- return x + y;
- }
+ using ArrayUtils for *;
+
+ function pyramid(uint l) public pure returns (uint) {
+ return ArrayUtils.range(l).map(square).reduce(sum);
+ }
+
+ function square(uint x) internal pure returns (uint) {
+ return x * x;
+ }
+
+ function sum(uint x, uint y) internal pure returns (uint) {
+ return x + y;
+ }
}
Another example that uses external function types::
pragma solidity >=0.4.22 <0.7.0;
+
contract Oracle {
- struct Request {
- bytes data;
- function(uint) external callback;
- }
- Request[] requests;
- event NewRequest(uint);
- function query(bytes memory data, function(uint) external callback) public {
- requests.push(Request(data, callback));
- emit NewRequest(requests.length - 1);
- }
- function reply(uint requestID, uint response) public {
- // Here goes the check that the reply comes from a trusted source
- requests[requestID].callback(response);
- }
+ struct Request {
+ bytes data;
+ function(uint) external callback;
+ }
+
+ Request[] private requests;
+ event NewRequest(uint);
+
+ function query(bytes memory data, function(uint) external callback) public {
+ requests.push(Request(data, callback));
+ emit NewRequest(requests.length - 1);
+ }
+
+ function reply(uint requestID, uint response) public {
+ // Here goes the check that the reply comes from a trusted source
+ requests[requestID].callback(response);
+ }
}
+
contract OracleUser {
- Oracle constant oracle = Oracle(0x1234567); // known contract
- uint exchangeRate;
- function buySomething() public {
- oracle.query("USD", this.oracleResponse);
- }
- function oracleResponse(uint response) public {
- require(
- msg.sender == address(oracle),
- "Only oracle can call this."
- );
- exchangeRate = response;
- }
+ Oracle constant private ORACLE_CONST = Oracle(0x1234567); // known contract
+ uint private exchangeRate;
+
+ function buySomething() public {
+ ORACLE_CONST.query("USD", this.oracleResponse);
+ }
+
+ function oracleResponse(uint response) public {
+ require(
+ msg.sender == address(ORACLE_CONST),
+ "Only oracle can call this."
+ );
+ exchangeRate = response;
+ }
}
.. note::
diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst
index 604386c47..8b8c06735 100644
--- a/docs/units-and-global-variables.rst
+++ b/docs/units-and-global-variables.rst
@@ -52,6 +52,8 @@ interpret a function parameter in days, you can in the following way::
}
}
+.. _special-variables-functions:
+
Special Variables and Functions
===============================
diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt
index b7bf917f8..a092e3140 100644
--- a/libdevcore/CMakeLists.txt
+++ b/libdevcore/CMakeLists.txt
@@ -12,6 +12,7 @@ set(sources
FixedHash.h
IndentedWriter.cpp
IndentedWriter.h
+ InvertibleMap.h
IpfsHash.cpp
IpfsHash.h
JSON.cpp
@@ -33,7 +34,6 @@ set(sources
)
add_library(devcore ${sources})
-target_link_libraries(devcore PUBLIC jsoncpp ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} Threads::Threads)
+target_link_libraries(devcore PUBLIC jsoncpp Boost::boost Boost::filesystem Boost::regex Boost::system Threads::Threads)
target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}")
-target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
add_dependencies(devcore solidity_BuildInfo.h)
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index 0a13e7940..2fca07171 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -81,6 +81,22 @@ inline std::vector operator+(std::vector&& _a, std::vector&& _b)
ret += std::move(_b);
return ret;
}
+/// Concatenate something to a sets of elements.
+template
+inline std::set operator+(std::set const& _a, U&& _b)
+{
+ std::set ret(_a);
+ ret += std::forward(_b);
+ return ret;
+}
+/// Concatenate something to a sets of elements, move variant.
+template
+inline std::set operator+(std::set&& _a, U&& _b)
+{
+ std::set ret(std::move(_a));
+ ret += std::forward(_b);
+ return ret;
+}
namespace dev
{
diff --git a/libdevcore/InvertibleMap.h b/libdevcore/InvertibleMap.h
new file mode 100644
index 000000000..4448d03d7
--- /dev/null
+++ b/libdevcore/InvertibleMap.h
@@ -0,0 +1,93 @@
+/*
+ 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 .
+*/
+
+#pragma once
+
+#include