diff --git a/circle.yml b/.circleci/config.yml similarity index 73% rename from circle.yml rename to .circleci/config.yml index 7c95fa7ff..cf9c92128 100644 --- a/circle.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ defaults: command: | mkdir -p build cd build - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo + cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo $CMAKE_OPTIONS make -j4 - run_tests: &run_tests name: Tests @@ -122,6 +122,7 @@ jobs: - image: buildpack-deps:artful environment: TERM: xterm + CMAKE_OPTIONS: -DCOVERAGE=OFF steps: - checkout - run: @@ -129,14 +130,41 @@ jobs: 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 libz3-dev + ./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 + - persist_to_workspace: + root: build + paths: + - "*" + + build_x86_clang7: + docker: + - image: buildpack-deps:cosmic + environment: + TERM: xterm + CC: /usr/bin/clang-7 + CXX: /usr/bin/clang++-7 + 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 libz3-dev + ./scripts/install_obsolete_jsoncpp_1_7_4.sh + - run: *setup_prerelease_commit_hash + - run: *run_build + - store_artifacts: *solc_artifact + - persist_to_workspace: + root: build + paths: + - "*" build_x86_mac: macos: - xcode: "9.0" + xcode: "10.0.0" environment: TERM: xterm steps: @@ -150,11 +178,39 @@ jobs: 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:artful + steps: + - checkout + - run: + name: Check for trailing whitespace + command: ./scripts/check_style.sh + test_buglist: docker: - image: circleci/node @@ -185,15 +241,28 @@ jobs: name: Install dependencies command: | apt-get -qq update - apt-get -qy install libz3-dev libleveldb1v5 + apt-get -qy install libz3-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_mac: macos: - xcode: "9.0" + xcode: "10.0.0" environment: TERM: xterm steps: @@ -211,6 +280,9 @@ jobs: - run: *run_tests - store_test_results: path: test_results/ + - store_artifacts: + path: test_results/ + destination: test_results/ docs: docker: @@ -221,7 +293,7 @@ jobs: name: Install build dependencies command: | apt-get -qq update - apt-get -qy install python-sphinx + apt-get -qy install python-sphinx python-pip - run: *setup_prerelease_commit_hash - run: name: Build documentation @@ -234,6 +306,8 @@ 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: @@ -245,6 +319,7 @@ workflows: requires: - build_emscripten - build_x86_linux: *build_on_tags + - build_x86_clang7: *build_on_tags - build_x86_mac: *build_on_tags - test_x86_linux: <<: *build_on_tags diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..ab452ecf2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +# out-of-tree builds usually go here. This helps improving performance of uploading +# the build context to the docker image build server +/build + +# in-tree builds +/deps diff --git a/.editorconfig b/.editorconfig index 86a837c14..7b8a7be9f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,7 @@ trim_trailing_whitespace = true [*.{cpp,h}] indent_style = tab +indent_size = 4 [*.{py,rst,sh,yml}] indent_style = space diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..c3caf86e3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,39 @@ +--- +name: Bug Report +about: Bug reports about the Solidity Compiler. +--- + + + +## Description + + + +## Environment + +- Compiler version: +- Framework/IDE (e.g. Truffle or Remix): +- EVM execution environment / backend / blockchain client: +- Operating system: + +## Steps to Reproduce + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..6702b62cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,47 @@ +--- +name: Feature Request +about: Solidity language or infrastructure feature requests. +--- + + + +## Abstract + + + +## Motivation + + + +## Specification + + + +## Backwards Compatibility + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/general.md b/.github/ISSUE_TEMPLATE/general.md new file mode 100644 index 000000000..410b42e00 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/general.md @@ -0,0 +1,21 @@ +--- +name: General Feedback +about: Any general feedback (neither feature request nor bug reports) +--- + + +## Description + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..9fdbf158e --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,22 @@ + + +### Description + + + +### Checklist +- [ ] Code compiles correctly +- [ ] All tests are passing +- [ ] New tests have been created which fail without the change (if possible) +- [ ] README / documentation was extended, if necessary +- [ ] Changelog entry (if change is visible to the user) +- [ ] Used meaningful commit messages diff --git a/.gitignore b/.gitignore index 87a3e5933..e0f010d34 100644 --- a/.gitignore +++ b/.gitignore @@ -36,13 +36,19 @@ docs/_build docs/utils/__pycache__ docs/utils/*.pyc /deps/downloads/ +deps/install +deps/cache # vim stuff -*.swp +[._]*.sw[a-p] +[._]sw[a-p] # IDE files .idea +.vscode browse.VC.db CMakeLists.txt.user /CMakeSettings.json /.vs +/.cproject +/.project diff --git a/.travis.yml b/.travis.yml index 8487deef8..ef4f8b398 100644 --- a/.travis.yml +++ b/.travis.yml @@ -184,7 +184,7 @@ deploy: # Both the build and deploy steps for Emscripten are only run within the Ubuntu # configurations (not for macOS). That is controlled by conditionals within the bash # scripts because TravisCI doesn't provide much in the way of conditional logic. - + - provider: script script: test $SOLC_EMSCRIPTEN != On || (scripts/release_emscripten.sh) skip_cleanup: true diff --git a/CMakeLists.txt b/CMakeLists.txt index f30872af6..f2c84d201 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.4.25") +set(PROJECT_VERSION "0.5.0") project(solidity VERSION ${PROJECT_VERSION}) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..36813f36f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at chris@ethereum.org which only goes to +Christian Reitwiessner or axic@ethereum.org which only goes to Alex Beregszaszi. +To report an issue involving either of them please email Hudson Jameson at +hudson@ethereum.org. +All complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/CODING_STYLE.md b/CODING_STYLE.md index f36503d03..a0fe98644 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -146,7 +146,7 @@ for (auto i = x->begin(); i != x->end(); ++i) {} ``` No: -```cp +```cpp const double d = 0; int i, j; char *s; @@ -193,7 +193,7 @@ for (map::iterator i = l.begin(); i != l.end(); 2. Generally avoid shortening a standard form that already includes all important information: - e.g. stick to `shared_ptr` rather than shortening to `ptr`. 3. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently: - - e.g. `using Guard = std::lock_guard;` ///< Guard is used throughout the codebase since it is clear in meaning and used commonly. + - e.g. `using Guard = std::lock_guard;` ///< Guard is used throughout the codebase since it is clear in meaning and used commonly. 4. In general expressions should be roughly as important/semantically meaningful as the space they occupy. 5. Avoid introducing aliases for types unless they are very complicated. Consider the number of items a brain can keep track of at the same time. diff --git a/Changelog.md b/Changelog.md index bfe82f8c0..026e2bac5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,142 @@ +### 0.5.0 (2018-11-13) + +How to update your code: + * Change every ``.call()`` to a ``.call("")`` and every ``.call(signature, a, b, c)`` to use ``.call(abi.encodeWithSignature(signature, a, b, c))`` (the last one only works for value types). + * Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``. + * Add ``public`` to every function and ``external`` to every fallback or interface function that does not specify its visibility already. + * Make your fallback functions ``external``. + * Explicitly state the data location for all variables of struct, array or mapping types (including function parameters), e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``. Note that ``external`` functions require parameters with a data location of ``calldata``. + * Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``. + * Declare variables and especially function arguments as ``address payable``, if you want to call ``transfer`` on them. + +Breaking Changes: + * ABI Encoder: Properly pad data from calldata (``msg.data`` and external function parameters). Use ``abi.encodePacked`` for unpadded encoding. + * C API (``libsolc`` / raw ``soljson.js``): Removed the ``version``, ``license``, ``compileSingle``, ``compileJSON``, ``compileJSONCallback`` methods + and replaced them with the ``solidity_license``, ``solidity_version`` and ``solidity_compile`` methods. + * Code Generator: Signed right shift uses proper arithmetic shift, i.e. rounding towards negative infinity. Warning: this may silently change the semantics of existing code! + * Code Generator: Revert at runtime if calldata is too short or points out of bounds. This is done inside the ``ABI decoder`` and therefore also applies to ``abi.decode()``. + * Code Generator: Use ``STATICCALL`` for ``pure`` and ``view`` functions. This was already the case in the experimental 0.5.0 mode. + * Commandline interface: Remove obsolete ``--formal`` option. + * Commandline interface: Rename the ``--julia`` option to ``--yul``. + * Commandline interface: Require ``-`` if standard input is used as source. + * Commandline interface: Use hash of library name for link placeholder instead of name itself. + * Compiler interface: Disallow remappings with empty prefix. + * Control Flow Analyzer: Consider mappings as well when checking for uninitialized return values. + * Control Flow Analyzer: Turn warning about returning uninitialized storage pointers into an error. + * General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code. + * General: Disallow declaring empty structs. + * General: Disallow raw ``callcode`` (was already deprecated in 0.4.12). It is still possible to use it via inline assembly. + * General: Disallow ``var`` keyword. + * General: Disallow ``sha3`` and ``suicide`` aliases. + * General: Disallow the ``throw`` statement. This was already the case in the experimental 0.5.0 mode. + * General: Disallow the ``years`` unit denomination (was already deprecated in 0.4.24) + * General: Introduce ``emit`` as a keyword instead of parsing it as identifier. + * General: New keywords: ``calldata`` and ``constructor`` + * General: New reserved keywords: ``alias``, ``apply``, ``auto``, ``copyof``, ``define``, ``immutable``, + ``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, + ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. + * General: Remove assembly instruction aliases ``sha3`` and ``suicide`` + * General: C99-style scoping rules are enforced now. This was already the case in the experimental 0.5.0 mode. + * General: Disallow combining hex numbers with unit denominations (e.g. ``0x1e wei``). This was already the case in the experimental 0.5.0 mode. + * JSON AST: Remove ``constant`` and ``payable`` fields (the information is encoded in the ``stateMutability`` field). + * JSON AST: Replace the ``isConstructor`` field by a new ``kind`` field, which can be ``constructor``, ``fallback`` or ``function``. + * Interface: Remove "clone contract" feature. The ``--clone-bin`` and ``--combined-json clone-bin`` commandline options are not available anymore. + * Name Resolver: Do not exclude public state variables when looking for conflicting declarations. + * Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence. + * Parser: Disallow trailing dots that are not followed by a number. + * Parser: Remove ``constant`` as function state mutability modifier. + * Parser: Disallow uppercase X in hex number literals + * Type Checker: Disallow assignments between tuples with different numbers of components. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow values for constants that are not compile-time constants. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow arithmetic operations for boolean variables. + * Type Checker: Disallow tight packing of literals. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow calling base constructors without parentheses. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size. + * Type Checker: Disallow conversions between unrelated contract types. Explicit conversion via ``address`` can still achieve it. + * Type Checker: Disallow empty return statements for functions with one or more return values. + * Type Checker: Disallow empty tuple components. This was partly already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow multi-variable declarations with mismatching number of values. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow specifying base constructor arguments multiple times in the same inheritance hierarchy. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow calling constructor with wrong argument count. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Disallow uninitialized storage variables. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Detecting cyclic dependencies in variables and structs is limited in recursion to 256. + * Type Checker: Require explicit data location for all variables, including function parameters. This was partly already the case in the experimental 0.5.0 mode. + * Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``. + * Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode. + * Type Checker: Address members are not included in contract types anymore. An explicit conversion is now required before invoking an ``address`` member from a contract. + * Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore. + * Type System: Disallow explicit and implicit conversions from decimal literals to ``bytesXX`` types. + * Type System: Disallow explicit and implicit conversions from hex literals to ``bytesXX`` types of different size. + * Type System: Distinguish between payable and non-payable address types. + * View Pure Checker: Disallow ``msg.value`` in (or introducing it via a modifier to) a non-payable function. + * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/solidity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. + * References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode. + * Syntax Checker: Disallow functions without implementation to use modifiers. This was already the case in the experimental 0.5.0 mode. + * Syntax Checker: Named return values in function types are an error. + * Syntax Checker: Strictly require visibility specifier for functions. This was already the case in the experimental 0.5.0 mode. + * Syntax Checker: Disallow unary ``+``. This was already the case in the experimental 0.5.0 mode. + * Syntax Checker: Disallow single statement variable declaration inside if/while/for bodies that are not blocks. + * View Pure Checker: Strictly enforce state mutability. This was already the case in the experimental 0.5.0 mode. + +Language Features: + * General: Add ``staticcall`` to ``address``. + * General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions. + * General: Support ``pop()`` for storage arrays. + * General: Scoping rules now follow the C99-style. + * General: Allow ``enum``s in interfaces. + * General: Allow ``mapping`` storage pointers as arguments and return values in all internal functions. + * General: Allow ``struct``s in interfaces. + * General: Provide access to the ABI decoder through ``abi.decode(bytes memory data, (...))``. + * General: Disallow zero length for fixed-size arrays. + * Parser: Accept the ``address payable`` type during parsing. + +Compiler Features: + * Build System: Support for Mojave version of macOS added. + * Code Generator: ``CREATE2`` instruction has been updated to match EIP1014 (aka "Skinny CREATE2"). It also is accepted as part of Constantinople. + * Code Generator: ``EXTCODEHASH`` instruction has been added based on EIP1052. + * Type Checker: Nicer error message when trying to reference overloaded identifiers in inline assembly. + * Type Checker: Show named argument in case of error. + * Type System: IntegerType is split into IntegerType and AddressType internally. + * Tests: Determine transaction status during IPC calls. + * Code Generator: Allocate and free local variables according to their scope. + * Removed ``pragma experimental "v0.5.0";``. + * Syntax Checker: Improved error message for lookup in function types. + * Name Resolver: Updated name suggestion look up function to take into account length of the identifier: 1: no search, 2-3: at most one change, 4-: at most two changes + * SMTChecker: Support calls to internal functions that return none or a single value. + +Bugfixes: + * Build System: Support versions of CVC4 linked against CLN instead of GMP. In case of compilation issues due to the experimental SMT solver support, the solvers can be disabled when configuring the project with CMake using ``-DUSE_CVC4=OFF`` or ``-DUSE_Z3=OFF``. + * Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum. + * Code Generator: Fix allocation of byte arrays (zeroed out too much memory). + * Code Generator: Properly handle negative number literals in ABIEncoderV2. + * Code Generator: Do not crash on using a length of zero for multidimensional fixed-size arrays. + * Commandline Interface: Correctly handle paths with backslashes on windows. + * Control Flow Analyzer: Ignore unimplemented functions when detecting uninitialized storage pointer returns. + * Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions. + * Optimizer: Correctly estimate gas costs of constants for special cases. + * Optimizer: Fix simplification rule initialization bug that appeared on some emscripten platforms. + * References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own. + * References Resolver: Enforce ``storage`` as data location for mappings. + * References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``. + * References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter. + * References Resolver: Fix high CPU usage when using large variable names issue. Only suggest similar name if identifiers shorter than 80 characters. + * Type Checker: Default data location for type conversions (e.g. from literals) is memory and not storage. + * Type Checker: Disallow assignments to mappings within tuple assignments as well. + * Type Checker: Disallow packed encoding of arrays of structs. + * Type Checker: Allow assignments to local variables of mapping types. + * Type Checker: Consider fixed size arrays when checking for recursive structs. + * Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined. + * Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``. + * Type Checker: Dynamic types as key for public mappings return error instead of assertion fail. + * Type Checker: Fix internal error when array index value is too large. + * Type Checker: Fix internal error when fixed-size array is too large to be encoded. + * Type Checker: Fix internal error for array type conversions. + * Type Checker: Fix internal error when array index is not an unsigned. + * Type System: Allow arbitrary exponents for literals with a mantissa of zero. + * Parser: Fix incorrect source location for nameless parameters. + * Command Line Interface: Fix internal error when compiling stdin with no content and --ast option. + ### 0.4.25 (2018-09-12) Important Bugfixes: @@ -63,6 +202,7 @@ Features: * General: Introduce new constructor syntax using the ``constructor`` keyword as experimental 0.5.0 feature. * General: Limit the number of errors output in a single run to 256. * General: Support accessing dynamic return data in post-byzantium EVMs. + * General: Allow underscores in numeric and hex literals to separate thousands and quads. * Inheritance: Error when using empty parentheses for base class constructors that require arguments as experimental 0.5.0 feature. * Inheritance: Error when using no parentheses in modifier-style constructor calls as experimental 0.5.0 feature. * Interfaces: Allow overriding external functions in interfaces with public in an implementing contract. @@ -106,7 +246,7 @@ Bugfixes: Features: * Code Generator: Assert that ``k != 0`` for ``mulmod(a, b, k)`` and ``addmod(a, b, k)`` as experimental 0.5.0 feature. * Code Generator: Do not retain any gas in calls (except if EVM version is set to homestead). - * Code Generator: Use ``STATICCALL`` opcode for calling ``view`` and ``pure`` functions as experimenal 0.5.0 feature. + * Code Generator: Use ``STATICCALL`` opcode for calling ``view`` and ``pure`` functions as experimental 0.5.0 feature. * General: C99/C++-style scoping rules (instead of JavaScript function scoping) take effect as experimental v0.5.0 feature. * General: Improved messaging when error spans multiple lines of a sourcefile * General: Support and recommend using ``emit EventName();`` to call events explicitly. @@ -659,7 +799,7 @@ Bugfixes: * Conditional: `x ? y : z` * Bugfix: Fixed several bugs where the optimizer generated invalid code. * Bugfix: Enums and structs were not accessible to other contracts. - * Bugfix: Fixed segfault connected to function paramater types, appeared during gas estimation. + * Bugfix: Fixed segfault connected to function parameter types, appeared during gas estimation. * Bugfix: Type checker crash for wrong number of base constructor parameters. * Bugfix: Allow function overloads with different array types. * Bugfix: Allow assignments of type `(x) = 7`. diff --git a/README.md b/README.md index 8303131c8..7a448e8c7 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,66 @@ # The Solidity Contract-Oriented Programming Language [![Join the chat at https://gitter.im/ethereum/solidity](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/solidity?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/ethereum/solidity.svg?branch=develop)](https://travis-ci.org/ethereum/solidity) +Solidity is a statically typed, contract-oriented, high-level language for implementing smart contracts on the Ethereum platform. -## Useful links -To get started you can find an introduction to the language in the [Solidity documentation](https://solidity.readthedocs.org). In the documentation, you can find [code examples](https://solidity.readthedocs.io/en/latest/solidity-by-example.html) as well as [a reference](https://solidity.readthedocs.io/en/latest/solidity-in-depth.html) of the syntax and details on how to write smart contracts. +## Table of Contents -You can start using [Solidity in your browser](http://remix.ethereum.org) with no need to download or compile anything. +- [Background](#background) +- [Build and Install](#build-and-install) +- [Example](#example) +- [Documentation](#documentation) +- [Development](#development) +- [Maintainers](#maintainers) +- [License](#license) -The changelog for this project can be found [here](https://github.com/ethereum/solidity/blob/develop/Changelog.md). +## Background -Solidity is still under development. So please do not hesitate and open an [issue in GitHub](https://github.com/ethereum/solidity/issues) if you encounter anything strange. +Solidity is a statically-typed curly-braces programming language designed for developing smart contracts +that run on the Ethereum Virtual Machine. Smart contracts are programs that are executed inside a peer-to-peer +network where nobody has special authority over the execution and thus they allow to implement tokens of value, +ownership, voting and other kinds of logics. -## Building -See the [Solidity documentation](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source) for build instructions. +## Build and Install -## How to Contribute -Please see our [contribution guidelines](https://solidity.readthedocs.io/en/latest/contributing.html) in the Solidity documentation. +Instructions about how to build and install the Solidity compiler can be found in the [Solidity documentation](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source) + + +## Example + +A "Hello World" program in Solidity is of even less use than in other languages, but still: + +``` +pragma solidity ^0.4.16; + +contract HelloWorld { + function helloWorld() external pure returns (string memory) { + return "Hello, World!"; + } +} +``` + +To get started with Solidity, you can use [Remix](https://remix.ethereum.org/), which is an +browser-based IDE. Here are some example contracts: + +1. [Voting](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#voting) +2. [Blind Auction](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#blind-auction) +3. [Safe remote purchase](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#safe-remote-purchase) +4. [Micropayment Channel](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#micropayment-channel) + +## Documentation + +The Solidity documentation is hosted at [Read the docs](https://solidity.readthedocs.io). + +## Development + +Solidity is still under development. Contributions are always welcome! +Please follow the +[Developers Guide](https://solidity.readthedocs.io/en/latest/contributing.html) +if you want to help. + +## Maintainers +[@axic](https://github.com/axic) +[@chriseth](https://github.com/chriseth) + +## License +Solidity is licensed under [GNU General Public License v3.0](https://github.com/ethereum/solidity/blob/develop/LICENSE.txt) -Any contributions are welcome! diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index ebdb75392..b84ae4c4d 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -8,7 +8,7 @@ Checklist for making a release: - [ ] Make a final check that there are no platform-dependency issues in the ``solc-test-bytecode`` repository. - [ ] Wait for the tests for the commit on ``release``, create a release in Github, creating the tag. - [ ] Thank voluntary contributors in the Github release page (use ``git shortlog -s -n -e origin/release..origin/develop``). - - [ ] Wait for the CI runs on the tag itself (they should push artefacts onto the Github release page). + - [ ] Wait for the CI runs on the tag itself (they should push artifacts onto the Github release page). - [ ] Run ``scripts/release_ppa.sh release`` to create the PPA release (you need the relevant openssl key). - [ ] Check that the Docker release was pushed to Docker Hub (this still seems to have problems, run ``./scripts/docker_deploy_manual.sh release``). - [ ] Update the homebrew realease in https://github.com/ethereum/homebrew-ethereum/blob/master/solidity.rb (version and hash) diff --git a/appveyor.yml b/appveyor.yml index 81ec711db..91ea8af77 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,7 +55,6 @@ install: $fileContent += "`n-----END RSA PRIVATE KEY-----`n"; Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent } - - git submodule update --init --recursive - ps: $prerelease = "nightly." - ps: $prerelease += Get-Date -format "yyyy.M.d" - ps: if($env:appveyor_repo_branch -eq 'release') { Set-Content prerelease.txt $null } else { Set-Content prerelease.txt $prerelease } diff --git a/cmake/EthBuildInfo.cmake b/cmake/EthBuildInfo.cmake index cae3e5cef..b87d29f54 100644 --- a/cmake/EthBuildInfo.cmake +++ b/cmake/EthBuildInfo.cmake @@ -31,7 +31,7 @@ function(create_build_info NAME) # Generate header file containing useful build information add_custom_target(${NAME}_BuildInfo.h ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - COMMAND ${CMAKE_COMMAND} -DETH_SOURCE_DIR="${PROJECT_SOURCE_DIR}" -DETH_BUILDINFO_IN="${ETH_CMAKE_DIR}/templates/BuildInfo.h.in" -DETH_DST_DIR="${PROJECT_BINARY_DIR}/include/${PROJECT_NAME}" -DETH_CMAKE_DIR="${ETH_CMAKE_DIR}" + COMMAND ${CMAKE_COMMAND} -DETH_SOURCE_DIR=${PROJECT_SOURCE_DIR} -DETH_BUILDINFO_IN=${ETH_CMAKE_DIR}/templates/BuildInfo.h.in -DETH_DST_DIR=${PROJECT_BINARY_DIR}/include/${PROJECT_NAME} -DETH_CMAKE_DIR=${ETH_CMAKE_DIR} -DETH_BUILD_TYPE="${_cmake_build_type}" -DETH_BUILD_OS="${ETH_BUILD_OS}" -DETH_BUILD_COMPILER="${ETH_BUILD_COMPILER}" diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 3ae5bf2ab..b4cc6656f 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -26,7 +26,7 @@ eth_add_cxx_compiler_flag_if_supported(-Wimplicit-fallthrough) if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) # Use ISO C++11 standard language. - set(CMAKE_CXX_FLAGS -std=c++11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # Enables all the warnings about constructions that some users consider questionable, # and that are easy to avoid. Also enable some extra warning flags that are not @@ -36,13 +36,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA add_compile_options(-Wextra) add_compile_options(-Werror) - # Disable warnings about unknown pragmas (which is enabled by -Wall). I assume we have external - # dependencies (probably Boost) which have some of these. Whatever the case, we shouldn't be - # disabling these globally. Instead, we should pragma around just the problem #includes. - # - # TODO - Track down what breaks if we do NOT do this. - add_compile_options(-Wno-unknown-pragmas) - # Configuration-specific compiler settings. set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") @@ -73,13 +66,13 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # TODO - Is this even necessary? Why? # See http://stackoverflow.com/questions/19774778/when-is-it-necessary-to-use-use-the-flag-stdlib-libstdc. add_compile_options(-stdlib=libstdc++) - + # Tell Boost that we're using Clang's libc++. Not sure exactly why we need to do. add_definitions(-DBOOST_ASIO_HAS_CLANG_LIBCXX) - + # Use fancy colors in the compiler diagnostics add_compile_options(-fcolor-diagnostics) - + # See "How to silence unused command line argument error with clang without disabling it?" # When using -Werror with clang, it transforms "warning: argument unused during compilation" messages # into errors, which makes sense. @@ -90,7 +83,7 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA if (EMSCRIPTEN) # Do not emit a separate memory initialiser file set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --memory-init-file 0") - # Leave only exported symbols as public and agressively remove others + # Leave only exported symbols as public and aggressively remove others set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections -fvisibility=hidden") # Optimisation level set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") @@ -146,26 +139,29 @@ endif () if (SANITIZE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=${SANITIZE}") - if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/sanitizer-blacklist.txt") - endif() endif() -if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))) - set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") - set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS}") - add_definitions(-DETH_PROFILING_GPERF) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofiler") -# set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -lprofiler") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofiler") -endif () +# Code coverage support. +# Copied from Cable: +# https://github.com/ethereum/cable/blob/v0.2.4/CableCompilerSettings.cmake#L118-L132 +option(COVERAGE "Build with code coverage support" OFF) +if(COVERAGE) + # Set the linker flags first, they are required to properly test the compiler flag. + set(CMAKE_SHARED_LINKER_FLAGS "--coverage ${CMAKE_SHARED_LINKER_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "--coverage ${CMAKE_EXE_LINKER_FLAGS}") -if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU"))) - set(CMAKE_CXX_FLAGS "-g --coverage ${CMAKE_CXX_FLAGS}") - set(CMAKE_C_FLAGS "-g --coverage ${CMAKE_C_FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS "--coverage ${CMAKE_SHARED_LINKER_FLAGS} -lprofiler") - set(CMAKE_EXE_LINKER_FLAGS "--coverage ${CMAKE_EXE_LINKER_FLAGS} -lprofiler") -endif () + set(CMAKE_REQUIRED_LIBRARIES "--coverage ${CMAKE_REQUIRED_LIBRARIES}") + check_cxx_compiler_flag(--coverage have_coverage) + string(REPLACE "--coverage " "" CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + if(NOT have_coverage) + message(FATAL_ERROR "Coverage not supported") + endif() + add_compile_options(-g --coverage) +endif() + +# SMT Solvers integration +option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON) +option(USE_CVC4 "Allow compiling with CVC4 SMT solver integration" ON) if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) option(USE_LD_GOLD "Use GNU gold linker" ON) diff --git a/cmake/EthOptions.cmake b/cmake/EthOptions.cmake index b4efd6c99..a79e5135a 100644 --- a/cmake/EthOptions.cmake +++ b/cmake/EthOptions.cmake @@ -2,7 +2,7 @@ macro(configure_project) set(NAME ${PROJECT_NAME}) # features - eth_default_option(PROFILING OFF) + eth_default_option(COVERAGE OFF) # components eth_default_option(TESTS ON) @@ -27,7 +27,7 @@ macro(print_config NAME) message("-- CMAKE_BUILD_TYPE Build type ${CMAKE_BUILD_TYPE}") message("-- TARGET_PLATFORM Target platform ${CMAKE_SYSTEM_NAME}") message("--------------------------------------------------------------- features") - message("-- PROFILING Profiling support ${PROFILING}") + message("-- COVERAGE Coverage support ${COVERAGE}") message("------------------------------------------------------------- components") if (SUPPORT_TESTS) message("-- TESTS Build tests ${TESTS}") diff --git a/cmake/EthPolicy.cmake b/cmake/EthPolicy.cmake index 31b09f154..4e29898cb 100644 --- a/cmake/EthPolicy.cmake +++ b/cmake/EthPolicy.cmake @@ -4,32 +4,16 @@ macro (eth_policy) # link_directories() treats paths relative to the source dir. cmake_policy(SET CMP0015 NEW) - # let cmake autolink dependencies on windows - cmake_policy(SET CMP0020 NEW) + # Avoid warnings in CMake 3.0.2: + cmake_policy(SET CMP0042 NEW) + cmake_policy(SET CMP0043 NEW) - # CMake 2.8.12 and lower allowed the use of targets and files with double - # colons in target_link_libraries, - cmake_policy(SET CMP0028 OLD) + # allow VERSION argument in project() + cmake_policy(SET CMP0048 NEW) - if (${CMAKE_VERSION} VERSION_GREATER 3.0) - - # fix MACOSX_RPATH - cmake_policy(SET CMP0042 OLD) - - # ignore COMPILE_DEFINITIONS_ properties - cmake_policy(SET CMP0043 OLD) - - # allow VERSION argument in project() - cmake_policy(SET CMP0048 NEW) - - endif() - - if (${CMAKE_VERSION} VERSION_GREATER 3.1) - + if (POLICY CMP0054) # do not interpret if() arguments as variables! cmake_policy(SET CMP0054 NEW) - endif() - endmacro() diff --git a/cmake/FindCLN.cmake b/cmake/FindCLN.cmake new file mode 100644 index 000000000..f2234bb40 --- /dev/null +++ b/cmake/FindCLN.cmake @@ -0,0 +1,3 @@ +find_library(CLN_LIBRARY NAMES cln) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CLN DEFAULT_MSG CLN_LIBRARY) diff --git a/cmake/FindCVC4.cmake b/cmake/FindCVC4.cmake index 0fb131963..2649d7c7a 100644 --- a/cmake/FindCVC4.cmake +++ b/cmake/FindCVC4.cmake @@ -1,4 +1,26 @@ -find_path(CVC4_INCLUDE_DIR cvc4/cvc4.h) -find_library(CVC4_LIBRARY NAMES cvc4 ) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(CVC4 DEFAULT_MSG CVC4_LIBRARY CVC4_INCLUDE_DIR) +if (USE_CVC4) + find_path(CVC4_INCLUDE_DIR cvc4/cvc4.h) + find_library(CVC4_LIBRARY NAMES cvc4) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(CVC4 DEFAULT_MSG CVC4_LIBRARY CVC4_INCLUDE_DIR) + if(CVC4_FOUND) + # CVC4 may depend on either CLN or GMP. + # We can assume that the one it requires is present on the system, + # so we quietly try to find both and link against them, if they are + # present. + find_package(CLN QUIET) + find_package(GMP QUIET) + + set(CVC4_LIBRARIES ${CVC4_LIBRARY}) + + if (CLN_FOUND) + set(CVC4_LIBRARIES ${CVC4_LIBRARIES} ${CLN_LIBRARY}) + endif () + + if (GMP_FOUND) + set(CVC4_LIBRARIES ${CVC4_LIBRARIES} ${GMP_LIBRARY}) + endif () + endif() +else() + set(CVC4_FOUND FALSE) +endif() diff --git a/cmake/FindZ3.cmake b/cmake/FindZ3.cmake index 971d3b4b3..c017cac2d 100644 --- a/cmake/FindZ3.cmake +++ b/cmake/FindZ3.cmake @@ -1,7 +1,9 @@ -find_path(Z3_INCLUDE_DIR z3++.h) -find_library(Z3_LIBRARY NAMES z3 ) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Z3 DEFAULT_MSG Z3_LIBRARY Z3_INCLUDE_DIR) - +if (USE_Z3) + find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3) + find_library(Z3_LIBRARY NAMES z3 ) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Z3 DEFAULT_MSG Z3_LIBRARY Z3_INCLUDE_DIR) +else() + set(Z3_FOUND FALSE) +endif() # TODO: Create IMPORTED library for Z3. - diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index efbfb8fb0..3fb6beb2b 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -1,5 +1,5 @@ # generates BuildInfo.h -# +# # this module expects # ETH_SOURCE_DIR - main CMAKE_SOURCE_DIR # ETH_DST_DIR - main CMAKE_BINARY_DIR @@ -19,7 +19,7 @@ if (NOT ETH_BUILD_PLATFORM) set(ETH_BUILD_PLATFORM "unknown") endif() -# Logic here: If prereleases.txt exists but is empty, it is a non-pre release. +# Logic here: If prerelease.txt exists but is empty, it is a non-pre release. # If it does not exist, create our own prerelease string if (EXISTS ${ETH_SOURCE_DIR}/prerelease.txt) file(READ ${ETH_SOURCE_DIR}/prerelease.txt SOL_VERSION_PRERELEASE) diff --git a/cmake/templates/license.h.in b/cmake/templates/license.h.in index 84524a523..4f22d8f4d 100644 --- a/cmake/templates/license.h.in +++ b/cmake/templates/license.h.in @@ -66,6 +66,37 @@ jsoncpp: Public Domain "license" you can re-license your copy using whatever license you like. +scanner/token: + The libsolidity/parsing/{scanner,token}.{h,cpp} files are dervied from + code originating from the V8 project licensed under the following terms: + + Copyright 2006-2012, the V8 project authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + All other code is licensed under GPL version 3: )"}; diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..f20980ef5 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,18 @@ +codecov: + branch: develop +coverage: + range: 70...100 + status: + project: + default: + target: auto + paths: "!test/" + syntax: + target: auto + paths: "libsolidity/analysis" + flags: syntax + tests: + target: auto + paths: "test/" +comment: + layout: "reach, diff, flags" diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst new file mode 100644 index 000000000..48112cd97 --- /dev/null +++ b/docs/050-breaking-changes.rst @@ -0,0 +1,511 @@ +******************************** +Solidity v0.5.0 Breaking Changes +******************************** + +This section highlights the main breaking changes introduced in Solidity +version 0.5.0, along with the reasoning behind the changes and how to update +affected code. +For the full list check +`the release changelog `_. + +.. note:: + Contracts compiled with Solidity v0.5.0 can still interface with contracts + and even libraries compiled with older versions without recompiling or + redeploying them. Changing the interfaces to include data locations and + visibility and mutability specifiers suffices. See the + :ref:`Interoperability With Older Contracts ` section below. + +Semantic Only Changes +===================== + +This section lists the changes that are semantic-only, thus potentially +hiding new and different behavior in existing code. + +* Signed right shift now uses proper arithmetic shift, i.e. rounding towards + negative infinity, instead of rounding towards zero. Signed and unsigned + shift will have dedicated opcodes in Constantinople, and are emulated by + Solidity for the moment. + +* The ``continue`` statement in a ``do...while`` loop now jumps to the + condition, which is the common behavior in such cases. It used to jump to the + loop body. Thus, if the condition is false, the loop terminates. + +* The functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` do not + pad anymore when given a single ``bytes`` parameter. + +* Pure and view functions are now called using the opcode ``STATICCALL`` + instead of ``CALL`` if the EVM version is Byzantium or later. This + disallows state changes on the EVM level. + +* The ABI encoder now properly pads byte arrays and strings from calldata + (``msg.data`` and external function parameters) when used in external + function calls and in ``abi.encode``. For unpadded encoding, use + ``abi.encodePacked``. + +* The ABI decoder reverts in the beginning of functions and in + ``abi.decode()`` if passed calldata is too short or points out of bounds. + Note that dirty higher order bits are still simply ignored. + +* Forward all available gas with external function calls starting from + Tangerine Whistle. + +Semantic and Syntactic Changes +============================== + +This section highlights changes that affect syntax and semantics. + +* The functions ``.call()``, ``.delegatecall()``, ``staticcall()``, + ``keccak256()``, ``sha256()`` and ``ripemd160()`` now accept only a single + ``bytes`` argument. Moreover, the argument is not padded. This was changed to + make more explicit and clear how the arguments are concatenated. Change every + ``.call()`` (and family) to a ``.call("")`` and every ``.call(signature, a, + b, c)`` to use ``.call(abi.encodeWithSignature(signature, a, b, c))`` (the + last one only works for value types). Change every ``keccak256(a, b, c)`` to + ``keccak256(abi.encodePacked(a, b, c))``. Even though it is not a breaking + change, it is suggested that developers change + ``x.call(bytes4(keccak256("f(uint256)"), a, b)`` to + ``x.call(abi.encodeWithSignature("f(uint256)", a, b))``. + +* Functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` now return + ``(bool, bytes memory)`` to provide access to the return data. Change + ``bool success = otherContract.call("f")`` to ``(bool success, bytes memory + data) = otherContract.call("f")``. + +* Solidity now implements C99-style scoping rules for function local + variables, that is, variables can only be used after they have been + declared and only in the same or nested scopes. Variables declared in the + initialization block of a ``for`` loop are valid at any point inside the + loop. + +Explicitness Requirements +========================= + +This section lists changes where the code now needs to be more explicit. +For most of the topics the compiler will provide suggestions. + +* Explicit function visibility is now mandatory. Add ``public`` to every + function and constructor, and ``external`` to every fallback or interface + function that does not specify its visibility already. + +* Explicit data location for all variables of struct, array or mapping types is + now mandatory. This is also applied to function parameters and return + variables. For example, change ``uint[] x = m_x`` to ``uint[] storage x = + m_x``, and ``function f(uint[][] x)`` to ``function f(uint[][] memory x)`` + where ``memory`` is the data location and might be replaced by ``storage`` or + ``calldata`` accordingly. Note that ``external`` functions require + parameters with a data location of ``calldata``. + +* Contract types do not include ``address`` members anymore in + order to separate the namespaces. Therefore, it is now necessary to + explicitly convert values of contract type to addresses before using an + ``address`` member. Example: if ``c`` is a contract, change + ``c.transfer(...)`` to ``address(c).transfer(...)``, + and ``c.balance`` to ``address(c).balance``. + +* Explicit conversions between unrelated contract types are now disallowed. You can only + convert from a contract type to one of its base or ancestor types. If you are sure that + a contract is compatible with the contract type you want to convert to, although it does not + inherit from it, you can work around this by converting to ``address`` first. + Example: if ``A`` and ``B`` are contract types, ``B`` does not inherit from ``A`` and + ``b`` is a contract of type ``B``, you can still convert ``b`` to type ``A`` using ``A(address(b))``. + Note that you still need to watch out for matching payable fallback functions, as explained below. + +* The ``address`` type was split into ``address`` and ``address payable``, + where only ``address payable`` provides the ``transfer`` function. An + ``address payable`` can be directly converted to an ``address``, but the + other way around is not allowed. Converting ``address`` to ``address + payable`` is possible via conversion through ``uint160``. If ``c`` is a + contract, ``address(c)`` results in ``address payable`` only if ``c`` has a + payable fallback function. If you use the :ref:`withdraw pattern`, + you most likely do not have to change your code because ``transfer`` + is only used on ``msg.sender`` instead of stored addresses and ``msg.sender`` + is an ``address payable``. + +* Conversions between ``bytesX`` and ``uintY`` of different size are now + disallowed due to ``bytesX`` padding on the right and ``uintY`` padding on + the left which may cause unexpected conversion results. The size must now be + adjusted within the type before the conversion. For example, you can convert + a ``bytes4`` (4 bytes) to a ``uint64`` (8 bytes) by first converting the + ``bytes4`` variable to ``bytes8`` and then to ``uint64``. You get the + opposite padding when converting through ``uint32``. + +* Using ``msg.value`` in non-payable functions (or introducing it via a + modifier) is disallowed as a security feature. Turn the function into + ``payable`` or create a new internal function for the program logic that + uses ``msg.value``. + +* For clarity reasons, the command line interface now requires ``-`` if the + standard input is used as source. + +Deprecated Elements +=================== + +This section lists changes that deprecate prior features or syntax. Note that +many of these changes were already enabled in the experimental mode +``v0.5.0``. + +Command Line and JSON Interfaces +-------------------------------- + +* The command line option ``--formal`` (used to generate Why3 output for + further formal verification) was deprecated and is now removed. A new + formal verification module, the SMTChecker, is enabled via ``pragma + experimental SMTChecker;``. + +* The command line option ``--julia`` was renamed to ``--yul`` due to the + renaming of the intermediate language ``Julia`` to ``Yul``. + +* The ``--clone-bin`` and ``--combined-json clone-bin`` command line options + were removed. + +* Remappings with empty prefix are disallowed. + +* The JSON AST fields ``constant`` and ``payable`` were removed. The + information is now present in the ``stateMutability`` field. + +* The JSON AST field ``isConstructor`` of the ``FunctionDefinition`` + node was replaced by a field called ``kind`` which can have the + value ``"constructor"``, ``"fallback"`` or ``"function"``. + +* In unlinked binary hex files, library address placeholders are now + the first 36 hex characters of the keccak256 hash of the fully qualified + library name, surrounded by ``$...$``. Previously, + just the fully qualified library name was used. + This recudes the chances of collisions, especially when long paths are used. + Binary files now also contain a list of mappings from these placeholders + to the fully qualified names. + +Constructors +------------ + +* Constructors must now be defined using the ``constructor`` keyword. + +* Calling base constructors without parentheses is now disallowed. + +* Specifying base constructor arguments multiple times in the same inheritance + hierarchy is now disallowed. + +* Calling a constructor with arguments but with wrong argument count is now + disallowed. If you only want to specify an inheritance relation without + giving arguments, do not provide parentheses at all. + +Functions +--------- + +* Function ``callcode`` is now disallowed (in favor of ``delegatecall``). It + is still possible to use it via inline assembly. + +* ``suicide`` is now disallowed (in favor of ``selfdestruct``). + +* ``sha3`` is now disallowed (in favor of ``keccak256``). + +* ``throw`` is now disallowed (in favor of ``revert``, ``require`` and + ``assert``). + +Conversions +----------- + +* Explicit and implicit conversions from decimal literals to ``bytesXX`` types + is now disallowed. + +* Explicit and implicit conversions from hex literals to ``bytesXX`` types + of different size is now disallowed. + +Literals and Suffixes +--------------------- + +* The unit denomination ``years`` is now disallowed due to complications and + confusions about leap years. + +* Trailing dots that are not followed by a number are now disallowed. + +* Combining hex numbers with unit denominations (e.g. ``0x1e wei``) is now + disallowed. + +* The prefix ``0X`` for hex numbers is disallowed, only ``0x`` is possible. + +Variables +--------- + +* Declaring empty structs is now disallowed for clarity. + +* The ``var`` keyword is now disallowed to favor explicitness. + +* Assignments between tuples with different number of components is now + disallowed. + +* Values for constants that are not compile-time constants are disallowed. + +* Multi-variable declarations with mismatching number of values are now + disallowed. + +* Uninitialized storage variables are now disallowed. + +* Empty tuple components are now disallowed. + +* Detecting cyclic dependencies in variables and structs is limited in + recursion to 256. + +* Fixed-size arrays with a length of zero are now disallowed. + +Syntax +------ + +* Using ``constant`` as function state mutability modifier is now disallowed. + +* Boolean expressions cannot use arithmetic operations. + +* The unary ``+`` operator is now disallowed. + +* Literals cannot anymore be used with ``abi.encodePacked`` without prior + conversion to an explicit type. + +* Empty return statements for functions with one or more return values are now + disallowed. + +* The "loose assembly" syntax is now disallowed entirely, that is, jump labels, + jumps and non-functional instructions cannot be used anymore. Use the new + ``while``, ``switch`` and ``if`` constructs instead. + +* Functions without implementation cannot use modifiers anymore. + +* Function types with named return values are now disallowed. + +* Single statement variable declarations inside if/while/for bodies that are + not blocks are now disallowed. + +* New keywords: ``calldata`` and ``constructor``. + +* New reserved keywords: ``alias``, ``apply``, ``auto``, ``copyof``, + ``define``, ``immutable``, ``implements``, ``macro``, ``mutable``, + ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, + ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. + +.. _interoperability: + +Interoperability With Older Contracts +===================================== + +It is still possible to interface with contracts written for Solidity versions prior to +v0.5.0 (or the other way around) by defining interfaces for them. +Consider you have the following pre-0.5.0 contract already deployed: + +:: + + // This will not compile with the current version of the compiler + pragma solidity ^0.4.25; + contract OldContract { + function someOldFunction(uint8 a) { + //... + } + function anotherOldFunction() constant returns (bool) { + //... + } + // ... + } + +This will no longer compile with Solidity v0.5.0. However, you can define a compatible interface for it: + +:: + + pragma solidity >0.4.99 <0.6.0; + interface OldContract { + function someOldFunction(uint8 a) external; + function anotherOldFunction() external returns (bool); + } + +Note that we did not declare ``anotherOldFunction`` to be ``view``, despite it being declared ``constant`` in the original +contract. This is due to the fact that starting with Solidity v0.5.0 ``staticcall`` is used to call ``view`` functions. +Prior to v0.5.0 the ``constant`` keyword was not enforced, so calling a function declared ``constant`` with ``staticcall`` +may still revert, since the ``constant`` function may still attempt to modify storage. Consequently, when defining an +interface for older contracts, you should only use ``view`` in place of ``constant`` in case you are absolutely sure that +the function will work with ``staticcall``. + +Given the interface defined above, you can now easily use the already deployed pre-0.5.0 contract: + +:: + + pragma solidity >0.4.99 <0.6.0; + + interface OldContract { + function someOldFunction(uint8 a) external; + function anotherOldFunction() external returns (bool); + } + + contract NewContract { + function doSomething(OldContract a) public returns (bool) { + a.someOldFunction(0x42); + return a.anotherOldFunction(); + } + } + +Similarly, pre-0.5.0 libraries can be used by defining the functions of the library without implementation and +supplying the address of the pre-0.5.0 library during linking (see :ref:`commandline-compiler` for how to use the +commandline compiler for linking): + +:: + + pragma solidity >0.4.99 <0.6.0; + + library OldLibrary { + function someFunction(uint8 a) public returns(bool); + } + + contract NewContract { + function f(uint8 a) public returns (bool) { + return OldLibrary.someFunction(a); + } + } + + +Example +======= + +The following example shows a contract and its updated version for Solidity +v0.5.0 with some of the changes listed in this section. + +Old version: + +:: + + // This will not compile + pragma solidity ^0.4.25; + + contract OtherContract { + uint x; + function f(uint y) external { + x = y; + } + function() payable external {} + } + + contract Old { + OtherContract other; + uint myNumber; + + // Function mutability not provided, not an error. + function someInteger() internal returns (uint) { return 2; } + + // Function visibility not provided, not an error. + // Function mutability not provided, not an error. + function f(uint x) returns (bytes) { + // Var is fine in this version. + var z = someInteger(); + x += z; + // Throw is fine in this version. + if (x > 100) + throw; + bytes b = new bytes(x); + y = -3 >> 1; + // y == -1 (wrong, should be -2) + do { + x += 1; + if (x > 10) continue; + // 'Continue' causes an infinite loop. + } while (x < 11); + // Call returns only a Bool. + bool success = address(other).call("f"); + if (!success) + revert(); + else { + // Local variables could be declared after their use. + int y; + } + return b; + } + + // No need for an explicit data location for 'arr' + function g(uint[] arr, bytes8 x, OtherContract otherContract) public { + otherContract.transfer(1 ether); + + // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes), + // the first 4 bytes of x will be lost. This might lead to + // unexpected behavior since bytesX are right padded. + uint32 y = uint32(x); + myNumber += y + msg.value; + } + } + +New version: + +:: + + pragma solidity >0.4.99 <0.6.0; + + contract OtherContract { + uint x; + function f(uint y) external { + x = y; + } + function() payable external {} + } + + contract New { + OtherContract other; + uint myNumber; + + // Function mutability must be specified. + function someInteger() internal pure returns (uint) { return 2; } + + // Function visibility must be specified. + // Function mutability must be specified. + function f(uint x) public returns (bytes memory) { + // The type must now be explicitly given. + uint z = someInteger(); + x += z; + // Throw is now disallowed. + require(x > 100); + int y = -3 >> 1; + // y == -2 (correct) + do { + x += 1; + if (x > 10) continue; + // 'Continue' jumps to the condition below. + } while (x < 11); + + // Call returns (bool, bytes). + // Data location must be specified. + (bool success, bytes memory data) = address(other).call("f"); + if (!success) + revert(); + return data; + } + + using address_make_payable for address; + // Data location for 'arr' must be specified + function g(uint[] memory arr, bytes8 x, OtherContract otherContract, address unknownContract) public payable { + // 'otherContract.transfer' is not provided. + // Since the code of 'OtherContract' is known and has the fallback + // function, address(otherContract) has type 'address payable'. + address(otherContract).transfer(1 ether); + + // 'unknownContract.transfer' is not provided. + // 'address(unknownContract).transfer' is not provided + // since 'address(unknownContract)' is not 'address payable'. + // If the function takes an 'address' which you want to send + // funds to, you can convert it to 'address payable' via 'uint160'. + // Note: This is not recommended and the explicit type + // 'address payable' should be used whenever possible. + // To increase clarity, we suggest the use of a library for + // the conversion (provided after the contract in this example). + address payable addr = unknownContract.make_payable(); + require(addr.send(1 ether)); + + // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes), + // the conversion is not allowed. + // We need to convert to a common size first: + bytes4 x4 = bytes4(x); // Padding happens on the right + uint32 y = uint32(x4); // Conversion is consistent + // 'msg.value' cannot be used in a 'non-payable' function. + // We need to make the function payable + myNumber += y + msg.value; + } + } + + // We can define a library for explicitly converting ``address`` + // to ``address payable`` as a workaround. + library address_make_payable { + function make_payable(address x) internal pure returns (address payable) { + return address(uint160(x)); + } + } diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css new file mode 100644 index 000000000..fd5062036 --- /dev/null +++ b/docs/_static/css/custom.css @@ -0,0 +1,14 @@ +pre { + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; +} + +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: normal; +} +.rst-content table.docutils td { + vertical-align: top; +} diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 000000000..1db4ef92c --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,6 @@ +{% extends "!layout.html" %} + + {% block menu %} + {{ super() }} + Keyword Index + {% endblock %} diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 8591a07f6..0f4a16b69 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -2,20 +2,20 @@ .. _ABI: -****************************************** -Application Binary Interface Specification -****************************************** +************************** +Contract ABI Specification +************************** Basic Design ============ -The Application Binary Interface is the standard way to interact with contracts in the Ethereum ecosystem, both +The Contract Application Binary Interface (ABI) is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interaction. Data is encoded according to its type, as described in this specification. The encoding is not self describing and thus requires a schema in order to decode. -We assume the interface functions of a contract are strongly typed, known at compilation time and static. No introspection mechanism will be provided. We assume that all contracts will have the interface definitions of any contracts they call available at compile-time. +We assume the interface functions of a contract are strongly typed, known at compilation time and static. We assume that all contracts will have the interface definitions of any contracts they call available at compile-time. -This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. Should these cases become important they can be adequately handled as facilities built within the Ethereum ecosystem. +This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. .. _abi_function_selector: @@ -23,12 +23,12 @@ Function Selector ================= The first four bytes of the call data for a function call specifies the function to be called. It is the -first (left, high-order in big-endian) four bytes of the Keccak (SHA-3) hash of the signature of the function. The signature is defined as the canonical expression of the basic prototype, i.e. +first (left, high-order in big-endian) four bytes of the Keccak-256 (SHA-3) hash of the signature of the function. The signature is defined as the canonical expression of the basic prototype without data location specifier, i.e. the function name with the parenthesised list of parameter types. Parameter types are split by a single comma - no spaces are used. .. note:: The return type of a function is not part of this signature. In :ref:`Solidity's function overloading ` return types are not considered. The reason is to keep function call resolution context-independent. - The JSON description of the ABI however contains both inputs and outputs. See (the :ref:`JSON ABI `) + The :ref:`JSON description of the ABI` however contains both inputs and outputs. Argument Encoding ================= @@ -72,27 +72,48 @@ The following non-fixed-size types exist: - ``[]``: a variable-length array of elements of the given type. -Types can be combined to a tuple by enclosing a finite non-negative number -of them inside parentheses, separated by commas: +Types can be combined to a tuple by enclosing them inside parentheses, separated by commas: - ``(T1,T2,...,Tn)``: tuple consisting of the types ``T1``, ..., ``Tn``, ``n >= 0`` It is possible to form tuples of tuples, arrays of tuples and so on. It is also possible to form zero-tuples (where ``n == 0``). -.. note:: - Solidity supports all the types presented above with the same names with the exception of tuples. The ABI tuple type is utilised for encoding Solidity ``structs``. +Mapping Solidity to ABI types +----------------------------- -Formal Specification of the Encoding -==================================== +Solidity supports all the types presented above with the same names with the +exception of tuples. On the other hand, some Solidity types are not supported +by the ABI. The following table shows on the left column Solidity types that +are not part of the ABI, and on the right column the ABI types that represent +them. -We will now formally specify the encoding, such that it will have the following -properties, which are especially useful if some arguments are nested arrays: ++-------------------------------+-----------------------------------------------------------------------------+ +| Solidity | ABI | ++===============================+=============================================================================+ +|:ref:`address payable
`|``address`` | ++-------------------------------+-----------------------------------------------------------------------------+ +|:ref:`contract` |``address`` | ++-------------------------------+-----------------------------------------------------------------------------+ +|:ref:`enum` |smallest ``uint`` type that is large enough to hold all values | +| | | +| |For example, an ``enum`` of 255 values or less is mapped to ``uint8`` and | +| |an ``enum`` of 256 values is mapped to ``uint16``. | ++-------------------------------+-----------------------------------------------------------------------------+ +|:ref:`struct` |``tuple`` | ++-------------------------------+-----------------------------------------------------------------------------+ -Properties: +Design Criteria for the Encoding +================================ + +The encoding is designed to have the following properties, which are especially useful if some arguments are nested arrays: 1. The number of reads necessary to access a value is at most the depth of the value inside the argument array structure, i.e. four reads are needed to retrieve ``a_i[k][l][r]``. In a previous version of the ABI, the number of reads scaled linearly with the total number of dynamic parameters in the worst case. - 2. The data of a variable or array element is not interleaved with other data and it is relocatable, i.e. it only uses relative "addresses" + 2. The data of a variable or array element is not interleaved with other data and it is relocatable, i.e. it only uses relative "addresses". + + +Formal Specification of the Encoding +==================================== We distinguish static and dynamic types. Static types are encoded in-place and dynamic types are encoded at a separately allocated location after the current block. @@ -152,8 +173,8 @@ on the type of ``X`` being - ``bytes``, of length ``k`` (which is assumed to be of type ``uint256``): ``enc(X) = enc(k) pad_right(X)``, i.e. the number of bytes is encoded as a - ``uint256`` followed by the actual value of ``X`` as a byte sequence, followed by - the minimum number of zero-bytes such that ``len(enc(X))`` is a multiple of 32. + ``uint256`` followed by the actual value of ``X`` as a byte sequence, followed by + the minimum number of zero-bytes such that ``len(enc(X))`` is a multiple of 32. - ``string``: @@ -191,12 +212,12 @@ Given the contract: :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract Foo { - function bar(bytes3[2]) public pure {} + function bar(bytes3[2] memory) public pure {} function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; } - function sam(bytes, bool, uint[]) public pure {} + function sam(bytes memory, bool, uint[] memory) public pure {} } @@ -206,7 +227,9 @@ Thus for our ``Foo`` example if we wanted to call ``baz`` with the parameters `` - ``0x0000000000000000000000000000000000000000000000000000000000000045``: the first parameter, a uint32 value ``69`` padded to 32 bytes - ``0x0000000000000000000000000000000000000000000000000000000000000001``: the second parameter - boolean ``true``, padded to 32 bytes -In total:: +In total: + +.. code-block:: none 0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001 @@ -218,7 +241,9 @@ If we wanted to call ``bar`` with the argument ``["abc", "def"]``, we would pass - ``0x6162630000000000000000000000000000000000000000000000000000000000``: the first part of the first parameter, a ``bytes3`` value ``"abc"`` (left-aligned). - ``0x6465660000000000000000000000000000000000000000000000000000000000``: the second part of the first parameter, a ``bytes3`` value ``"def"`` (left-aligned). -In total:: +In total: + +.. code-block:: none 0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000 @@ -235,7 +260,9 @@ If we wanted to call ``sam`` with the arguments ``"dave"``, ``true`` and ``[1,2, - ``0x0000000000000000000000000000000000000000000000000000000000000002``: the second entry of the third parameter. - ``0x0000000000000000000000000000000000000000000000000000000000000003``: the third entry of the third parameter. -In total:: +In total: + +.. code-block:: none 0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003 @@ -265,7 +292,7 @@ Finally, we encode the data part of the second dynamic argument, ``"Hello, world All together, the encoding is (newline after function selector and each 32-bytes for clarity): -:: +.. code-block:: none 0x8be65246 0000000000000000000000000000000000000000000000000000000000000123 @@ -278,6 +305,108 @@ All together, the encoding is (newline after function selector and each 32-bytes 000000000000000000000000000000000000000000000000000000000000000d 48656c6c6f2c20776f726c642100000000000000000000000000000000000000 +Let us apply the same principle to encode the data for a function with a signature ``g(uint[][],string[])`` with values ``([[1, 2], [3]], ["one", "two", "three"])`` but start from the most atomic parts of the encoding: + +First we encode the length and data of the first embedded dynamic array ``[1, 2]`` of the first root array ``[[1, 2], [3]]``: + + - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first array, 2; the elements themselves are ``1`` and ``2``) + - ``0x0000000000000000000000000000000000000000000000000000000000000001`` (first element) + - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (second element) + +Then we encode the length and data of the second embedded dynamic array ``[3]`` of the first root array ``[[1, 2], [3]]``: + + - ``0x0000000000000000000000000000000000000000000000000000000000000001`` (number of elements in the second array, 1; the element is ``3``) + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (first element) + +Then we need to find the offsets ``a`` and ``b`` for their respective dynamic arrays ``[1, 2]`` and ``[3]``. To calculate the offsets we can take a look at the encoded data of the first root array ``[[1, 2], [3]]`` enumerating each line in the encoding: + +.. code-block:: none + + 0 - a - offset of [1, 2] + 1 - b - offset of [3] + 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] + 3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 + 4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 + 5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] + 6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 + +Offset ``a`` points to the start of the content of the array ``[1, 2]`` which is line 2 (64 bytes); thus ``a = 0x0000000000000000000000000000000000000000000000000000000000000040``. + +Offset ``b`` points to the start of the content of the array ``[3]`` which is line 5 (160 bytes); thus ``b = 0x00000000000000000000000000000000000000000000000000000000000000a0``. + + +Then we encode the embedded strings of the second root array: + + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"one"``) + - ``0x6f6e650000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"one"``) + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"two"``) + - ``0x74776f0000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"two"``) + - ``0x0000000000000000000000000000000000000000000000000000000000000005`` (number of characters in word ``"three"``) + - ``0x7468726565000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"three"``) + +In parallel to the first root array, since strings are dynamic elements we need to find their offsets ``c``, ``d`` and ``e``: + +.. code-block:: none + + 0 - c - offset for "one" + 1 - d - offset for "two" + 2 - e - offset for "three" + 3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" + 4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" + 5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" + 6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" + 7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" + 8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" + +Offset ``c`` points to the start of the content of the string ``"one"`` which is line 3 (96 bytes); thus ``c = 0x0000000000000000000000000000000000000000000000000000000000000060``. + +Offset ``d`` points to the start of the content of the string ``"two"`` which is line 5 (160 bytes); thus ``d = 0x00000000000000000000000000000000000000000000000000000000000000a0``. + +Offset ``e`` points to the start of the content of the string ``"three"`` which is line 7 (224 bytes); thus ``e = 0x00000000000000000000000000000000000000000000000000000000000000e0``. + + +Note that the encodings of the embedded elements of the root arrays are not dependent on each other and have the same encodings for a function with a signature ``g(string[],uint[][])``. + +Then we encode the length of the first root array: + + - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first root array, 2; the elements themselves are ``[1, 2]`` and ``[3]``) + +Then we encode the length of the second root array: + + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of strings in the second root array, 3; the strings themselves are ``"one"``, ``"two"`` and ``"three"``) + +Finally we find the offsets ``f`` and ``g`` for their respective root dynamic arrays ``[[1, 2], [3]]`` and ``["one", "two", "three"]``, and assemble parts in the correct order: + +.. code-block:: none + + 0x2289b18c - function signature + 0 - f - offset of [[1, 2], [3]] + 1 - g - offset of ["one", "two", "three"] + 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]] + 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2] + 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3] + 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] + 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 + 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 + 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] + 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 + 10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"] + 11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one" + 12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two" + 13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three" + 14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" + 15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" + 16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" + 17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" + 18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" + 19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" + +Offset ``f`` points to the start of the content of the array ``[[1, 2], [3]]`` which is line 2 (64 bytes); thus ``f = 0x0000000000000000000000000000000000000000000000000000000000000040``. + +Offset ``g`` points to the start of the content of the array ``["one", "two", "three"]`` which is line 10 (320 bytes); thus ``g = 0x0000000000000000000000000000000000000000000000000000000000000140``. + +.. _abi_events: + Events ====== @@ -292,7 +421,7 @@ In effect, a log entry using this ABI is described as: - ``topics[n]``: ``EVENT_INDEXED_ARGS[n - 1]`` (``EVENT_INDEXED_ARGS`` is the series of ``EVENT_ARGS`` that are indexed); - ``data``: ``abi_serialise(EVENT_NON_INDEXED_ARGS)`` (``EVENT_NON_INDEXED_ARGS`` is the series of ``EVENT_ARGS`` that are not indexed, ``abi_serialise`` is the ABI serialisation function used for returning a series of typed values from a function, as described above). -For all fixed-length Solidity types, the ``EVENT_INDEXED_ARGS`` array contains the 32-byte encoded value directly. However, for *types of dynamic length*, which include ``string``, ``bytes``, and arrays, ``EVENT_INDEXED_ARGS`` will contain the *Keccak hash* of the encoded value, rather than the encoded value directly. This allows applications to efficiently query for values of dynamic-length types (by setting the hash of the encoded value as the topic), but leaves applications unable to decode indexed values they have not queried for. For dynamic-length types, application developers face a trade-off between fast search for predetermined values (if the argument is indexed) and legibility of arbitrary values (which requires that the arguments not be indexed). Developers may overcome this tradeoff and achieve both efficient search and arbitrary legibility by defining events with two arguments — one indexed, one not — intended to hold the same value. +For all fixed-length Solidity types, the ``EVENT_INDEXED_ARGS`` array contains the 32-byte encoded value directly. However, for *types of dynamic length*, which include ``string``, ``bytes``, and arrays, ``EVENT_INDEXED_ARGS`` will contain the *Keccak hash* of the packed encoded value (see :ref:`abi_packed_mode`), rather than the encoded value directly. This allows applications to efficiently query for values of dynamic-length types (by setting the hash of the encoded value as the topic), but leaves applications unable to decode indexed values they have not queried for. For dynamic-length types, application developers face a trade-off between fast search for predetermined values (if the argument is indexed) and legibility of arbitrary values (which requires that the arguments not be indexed). Developers may overcome this tradeoff and achieve both efficient search and arbitrary legibility by defining events with two arguments — one indexed, one not — intended to hold the same value. .. _abi_json: @@ -311,15 +440,19 @@ A function description is a JSON object with the fields: * ``components``: used for tuple types (more below). - ``outputs``: an array of objects similar to ``inputs``, can be omitted if function doesn't return anything; -- ``payable``: ``true`` if function accepts ether, defaults to ``false``; -- ``stateMutability``: a string with one of the following values: ``pure`` (:ref:`specified to not read blockchain state `), ``view`` (:ref:`specified to not modify the blockchain state `), ``nonpayable`` and ``payable`` (same as ``payable`` above). -- ``constant``: ``true`` if function is either ``pure`` or ``view`` +- ``stateMutability``: a string with one of the following values: ``pure`` (:ref:`specified to not read blockchain state `), ``view`` (:ref:`specified to not modify the blockchain state `), ``nonpayable`` (function does not accept Ether) and ``payable`` (function accepts Ether); +- ``payable``: ``true`` if function accepts Ether, ``false`` otherwise; +- ``constant``: ``true`` if function is either ``pure`` or ``view``, ``false`` otherwise. -``type`` can be omitted, defaulting to ``"function"``. +``type`` can be omitted, defaulting to ``"function"``, likewise ``payable`` and ``constant`` can be omitted, both defaulting to ``false``. Constructor and fallback function never have ``name`` or ``outputs``. Fallback function doesn't have ``inputs`` either. -Sending non-zero ether to non-payable function will throw. Don't do it. +.. warning:: + The fields ``constant`` and ``payable`` are deprecated and will be removed in the future. Instead, the ``stateMutability`` field can be used to determine the same properties. + +.. note:: + Sending non-zero Ether to non-payable function will revert the transaction. An event description is a JSON object with fairly similar fields: @@ -338,19 +471,19 @@ For example, :: - pragma solidity ^0.4.0; + pragma solidity >0.4.99 <0.6.0; contract Test { - function Test() public { b = 0x12345678901234567890123456789012; } + constructor() public { b = hex"12345678901234567890123456789012"; } event Event(uint indexed a, bytes32 b); event Event2(uint indexed a, bytes32 b); - function foo(uint a) public { Event(a, b); } + function foo(uint a) public { emit Event(a, b); } bytes32 b; } would result in the JSON: -.. code:: json +.. code-block:: json [{ "type":"event", @@ -385,19 +518,19 @@ As an example, the code :: - pragma solidity ^0.4.19; + pragma solidity >=0.4.19 <0.6.0; pragma experimental ABIEncoderV2; contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } - function f(S s, T t, uint a) public { } - function g() public returns (S s, T t, uint a) {} + function f(S memory s, T memory t, uint a) public; + function g() public returns (S memory s, T memory t, uint a); } would result in the JSON: -.. code:: json +.. code-block:: json [ { @@ -457,19 +590,31 @@ would result in the JSON: .. _abi_packed_mode: +Strict Encoding Mode +==================== + +Strict encoding mode is the mode that leads to exactly the same encoding as defined in the formal specification above. +This means offsets have to be as small as possible while still not creating overlaps in the data areas and thus no gaps are +allowed. + +Usually, ABI decoders are written in a straigthforward way just following offset pointers, but some decoders +might enforce strict mode. The Solidity ABI decoder currently does not enforce strict mode, but the encoder +always creates data in strict mode. + Non-standard Packed Mode ======================== -Solidity supports a non-standard packed mode where: +Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode where: -- no :ref:`function selector ` is encoded, - types shorter than 32 bytes are neither zero padded nor sign extended and - dynamic types are encoded in-place and without the length. -As an example encoding ``int1, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in :: +As an example encoding ``int8, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in: + +.. code-block:: none 0xff42242448656c6c6f2c20776f726c6421 - ^^ int1(-1) + ^^ int8(-1) ^^ bytes1(0x42) ^^^^ uint16(0x2424) ^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field @@ -478,3 +623,8 @@ More specifically, each statically-sized type takes as many bytes as its range h and dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded without their length field. This means that the encoding is ambiguous as soon as there are two dynamically-sized elements. + +If padding is needed, explicit type conversions can be used: ``abi.encodePacked(uint16(0x12)) == hex"0012"``. + +Since packed encoding is not used when calling functions, there is no special support +for prepending a function selector. diff --git a/docs/assembly.rst b/docs/assembly.rst index 443cb7dac..5bb9825aa 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -4,57 +4,82 @@ Solidity Assembly .. index:: ! assembly, ! asm, ! evmasm -Solidity defines an assembly language that can also be used without Solidity. -This assembly language can also be used as "inline assembly" inside Solidity -source code. We start with describing how to use inline assembly and how it -differs from standalone assembly and then specify assembly itself. +Solidity defines an assembly language that you can use without Solidity and also +as "inline assembly" inside Solidity source code. This guide starts with describing +how to use inline assembly, how it differs from standalone assembly, and +specifies assembly itself. .. _inline-assembly: Inline Assembly =============== -For more fine-grained control especially in order to enhance the language by writing libraries, -it is possible to interleave Solidity statements with inline assembly in a language close -to the one of the virtual machine. Due to the fact that the EVM is a stack machine, it is -often hard to address the correct stack slot and provide arguments to opcodes at the correct -point on the stack. Solidity's inline assembly tries to facilitate that and other issues -arising when writing manual assembly by the following features: +You can interleave Solidity statements with inline assembly in a language close +to the one of the virtual machine. This gives you more fine-grained control, +especially when you are enhancing the language by writing libraries. -* functional-style opcodes: ``mul(1, add(2, 3))`` instead of ``push1 3 push1 2 add push1 1 mul`` +As the EVM is a stack machine, it is often hard to address the correct stack slot +and provide arguments to opcodes at the correct point on the stack. Solidity's inline +assembly helps you do this, and with other issues that arise when writing manual assembly. + +Inline assembly has the following features: + +* functional-style opcodes: ``mul(1, add(2, 3))`` * assembly-local variables: ``let x := add(2, 3) let y := mload(0x40) x := add(x, y)`` * access to external variables: ``function f(uint x) public { assembly { x := sub(x, 1) } }`` -* labels: ``let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))`` * loops: ``for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) }`` * if statements: ``if slt(x, 0) { x := sub(0, x) }`` * switch statements: ``switch x case 0 { y := mul(x, 2) } default { y := 0 }`` * function calls: ``function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } }`` -We now want to describe the inline assembly language in detail. - .. warning:: Inline assembly is a way to access the Ethereum Virtual Machine - at a low level. This discards several important safety - features of Solidity. + at a low level. This bypasses several important safety + features and checks of Solidity. You should only use it for + tasks that need it, and only if you are confident with using it. + +Syntax +------ + +Assembly parses comments, literals and identifiers in the same way as Solidity, so you can use the +usual ``//`` and ``/* */`` comments. Inline assembly is marked by ``assembly { ... }`` and inside +these curly braces, you can use the following (see the later sections for more details): + + - literals, i.e. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters) + - opcodes in functional style, e.g. ``add(1, mlod(0))`` + - variable declarations, e.g. ``let x := 7``, ``let x := add(y, 3)`` or ``let x`` (initial value of empty (0) is assigned) + - identifiers (assembly-local variables and externals if used as inline assembly), e.g. ``add(3, x)``, ``sstore(x_slot, 2)`` + - assignments, e.g. ``x := add(y, 3)`` + - blocks where local variables are scoped inside, e.g. ``{ let x := 3 { let y := add(x, 1) } }`` + +The following features are only available for standalone assembly: + + - direct stack control via ``dup1``, ``swap1``, ... + - direct stack assignments (in "instruction style"), e.g. ``3 =: x`` + - labels, e.g. ``name:`` + - jump opcodes .. note:: - TODO: Write about how scoping rules of inline assembly are a bit different - and the complications that arise when for example using internal functions - of libraries. Furthermore, write about the symbols defined by the compiler. + Standalone assembly is supported for backwards compatibility but is not documented + here anymore. + +At the end of the ``assembly { ... }`` block, the stack must be balanced, +unless you require it otherwise. If it is not balanced, the compiler generates +a warning. Example ------- The following example provides library code to access the code of another contract and -load it into a ``bytes`` variable. This is not possible at all with "plain Solidity" and the -idea is that assembly libraries will be used to enhance the language in such ways. +load it into a ``bytes`` variable. This is not possible with "plain Solidity" and the +idea is that assembly libraries will be used to enhance the Solidity language. .. code:: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; library GetCode { - function at(address _addr) public view returns (bytes o_code) { + function at(address _addr) public view returns (bytes memory o_code) { assembly { // retrieve the size of the code, this needs assembly let size := extcodesize(_addr) @@ -71,19 +96,17 @@ idea is that assembly libraries will be used to enhance the language in such way } } -Inline assembly could also be beneficial in cases where the optimizer fails to produce -efficient code. Please be aware that assembly is much more difficult to write because -the compiler does not perform checks, so you should use it for complex things only if -you really know what you are doing. +Inline assembly is also beneficial in cases where the optimizer fails to produce +efficient code, for example: .. code:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; library VectorSum { // This function is less efficient because the optimizer currently fails to // remove the bounds checks in array access. - function sumSolidity(uint[] _data) public view returns (uint o_sum) { + function sumSolidity(uint[] memory _data) public pure returns (uint o_sum) { for (uint i = 0; i < _data.length; ++i) o_sum += _data[i]; } @@ -91,7 +114,7 @@ you really know what you are doing. // We know that we only access the array in bounds, so we can avoid the check. // 0x20 needs to be added to an array because the first slot contains the // array length. - function sumAsm(uint[] _data) public view returns (uint o_sum) { + function sumAsm(uint[] memory _data) public pure returns (uint o_sum) { for (uint i = 0; i < _data.length; ++i) { assembly { o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20)))) @@ -100,7 +123,7 @@ you really know what you are doing. } // Same as above, but accomplish the entire code within inline assembly. - function sumPureAsm(uint[] _data) public view returns (uint o_sum) { + function sumPureAsm(uint[] memory _data) public pure returns (uint o_sum) { assembly { // Load the length (first 32 bytes) let len := mload(_data) @@ -115,7 +138,7 @@ you really know what you are doing. // Iterate until the bound is not met. for - { let end := add(data, len) } + { let end := add(data, mul(len, 0x20)) } lt(data, end) { data := add(data, 0x20) } { @@ -126,22 +149,7 @@ you really know what you are doing. } -Syntax ------- - -Assembly parses comments, literals and identifiers exactly as Solidity, so you can use the -usual ``//`` and ``/* */`` comments. Inline assembly is marked by ``assembly { ... }`` and inside -these curly braces, the following can be used (see the later sections for more details) - - - literals, i.e. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters) - - opcodes (in "instruction style"), e.g. ``mload sload dup1 sstore``, for a list see below - - opcodes in functional style, e.g. ``add(1, mlod(0))`` - - labels, e.g. ``name:`` - - variable declarations, e.g. ``let x := 7``, ``let x := add(y, 3)`` or ``let x`` (initial value of empty (0) is assigned) - - identifiers (labels or assembly-local variables and externals if used as inline assembly), e.g. ``jump(name)``, ``3 x add`` - - assignments (in "instruction style"), e.g. ``3 =: x`` - - assignments in functional style, e.g. ``x := add(y, 3)`` - - blocks where local variables are scoped inside, e.g. ``{ let x := 3 { let y := add(x, 1) } }`` +.. _opcodes: Opcodes ------- @@ -157,7 +165,7 @@ Opcodes marked with ``F``, ``H``, ``B`` or ``C`` are present since Frontier, Hom Constantinople is still in planning and all instructions marked as such will result in an invalid instruction exception. In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to -(excluding) position ``b`` and ``storage[p]`` signifies the storage contents at position ``p``. +but not including position ``b`` and ``storage[p]`` signifies the storage contents at position ``p``. The opcodes ``pushi`` and ``jumpdest`` cannot be used directly. @@ -212,16 +220,14 @@ In the grammar, opcodes are represented as pre-defined identifiers. +-------------------------+-----+---+-----------------------------------------------------------------+ | sar(x, y) | | C | arithmetic shift right y by x bits | +-------------------------+-----+---+-----------------------------------------------------------------+ -| addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetics | +| addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetic | +-------------------------+-----+---+-----------------------------------------------------------------+ -| mulmod(x, y, m) | | F | (x * y) % m with arbitrary precision arithmetics | +| mulmod(x, y, m) | | F | (x * y) % m with arbitrary precision arithmetic | +-------------------------+-----+---+-----------------------------------------------------------------+ | signextend(i, x) | | F | sign extend from (i*8+7)th bit counting from least significant | +-------------------------+-----+---+-----------------------------------------------------------------+ | keccak256(p, n) | | F | keccak(mem[p...(p+n))) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| sha3(p, n) | | F | keccak(mem[p...(p+n))) | -+-------------------------+-----+---+-----------------------------------------------------------------+ | jump(label) | `-` | F | jump to label / code position | +-------------------------+-----+---+-----------------------------------------------------------------+ | jumpi(label, cond) | `-` | F | jump to label if cond is nonzero | @@ -230,13 +236,13 @@ In the grammar, opcodes are represented as pre-defined identifiers. +-------------------------+-----+---+-----------------------------------------------------------------+ | pop(x) | `-` | F | remove the element pushed by x | +-------------------------+-----+---+-----------------------------------------------------------------+ -| dup1 ... dup16 | | F | copy ith stack slot to the top (counting from top) | +| dup1 ... dup16 | | F | copy nth stack slot to the top (counting from top) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| swap1 ... swap16 | `*` | F | swap topmost and ith stack slot below it | +| swap1 ... swap16 | `*` | F | swap topmost and nth stack slot below it | +-------------------------+-----+---+-----------------------------------------------------------------+ -| mload(p) | | F | mem[p..(p+32)) | +| mload(p) | | F | mem[p...(p+32)) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| mstore(p, v) | `-` | F | mem[p..(p+32)) := v | +| mstore(p, v) | `-` | F | mem[p...(p+32)) := v | +-------------------------+-----+---+-----------------------------------------------------------------+ | mstore8(p, v) | `-` | F | mem[p] := v & 0xff (only modifies a single byte) | +-------------------------+-----+---+-----------------------------------------------------------------+ @@ -274,16 +280,20 @@ In the grammar, opcodes are represented as pre-defined identifiers. +-------------------------+-----+---+-----------------------------------------------------------------+ | returndatacopy(t, f, s) | `-` | B | copy s bytes from returndata at position f to mem at position t | +-------------------------+-----+---+-----------------------------------------------------------------+ -| create(v, p, s) | | F | create new contract with code mem[p..(p+s)) and send v wei | +| extcodehash(a) | | C | code hash of address a | ++-------------------------+-----+---+-----------------------------------------------------------------+ +| create(v, p, n) | | F | create new contract with code mem[p...(p+n)) and send v wei | | | | | and return the new address | +-------------------------+-----+---+-----------------------------------------------------------------+ -| create2(v, n, p, s) | | C | create new contract with code mem[p..(p+s)) at address | -| | | | keccak256(
. n . keccak256(mem[p..(p+s))) and send v | -| | | | wei and return the new address | +| create2(v, p, n, s) | | C | create new contract with code mem[p...(p+n)) at address | +| | | | keccak256(0xff . this . s . keccak256(mem[p...(p+n))) | +| | | | and send v wei and return the new address, where ``0xff`` is a | +| | | | 8 byte value, ``this`` is the current contract's address | +| | | | as a 20 byte value and ``s`` is a big-endian 256-bit value | +-------------------------+-----+---+-----------------------------------------------------------------+ -| call(g, a, v, in, | | F | call contract at address a with input mem[in..(in+insize)) | +| call(g, a, v, in, | | F | call contract at address a with input mem[in...(in+insize)) | | insize, out, outsize) | | | providing g gas and v wei and output area | -| | | | mem[out..(out+outsize)) returning 0 on error (eg. out of gas) | +| | | | mem[out...(out+outsize)) returning 0 on error (eg. out of gas) | | | | | and 1 on success | +-------------------------+-----+---+-----------------------------------------------------------------+ | callcode(g, a, v, in, | | F | identical to ``call`` but only use the code from a and stay | @@ -295,23 +305,23 @@ In the grammar, opcodes are represented as pre-defined identifiers. | staticcall(g, a, in, | | B | identical to ``call(g, a, 0, in, insize, out, outsize)`` but do | | insize, out, outsize) | | | not allow state modifications | +-------------------------+-----+---+-----------------------------------------------------------------+ -| return(p, s) | `-` | F | end execution, return data mem[p..(p+s)) | +| return(p, s) | `-` | F | end execution, return data mem[p...(p+s)) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| revert(p, s) | `-` | B | end execution, revert state changes, return data mem[p..(p+s)) | +| revert(p, s) | `-` | B | end execution, revert state changes, return data mem[p...(p+s)) | +-------------------------+-----+---+-----------------------------------------------------------------+ | selfdestruct(a) | `-` | F | end execution, destroy current contract and send funds to a | +-------------------------+-----+---+-----------------------------------------------------------------+ | invalid | `-` | F | end execution with invalid instruction | +-------------------------+-----+---+-----------------------------------------------------------------+ -| log0(p, s) | `-` | F | log without topics and data mem[p..(p+s)) | +| log0(p, s) | `-` | F | log without topics and data mem[p...(p+s)) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| log1(p, s, t1) | `-` | F | log with topic t1 and data mem[p..(p+s)) | +| log1(p, s, t1) | `-` | F | log with topic t1 and data mem[p...(p+s)) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| log2(p, s, t1, t2) | `-` | F | log with topics t1, t2 and data mem[p..(p+s)) | +| log2(p, s, t1, t2) | `-` | F | log with topics t1, t2 and data mem[p...(p+s)) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| log3(p, s, t1, t2, t3) | `-` | F | log with topics t1, t2, t3 and data mem[p..(p+s)) | +| log3(p, s, t1, t2, t3) | `-` | F | log with topics t1, t2, t3 and data mem[p...(p+s)) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| log4(p, s, t1, t2, t3, | `-` | F | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) | +| log4(p, s, t1, t2, t3, | `-` | F | log with topics t1, t2, t3, t4 and data mem[p...(p+s)) | | t4) | | | | +-------------------------+-----+---+-----------------------------------------------------------------+ | origin | | F | transaction sender | @@ -337,75 +347,66 @@ Literals You can use integer constants by typing them in decimal or hexadecimal notation and an appropriate ``PUSHi`` instruction will automatically be generated. The following creates code to add 2 and 3 resulting in 5 and then computes the bitwise and with the string "abc". +The final value is assigned to a local variable called ``x``. Strings are stored left-aligned and cannot be longer than 32 bytes. .. code:: - assembly { 2 3 add "abc" and } + assembly { let x := and("abc", add(3, 2)) } + Functional Style ----------------- -You can type opcode after opcode in the same way they will end up in bytecode. For example -adding ``3`` to the contents in memory at position ``0x80`` would be +For a sequence of opcodes, it is often hard to see what the actual +arguments for certain opcodes are. In the following example, +``3`` is added to the contents in memory at position ``0x80``. .. code:: 3 0x80 mload add 0x80 mstore -As it is often hard to see what the actual arguments for certain opcodes are, -Solidity inline assembly also provides a "functional style" notation where the same code -would be written as follows +Solidity inline assembly has a "functional style" notation where the same code +would be written as follows: .. code:: mstore(0x80, add(mload(0x80), 3)) -Functional style expressions cannot use instructional style internally, i.e. -``1 2 mstore(0x80, add)`` is not valid assembly, it has to be written as -``mstore(0x80, add(2, 1))``. For opcodes that do not take arguments, the -parentheses can be omitted. +If you read the code from right to left, you end up with exactly the same +sequence of constants and opcodes, but it is much clearer where the +values end up. -Note that the order of arguments is reversed in functional-style as opposed to the instruction-style -way. If you use functional-style, the first argument will end up on the stack top. +If you care about the exact stack layout, just note that the +syntactically first argument for a function or opcode will be put at the +top of the stack. +Access to External Variables, Functions and Libraries +----------------------------------------------------- -Access to External Variables and Functions ------------------------------------------- - -Solidity variables and other identifiers can be accessed by simply using their name. -For memory variables, this will push the address and not the value onto the -stack. Storage variables are different: Values in storage might not occupy a -full storage slot, so their "address" is composed of a slot and a byte-offset +You can access Solidity variables and other identifiers by using their name. +For variables stored in the memory data location, this pushes the address, and not the value +onto the stack. Variables stored in the storage data location are different, as they might not +occupy a full storage slot, so their "address" is composed of a slot and a byte-offset inside that slot. To retrieve the slot pointed to by the variable ``x``, you -used ``x_slot`` and to retrieve the byte-offset you used ``x_offset``. +use ``x_slot``, and to retrieve the byte-offset you use ``x_offset``. -In assignments (see below), we can even use local Solidity variables to assign to. - -Functions external to inline assembly can also be accessed: The assembly will -push their entry label (with virtual function resolution applied). The calling semantics -in solidity are: - - - the caller pushes ``return label``, ``arg1``, ``arg2``, ..., ``argn`` - - the call returns with ``ret1``, ``ret2``, ..., ``retm`` - -This feature is still a bit cumbersome to use, because the stack offset essentially -changes during the call, and thus references to local variables will be wrong. +Local Solidity variables are available for assignments, for example: .. code:: - pragma solidity ^0.4.11; + pragma solidity >=0.4.11 <0.6.0; contract C { uint b; - function f(uint x) public returns (uint r) { + function f(uint x) public view returns (uint r) { assembly { r := mul(x, sload(b_slot)) // ignore the offset, we know it is zero } } } -.. note:: +.. warning:: If you access variables of a type that spans less than 256 bits (for example ``uint64``, ``address``, ``bytes16`` or ``byte``), you cannot make any assumptions about bits not part of the @@ -418,57 +419,8 @@ changes during the call, and thus references to local variables will be wrong. Labels ------ -.. note:: - Labels are deprecated. Please use functions, loops, if or switch statements instead. - -Another problem in EVM assembly is that ``jump`` and ``jumpi`` use absolute addresses -which can change easily. Solidity inline assembly provides labels to make the use of -jumps easier. Note that labels are a low-level feature and it is possible to write -efficient assembly without labels, just using assembly functions, loops, if and switch instructions -(see below). The following code computes an element in the Fibonacci series. - -.. code:: - - { - let n := calldataload(4) - let a := 1 - let b := a - loop: - jumpi(loopend, eq(n, 0)) - a add swap1 - n := sub(n, 1) - jump(loop) - loopend: - mstore(0, a) - return(0, 0x20) - } - -Please note that automatically accessing stack variables can only work if the -assembler knows the current stack height. This fails to work if the jump source -and target have different stack heights. It is still fine to use such jumps, but -you should just not access any stack variables (even assembly variables) in that case. - -Furthermore, the stack height analyser goes through the code opcode by opcode -(and not according to control flow), so in the following case, the assembler -will have a wrong impression about the stack height at label ``two``: - -.. code:: - - { - let x := 8 - jump(two) - one: - // Here the stack height is 2 (because we pushed x and 7), - // but the assembler thinks it is 1 because it reads - // from top to bottom. - // Accessing the stack variable x here will lead to errors. - x := 9 - jump(three) - two: - 7 // push something onto the stack - jump(one) - three: - } +Support for labels has been removed in version 0.5.0 of Solidity. +Please use functions, loops, if or switch statements instead. Declaring Assembly-Local Variables ---------------------------------- @@ -482,7 +434,7 @@ be just ``0``, but it can also be a complex functional-style expression. .. code:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { function f(uint x) public view returns (uint b) { @@ -506,26 +458,19 @@ Assignments are possible to assembly-local variables and to function-local variables. Take care that when you assign to variables that point to memory or storage, you will only change the pointer and not the data. -There are two kinds of assignments: functional-style and instruction-style. -For functional-style assignments (``variable := value``), you need to provide a value in a -functional-style expression that results in exactly one stack value -and for instruction-style (``=: variable``), the value is just taken from the stack top. -For both ways, the colon points to the name of the variable. The assignment -is performed by replacing the variable's value on the stack by the new value. +Variables can only be assigned expressions that result in exactly one value. +If you want to assign the values returned from a function that has +multiple return parameters, you have to provide multiple variables. .. code:: { - let v := 0 // functional-style assignment as part of variable declaration + let v := 0 let g := add(v, 2) - sload(10) - =: v // instruction style assignment, puts the result of sload(10) into v + function f() -> a, b { } + let c, d := f() } -.. note:: - Instruction-style assignment is deprecated. - - If -- @@ -642,12 +587,9 @@ Things to Avoid Inline assembly might have a quite high-level look, but it actually is extremely low-level. Function calls, loops, ifs and switches are converted by simple rewriting rules and after that, the only thing the assembler does for you is re-arranging -functional-style opcodes, managing jump labels, counting stack height for +functional-style opcodes, counting stack height for variable access and removing stack slots for assembly-local variables when the end -of their block is reached. Especially for those two last cases, it is important -to know that the assembler only counts stack height from top to bottom, not -necessarily following control flow. Furthermore, operations like swap will only -swap the contents of the stack but not the location of variables. +of their block is reached. Conventions in Solidity ----------------------- @@ -662,20 +604,31 @@ 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 -from that point on and update the pointer accordingly. +starting from where this pointer points at and update it accordingly. +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:: + + function allocate(length) -> pos { + pos := mload(0x40) + mstore(0x40, add(pos, length)) + } 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 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 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 then only the array elements follow. +first slot of the array and followed by the array elements. .. warning:: - Statically-sized memory arrays do not have a length field, but it will be added soon + 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. @@ -710,7 +663,7 @@ Scoping: An identifier that is declared (label, variable, function, assembly) is only visible in the block where it was declared (including nested blocks inside the current block). It is not legal to access local variables across function borders, even if they would be in scope. Shadowing is not allowed. -Local variables cannot be accessed before they were declared, but labels, +Local variables cannot be accessed before they were declared, but functions and assemblies can. Assemblies are special blocks that are used for e.g. returning runtime code or creating contracts. No identifier from an outer assembly is visible in a sub-assembly. @@ -721,7 +674,7 @@ Whenever a local variable is referenced, the code generator needs to know its current relative position in the stack and thus it needs to keep track of the current so-called stack height. Since all local variables are removed at the end of a block, the stack height before and after the block -should be the same. If this is not the case, a warning is issued. +should be the same. If this is not the case, compilation fails. Using ``switch``, ``for`` and functions, it should be possible to write complex code without using ``jump`` or ``jumpi`` manually. This makes it much @@ -738,7 +691,7 @@ Example: We will follow an example compilation from Solidity to assembly. We consider the runtime bytecode of the following Solidity program:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { function f(uint x) public pure returns (uint y) { @@ -751,7 +704,7 @@ We consider the runtime bytecode of the following Solidity program:: The following assembly will be generated:: { - mstore(0x40, 0x60) // store the "free memory pointer" + mstore(0x40, 0x80) // store the "free memory pointer" // function dispatcher switch div(calldataload(0), exp(2, 226)) case 0xb3de648b { diff --git a/docs/bugs.json b/docs/bugs.json index c1e377a41..28c0fe623 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -17,12 +17,13 @@ "check": {"ast-compact-json-path": "$..[?(@.nodeType === 'EventDefinition')]..[?(@.nodeType === 'UserDefinedTypeName' && @.typeDescriptions.typeString.startsWith('struct'))]"} }, { - "name": "PublicLibFunctionsDoNotReturnNestedArrays", - "summary": "Calls to public library functions (internal functions are safe) that return nested arrays return only zeroes.", - "description": "The compiler does not complain about public library functions (internal functions are safe) returning nested arrays, but it also does not return it correctly. Thus, the function caller receives only zeroes.", - "introduced": "0.4.11", + "name": "NestedArrayFunctionCallDecoder", + "summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.", + "description": "If Solidity code calls a function that returns a multi-dimensional fixed-size array, array elements are incorrectly interpreted as memory pointers and thus can cause memory corruption if the return values are accessed. Calling functions with multi-dimensional fixed-size arrays is unaffected as is returning fixed-size arrays from function calls. The regular expression only checks if such functions are present, not if they are called, which is required for the contract to be affected.", + "introduced": "0.1.4", "fixed": "0.4.22", - "severity": "low" + "severity": "medium", + "check": {"regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"} }, { "name": "OneOfTwoConstructorsSkipped", @@ -32,15 +33,6 @@ "fixed": "0.4.23", "severity": "very low" }, - { - "name": "NestedArrayFunctionCallDecoder", - "summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.", - "description": "If Solidity code calls a function that returns a multi-dimensional fixed-size array, array elements are incorrectly interpreted as memory pointers and thus can cause memory corruption if the return values are accessed. Calling functions with multi-dimensional fixed-size arrays is unaffected as is returning fixed-size arrays from function calls. The regular expression only checks if such functions are present, not if they are called, which is required for the contract to be affected.", - "introduced": "0.1.4", - "fixed": "0.4.22", - "severity": "medium", - "check": {"regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"} - }, { "name": "ZeroFunctionSelector", "summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.", diff --git a/docs/bugs.rst b/docs/bugs.rst index 8e3382c86..f7522183a 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -57,15 +57,14 @@ conditions means that the optimizer has to be switched on to enable the bug. If no conditions are given, assume that the bug is present. check - This field contains different checks that can be used to determine - whether a smart contract + This field contains different checks that report whether the smart contract contains the bug or not. The first type of check are Javascript regular - expressions that are to be matched against the source code ("source-regex"). - If there is no match, then the bug is very likely + expressions that are to be matched against the source code ("source-regex") + if the bug is present. If there is no match, then the bug is very likely not present. If there is a match, the bug might be present. For improved accuracy, the checks should be applied to the source code after stripping comments. - The second type of check are patterns to be applied to the compact AST of + The second type of check are patterns to be checked on the compact AST of the Solidity program ("ast-compact-json-path"). The specified search query is a `JsonPath `_ expression. If at least one path of the Solidity AST matches the query, the bug is diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index ef0846606..2631b2867 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,623 +1,616 @@ { "0.1.0": { "bugs": [ - "ExpExponentCleanup", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-07-10" - }, + }, "0.1.1": { "bugs": [ - "ExpExponentCleanup", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-08-04" - }, + }, "0.1.2": { "bugs": [ - "ExpExponentCleanup", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-08-20" - }, + }, "0.1.3": { "bugs": [ - "ExpExponentCleanup", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-09-25" - }, + }, "0.1.4": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-09-30" - }, + }, "0.1.5": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-10-07" - }, + }, "0.1.6": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-10-16" - }, + }, "0.1.7": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-11-17" - }, + }, "0.2.0": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-12-02" - }, + }, "0.2.1": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2016-01-30" - }, + }, "0.2.2": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2016-02-17" - }, + }, "0.3.0": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits" - ], + ], "released": "2016-03-11" - }, + }, "0.3.1": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits" - ], + ], "released": "2016-03-31" - }, + }, "0.3.2": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits" - ], + ], "released": "2016-04-18" - }, + }, "0.3.3": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" - ], + ], "released": "2016-05-27" - }, + }, "0.3.4": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" - ], + ], "released": "2016-05-31" - }, + }, "0.3.5": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" - ], + ], "released": "2016-06-10" - }, + }, "0.3.6": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther" - ], + ], "released": "2016-08-10" - }, + }, "0.4.0": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", "LibrariesNotCallableFromPayableFunctions" - ], + ], "released": "2016-09-08" - }, + }, "0.4.1": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", "LibrariesNotCallableFromPayableFunctions" - ], + ], "released": "2016-09-09" - }, + }, "0.4.10": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2017-03-15" - }, + }, "0.4.11": { "bugs": [ - "ExpExponentCleanup", - "PublicLibFunctionsDoNotReturnNestedArrays", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", "SkipEmptyStringLiteral" - ], + ], "released": "2017-05-03" - }, + }, "0.4.12": { "bugs": [ - "ExpExponentCleanup", - "PublicLibFunctionsDoNotReturnNestedArrays", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", "ECRecoverMalformedInput" - ], + ], "released": "2017-07-03" - }, + }, "0.4.13": { "bugs": [ - "ExpExponentCleanup", - "PublicLibFunctionsDoNotReturnNestedArrays", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", "ECRecoverMalformedInput" - ], + ], "released": "2017-07-06" - }, + }, "0.4.14": { "bugs": [ - "ExpExponentCleanup", - "PublicLibFunctionsDoNotReturnNestedArrays", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", "DelegateCallReturnValue" - ], + ], "released": "2017-07-31" - }, + }, "0.4.15": { "bugs": [ - "ExpExponentCleanup", - "PublicLibFunctionsDoNotReturnNestedArrays", - "NestedArrayFunctionCallDecoder", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" - ], + ], "released": "2017-08-08" - }, + }, "0.4.16": { "bugs": [ - "ExpExponentCleanup", - "PublicLibFunctionsDoNotReturnNestedArrays", - "NestedArrayFunctionCallDecoder", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" - ], + ], "released": "2017-08-24" - }, + }, "0.4.17": { "bugs": [ - "ExpExponentCleanup", - "EventStructWrongData", - "PublicLibFunctionsDoNotReturnNestedArrays", - "NestedArrayFunctionCallDecoder", + "ExpExponentCleanup", + "EventStructWrongData", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" - ], + ], "released": "2017-09-21" - }, + }, "0.4.18": { "bugs": [ - "ExpExponentCleanup", - "EventStructWrongData", - "PublicLibFunctionsDoNotReturnNestedArrays", + "ExpExponentCleanup", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2017-10-18" - }, + }, "0.4.19": { "bugs": [ - "ExpExponentCleanup", - "EventStructWrongData", - "PublicLibFunctionsDoNotReturnNestedArrays", + "ExpExponentCleanup", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2017-11-30" - }, + }, "0.4.2": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3" - ], + ], "released": "2016-09-17" - }, + }, "0.4.20": { "bugs": [ - "ExpExponentCleanup", - "EventStructWrongData", - "PublicLibFunctionsDoNotReturnNestedArrays", + "ExpExponentCleanup", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2018-02-14" - }, + }, "0.4.21": { "bugs": [ - "ExpExponentCleanup", - "EventStructWrongData", - "PublicLibFunctionsDoNotReturnNestedArrays", + "ExpExponentCleanup", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2018-03-07" - }, + }, "0.4.22": { "bugs": [ - "ExpExponentCleanup", - "EventStructWrongData", + "ExpExponentCleanup", + "EventStructWrongData", "OneOfTwoConstructorsSkipped" - ], + ], "released": "2018-04-16" - }, + }, "0.4.23": { "bugs": [ - "ExpExponentCleanup", + "ExpExponentCleanup", "EventStructWrongData" - ], + ], "released": "2018-04-19" - }, + }, "0.4.24": { "bugs": [ - "ExpExponentCleanup", + "ExpExponentCleanup", "EventStructWrongData" - ], + ], "released": "2018-05-16" - }, + }, "0.4.25": { - "bugs": [], + "bugs": [], "released": "2018-09-12" - }, + }, "0.4.3": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage" - ], + ], "released": "2016-10-25" - }, + }, "0.4.4": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" - ], + ], "released": "2016-10-31" - }, + }, "0.4.5": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", "OptimizerStateKnowledgeNotResetForJumpdest" - ], + ], "released": "2016-11-21" - }, + }, "0.4.6": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" - ], + ], "released": "2016-11-22" - }, + }, "0.4.7": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2016-12-15" - }, + }, "0.4.8": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2017-01-13" - }, + }, "0.4.9": { "bugs": [ - "ExpExponentCleanup", - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2017-01-31" + }, + "0.5.0": { + "bugs": [], + "released": "2018-11-13" } } \ No newline at end of file diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index 739e136f5..84c189369 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -13,11 +13,11 @@ Withdrawal from Contracts The recommended method of sending funds after an effect is using the withdrawal pattern. Although the most intuitive method of sending Ether, as a result of an effect, is a -direct ``send`` call, this is not recommended as it +direct ``transfer`` call, this is not recommended as it introduces a potential security risk. You may read more about this on the :ref:`security_considerations` page. -This is an example of the withdrawal pattern in practice in +The following is an example of the withdrawal pattern in practice in a contract where the goal is to send the most money to the contract in order to become the "richest", inspired by `King of the Ether `_. @@ -28,7 +28,7 @@ become the new richest. :: - pragma solidity ^0.4.11; + pragma solidity >0.4.99 <0.6.0; contract WithdrawalContract { address public richest; @@ -36,7 +36,7 @@ become the new richest. mapping (address => uint) pendingWithdrawals; - function WithdrawalContract() public payable { + constructor() public payable { richest = msg.sender; mostSent = msg.value; } @@ -65,13 +65,13 @@ This is as opposed to the more intuitive sending pattern: :: - pragma solidity ^0.4.11; + pragma solidity >0.4.99 <0.6.0; contract SendContract { - address public richest; + address payable public richest; uint public mostSent; - function SendContract() public payable { + constructor() public payable { richest = msg.sender; mostSent = msg.value; } @@ -93,7 +93,7 @@ Notice that, in this example, an attacker could trap the contract into an unusable state by causing ``richest`` to be the address of a contract that has a fallback function which fails (e.g. by using ``revert()`` or by just -consuming more than the 2300 gas stipend). That way, +consuming more than the 2300 gas stipend transferred to them). That way, whenever ``transfer`` is called to deliver funds to the "poisoned" contract, it will fail and thus also ``becomeRichest`` will fail, with the contract being stuck forever. @@ -130,7 +130,7 @@ restrictions highly readable. :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract AccessRestriction { // These will be assigned at the construction @@ -198,7 +198,7 @@ restrictions highly readable. ); _; if (msg.value > _amount) - msg.sender.send(msg.value - _amount); + msg.sender.transfer(msg.value - _amount); } function forceOwnerChange(address _newOwner) @@ -282,7 +282,7 @@ function finishes. :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract StateMachine { enum Stages { diff --git a/docs/conf.py b/docs/conf.py index 7e107f2a7..233ff7b6e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,9 +24,11 @@ import re def setup(sphinx): thisdir = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, thisdir + '/utils') - from SolidityLexer import SolidityLexer + from pygments_lexer_solidity import SolidityLexer sphinx.add_lexer('Solidity', SolidityLexer()) + sphinx.add_stylesheet('css/custom.css') + # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -112,7 +114,7 @@ highlight_language = 'Solidity' # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -141,7 +143,7 @@ html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] +html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied diff --git a/docs/contracts.rst b/docs/contracts.rst index b73fe2caf..c1c51e568 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -1,5 +1,7 @@ .. index:: ! contract +.. _contracts: + ########## Contracts ########## @@ -20,15 +22,20 @@ Contracts can be created "from outside" via Ethereum transactions or from within IDEs, such as `Remix `_, make the creation process seamless using UI elements. -Creating contracts programatically on Ethereum is best done via using the JavaScript API `web3.js `_. -As of today it has a method called `web3.eth.Contract `_ +Creating contracts programmatically on Ethereum is best done via using the JavaScript API `web3.js `_. +It has a function called `web3.eth.Contract `_ to facilitate contract creation. -When a contract is created, its constructor (a function declared with the -``constructor`` keyword) is executed once. -A constructor is optional. Only one constructor is allowed, and this means +When a contract is created, its constructor_ (a function declared with the ``constructor`` keyword) is executed once. + +A constructor is optional. Only one constructor is allowed, which means overloading is not supported. +After the constructor has executed, the final code of the contract is deployed to the +blockchain. This code includes all public and external functions and all functions +that are reachable from there through function calls. The deployed code does not +include the constructor code or internal functions only called from the constructor. + .. index:: constructor;arguments Internally, constructor arguments are passed :ref:`ABI encoded ` after the code of @@ -40,10 +47,10 @@ This means that cyclic creation dependencies are impossible. :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract OwnedToken { - // TokenCreator is a contract type that is defined below. + // `TokenCreator` is a contract type that is defined below. // It is fine to reference it as long as it is not used // to create a new contract. TokenCreator creator; @@ -54,14 +61,18 @@ This means that cyclic creation dependencies are impossible. // creator and the assigned name. constructor(bytes32 _name) public { // State variables are accessed via their name - // and not via e.g. this.owner. This also applies - // to functions and especially in the constructors, - // you can only call them like that ("internally"), - // because the contract itself does not exist yet. + // and not via e.g. `this.owner`. Functions can + // be accessed directly or through `this.f`, + // but the latter provides an external view + // to the function. Especially in the constructor, + // you should not access functions externally, + // because the function does not exist yet. + // See the next section for details. owner = msg.sender; + // We do an explicit type conversion from `address` // to `TokenCreator` and assume that the type of - // the calling contract is TokenCreator, there is + // the calling contract is `TokenCreator`, there is // no real way to check that. creator = TokenCreator(msg.sender); name = _name; @@ -70,7 +81,7 @@ This means that cyclic creation dependencies are impossible. function changeName(bytes32 newName) public { // Only the creator can alter the name -- // the comparison is possible since contracts - // are implicitly convertible to addresses. + // are explicitly convertible to addresses. if (msg.sender == address(creator)) name = newName; } @@ -78,11 +89,12 @@ This means that cyclic creation dependencies are impossible. function transfer(address newOwner) public { // Only the current owner can transfer the token. if (msg.sender != owner) return; - // We also want to ask the creator if the transfer - // is fine. Note that this calls a function of the - // contract defined below. If the call fails (e.g. - // due to out-of-gas), the execution here stops - // immediately. + + // We ask the creator contract if the transfer + // should proceed by using a function of the + // `TokenCreator` contract defined below. If + // the call fails (e.g. due to out-of-gas), + // the execution also fails here. if (creator.isTokenTransferOK(owner, newOwner)) owner = newOwner; } @@ -93,27 +105,28 @@ This means that cyclic creation dependencies are impossible. public returns (OwnedToken tokenAddress) { - // Create a new Token contract and return its address. - // From the JavaScript side, the return type is simply + // Create a new `Token` contract and return its address. + // From the JavaScript side, the return type is // `address`, as this is the closest type available in // the ABI. return new OwnedToken(name); } - function changeName(OwnedToken tokenAddress, bytes32 name) public { + function changeName(OwnedToken tokenAddress, bytes32 name) public { // Again, the external type of `tokenAddress` is // simply `address`. tokenAddress.changeName(name); } + // Perform checks to determine if transferring a token to the + // `OwnedToken` contract should proceed function isTokenTransferOK(address currentOwner, address newOwner) public - view + pure returns (bool ok) { - // Check some arbitrary condition. - address tokenAddress = msg.sender; - return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff); + // Check an arbitrary condition to see if transfer should proceed + return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; } } @@ -131,22 +144,21 @@ a "message call") and external ones that do), there are four types of visibilities for functions and state variables. -Functions can be specified as being ``external``, -``public``, ``internal`` or ``private``, where the default is -``public``. For state variables, ``external`` is not possible -and the default is ``internal``. +Functions have to be specified as being ``external``, +``public``, ``internal`` or ``private``. +For state variables, ``external`` is not possible. ``external``: - External functions are part of the contract - interface, which means they can be called from other contracts and + External functions are part of the contract interface, + which means they can be called from other contracts and via transactions. An external function ``f`` cannot be called internally (i.e. ``f()`` does not work, but ``this.f()`` works). External functions are sometimes more efficient when they receive large arrays of data. ``public``: - Public functions are part of the contract - interface and can be either called internally or via + Public functions are part of the contract interface + and can be either called internally or via messages. For public state variables, an automatic getter function (see below) is generated. @@ -162,7 +174,7 @@ and the default is ``internal``. .. note:: Everything that is inside a contract is visible to - all external observers. Making something ``private`` + all observers external to the blockchain. Making something ``private`` only prevents other contracts from accessing and modifying the information, but it will still be visible to the whole world outside of the blockchain. @@ -173,7 +185,7 @@ return parameter list for functions. :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { function f(uint a) private pure returns (uint b) { return a + 1; } @@ -187,19 +199,18 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value :: - // This will not compile - - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { uint private data; - function f(uint a) private returns(uint b) { return a + 1; } + function f(uint a) private pure returns(uint b) { return a + 1; } function setData(uint a) public { data = a; } - function getData() public returns(uint) { return data; } - function compute(uint a, uint b) internal returns (uint) { return a+b; } + function getData() public view returns(uint) { return data; } + function compute(uint a, uint b) internal pure returns (uint) { return a + b; } } + // This will not compile contract D { function readData() public { C c = new C(); @@ -227,12 +238,12 @@ The compiler automatically creates getter functions for all **public** state variables. For the contract given below, the compiler will generate a function called ``data`` that does not take any arguments and returns a ``uint``, the value of the state -variable ``data``. The initialization of state variables can -be done at declaration. +variable ``data``. State variables can be initialized +when they are declared. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { uint public data = 42; @@ -240,33 +251,64 @@ be done at declaration. contract Caller { C c = new C(); - function f() public { - uint local = c.data(); + function f() public view returns (uint) { + return c.data(); } } The getter functions have external visibility. If the symbol is accessed internally (i.e. without ``this.``), -it is evaluated as a state variable. If it is accessed externally -(i.e. with ``this.``), it is evaluated as a function. +it evaluates to a state variable. If it is accessed externally +(i.e. with ``this.``), it evaluates to a function. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { uint public data; - function x() public { + function x() public returns (uint) { data = 3; // internal access - uint val = this.data(); // external access + return this.data(); // external access } } -The next example is a bit more complex: +If you have a ``public`` state variable of array type, then you can only retrieve +single elements of the array via the generated getter function. This mechanism +exists to avoid high gas costs when returning an entire array. You can use +arguments to specify which individual element to return, for example +``data(0)``. If you want to return an entire array in one call, then you need +to write a function, for example: :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; + + contract arrayExample { + // public state variable + uint[] public myArray; + + // Getter function generated by the compiler + /* + function myArray(uint i) returns (uint) { + return myArray[i]; + } + */ + + // function that returns entire array + function getArray() returns (uint[] memory) { + return myArray; + } + } + +Now you can use ``getArray()`` to retrieve the entire array, instead of +``myArray(i)``, which returns a single element per call. + +The next example is more complex: + +:: + + pragma solidity >=0.4.0 <0.6.0; contract Complex { struct Data { @@ -277,16 +319,16 @@ The next example is a bit more complex: mapping (uint => mapping(bool => Data[])) public data; } -It will generate a function of the following form:: +It generates a function of the following form. The mapping in the struct is omitted +because there is no good way to provide the key for the mapping: + +:: function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b) { a = data[arg1][arg2][arg3].a; b = data[arg1][arg2][arg3].b; } -Note that the mapping in the struct is omitted because there -is no good way to provide the key for the mapping. - .. index:: ! function;modifier .. _modifiers: @@ -301,11 +343,11 @@ inheritable properties of contracts and may be overridden by derived contracts. :: - pragma solidity ^0.4.22; + pragma solidity >0.4.99 <0.6.0; contract owned { - function owned() public { owner = msg.sender; } - address owner; + constructor() public { owner = msg.sender; } + address payable owner; // This contract only defines a modifier but does not use // it: it will be used in derived contracts. @@ -346,7 +388,7 @@ inheritable properties of contracts and may be overridden by derived contracts. mapping (address => bool) registeredAddresses; uint price; - function Register(uint initialPrice) public { price = initialPrice; } + constructor(uint initialPrice) public { price = initialPrice; } // It is important to also provide the // `payable` keyword here, otherwise the function will @@ -377,7 +419,8 @@ inheritable properties of contracts and may be overridden by derived contracts. /// The `return 7` statement assigns 7 to the return value but still /// executes the statement `locked = false` in the modifier. function f() public noReentrancy returns (uint) { - require(msg.sender.call()); + (bool success,) = msg.sender.call(""); + require(success); return 7; } } @@ -406,13 +449,13 @@ Constant State Variables State variables can be declared as ``constant``. In this case, they have to be assigned from an expression which is a constant at compile time. Any expression -that accesses storage, blockchain data (e.g. ``now``, ``this.balance`` or +that accesses storage, blockchain data (e.g. ``now``, ``address(this).balance`` or ``block.number``) or -execution data (``msg.value`` or ``gasleft()``) or make calls to external contracts are disallowed. Expressions +execution data (``msg.value`` or ``gasleft()``) or makes calls to external contracts is disallowed. Expressions that might have a side-effect on memory allocation are allowed, but those that might have a side-effect on other memory objects are not. The built-in functions ``keccak256``, ``sha256``, ``ripemd160``, ``ecrecover``, ``addmod`` and ``mulmod`` -are allowed (even though they do call external contracts). +are allowed (even though, with the exception of ``keccak256``, they do call external contracts). The reason behind allowing side-effects on the memory allocator is that it should be possible to construct complex objects like e.g. lookup-tables. @@ -426,7 +469,7 @@ value types and strings. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { uint constant x = 32**22 + 8; @@ -451,6 +494,15 @@ View Functions Functions can be declared ``view`` in which case they promise not to modify the state. +.. note:: + If the compiler's EVM target is Byzantium or newer (default) the opcode + ``STATICCALL`` is used for ``view`` functions which enforces the state + to stay unmodified as part of the EVM execution. For library ``view`` functions + ``DELEGATECALL`` is used, because there is no combined ``DELEGATECALL`` and ``STATICCALL``. + This means library ``view`` functions do not have run-time checks that prevent state + modifications. This should not impact security negatively because library code is + usually known at compile-time and the static checker performs compile-time checks. + The following statements are considered modifying the state: #. Writing to state variables. @@ -464,7 +516,7 @@ The following statements are considered modifying the state: :: - pragma solidity ^0.4.16; + pragma solidity >0.4.99 <0.6.0; contract C { function f(uint a, uint b) public view returns (uint) { @@ -473,20 +525,18 @@ The following statements are considered modifying the state: } .. note:: - ``constant`` on functions is an alias to ``view``, but this is deprecated and will be dropped in version 0.5.0. + ``constant`` on functions used to be an alias to ``view``, but this was dropped in version 0.5.0. .. note:: - Getter methods are marked ``view``. + Getter methods are automatically marked ``view``. .. note:: - If invalid explicit type conversions are used, state modifications are possible - even though a ``view`` function was called. - You can switch the compiler to use ``STATICCALL`` when calling such functions and thus - prevent modifications to the state on the level of the EVM by adding - ``pragma experimental "v0.5.0";`` - -.. warning:: - The compiler does not enforce yet that a ``view`` method is not modifying state. It raises a warning though. + Prior to version 0.5.0, the compiler did not use the ``STATICCALL`` opcode + for ``view`` functions. + This enabled state modifications in ``view`` functions through the use of + invalid explicit type conversions. + By using ``STATICCALL`` for ``view`` functions, modifications to the + state are prevented on the level of the EVM. .. index:: ! pure function, function;pure @@ -497,17 +547,21 @@ Pure Functions Functions can be declared ``pure`` in which case they promise not to read from or modify the state. +.. note:: + If the compiler's EVM target is Byzantium or newer (default) the opcode ``STATICCALL`` is used, + which does not guarantee that the state is not read, but at least that it is not modified. + In addition to the list of state modifying statements explained above, the following are considered reading from the state: #. Reading from state variables. -#. Accessing ``this.balance`` or ``
.balance``. +#. Accessing ``address(this).balance`` or ``
.balance``. #. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``). #. Calling any function not marked ``pure``. #. Using inline assembly that contains certain opcodes. :: - pragma solidity ^0.4.16; + pragma solidity >0.4.99 <0.6.0; contract C { function f(uint a, uint b) public pure returns (uint) { @@ -516,11 +570,12 @@ In addition to the list of state modifying statements explained above, the follo } .. note:: - If invalid explicit type conversions are used, state modifications are possible - even though a ``pure`` function was called. - You can switch the compiler to use ``STATICCALL`` when calling such functions and thus - prevent modifications to the state on the level of the EVM by adding - ``pragma experimental "v0.5.0";`` + Prior to version 0.5.0, the compiler did not use the ``STATICCALL`` opcode + for ``pure`` functions. + This enabled state modifications in ``pure`` functions through the use of + invalid explicit type conversions. + By using ``STATICCALL`` for ``pure`` functions, modifications to the + state are prevented on the level of the EVM. .. warning:: It is not possible to prevent functions from reading the state at the level @@ -528,7 +583,11 @@ In addition to the list of state modifying statements explained above, the follo (i.e. only ``view`` can be enforced at the EVM level, ``pure`` can not). .. warning:: - Before version 0.4.17 the compiler didn't enforce that ``pure`` is not reading the state. + Before version 0.4.17 the compiler did not enforce that ``pure`` is not reading the state. + It is a compile-time type check, which can be circumvented doing invalid explicit conversions + between contract types, because the compiler can verify that the type of the contract does + not do state-changing operations, but it cannot check that the contract that will be called + at runtime is actually of that type. .. index:: ! fallback function, function;fallback @@ -538,7 +597,7 @@ Fallback Function ================= A contract can have exactly one unnamed function. This function cannot have -arguments and cannot return anything. +arguments, cannot return anything and has to have ``external`` visibility. It is executed on a call to the contract if none of the other functions match the given function identifier (or if no data was supplied at all). @@ -548,7 +607,10 @@ Ether (without data). Additionally, in order to receive Ether, the fallback func must be marked ``payable``. If no such function exists, the contract cannot receive Ether through regular transactions. -In the worst case, the fallback function can only rely on 2300 gas being available (for example when send or transfer is used), leaving not much room to perform other operations except basic logging. The following operations will consume more gas than the 2300 gas stipend: +In the worst case, the fallback function can only rely on 2300 gas being +available (for example when `send` or `transfer` is used), leaving little +room to perform other operations except basic logging. The following operations +will consume more gas than the 2300 gas stipend: - Writing to storage - Creating a contract @@ -561,12 +623,18 @@ Like any function, the fallback function can execute complex operations as long 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 + function only to receive ether, you should add a check + like ``require(msg.data.length == 0)`` to prevent invalid calls. + .. warning:: Contracts that receive Ether directly (without a function call, i.e. using ``send`` or ``transfer``) but do not define a fallback function throw an exception, sending back the Ether (this was different before Solidity v0.4.0). So if you want your contract to receive Ether, - you have to implement a fallback function. + you have to implement a payable fallback function. .. warning:: A contract without a payable fallback function can receive Ether as a recipient of a `coinbase transaction` (aka `miner block reward`) @@ -574,11 +642,11 @@ Like any function, the fallback function can execute complex operations as long 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 ``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). + 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). :: - pragma solidity ^0.4.0; + pragma solidity >0.4.99 <0.6.0; contract Test { // This function is called for all messages sent to @@ -586,7 +654,7 @@ Like any function, the fallback function can execute complex operations as long // Sending Ether to this contract will cause an exception, // because the fallback function does not have the `payable` // modifier. - function() public { x = 1; } + function() external { x = 1; } uint x; } @@ -594,19 +662,23 @@ Like any function, the fallback function can execute complex operations as long // This contract keeps all Ether sent to it with no way // to get it back. contract Sink { - function() public payable { } + function() external payable { } } contract Caller { - function callTest(Test test) public { - test.call(0xabcdef01); // hash does not exist + function callTest(Test test) public returns (bool) { + (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); + require(success); // results in test.x becoming == 1. - // The following will not compile, but even - // if someone sends ether to that contract, - // the transaction will fail and reject the - // Ether. - //test.send(2 ether); + // address(test) will not allow to call ``send`` directly, since ``test`` has no payable + // fallback function. It has to be converted to the ``address payable`` type via an + // intermediate conversion to ``uint160`` to even allow calling ``send`` on it. + address payable testPayable = address(uint160(address(test))); + + // If someone sends ether to that contract, + // the transfer will fail, i.e. this returns false here. + return testPayable.send(2 ether); } } @@ -617,21 +689,24 @@ Like any function, the fallback function can execute complex operations as long Function Overloading ==================== -A Contract can have multiple functions of the same name but with different arguments. -This also applies to inherited functions. The following example shows overloading of the -``f`` function in the scope of contract ``A``. +A contract can have multiple functions of the same name but with different parameter +types. +This process is called "overloading" and also applies to inherited functions. +The following example shows overloading of the function +``f`` in the scope of contract ``A``. :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract A { function f(uint _in) public pure returns (uint out) { - out = 1; + out = _in; } - function f(uint _in, bytes32 _key) public pure returns (uint out) { - out = 2; + function f(uint _in, bool _really) public pure returns (uint out) { + if (_really) + out = _in; } } @@ -640,9 +715,9 @@ externally visible functions differ by their Solidity types but not by their ext :: - // This will not compile - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; + // This will not compile contract A { function f(B _in) public pure returns (B out) { out = _in; @@ -673,7 +748,7 @@ candidate, resolution fails. :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract A { function f(uint8 _in) public pure returns (uint8 out) { @@ -697,47 +772,64 @@ converted to ``uint8``. Events ****** -Events allow the convenient usage of the EVM logging facilities, -which in turn can be used to "call" JavaScript callbacks in the user interface -of a dapp, which listen for these events. +Solidity events give an abstraction on top of the EVM's logging functionality. +Applications can subscribe and listen to these events through the RPC interface of an Ethereum client. -Events are -inheritable members of contracts. When they are called, they cause the +Events are inheritable members of contracts. When you call them, they cause the arguments to be stored in the transaction's log - a special data structure -in the blockchain. These logs are associated with the address of -the contract and will be incorporated into the blockchain -and stay there as long as a block is accessible (forever as of -Frontier and Homestead, but this might change with Serenity). Log and -event data is not accessible from within contracts (not even from -the contract that created them). +in the blockchain. These logs are associated with the address of the contract, +are incorporated into the blockchain, and stay there as long as a block is +accessible (forever as of the Frontier and Homestead releases, but this might +change with Serenity). The Log and its event data is not accessible from within +contracts (not even from the contract that created them). -SPV proofs for logs are possible, so if an external entity supplies -a contract with such a proof, it can check that the log actually -exists inside the blockchain. But be aware that block headers have to be supplied because -the contract can only see the last 256 block hashes. +It is possible to request a simple payment verification (SPV) for logs, so if +an external entity supplies a contract with such a verification, it can check +that the log actually exists inside the blockchain. You have to supply block headers +because the contract can only see the last 256 block hashes. -Up to three parameters can -receive the attribute ``indexed`` which will cause the respective arguments -to be searched for: It is possible to filter for specific values of -indexed arguments in the user interface. +You can add the attribute ``indexed`` to up to three parameters which adds them +to a special data structure known as :ref:`"topics" ` instead of +the data part of the log. If you use arrays (including ``string`` and ``bytes``) +as indexed arguments, its Keccak-256 hash is stored as a topic instead, this is +because a topic can only hold a single word (32 bytes). -If arrays (including ``string`` and ``bytes``) are used as indexed arguments, the -Keccak-256 hash of it is stored as topic instead. +All parameters without the ``indexed`` attribute are :ref:`ABI-encoded ` +into the data part of the log. -The hash of the signature of the event is one of the topics except if you -declared the event with ``anonymous`` specifier. This means that it is +Topics allow you to search for events, for example when filtering a sequence of +blocks for certain events. You can also filter events by the address of the +contract that emitted the event. + +For example, the code below uses the web3.js ``subscribe("logs")`` +`method `_ to filter +logs that match a topic with a certain address value: + +.. code-block:: javascript + + var options = { + fromBlock: 0, + address: web3.eth.defaultAccount, + topics: ["0x0000000000000000000000000000000000000000000000000000000000000000", null, null] + }; + web3.eth.subscribe('logs', options, function (error, result) { + if (!error) + console.log(result); + }) + .on("data", function (log) { + console.log(log); + }) + .on("changed", function (log) { + }); + + +The hash of the signature of the event is one of the topics, except if you +declared the event with the ``anonymous`` specifier. This means that it is not possible to filter for specific anonymous events by name. -All non-indexed arguments will be stored in the data part of the log. - -.. note:: - Indexed arguments will not be stored themselves. You can only - search for the values, but it is impossible to retrieve the - values themselves. - :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.21 <0.6.0; contract ClientReceipt { event Deposit( @@ -756,7 +848,7 @@ All non-indexed arguments will be stored in the data part of the log. } } -The use in the JavaScript API would be as follows: +The use in the JavaScript API is as follows: :: @@ -768,19 +860,35 @@ The use in the JavaScript API would be as follows: // watch for changes event.watch(function(error, result){ - // result will contain various information - // including the argumets given to the `Deposit` - // call. + // result contains non-indexed arguments and topics + // given to the `Deposit` call. if (!error) console.log(result); }); + // Or pass a callback to start watching immediately var event = clientReceipt.Deposit(function(error, result) { if (!error) console.log(result); }); +The output of the above looks like the following (trimmed): + +.. code-block:: json + + { + "returnValues": { + "_from": "0x1111…FFFFCCCC", + "_id": "0x50…sd5adb20", + "_value": "0x420042" + }, + "raw": { + "data": "0x7f…91385", + "topics": ["0xfd4…b4ead7", "0x7f…1a91385"] + } + } + .. index:: ! log Low-Level Interface to Logs @@ -794,16 +902,16 @@ as topics. The event call above can be performed in the same way as :: - pragma solidity ^0.4.10; + pragma solidity >=0.4.10 <0.6.0; contract C { function f() public payable { - bytes32 _id = 0x420042; + uint256 _id = 0x420042; log3( bytes32(msg.value), bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), - bytes32(msg.sender), - _id + bytes32(uint256(msg.sender)), + bytes32(_id) ); } } @@ -829,23 +937,24 @@ Solidity supports multiple inheritance by copying code including polymorphism. All function calls are virtual, which means that the most derived function is called, except when the contract name is explicitly given. -When a contract inherits from multiple contracts, only a single +When a contract inherits from other contracts, only a single contract is created on the blockchain, and the code from all the base contracts is copied into the created contract. The general inheritance system is very similar to `Python's `_, -especially concerning multiple inheritance. +especially concerning multiple inheritance, but there are also +some :ref:`differences `. Details are given in the following example. :: - pragma solidity ^0.4.22; + pragma solidity >0.4.99 <0.6.0; contract owned { - constructor() { owner = msg.sender; } - address owner; + constructor() public { owner = msg.sender; } + address payable owner; } // Use `is` to derive from another contract. Derived @@ -853,7 +962,7 @@ Details are given in the following example. // internal functions and state variables. These cannot be // accessed externally via `this`, though. contract mortal is owned { - function kill() { + function kill() public { if (msg.sender == owner) selfdestruct(owner); } } @@ -875,7 +984,7 @@ Details are given in the following example. // also a base class of `mortal`, yet there is only a single // instance of `owned` (as for virtual inheritance in C++). contract named is owned, mortal { - constructor(bytes32 name) { + constructor(bytes32 name) public { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).register(name); } @@ -913,11 +1022,11 @@ Note that above, we call ``mortal.kill()`` to "forward" the destruction request. The way this is done is problematic, as seen in the following example:: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract owned { constructor() public { owner = msg.sender; } - address owner; + address payable owner; } contract mortal is owned { @@ -942,11 +1051,11 @@ derived override, but this function will bypass ``Base1.kill``, basically because it does not even know about ``Base1``. The way around this is to use ``super``:: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract owned { constructor() public { owner = msg.sender; } - address owner; + address payable owner; } contract mortal is owned { @@ -980,16 +1089,33 @@ virtual method lookup. .. index:: ! constructor +.. _constructor: + Constructors ============ -A constructor is an optional function declared with the ``constructor`` keyword which is executed upon contract creation. -Constructor functions can be either ``public`` or ``internal``. If there is no constructor, the contract will assume the -default constructor: ``contructor() public {}``. +A constructor is an optional function declared with the ``constructor`` keyword +which is executed upon contract creation, and where you can run contract +initialisation code. + +Before the constructor code is executed, state variables are initialised to +their specified value if you initialise them inline, or zero if you do not. + +After the constructor has run, the final code of the contract is deployed +to the blockchain. The deployment of +the code costs additional gas linear to the length of the code. +This code includes all functions that are part of the public interface +and all functions that are reachable from there through function calls. +It does not include the constructor code or internal functions that are +only called from the constructor. + +Constructor functions can be either ``public`` or ``internal``. If there is no +constructor, the contract will assume the default constructor, which is +equivalent to ``constructor() public {}``. For example: :: - pragma solidity ^0.4.22; + pragma solidity >0.4.99 <0.6.0; contract A { uint public a; @@ -1005,24 +1131,9 @@ default constructor: ``contructor() public {}``. A constructor set as ``internal`` causes the contract to be marked as :ref:`abstract `. -.. note :: - Prior to version 0.4.22, constructors were defined as functions with the same name as the contract. This syntax is now deprecated. - -:: - - pragma solidity ^0.4.11; - - contract A { - uint public a; - - function A(uint _a) internal { - a = _a; - } - } - - contract B is A(1) { - function B() public {} - } +.. warning :: + Prior to version 0.4.22, constructors were defined as functions with the same name as the contract. + This syntax was deprecated and is not allowed anymore in version 0.5.0. .. index:: ! base;constructor @@ -1034,61 +1145,70 @@ The constructors of all the base contracts will be called following the linearization rules explained below. If the base constructors have arguments, derived contracts need to specify all of them. This can be done in two ways:: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract Base { uint x; constructor(uint _x) public { x = _x; } } + // Either directly specify in the inheritance list... contract Derived1 is Base(7) { - constructor(uint _y) public {} + constructor() public {} } + // or through a "modifier" of the derived constructor. contract Derived2 is Base { constructor(uint _y) Base(_y * _y) public {} } One way is directly in the inheritance list (``is Base(7)``). The other is in -the way a modifier would be invoked as part of the header of +the way a modifier is invoked as part of the derived constructor (``Base(_y * _y)``). The first way to do it is more convenient if the constructor argument is a constant and defines the behaviour of the contract or describes it. The second way has to be used if the constructor arguments of the base depend on those of the derived contract. Arguments have to be given either in the -inheritance list or in modifier-style in the derived constuctor. +inheritance list or in modifier-style in the derived constructor. Specifying arguments in both places is an error. -If a derived contract doesn't specify the arguments to all of its base +If a derived contract does not specify the arguments to all of its base contracts' constructors, it will be abstract. .. index:: ! inheritance;multiple, ! linearization, ! C3 linearization +.. _multi-inheritance: + Multiple Inheritance and Linearization ====================================== Languages that allow multiple inheritance have to deal with several problems. One is the `Diamond Problem `_. Solidity is similar to Python in that it uses "`C3 Linearization `_" -to force a specific order in the DAG of base classes. This +to force a specific order in the directed acyclic graph (DAG) of base classes. This results in the desirable property of monotonicity but disallows some inheritance graphs. Especially, the order in which the base classes are given in the ``is`` directive is important: You have to list the direct base contracts in the order from "most base-like" to "most derived". -Note that this order is different from the one used in Python. +Note that this order is the reverse of the one used in Python. + +Another simplifying way to explain this is that when a function is called that +is defined multiple times in different contracts, the given bases +are searched from right to left (left to right in Python) in a depth-first manner, +stopping at the first match. If a base contract has already been searched, it is skipped. + In the following code, Solidity will give the error "Linearization of inheritance graph impossible". :: - // This will not compile - - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract X {} contract A is X {} + // This will not compile contract C is A, X {} The reason for this is that ``C`` requests ``X`` to override ``A`` @@ -1096,6 +1216,8 @@ The reason for this is that ``C`` requests ``X`` to override ``A`` requests to override ``X``, which is a contradiction that cannot be resolved. + + Inheriting Different Kinds of Members of the Same Name ====================================================== @@ -1113,7 +1235,7 @@ Abstract Contracts Contracts are marked as abstract when at least one of their functions lacks an implementation as in the following example (note that the function declaration header is terminated by ``;``):: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract Feline { function utterance() public returns (bytes32); @@ -1121,7 +1243,7 @@ Contracts are marked as abstract when at least one of their functions lacks an i Such contracts cannot be compiled (even if they contain implemented functions alongside non-implemented functions), but they can be used as base contracts:: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract Feline { function utterance() public returns (bytes32); @@ -1150,42 +1272,48 @@ Abstract contracts are useful in the same way that defining methods in an interf .. index:: ! contract;interface, ! interface contract +.. _interfaces: + ********** Interfaces ********** Interfaces are similar to abstract contracts, but they cannot have any functions implemented. There are further restrictions: -#. Cannot inherit other contracts or interfaces. -#. Cannot define constructor. -#. Cannot define variables. -#. Cannot define structs. -#. Cannot define enums. +- They cannot inherit other contracts or interfaces. +- All declared functions must be external. +- They cannot declare a constructor. +- They cannot declare state variables. Some of these restrictions might be lifted in the future. Interfaces are basically limited to what the Contract ABI can represent, and the conversion between the ABI and -an Interface should be possible without any information loss. +an interface should be possible without any information loss. Interfaces are denoted by their own keyword: :: - pragma solidity ^0.4.11; + pragma solidity >=0.4.11 <0.6.0; interface Token { - function transfer(address recipient, uint amount) public; + enum TokenType { Fungible, NonFungible } + struct Coin { string obverse; string reverse; } + function transfer(address recipient, uint amount) external; } 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``. + .. index:: ! library, callcode, delegatecall .. _libraries: -************ +********* Libraries -************ +********* Libraries are similar to contracts, but their purpose is that they are deployed only once at a specific address and their code is reused using the ``DELEGATECALL`` @@ -1199,7 +1327,14 @@ would have no way to name them, otherwise). Library functions can only be called directly (i.e. without the use of ``DELEGATECALL``) if they do not modify the state (i.e. if they are ``view`` or ``pure`` functions), because libraries are assumed to be stateless. In particular, it is -not possible to destroy a library unless Solidity's type system is circumvented. +not possible to destroy a library. + +.. note:: + Until version 0.4.20, it was possible to destroy libraries by + circumventing Solidity's type system. Starting from that version, + libraries contain a :ref:`mechanism` that + disallows state-modifying functions + to be called directly (i.e. without ``DELEGATECALL``). Libraries can be seen as implicit base contracts of the contracts that use them. They will not be explicitly visible in the inheritance hierarchy, but calls @@ -1208,20 +1343,20 @@ contracts (``L.f()`` if ``L`` is the name of the library). Furthermore, ``internal`` functions of libraries are visible in all contracts, just as if the library were a base contract. Of course, calls to internal functions use the internal calling convention, which means that all internal types -can be passed and memory types will be passed by reference and not copied. +can be passed and types :ref:`stored in memory ` will be passed by reference and not copied. To realize this in the EVM, code of internal library functions and all functions called from therein will at compile time be pulled into the calling contract, and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``. .. index:: using for, set -The following example illustrates how to use libraries (but +The following example illustrates how to use libraries (but manual method be sure to check out :ref:`using for ` for a more advanced example to implement a set). :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; library Set { // We define a new struct datatype that will be used to @@ -1283,31 +1418,31 @@ parameters and in any position. The calls to ``Set.contains``, ``Set.insert`` and ``Set.remove`` are all compiled as calls (``DELEGATECALL``) to an external -contract/library. If you use libraries, take care that an +contract/library. If you use libraries, be aware that an actual external function call is performed. ``msg.sender``, ``msg.value`` and ``this`` will retain their values in this call, though (prior to Homestead, because of the use of ``CALLCODE``, ``msg.sender`` and ``msg.value`` changed, though). -The following example shows how to use memory types and +The following example shows how to use :ref:`types stored in memory ` and internal functions in libraries in order to implement custom types without the overhead of external function calls: :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; library BigInt { struct bigint { uint[] limbs; } - function fromUint(uint x) internal pure returns (bigint r) { + function fromUint(uint x) internal pure returns (bigint memory r) { r.limbs = new uint[](1); r.limbs[0] = x; } - function add(bigint _a, bigint _b) internal pure returns (bigint r) { + function add(bigint memory _a, bigint memory _b) internal pure returns (bigint memory r) { r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length)); uint carry = 0; for (uint i = 0; i < r.limbs.length; ++i) { @@ -1322,6 +1457,7 @@ custom types without the overhead of external function calls: if (carry > 0) { // too bad, we have to add a limb uint[] memory newLimbs = new uint[](r.limbs.length + 1); + uint i; for (i = 0; i < r.limbs.length; ++i) newLimbs[i] = r.limbs[i]; newLimbs[i] = carry; @@ -1329,7 +1465,7 @@ custom types without the overhead of external function calls: } } - function limb(bigint _a, uint _limb) internal pure returns (uint) { + function limb(bigint memory _a, uint _limb) internal pure returns (uint) { return _limb < _a.limbs.length ? _a.limbs[_limb] : 0; } @@ -1342,9 +1478,10 @@ custom types without the overhead of external function calls: using BigInt for BigInt.bigint; function f() public pure { - var x = BigInt.fromUint(7); - var y = BigInt.fromUint(uint(-1)); - var z = x.add(y); + BigInt.bigint memory x = BigInt.fromUint(7); + BigInt.bigint memory y = BigInt.fromUint(uint(-1)); + BigInt.bigint memory z = x.add(y); + assert(z.limb(1) > 0); } } @@ -1359,6 +1496,14 @@ will contain placeholders of the form ``__Set______`` (where manually by replacing all those 40 symbols by the hex encoding of the address of the library contract. +.. note:: + Manually linking libraries on the generated bytecode is discouraged, because + it is restricted to 36 characters. + You should ask the compiler to link the libraries at the time + a contract is compiled by either using + the ``--libraries`` option of ``solc`` or the ``libraries`` key if you use + the standard-JSON interface to the compiler. + Restrictions for libraries in comparison to contracts: - No state variables @@ -1367,6 +1512,8 @@ Restrictions for libraries in comparison to contracts: (These might be lifted at a later point.) +.. _call-protection: + Call Protection For Libraries ============================= @@ -1402,28 +1549,29 @@ Using For The directive ``using A for B;`` can be used to attach library functions (from the library ``A``) to any type (``B``). These functions will receive the object they are called on -as their first parameter (like the ``self`` variable in -Python). +as their first parameter (like the ``self`` variable in Python). The effect of ``using A for *;`` is that the functions from -the library ``A`` are attached to any type. +the library ``A`` are attached to *any* type. -In both situations, all functions, even those where the -type of the first parameter does not match the type of -the object, are attached. The type is checked at the +In both situations, *all* functions in the library are attached, +even those where the type of the first parameter does not +match the type of the object. The type is checked at the point the function is called and function overload resolution is performed. -The ``using A for B;`` directive is active for the current -scope, which is limited to a contract for now but will -be lifted to the global scope later, so that by including -a module, its data types including library functions are +The ``using A for B;`` directive is active only within the current +contract, including within all of its functions, and has no effect +outside of the contract in which it is used. The directive +may only be used inside a contract, not inside any of its functions. + +By including a library, its data types including library functions are available without having to add further code. Let us rewrite the set example from the :ref:`libraries` in this way:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; // This is the same code as before, just without comments library Set { @@ -1473,7 +1621,7 @@ Let us rewrite the set example from the It is also possible to extend elementary types in that way:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; library Search { function indexOf(uint[] storage self, uint value) diff --git a/docs/contributing.rst b/docs/contributing.rst index 6717a8b92..11f952069 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -16,9 +16,11 @@ In particular, we need help in the following areas: `_ * Fixing and responding to `Solidity's GitHub issues `_, especially those tagged as - `up-for-grabs `_ which are + `good first issue `_ which are meant as introductory issues for external contributors. +Please note that this project is released with a `Contributor Code of Conduct `_. By participating in this project - in the issues, pull requests, or Gitter channels - you agree to abide by its terms. + How to Report Issues ==================== @@ -45,15 +47,18 @@ in addition to *what* you did (unless it is a tiny change). If you need to pull in any changes from ``develop`` after making your fork (for example, to resolve potential merge conflicts), please avoid using ``git merge`` -and instead, ``git rebase`` your branch. +and instead, ``git rebase`` your branch. This will help us review your change +more easily. -Additionally, if you are writing a new feature, please ensure you write appropriate -Boost test cases and place them under ``test/``. +Additionally, if you are writing a new feature, please ensure you add appropriate +test cases under ``test/`` (see below). However, if you are making a larger change, please consult with the `Solidity Development Gitter channel -`_ (different from the one mentioned above, this on is +`_ (different from the one mentioned above, this one is focused on compiler and language development instead of language use) first. +New features and bugfixes should be added to the ``Changelog.md`` file: please +follow the style of previous entries, when applicable. Finally, please make sure you respect the `coding style `_ @@ -65,36 +70,52 @@ Thank you for your help! Running the compiler tests ========================== -Solidity includes different types of tests. They are included in the application -called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode, +There is a script at ``scripts/tests.sh`` which executes most of the tests and +runs ``aleth`` automatically if it is in the path, but does not download it, +so it most likely will not work right away. Please read on for the details. + +Solidity includes different types of tests. Most of them are bundled in the application +called ``soltest``. Some of them require the ``aleth`` client in testing mode, some others require ``libz3`` to be installed. -``soltest`` reads test contracts that are annotated with expected results -stored in ``./test/libsolidity/syntaxTests``. In order for soltest to find these -tests the root test directory has to be specified using the ``--testpath`` command -line option, e.g. ``./build/test/soltest -- --testpath ./test``. +To run a basic set of tests that neither require ``aleth`` nor ``libz3``, run +``./scripts/soltest.sh --no-ipc --no-smt``. This script will run ``build/test/soltest`` +internally. -To disable the z3 tests, use ``./build/test/soltest -- --no-smt --testpath ./test`` and -to run a subset of the tests that do not require ``cpp-ethereum``, use -``./build/test/soltest -- --no-ipc --testpath ./test``. +.. note :: -For all other tests, you need to install `cpp-ethereum `_ and run it in testing mode: ``eth --test -d /tmp/testeth``. + Those working in a Windows environment wanting to run the above basic sets without aleth or libz3 in Git Bash, you would have to do: ``./build/test/RelWithDebInfo/soltest.exe -- --no-ipc --no-smt``. + If you're running this in plain Command Prompt, use ``.\build\test\RelWithDebInfo\soltest.exe -- --no-ipc --no-smt``. -Then you run the actual tests: ``./build/test/soltest -- --ipcpath /tmp/testeth/geth.ipc --testpath ./test``. +The option ``--no-smt`` disables the tests that require ``libz3`` and +``--no-ipc`` disables those that require ``aleth``. + +If you want to run the ipc tests (those test the semantics of the generated code), +you need to install `aleth `_ and run it in testing mode: ``aleth --test -d /tmp/testeth`` (make sure to rename it). + +Then you run the actual tests: ``./scripts/soltest.sh --ipcpath /tmp/testeth/geth.ipc``. To run a subset of tests, filters can be used: -``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc --testpath ./test``, +``./scripts/soltest.sh -t TestSuite/TestName --ipcpath /tmp/testeth/geth.ipc``, where ``TestName`` can be a wildcard ``*``. -Alternatively, there is a testing script at ``scripts/test.sh`` which executes all tests and runs -``cpp-ethereum`` automatically if it is in the path (but does not download it). +The script ``scripts/tests.sh`` also runs commandline tests and compilation tests +in addition to those found in ``soltest``. -Travis CI even runs some additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target. +The CI even runs some additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target. + +.. note :: + + Some versions of ``aleth`` cannot be used for testing. We suggest using the same version that is used by the Solidity continuous integration tests. + Currently the CI uses ``d661ac4fec0aeffbedcdc195f67f5ded0c798278`` of ``aleth``. Writing and running syntax tests -------------------------------- -As mentioned above, syntax tests are stored in individual contracts. These files must contain annotations, stating the expected result(s) of the respective test. +Syntax tests check that the compiler generates the correct error messages for invalid code +and properly accepts valid code. +They are stored in individual files inside ``tests/libsolidity/syntaxTests``. +These files must contain annotations, stating the expected result(s) of the respective test. The test suite will compile and check them against the given expectations. Example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol`` @@ -106,15 +127,17 @@ Example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol`` uint128 variable; } // ---- - // DeclarationError: Identifier already declared. + // DeclarationError: (36-52): Identifier already declared. -A syntax test must contain at least the contract under test itself, followed by the seperator ``----``. The additional comments above are used to describe the -expected compiler errors or warnings. This section can be empty in case that the contract should compile without any errors or warnings. +A syntax test must contain at least the contract under test itself, followed by the separator ``// ----``. The following comments are used to describe the +expected compiler errors or warnings. The number range denotes the location in the source where the error occurred. +In case the contract should compile without any errors or warning, the section after the separator has to be empty +and the separator can be left out completely. -In the above example, the state variable ``variable`` was declared twice, which is not allowed. This will result in a ``DeclarationError`` stating that the identifer was already declared. +In the above example, the state variable ``variable`` was declared twice, which is not allowed. This will result in a ``DeclarationError`` stating that the identifier was already declared. The tool that is being used for those tests is called ``isoltest`` and can be found under ``./test/tools/``. It is an interactive tool which allows -editing of failing contracts using your prefered text editor. Let's try to break this test by removing the second declaration of ``variable``: +editing of failing contracts using your preferred text editor. Let's try to break this test by removing the second declaration of ``variable``: :: @@ -122,7 +145,7 @@ editing of failing contracts using your prefered text editor. Let's try to break uint256 variable; } // ---- - // DeclarationError: Identifier already declared. + // DeclarationError: (36-52): Identifier already declared. Running ``./test/isoltest`` again will result in a test failure: @@ -135,16 +158,16 @@ Running ``./test/isoltest`` again will result in a test failure: } Expected result: - DeclarationError: Identifier already declared. + DeclarationError: (36-52): Identifier already declared. Obtained result: Success -which prints the expected result next to the obtained result, but also provides a way to change edit / update / skip the current contract or to even quit. -``isoltest`` offers several options for failing tests: +``isoltest`` prints the expected result next to the obtained result, but also provides a way to change edit / update / skip the current contract or to even quit. +It offers several options for failing tests: -- edit: ``isoltest`` will try to open the editor that was specified before using ``isoltest --editor /path/to/editor``. If no path was set, this will result in a runtime error. In case an editor was specified, this will open it such that the contract can be adjusted. -- update: Updates the contract under test. This will either remove the annotation which contains the exception not met or will add missing expectations. The test will then be run again. +- edit: ``isoltest`` tries to open the contract in an editor so you can adjust it. It either uses the editor given on the command line (as ``isoltest --editor /path/to/editor``), in the environment variable ``EDITOR`` or just ``/usr/bin/editor`` (in this order). +- update: Updates the contract under test. This either removes the annotation which contains the exception not met or adds missing expectations. The test will then be run again. - skip: Skips the execution of this particular test. - quit: Quits ``isoltest``. @@ -167,22 +190,23 @@ and re-run the test. It will now pass again: .. note:: - Please choose a name for the contract file, that is self-explainatory in the sense of what is been tested, e.g. ``double_variable_declaration.sol``. - Do not put more than one contract into a single file. ``isoltest`` is currently not able to recognize them individually. + Please choose a name for the contract file that explains what it tests, e.g. ``double_variable_declaration.sol``. + Do not put more than one contract into a single file, unless you are testing inheritance or cross-contract calls. + Each file should test one aspect of your new feature. Running the Fuzzer via AFL ========================== Fuzzing is a technique that runs programs on more or less random inputs to find exceptional execution -states (segmentation faults, exceptions, etc). Modern fuzzers are clever and do a directed search +states (segmentation faults, exceptions, etc). Modern fuzzers are clever and run a directed search inside the input. We have a specialized binary called ``solfuzzer`` which takes source code as input and fails whenever it encounters an internal compiler error, segmentation fault or similar, but -does not fail if e.g. the code contains an error. This way, internal problems in the compiler -can be found by fuzzing tools. +does not fail if e.g., the code contains an error. This way, fuzzing tools can find internal problems in the compiler. We mainly use `AFL `_ for fuzzing. You need to download and -build AFL manually. Next, build Solidity (or just the ``solfuzzer`` binary) with AFL as your compiler: +install the AFL packages from your repositories (afl, afl-clang) or build them manually. +Next, build Solidity (or just the ``solfuzzer`` binary) with AFL as your compiler: :: @@ -192,7 +216,49 @@ build AFL manually. Next, build Solidity (or just the ``solfuzzer`` binary) with cmake .. -DCMAKE_C_COMPILER=path/to/afl-gcc -DCMAKE_CXX_COMPILER=path/to/afl-g++ make solfuzzer -Next, you need some example source files. This will make it much easer for the fuzzer +At this stage you should be able to see a message similar to the following: + +:: + + Scanning dependencies of target solfuzzer + [ 98%] Building CXX object test/tools/CMakeFiles/solfuzzer.dir/fuzzer.cpp.o + afl-cc 2.52b by + afl-as 2.52b by + [+] Instrumented 1949 locations (64-bit, non-hardened mode, ratio 100%). + [100%] Linking CXX executable solfuzzer + +If the instrumentation messages did not appear, try switching the cmake flags pointing to AFL's clang binaries: + +:: + + # if previously failed + make clean + cmake .. -DCMAKE_C_COMPILER=path/to/afl-clang -DCMAKE_CXX_COMPILER=path/to/afl-clang++ + make solfuzzer + +Otherwise, upon execution the fuzzer halts with an error saying binary is not instrumented: + +:: + + afl-fuzz 2.52b by + ... (truncated messages) + [*] Validating target binary... + + [-] Looks like the target binary is not instrumented! The fuzzer depends on + compile-time instrumentation to isolate interesting test cases while + mutating the input data. For more information, and for tips on how to + instrument binaries, please see /usr/share/doc/afl-doc/docs/README. + + When source code is not available, you may be able to leverage QEMU + mode support. Consult the README for tips on how to enable this. + (It is also possible to use afl-fuzz as a traditional, "dumb" fuzzer. + For that, you can use the -n option - but expect much worse results.) + + [-] PROGRAM ABORT : No instrumentation detected + Location : check_binary(), afl-fuzz.c:6920 + + +Next, you need some example source files. This makes it much easier for the fuzzer to find errors. You can either copy some files from the syntax tests or extract test files from the documentation or the other tests: @@ -207,8 +273,8 @@ from the documentation or the other tests: The AFL documentation states that the corpus (the initial input files) should not be too large. The files themselves should not be larger than 1 kB and there should be -at most one input file per functionality, so better start with a small number of -input files. There is also a tool called ``afl-cmin`` that can trim input files +at most one input file per functionality, so better start with a small number of. +There is also a tool called ``afl-cmin`` that can trim input files that result in similar behaviour of the binary. Now run the fuzzer (the ``-m`` extends the size of memory to 60 MB): @@ -217,20 +283,20 @@ Now run the fuzzer (the ``-m`` extends the size of memory to 60 MB): afl-fuzz -m 60 -i /tmp/test_cases -o /tmp/fuzzer_reports -- /path/to/solfuzzer -The fuzzer will create source files that lead to failures in ``/tmp/fuzzer_reports``. +The fuzzer creates source files that lead to failures in ``/tmp/fuzzer_reports``. Often it finds many similar source files that produce the same error. You can use the tool ``scripts/uniqueErrors.sh`` to filter out the unique errors. Whiskers ======== -*Whiskers* is a templating system similar to `Mustache `_. It is used by the +*Whiskers* is a string templating system similar to `Mustache `_. It is used by the compiler in various places to aid readability, and thus maintainability and verifiability, of the code. -The syntax comes with a substantial difference to Mustache: the template markers ``{{`` and ``}}`` are +The syntax comes with a substantial difference to Mustache. The template markers ``{{`` and ``}}`` are replaced by ``<`` and ``>`` in order to aid parsing and avoid conflicts with :ref:`inline-assembly` (The symbols ``<`` and ``>`` are invalid in inline assembly, while ``{`` and ``}`` are used to delimit blocks). -Another limitation is that lists are only resolved one depth and they will not recurse. This may change in the future. +Another limitation is that lists are only resolved one depth and they do not recurse. This may change in the future. A rough specification is the following: diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 7849d15af..5e3b722bb 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -2,7 +2,7 @@ Expressions and Control Structures ################################## -.. index:: ! parameter, parameter;input, parameter;output +.. index:: ! parameter, parameter;input, parameter;output, parameter;multiple Input Parameters and Output Parameters ====================================== @@ -14,20 +14,26 @@ parameters as output. Input Parameters ---------------- -The input parameters are declared the same way as variables are. As an -exception, unused parameters can omit the variable name. +The input parameters are declared the same way as variables are. +The name of unused parameters can be omitted. For example, suppose we want our contract to accept one kind of external calls with two integers, we would write something like:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract Simple { - function taker(uint _a, uint _b) public pure { - // do something with _a and _b. + uint sum; + function taker(uint _a, uint _b) public { + sum = _a + _b; } } +Input parameters can be used just as any other local variable +can be used, they can also be assigned to. + +.. index:: return array, return string, array, string, array of strings, dynamic array, variably sized array, return struct, struct + Output Parameters ----------------- @@ -36,10 +42,10 @@ The output parameters can be declared with the same syntax after the the sum and the product of the two given integers, then we would write:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract Simple { - function arithmetics(uint _a, uint _b) + function arithmetic(uint _a, uint _b) public pure returns (uint o_sum, uint o_product) @@ -50,24 +56,29 @@ write:: } The names of output parameters can be omitted. -The output values can also be specified using ``return`` statements. -The ``return`` statements are also capable of returning multiple -values, see :ref:`multi-return`. -Return parameters are initialized to zero; if they are not explicitly -set, they stay to be zero. +The return values can be specified using ``return`` statements, +which are also capable of :ref:`returning multiple values`. +Return parameters can be used as any other local variable and they +are zero-initialized; if they are not explicitly +set, they stay zero. -Input parameters and output parameters can be used as expressions in -the function body. There, they are also usable in the left-hand side -of assignment. + +.. note:: + You cannot return some types from non-internal functions, notably + multi-dimensional dynamic arrays and structs. If you enable the + new experimental ``ABIEncoderV2`` feature by adding ``pragma experimental + ABIEncoderV2;`` to your source file then more types are available, but + ``mapping`` types are still limited to inside a single contract and you + cannot transfer them. .. index:: if, else, while, do/while, for, break, continue, return, switch, goto Control Structures =================== -Most of the control structures from JavaScript are available in Solidity -except for ``switch`` and ``goto``. So -there is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, ``? :``, with +Most of the control structures known from curly-braces languages are available in Solidity: + +There is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, with the usual semantics known from C or JavaScript. Parentheses can *not* be omitted for conditionals, but curly brances can be omitted @@ -99,10 +110,10 @@ Internal Function Calls Functions of the current contract can be called directly ("internally"), also recursively, as seen in this nonsensical example:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { - function g(uint a) public pure returns (uint ret) { return f(); } + function g(uint a) public pure returns (uint ret) { return a + f(); } function f() internal pure returns (uint ret) { return g(7) + f(); } } @@ -111,22 +122,31 @@ the effect that the current memory is not cleared, i.e. passing memory reference to internally-called functions is very efficient. Only functions of the same contract can be called internally. +You should still avoid excessive recursion, as every internal function call +uses up at least one stack slot and there are at most 1024 slots available. + External Function Calls ----------------------- The expressions ``this.g(8);`` and ``c.g(2);`` (where ``c`` is a contract instance) are also valid function calls, but this time, the function will be called "externally", via a message call and not directly via jumps. -Please note that function calls on ``this`` cannot be used in the constructor, as the -actual contract has not been created yet. +Please note that function calls on ``this`` cannot be used in the constructor, +as the actual contract has not been created yet. Functions of other contracts have to be called externally. For an external call, all function arguments have to be copied to memory. -When calling functions of other contracts, the amount of Wei sent with the call and -the gas can be specified with special options ``.value()`` and ``.gas()``, respectively:: +.. note:: + A function call from one contract to another does not create its own transaction, + it is a message call as part of the overall transaction. - pragma solidity ^0.4.0; +When calling functions of other contracts, you can specify the amount of Wei or gas sent with the call with the special options ``.value()`` and ``.gas()``, respectively. Any Wei you send to the contract is added to the total balance of the contract: + + +:: + + pragma solidity >=0.4.0 <0.6.0; contract InfoFeed { function info() public payable returns (uint ret) { return 42; } @@ -134,23 +154,15 @@ the gas can be specified with special options ``.value()`` and ``.gas()``, respe contract Consumer { InfoFeed feed; - function setFeed(address addr) public { feed = InfoFeed(addr); } + function setFeed(InfoFeed addr) public { feed = addr; } function callFeed() public { feed.info.value(10).gas(800)(); } } -The modifier ``payable`` has to be used for ``info``, because otherwise, the `.value()` -option would not be available. +You need to use the modifier ``payable`` with the ``info`` function because +otherwise, the ``.value()`` option would not be available. -Note that the expression ``InfoFeed(addr)`` performs an explicit type conversion stating -that "we know that the type of the contract at the given address is ``InfoFeed``" and -this does not execute a constructor. Explicit type conversions have to be -handled with extreme caution. Never call a function on a contract where you -are not sure about its type. - -We could also have used ``function setFeed(InfoFeed _feed) { feed = _feed; }`` directly. -Be careful about the fact that ``feed.info.value(10).gas(800)`` -only (locally) sets the value and amount of gas sent with the function call and only the -parentheses at the end perform the actual call. +.. warning:: + Be careful that ``feed.info.value(10).gas(800)`` only locally sets the ``value`` and amount of ``gas`` sent with the function call, and the parentheses at the end perform the actual call. So in this case, the function is not called. Function calls cause exceptions if the called contract does not exist (in the sense that the account does not contain code) or if the called contract itself @@ -158,8 +170,8 @@ throws an exception or goes out of gas. .. warning:: Any interaction with another contract imposes a potential danger, especially - if the source code of the contract is not known in advance. The current - contract hands over control to the called contract and that may potentially + if the source code of the contract is not known in advance. The + current contract hands over control to the called contract and that may potentially do just about anything. Even if the called contract inherits from a known parent contract, the inheriting contract is only required to have a correct interface. The implementation of the contract, however, can be completely arbitrary and thus, @@ -174,24 +186,26 @@ throws an exception or goes out of gas. Named Calls and Anonymous Function Parameters --------------------------------------------- -Function call arguments can also be given by name, in any order, +Function call arguments can be given by name, in any order, if they are enclosed in ``{ }`` as can be seen in the following example. The argument list has to coincide by name with the list of parameters from the function declaration, but can be in arbitrary order. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { - function f(uint key, uint value) public { - // ... + mapping(uint => uint) data; + + function f() public { + set({value: 2, key: 3}); } - function g() public { - // named arguments - f({value: 2, key: 3}); + function set(uint key, uint value) public { + data[key] = value; } + } Omitted Function Parameter Names @@ -202,7 +216,7 @@ Those parameters will still be present on the stack, but they are inaccessible. :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { // omitted name for parameter @@ -219,17 +233,17 @@ Those parameters will still be present on the stack, but they are inaccessible. Creating Contracts via ``new`` ============================== -A contract can create a new contract using the ``new`` keyword. The full -code of the contract being created has to be known in advance, so recursive -creation-dependencies are not possible. +A contract can create other contracts using the ``new`` keyword. The full +code of the contract being created has to be known when the creating contract +is compiled so recursive creation-dependencies are not possible. :: - pragma solidity ^0.4.0; + pragma solidity >0.4.99 <0.6.0; contract D { - uint x; - function D(uint a) public payable { + uint public x; + constructor(uint a) public payable { x = a; } } @@ -239,15 +253,17 @@ creation-dependencies are not possible. function createD(uint arg) public { D newD = new D(arg); + newD.x(); } function createAndEndowD(uint arg, uint amount) public payable { // Send ether along with the creation D newD = (new D).value(amount)(arg); + newD.x(); } } -As seen in the example, it is possible to forward Ether while creating +As seen in the example, it is possible to send Ether while creating an instance of ``D`` using the ``.value()`` option, but it is not possible to limit the amount of gas. If the creation fails (due to out-of-stack, not enough balance or other problems), @@ -272,12 +288,15 @@ Assignment Destructuring Assignments and Returning Multiple Values ------------------------------------------------------- -Solidity internally allows tuple types, i.e. a list of objects of potentially different types whose size is a constant at compile-time. Those tuples can be used to return multiple values at the same time. -These can then either be assigned to newly declared variables or to pre-existing variables (or LValues in general): +Solidity internally allows tuple types, i.e. a list of objects of potentially different types whose number is a constant at compile-time. Those tuples can be used to return multiple values at the same time. +These can then either be assigned to newly declared variables or to pre-existing variables (or LValues in general). + +Tuples are not proper types in Solidity, they can only be used to form syntactic +groupings of expressions. :: - pragma solidity >0.4.23 <0.5.0; + pragma solidity >0.4.23 <0.6.0; contract C { uint[] data; @@ -287,29 +306,33 @@ These can then either be assigned to newly declared variables or to pre-existing } function g() public { - // Variables declared with type and assigned from the returned tuple. - (uint x, bool b, uint y) = f(); + // Variables declared with type and assigned from the returned tuple, + // not all elements have to be specified (but the number must match). + (uint x, , uint y) = f(); // Common trick to swap values -- does not work for non-value storage types. (x, y) = (y, x); // Components can be left out (also for variable declarations). - (data.length,,) = f(); // Sets the length to 7 - // Components can only be left out at the left-hand-side of assignments, with - // one exception: - (x,) = (1,); - // (1,) is the only way to specify a 1-component tuple, because (1) is - // equivalent to 1. + (data.length, , ) = f(); // Sets the length to 7 } } +It is not possible to mix variable declarations and non-declaration assignments, +i.e. the following is not valid: ``(x, uint y) = (1, 2);`` + .. note:: - Prior to version 0.4.24 it was possible to assign to tuples of smaller size, either + Prior to version 0.5.0 it was possible to assign to tuples of smaller size, either filling up on the left or on the right side (which ever was empty). This is - now deprecated, both sides have to have the same number of components. + now disallowed, so both sides have to have the same number of components. + +.. warning:: + Be careful when assigning to multiple variables at the same time when + reference types are involved, because it could lead to unexpected + copying behaviour. Complications for Arrays and Structs ------------------------------------ -The semantics of assignment are a bit more complicated for non-value types like arrays and structs. +The semantics of assignments are a bit more complicated for non-value types like arrays and structs. Assigning *to* a state variable always creates an independent copy. On the other hand, assigning to a local variable creates an independent copy only for elementary types, i.e. static types that fit into 32 bytes. If structs or arrays (including ``bytes`` and ``string``) are assigned from a state variable to a local variable, the local variable holds a reference to the original state variable. A second assignment to the local variable does not modify the state but only changes the reference. Assignments to members (or elements) of the local variable *do* change the state. .. index:: ! scoping, declarations, default value @@ -325,101 +348,31 @@ is ``false``. The default value for the ``uint`` or ``int`` types is ``0``. For 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. -A variable declared anywhere within a function will be in scope for the *entire function*, regardless of where it is declared -(this will change soon, see below). -This happens because Solidity inherits its scoping rules from JavaScript. -This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block. -As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``: - -:: - - // This will not compile - - pragma solidity ^0.4.16; - - contract ScopingErrors { - function scoping() public { - uint i = 0; - - while (i++ < 1) { - uint same1 = 0; - } - - while (i++ < 2) { - uint same1 = 0;// Illegal, second declaration of same1 - } - } - - function minimalScoping() public { - { - uint same2 = 0; - } - - { - uint same2 = 0;// Illegal, second declaration of same2 - } - } - - function forLoopScoping() public { - for (uint same3 = 0; same3 < 1; same3++) { - } - - for (uint same3 = 0; same3 < 1; same3++) {// Illegal, second declaration of same3 - } - } - } - -In addition to this, if a variable is declared, it will be initialized at the beginning of the function to its default value. -As a result, the following code is legal, despite being poorly written: - -:: - - pragma solidity ^0.4.0; - - contract C { - function foo() public pure returns (uint) { - // baz is implicitly initialized as 0 - uint bar = 5; - if (true) { - bar += baz; - } else { - uint baz = 10;// never executes - } - return bar;// returns 5 - } - } - -Scoping starting from Version 0.5.0 ------------------------------------ - -Starting from version 0.5.0, Solidity will change to the more widespread scoping rules of C99 +Scoping in Solidity follows the widespread scoping rules of C99 (and many other languages): Variables are visible from the point right after their declaration -until the end of a ``{ }``-block. As an exception to this rule, variables declared in the +until the end of the smallest ``{ }``-block that contains the declaration. As an exception to this rule, variables declared in the initialization part of a for-loop are only visible until the end of the for-loop. Variables and other items declared outside of a code block, for example functions, contracts, -user-defined types, etc., do not change their scoping behaviour. This means you can +user-defined types, etc., are visible even before they were declared. This means you can use state variables before they are declared and call functions recursively. -These rules are already introduced now as an experimental feature. - As a consequence, the following examples will compile without warnings, since -the two variables have the same name but disjoint scopes. In non-0.5.0-mode, -they have the same scope (the function ``minimalScoping``) and thus it does -not compile there. +the two variables have the same name but disjoint scopes. :: - pragma solidity ^0.4.0; - pragma experimental "v0.5.0"; + pragma solidity >0.4.99 <0.6.0; contract C { function minimalScoping() pure public { { - uint same2 = 0; + uint same; + same = 1; } { - uint same2 = 0; + uint same; + same = 3; } } } @@ -430,8 +383,8 @@ In any case, you will get a warning about the outer variable being shadowed. :: - pragma solidity ^0.4.0; - pragma experimental "v0.5.0"; + pragma solidity >0.4.99 <0.6.0; + // This will report a warning contract C { function f() pure public returns (uint) { uint x = 1; @@ -443,7 +396,26 @@ In any case, you will get a warning about the outer variable being shadowed. } } -.. index:: ! exception, ! throw, ! assert, ! require, ! revert +.. warning:: + Before version 0.5.0 Solidity followed the same scoping rules as JavaScript, that is, a variable declared anywhere within a function would be in scope + for the entire function, regardless where it was declared. The following example shows a code snippet that used + to compile but leads to an error starting from version 0.5.0. + + :: + + pragma solidity >0.4.99 <0.6.0; + // This will not compile + contract C { + function f() pure public returns (uint) { + x = 2; + uint x; + return x; + } + } + +.. index:: ! exception, ! throw, ! assert, ! require, ! revert, ! errors + +.. _assert-and-require: Error handling: Assert, Require, Revert and Exceptions ====================================================== @@ -458,17 +430,17 @@ If used properly, analysis tools can evaluate your contract to identify the cond 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. -The deprecated keyword ``throw`` can also be used as an alternative to ``revert()`` (but only without error message). .. note:: - From version 0.4.13 the ``throw`` keyword is deprecated and will be phased out in the future. + 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 ``callcode`` -- those return ``false`` in case +and the low-level functions ``call``, ``delegatecall`` and ``staticcall`` -- those return ``false`` as their first return value in case of an exception instead of "bubbling up". .. warning:: - The low-level ``call``, ``delegatecall`` and ``callcode`` will return success 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 called account is non-existent, as part of the design of EVM. Existence must be checked prior to calling if desired. Catching exceptions is not yet possible. @@ -478,18 +450,18 @@ a message string for ``require``, but not for ``assert``. :: - pragma solidity ^0.4.22; + pragma solidity >0.4.99 <0.6.0; contract Sharer { - function sendHalf(address addr) public payable returns (uint balance) { + function sendHalf(address payable addr) public payable returns (uint balance) { require(msg.value % 2 == 0, "Even value required."); - uint balanceBeforeTransfer = this.balance; + uint balanceBeforeTransfer = address(this).balance; addr.transfer(msg.value / 2); // Since transfer throws an exception on failure and // cannot call back here, there should be no way for us to // still have half of the money. - assert(this.balance == balanceBeforeTransfer - msg.value / 2); - return this.balance; + assert(address(this).balance == balanceBeforeTransfer - msg.value / 2); + return address(this).balance; } } @@ -505,9 +477,8 @@ An ``assert``-style exception is generated in the following situations: A ``require``-style exception is generated in the following situations: -#. Calling ``throw``. #. 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`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``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). @@ -525,10 +496,10 @@ The following example shows how an error string can be used together with revert :: - pragma solidity ^0.4.22; + pragma solidity >0.4.99 <0.6.0; contract VendingMachine { - function buy(uint amount) payable { + function buy(uint amount) public payable { if (amount > msg.value / 2 ether) revert("Not enough Ether provided."); // Alternative way to do it: diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index ca5a1aee8..8b655b0d3 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -9,36 +9,11 @@ This list was originally compiled by `fivedogit `_. Basic Questions *************** -Is it possible to do something on a specific block number? (e.g. publish a contract or execute a transaction) -============================================================================================================= - -Transactions are not guaranteed to happen on the next block or any future -specific block, since it is up to the miners to include transactions and not up -to the submitter of the transaction. This applies to function calls/transactions and contract -creation transactions. - -If you want to schedule future calls of your contract, you can use the -`alarm clock `_. - What is the transaction "payload"? ================================== This is just the bytecode "data" sent along with the request. -Is there a decompiler available? -================================ - -There is no exact decompiler to Solidity, but -`Porosity `_ is close. -Because some information like variable names, comments, and -source code formatting is lost in the compilation process, -it is not possible to completely recover the original source code. - -Bytecode can be disassembled to opcodes, a service that is provided by -several blockchain explorers. - -Contracts on the blockchain should have their original source -code published if they are to be used by third parties. Create a contract that can be killed and return funds ===================================================== @@ -63,39 +38,24 @@ has it (which includes `Remix `_), then ``contractname.kill.sendTransaction({from:eth.coinbase})``, just the same as my examples. -Can you return an array or a ``string`` from a solidity function call? -====================================================================== - -Yes. See `array_receiver_and_returner.sol `_. - -What is problematic, though, is returning any variably-sized data (e.g. a -variably-sized array like ``uint[]``) from a fuction **called from within Solidity**. -This is a limitation of the EVM and will be solved with the next protocol update. - -Returning variably-sized data as part of an external transaction or call is fine. - Is it possible to in-line initialize an array like so: ``string[] myarray = ["a", "b"];`` ========================================================================================= Yes. However it should be noted that this currently only works with statically sized memory arrays. You can even create an inline memory -array in the return statement. Pretty cool, huh? +array in the return statement. Example:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { - function f() public pure returns (uint8[5]) { + function f() public pure returns (uint8[5] memory) { string[4] memory adaArr = ["This", "is", "an", "array"]; - return ([1, 2, 3, 4, 5]); + adaArr[0] = "That"; + return [1, 2, 3, 4, 5]; } } -Can a contract function return a ``struct``? -============================================ - -Yes, but only in ``internal`` function calls. - If I return an ``enum``, I only get integer values in web3.js. How to get the named values? =========================================================================================== @@ -111,7 +71,7 @@ should be noted that you must declare them as static memory arrays. Examples:: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { struct S { @@ -133,20 +93,6 @@ How do structs work? See `struct_and_for_loop_tester.sol `_. -How do for loops work? -====================== - -Very similar to JavaScript. There is one point to watch out for, though: - -If you use ``for (var i = 0; i < a.length; i ++) { a[i] = i; }``, then -the type of ``i`` will be inferred only from ``0``, whose type is ``uint8``. -This means that if ``a`` has more than ``255`` elements, your loop will -not terminate because ``i`` can only hold values up to ``255``. - -Better use ``for (uint i = 0; i < a.length...`` - -See `struct_and_for_loop_tester.sol `_. - What are some examples of basic string manipulation (``substring``, ``indexOf``, ``charAt``, etc)? ================================================================================================== @@ -156,7 +102,7 @@ which will be extended in the future. In addition, Arachnid has written `solidit For now, if you want to modify a string (even when you only want to know its length), you should always convert it to a ``bytes`` first:: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { string s; @@ -174,7 +120,17 @@ you should always convert it to a ``bytes`` first:: Can I concatenate two strings? ============================== -You have to do it manually for now. +Yes, you can use ``abi.encodePacked``:: + + pragma solidity >=0.4.0 <0.6.0; + + library ConcatHelper { + function concat(bytes memory a, bytes memory b) + internal pure returns (bytes memory) { + return abi.encodePacked(a, b); + } + } + Why is the low-level function ``.call()`` less favorable than instantiating a contract with a variable (``ContractB b;``) and executing its functions (``b.doSomething();``)? ============================================================================================================================================================================= @@ -187,11 +143,6 @@ arguments for you. See `ping.sol `_ and `pong.sol `_. -Is unused gas automatically refunded? -===================================== - -Yes and it is immediate, i.e. done as part of the transaction. - When returning a value of say ``uint`` type, is it possible to return an ``undefined`` or "null"-like value? ============================================================================================================ @@ -203,7 +154,7 @@ situation. If you do not want to throw, you can return a pair:: - pragma solidity >0.4.23 <0.5.0; + pragma solidity >0.4.23 <0.6.0; contract C { uint[] counters; @@ -221,9 +172,10 @@ If you do not want to throw, you can return a pair:: function checkCounter(uint index) public view { (uint counter, bool error) = getCounter(index); if (error) { - // ... + // Handle the error } else { - // ... + // Do something with counter. + require(counter > 7, "Invalid counter value"); } } } @@ -242,118 +194,6 @@ It gets added to the total balance of the contract, just like when you send ethe You can only send ether along to a function that has the ``payable`` modifier, otherwise an exception is thrown. -Is it possible to get a tx receipt for a transaction executed contract-to-contract? -=================================================================================== - -No, a function call from one contract to another does not create its own transaction, -you have to look in the overall transaction. This is also the reason why several -block explorer do not show Ether sent between contracts correctly. - -What is the ``memory`` keyword? What does it do? -================================================ - -The Ethereum Virtual Machine has three areas where it can store items. - -The first is "storage", where all the contract state variables reside. -Every contract has its own storage and it is persistent between function calls -and quite expensive to use. - -The second is "memory", this is used to hold temporary values. It -is erased between (external) function calls and is cheaper to use. - -The third one is the stack, which is used to hold small local variables. -It is almost free to use, but can only hold a limited amount of values. - -For almost all types, you cannot specify where they should be stored, because -they are copied everytime they are used. - -The types where the so-called storage location is important are structs -and arrays. If you e.g. pass such variables in function calls, their -data is not copied if it can stay in memory or stay in storage. -This means that you can modify their content in the called function -and these modifications will still be visible in the caller. - -There are defaults for the storage location depending on which type -of variable it concerns: - -* state variables are always in storage -* function arguments are in memory by default -* local variables of struct, array or mapping type reference storage by default -* local variables of value type (i.e. neither array, nor struct nor mapping) are stored in the stack - -Example:: - - pragma solidity ^0.4.0; - - contract C { - uint[] data1; - uint[] data2; - - function appendOne() public { - append(data1); - } - - function appendTwo() public { - append(data2); - } - - function append(uint[] storage d) internal { - d.push(1); - } - } - -The function ``append`` can work both on ``data1`` and ``data2`` and its modifications will be -stored permanently. If you remove the ``storage`` keyword, the default -is to use ``memory`` for function arguments. This has the effect that -at the point where ``append(data1)`` or ``append(data2)`` is called, an -independent copy of the state variable is created in memory and -``append`` operates on this copy (which does not support ``.push`` - but that -is another issue). The modifications to this independent copy do not -carry back to ``data1`` or ``data2``. - -A common mistake is to declare a local variable and assume that it will -be created in memory, although it will be created in storage:: - - /// THIS CONTRACT CONTAINS AN ERROR - - pragma solidity ^0.4.0; - - contract C { - uint someVariable; - uint[] data; - - function f() public { - uint[] x; - x.push(2); - data = x; - } - } - -The type of the local variable ``x`` is ``uint[] storage``, but since -storage is not dynamically allocated, it has to be assigned from -a state variable before it can be used. So no space in storage will be -allocated for ``x``, but instead it functions only as an alias for -a pre-existing variable in storage. - -What will happen is that the compiler interprets ``x`` as a storage -pointer and will make it point to the storage slot ``0`` by default. -This has the effect that ``someVariable`` (which resides at storage -slot ``0``) is modified by ``x.push(2)``. - -The correct way to do this is the following:: - - pragma solidity ^0.4.0; - - contract C { - uint someVariable; - uint[] data; - - function f() public { - uint[] x = data; - x.push(2); - } - } - ****************** Advanced Questions ****************** @@ -375,13 +215,6 @@ The key point is that the calling contract needs to know about the function it i See `ping.sol `_ and `pong.sol `_. -Get contract to do something when it is first mined -=================================================== - -Use the constructor. Anything inside it will be executed when the contract is first mined. - -See `replicator.sol `_. - How do you create 2-dimensional arrays? ======================================= @@ -414,7 +247,7 @@ This is a very interesting question. Suppose that we have a contract field set u User user2 = user1; } -In this case, the mapping of the struct being copied over into the userList is ignored as there is no "list of mapped keys". +In this case, the mapping of the struct being copied over into ``user2`` is ignored as there is no "list of mapped keys". Therefore it is not possible to find out which values should be copied over. How do I initialize a contract with only a specific amount of wei? @@ -426,26 +259,20 @@ In the case of a ``contract A`` calling a new instance of ``contract B``, parent You will need to make sure that you have both contracts aware of each other's presence and that ``contract B`` has a ``payable`` constructor. In this example:: - pragma solidity ^0.4.0; + pragma solidity >0.4.99 <0.6.0; contract B { - function B() public payable {} + constructor() public payable {} } contract A { - address child; + B child; function test() public { child = (new B).value(10)(); //construct a new B with 10 wei } } -Can a contract function accept a two-dimensional array? -======================================================= - -This is not yet implemented for external calls and dynamic arrays - -you can only use one level of dynamic arrays. - What is the relationship between ``bytes32`` and ``string``? Why is it that ``bytes32 somevar = "stringliteral";`` works and what does the saved 32-byte hex value mean? ======================================================================================================================================================================== @@ -474,7 +301,7 @@ Can a contract pass an array (static size) or string or ``bytes`` (dynamic size) Sure. Take care that if you cross the memory / storage boundary, independent copies will be created:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { uint[20] x; @@ -484,7 +311,7 @@ independent copies will be created:: h(x); } - function g(uint[20] y) internal pure { + function g(uint[20] memory y) internal pure { y[2] = 3; } @@ -494,10 +321,9 @@ independent copies will be created:: } The call to ``g(x)`` will not have an effect on ``x`` because it needs -to create an independent copy of the storage value in memory -(the default storage location is memory). On the other hand, -``h(x)`` successfully modifies ``x`` because only a reference -and not a copy is passed. +to create an independent copy of the storage value in memory. +On the other hand, ``h(x)`` successfully modifies ``x`` because only +a reference and not a copy is passed. Sometimes, when I try to change the length of an array with ex: ``arrayname.length = 7;`` I get a compiler error ``Value must be an lvalue``. Why? ================================================================================================================================================== @@ -512,15 +338,14 @@ contract level) with ``arrayname.length = ;``. If you get the :: + pragma solidity >=0.4.18 <0.6.0; + // This will not compile - - pragma solidity ^0.4.18; - contract C { int8[] dynamicStorageArray; int8[5] fixedStorageArray; - function f() { + function f() public { int8[] memory memArr; // Case 1 memArr.length++; // illegal @@ -547,29 +372,7 @@ case in C or Java). Is it possible to return an array of strings (``string[]``) from a Solidity function? ===================================================================================== -Not yet, as this requires two levels of dynamic arrays (``string`` is a dynamic array itself). - -If you issue a call for an array, it is possible to retrieve the whole array? Or must you write a helper function for that? -=========================================================================================================================== - -The automatic :ref:`getter function` for a public state variable of array type only returns -individual elements. If you want to return the complete array, you have to -manually write a function to do that. - - -What could have happened if an account has storage value(s) but no code? Example: http://test.ether.camp/account/5f740b3a43fbb99724ce93a879805f4dc89178b5 -========================================================================================================================================================== - -The last thing a constructor does is returning the code of the contract. -The gas costs for this depend on the length of the code and it might be -that the supplied gas is not enough. This situation is the only one -where an "out of gas" exception does not revert changes to the state, -i.e. in this case the initialisation of the state variables. - -https://github.com/ethereum/wiki/wiki/Subtleties - -After a successful CREATE operation's sub-execution, if the operation returns x, 5 * len(x) gas is subtracted from the remaining gas before the contract is created. If the remaining gas is less than 5 * len(x), then no gas is subtracted, the code of the created contract becomes the empty string, but this is not treated as an exceptional condition - no reverts happen. - +Only when ``pragma experimental "ABIEncoderV2";`` is used. What does the following strange check do in the Custom Token contract? ====================================================================== @@ -585,6 +388,25 @@ does not fit inside this range, it is truncated. These truncations can have above is necessary to avoid certain attacks. +Why are explicit conversions between fixed-size bytes types and integer types failing? +====================================================================================== + +Since version 0.5.0 explicit conversions between fixed-size byte arrays and integers are only allowed, +if both types have the same size. This prevents unexpected behaviour when truncating or padding. +Such conversions are still possible, but intermediate casts are required that make the desired +truncation and padding convention explicit. See :ref:`types-conversion-elementary-types` for a full +explanation and examples. + + +Why can number literals not be converted to fixed-size bytes types? +=================================================================== + +Since version 0.5.0 only hexadecimal number literals can be converted to fixed-size bytes +types and only if the number of hex digits matches the size of the type. See :ref:`types-conversion-literals` +for a full explanation and examples. + + + More Questions? =============== diff --git a/docs/grammar.txt b/docs/grammar.txt index 0dda4f49d..b9c8ddb9b 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -50,6 +50,7 @@ TypeName = ElementaryTypeName | Mapping | ArrayTypeName | FunctionTypeName + | ( 'address' 'payable' ) UserDefinedTypeName = Identifier ( '.' Identifier )* @@ -57,8 +58,8 @@ Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')' ArrayTypeName = TypeName '[' Expression? ']' FunctionTypeName = 'function' FunctionTypeParameterList ( 'internal' | 'external' | StateMutability )* ( 'returns' FunctionTypeParameterList )? -StorageLocation = 'memory' | 'storage' -StateMutability = 'pure' | 'constant' | 'view' | 'payable' +StorageLocation = 'memory' | 'storage' | 'calldata' +StateMutability = 'pure' | 'view' | 'payable' Block = '{' Statement* '}' Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement | @@ -78,8 +79,7 @@ Break = 'break' Return = 'return' Expression? Throw = 'throw' EmitStatement = 'emit' FunctionCall -VariableDefinition = ('var' IdentifierList | VariableDeclaration | '(' VariableDeclaration? (',' VariableDeclaration? )* ')' ) ( '=' Expression )? -IdentifierList = '(' ( Identifier? ',' )* Identifier? ')' +VariableDefinition = (VariableDeclaration | '(' VariableDeclaration? (',' VariableDeclaration? )* ')' ) ( '=' Expression )? // Precedence by order (see github.com/ethereum/solidity/pull/732) Expression @@ -140,8 +140,7 @@ TupleExpression = '(' ( Expression? ( ',' Expression? )* )? ')' ElementaryTypeNameExpression = ElementaryTypeName -ElementaryTypeName = 'address' | 'bool' | 'string' | 'var' - | Int | Uint | Byte | Fixed | Ufixed +ElementaryTypeName = 'address' | 'bool' | 'string' | Int | Uint | Byte | Fixed | Ufixed Int = 'int' | 'int8' | 'int16' | 'int24' | 'int32' | 'int40' | 'int48' | 'int56' | 'int64' | 'int72' | 'int80' | 'int88' | 'int96' | 'int104' | 'int112' | 'int120' | 'int128' | 'int136' | 'int144' | 'int152' | 'int160' | 'int168' | 'int176' | 'int184' | 'int192' | 'int200' | 'int208' | 'int216' | 'int224' | 'int232' | 'int240' | 'int248' | 'int256' @@ -155,8 +154,9 @@ Ufixed = 'ufixed' | ( 'ufixed' [0-9]+ 'x' [0-9]+ ) InlineAssemblyBlock = '{' AssemblyItem* '}' -AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyLocalBinding | AssemblyAssignment | AssemblyLabel | NumberLiteral | StringLiteral | HexLiteral -AssemblyLocalBinding = 'let' Identifier ':=' FunctionalAssemblyExpression -AssemblyAssignment = ( Identifier ':=' FunctionalAssemblyExpression ) | ( '=:' Identifier ) +AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyVariableDeclaration | AssemblyAssignment | AssemblyLabel | NumberLiteral | StringLiteral | HexLiteral +AssemblyExpression = Identifier | FunctionalAssemblyExpression | NumberLiteral | StringLiteral | HexLiteral +AssemblyVariableDeclaration = 'let' Identifier ':=' AssemblyExpression +AssemblyAssignment = ( Identifier ':=' AssemblyExpression ) | ( '=:' Identifier ) AssemblyLabel = Identifier ':' FunctionalAssemblyExpression = Identifier '(' AssemblyItem? ( ',' AssemblyItem )* ')' diff --git a/docs/index.rst b/docs/index.rst index 80b0d6e70..17abf4b24 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,22 +6,25 @@ Solidity :alt: Solidity logo :align: center -Solidity is a contract-oriented, high-level language for implementing smart contracts. -It was influenced by C++, Python and JavaScript -and is designed to target the Ethereum Virtual Machine (EVM). +Solidity is an object-oriented, high-level language for implementing smart +contracts. Smart contracts are programs which govern the behaviour of accounts +within the Ethereum state. + +Solidity was influenced by C++, Python and JavaScript and is designed to target +the Ethereum Virtual Machine (EVM). Solidity is statically typed, supports inheritance, libraries and complex user-defined types among other features. -As you will see, it is possible to create contracts for voting, -crowdfunding, blind auctions, multi-signature wallets and more. +With Solidity you can create contracts for uses such as voting, crowdfunding, blind auctions, +and multi-signature wallets. .. note:: The best way to try out Solidity right now is using `Remix `_ (it can take a while to load, please be patient). Remix is a web browser - based IDE that allows you to write Solidity smart contracts, then deploy - and run the smart contracts. + based IDE that allows you to write Solidity smart contracts, then deploy + and run the smart contracts. .. warning:: Since software is written by humans, it can have bugs. Thus, also @@ -34,105 +37,14 @@ crowdfunding, blind auctions, multi-signature wallets and more. Translations ------------ -This documentation is translated into several languages by community volunteers, but the English version stands as a reference. +This documentation is translated into several languages by community volunteers +with varying degrees of completeness and up-to-dateness. The English version stands as a reference. * `Simplified Chinese `_ (in progress) * `Spanish `_ * `Russian `_ (rather outdated) * `Korean `_ (in progress) - - -Useful links ------------- - -* `Ethereum `_ - -* `Changelog `_ - -* `Story Backlog `_ - -* `Source Code `_ - -* `Ethereum Stackexchange `_ - -* `Gitter Chat `_ - -Available Solidity Integrations -------------------------------- - -* `Remix `_ - Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. - -* `IntelliJ IDEA plugin `_ - Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs) - -* `Visual Studio Extension `_ - Solidity plugin for Microsoft Visual Studio that includes the Solidity compiler. - -* `Package for SublimeText — Solidity language syntax `_ - Solidity syntax highlighting for SublimeText editor. - -* `Etheratom `_ - Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible). - -* `Atom Solidity Linter `_ - Plugin for the Atom editor that provides Solidity linting. - -* `Atom Solium Linter `_ - Configurable Solidty linter for Atom using Solium as a base. - -* `Solium `_ - Linter to identify and fix style and security issues in Solidity. - -* `Solhint `_ - Solidity linter that provides security, style guide and best practice rules for smart contract validation. - -* `Visual Studio Code extension `_ - Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. - -* `Emacs Solidity `_ - Plugin for the Emacs editor providing syntax highlighting and compilation error reporting. - -* `Vim Solidity `_ - Plugin for the Vim editor providing syntax highlighting. - -* `Vim Syntastic `_ - Plugin for the Vim editor providing compile checking. - -Discontinued: - -* `Mix IDE `_ - Qt based IDE for designing, debugging and testing solidity smart contracts. - -* `Ethereum Studio `_ - Specialized web IDE that also provides shell access to a complete Ethereum environment. - -Solidity Tools --------------- - -* `Dapp `_ - Build tool, package manager, and deployment assistant for Solidity. - -* `Solidity REPL `_ - Try Solidity instantly with a command-line Solidity console. - -* `solgraph `_ - Visualize Solidity control flow and highlight potential security vulnerabilities. - -* `evmdis `_ - EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. - -* `Doxity `_ - Documentation Generator for Solidity. - -Third-Party Solidity Parsers and Grammars ------------------------------------------ - -* `solidity-parser `_ - Solidity parser for JavaScript - -* `Solidity Grammar for ANTLR 4 `_ - Solidity grammar for the ANTLR 4 parser generator +* `French `_ (in progress) Language Documentation ---------------------- @@ -142,11 +54,11 @@ in Solidity followed by the basics about :ref:`blockchains ` and the :ref:`Ethereum Virtual Machine `. The next section will explain several *features* of Solidity by giving -useful :ref:`example contracts ` +useful :ref:`example contracts `. Remember that you can always try out the contracts `in your browser `_! -The last and most extensive section will cover all aspects of Solidity in depth. +The fourth and most extensive section will cover all aspects of Solidity in depth. If you still have questions, you can try searching or asking on the `Ethereum Stackexchange `_ @@ -166,12 +78,14 @@ Contents solidity-by-example.rst solidity-in-depth.rst security-considerations.rst + resources.rst using-the-compiler.rst metadata.rst abi-spec.rst - julia.rst + yul.rst style-guide.rst common-patterns.rst bugs.rst contributing.rst frequently-asked-questions.rst + lll.rst diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 05ee0748d..f8de0e8d9 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -22,7 +22,7 @@ Remix `Access Remix online `_, you don't need to install anything. If you want to use it without connection to the Internet, go to -https://github.com/ethereum/browser-solidity/tree/gh-pages and download the .ZIP file as +https://github.com/ethereum/remix-live/tree/gh-pages and download the ``.zip`` file as explained on that page. Further options on this page detail installing commandline Solidity compiler software @@ -35,22 +35,24 @@ npm / Node.js ============= Use `npm` for a convenient and portable way to install `solcjs`, a Solidity compiler. The -`solcjs` program has fewer features than all options further down this page. Our +`solcjs` program has fewer features than the ways to access the compiler described +further down this page. The :ref:`commandline-compiler` documentation assumes you are using -the full-featured compiler, `solc`. So if you install `solcjs` from `npm` then you will -stop reading the documentation here and then continue to `solc-js `_. +the full-featured compiler, `solc`. The usage of `solcjs` is documented inside its own +`repository `_. Note: The solc-js project is derived from the C++ -`solc` by using Emscripten. `solc-js` can be used in JavaScript projects directly (such as Remix). +`solc` by using Emscripten which means that both use the same compiler source code. +`solc-js` can be used in JavaScript projects directly (such as Remix). Please refer to the solc-js repository for instructions. -.. code:: bash +.. code-block:: bash npm install -g solc .. note:: - The commandline is named `solcjs`. + The commandline executable is named `solcjs`. The comandline options of `solcjs` are not compatible with `solc` and tools (such as `geth`) expecting the behaviour of `solc` will not work with `solcjs`. @@ -62,9 +64,9 @@ We provide up to date docker builds for the compiler. The ``stable`` repository contains released versions while the ``nightly`` repository contains potentially unstable changes in the develop branch. -.. code:: bash +.. code-block:: bash - docker run ethereum/solc:stable solc --version + docker run ethereum/solc:stable --version Currently, the docker image only contains the compiler executable, so you have to do some additional work to link in the source and @@ -76,65 +78,66 @@ Binary Packages Binary packages of Solidity are available at `solidity/releases `_. -We also have PPAs for Ubuntu. For the latest stable version. +We also have PPAs for Ubuntu, you can get the latest stable +version using the following commands: -.. code:: bash +.. code-block:: bash sudo add-apt-repository ppa:ethereum/ethereum sudo apt-get update sudo apt-get install solc -If you want to use the cutting edge developer version: +The nightly version can be installed using these commands: -.. code:: bash +.. code-block:: bash sudo add-apt-repository ppa:ethereum/ethereum sudo add-apt-repository ppa:ethereum/ethereum-dev sudo apt-get update sudo apt-get install solc - + We are also releasing a `snap package `_, which is installable in all the `supported Linux distros `_. To install the latest stable version of solc: -.. code:: bash +.. code-block:: bash sudo snap install solc -Or if you want to help testing the unstable solc with the most recent changes from the development branch: +If you want to help testing the latest development version of Solidity +with the most recent changes, please use the following: -.. code:: bash +.. code-block:: bash sudo snap install solc --edge Arch Linux also has packages, albeit limited to the latest development version: -.. code:: bash +.. code-block:: bash pacman -S solidity -Homebrew is missing pre-built bottles at the time of writing, -following a Jenkins to TravisCI migration, but Homebrew -should still work just fine as a means to build-from-source. -We will re-add the pre-built bottles soon. +We distribute the Solidity compiler through Homebrow +as a build-from-source version. Pre-built bottles are +currently not supported. -.. code:: bash +.. code-block:: bash brew update brew upgrade brew tap ethereum/ethereum brew install solidity -If you need a specific version of Solidity you can install a +If you need a specific version of Solidity you can install a Homebrew formula directly from Github. -View +View `solidity.rb commits on Github `_. -Follow the history links until you have a raw file link of a +Follow the history links until you have a raw file link of a specific commit of ``solidity.rb``. Install it using ``brew``: -.. code:: bash +.. code-block:: bash brew unlink solidity # Install 0.4.8 @@ -142,7 +145,7 @@ Install it using ``brew``: Gentoo Linux also provides a solidity package that can be installed using ``emerge``: -.. code:: bash +.. code-block:: bash emerge dev-lang/solidity @@ -151,29 +154,18 @@ Gentoo Linux also provides a solidity package that can be installed using ``emer Building from Source ==================== -Clone the Repository --------------------- +Prerequisites - Linux +--------------------- -To clone the source code, execute the following command: +You need to install the following dependencies for Linux builds of Solidity: -.. code:: bash ++-----------------------------------+-------------------------------------------------------+ +| Software | Notes | ++===================================+=======================================================+ +| `Git for Linux`_ | Command-line tool for retrieving source from Github. | ++-----------------------------------+-------------------------------------------------------+ - git clone --recursive https://github.com/ethereum/solidity.git - cd solidity - -If you want to help developing Solidity, -you should fork Solidity and add your personal fork as a second remote: - -.. code:: bash - - cd solidity - git remote add personal git@github.com:[username]/solidity.git - -Solidity has git submodules. Ensure they are properly loaded: - -.. code:: bash - - git submodule update --init --recursive +.. _Git for Linux: https://git-scm.com/download/linux Prerequisites - macOS --------------------- @@ -187,7 +179,7 @@ If you are installing Xcode for the first time, or have just installed a new version then you will need to agree to the license before you can do command-line builds: -.. code:: bash +.. code-block:: bash sudo xcodebuild -license accept @@ -201,7 +193,7 @@ if you ever want to start again from scratch. Prerequisites - Windows ----------------------- -You will need to install the following dependencies for Windows builds of Solidity: +You need to install the following dependencies for Windows builds of Solidity: +-----------------------------------+-------------------------------------------------------+ | Software | Notes | @@ -236,21 +228,36 @@ in Visual Studio 2017 Build Tools or Visual Studio 2017: .. _Visual Studio 2017: https://www.visualstudio.com/vs/ .. _Visual Studio 2017 Build Tools: https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017 +Clone the Repository +-------------------- + +To clone the source code, execute the following command: + +.. code-block:: bash + + git clone --recursive https://github.com/ethereum/solidity.git + cd solidity + +If you want to help developing Solidity, +you should fork Solidity and add your personal fork as a second remote: + +.. code-block:: bash + + git remote add personal git@github.com:[username]/solidity.git External Dependencies --------------------- -We now have a "one button" script which installs all required external dependencies -on macOS, Windows and on numerous Linux distros. This used to be a multi-step -manual process, but is now a one-liner: +We have a helper script which installs all required external dependencies +on macOS, Windows and on numerous Linux distros. -.. code:: bash +.. code-block:: bash ./scripts/install_deps.sh Or, on Windows: -.. code:: bat +.. code-block:: bat scripts\install_deps.bat @@ -261,9 +268,11 @@ Command-Line Build **Be sure to install External Dependencies (see above) before build.** Solidity project uses CMake to configure the build. +You might want to install ccache to speed up repeated builds. +CMake will pick it up automatically. Building Solidity is quite similar on Linux, macOS and other Unices: -.. code:: bash +.. code-block:: bash mkdir build cd build @@ -271,14 +280,14 @@ Building Solidity is quite similar on Linux, macOS and other Unices: or even easier: -.. code:: bash - +.. code-block:: bash + #note: this will install binaries solc and soltest at usr/local/bin ./scripts/build.sh -And even for Windows: +And for Windows: -.. code:: bash +.. code-block:: bash mkdir build cd build @@ -291,7 +300,7 @@ should result in Visual Studio firing up. We suggest building Alternatively, you can build for Windows on the command-line, like so: -.. code:: bash +.. code-block:: bash cmake --build . --config RelWithDebInfo @@ -300,6 +309,29 @@ CMake options If you are interested what CMake options are available run ``cmake .. -LH``. +.. _smt_solvers_build: + +SMT Solvers +----------- +Solidity can be built against SMT solvers and will do so by default if +they are found in the system. Each solver can be disabled by a `cmake` option. + +*Note: In some cases, this can also be a potential workaround for build failures.* + + +Inside the build folder you can disable them, since they are enabled by default: + +.. code-block:: bash + + # disables only Z3 SMT Solver. + cmake .. -DUSE_Z3=OFF + + # disables only CVC4 SMT Solver. + cmake .. -DUSE_CVC4=OFF + + # disables both Z3 and CVC4 + cmake .. -DUSE_CVC4=OFF -DUSE_Z3=OFF + The version string in detail ============================ @@ -308,7 +340,7 @@ The Solidity version string contains four parts: - the version number - pre-release tag, usually set to ``develop.YYYY.MM.DD`` or ``nightly.YYYY.MM.DD`` - commit in the format of ``commit.GITHASH`` -- platform has arbitrary number of items, containing details about the platform and compiler +- platform, which has an arbitrary number of items, containing details about the platform and compiler If there are local modifications, the commit will be postfixed with ``.mod``. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index d1789c447..9245300ba 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -8,15 +8,16 @@ Introduction to Smart Contracts A Simple Smart Contract *********************** -Let us begin with the most basic example. It is fine if you do not understand everything -right now, we will go into more detail later. +Let us begin with a basic example that sets the value of a variable and exposes +it for other contracts to access. It is fine if you do not understand +everything right now, we will go into more detail later. Storage ======= :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract SimpleStorage { uint storedData; @@ -32,15 +33,15 @@ Storage The first line simply tells that the source code is written for Solidity version 0.4.0 or anything newer that does not break functionality -(up to, but not including, version 0.5.0). This is to ensure that the -contract does not suddenly behave differently with a new compiler version. The keyword ``pragma`` is called that way because, in general, -pragmas are instructions for the compiler about how to treat the +(up to, but not including, version 0.6.0). This is to ensure that the +contract is not compilable with a new (breaking) compiler version, where it could behave differently. +So-called pragmas are common instructions for compilers about how to treat the source code (e.g. `pragma once `_). A contract in the sense of Solidity is a collection of code (its *functions*) and 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`` (unsigned integer of 256 bits). You can think of it as a single slot +type ``uint`` (*u*nsigned *int*eger of *256* bits). You can think of it as a single slot in a database that can be queried and altered by calling functions of the code that manages the database. In the case of Ethereum, this is always the owning contract. And in this case, the functions ``set`` and ``get`` can be used to modify @@ -49,8 +50,8 @@ or retrieve the value of the variable. To access a state variable, you do not need the prefix ``this.`` as is common in other languages. -This contract does not do much yet (due to the infrastructure -built by Ethereum) apart from allowing anyone to store a single number that is accessible by +This contract does not do much yet apart from (due to the infrastructure +built by Ethereum) allowing anyone to store a single number that is accessible by anyone in the world without a (feasible) way to prevent you from publishing this number. Of course, anyone could just call ``set`` again with a different value and overwrite your number, but the number will still be stored in the history @@ -62,7 +63,7 @@ so that only you can alter the number. the ASCII character set. It is possible to store UTF-8 encoded data in string variables. .. warning:: - Be careful with using Unicode text as similarly looking (or even identical) characters can + Be careful with using Unicode text, as similar looking (or even identical) characters can have different code points and as such will be encoded as a different byte array. .. index:: ! subcurrency @@ -72,39 +73,40 @@ 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 trivial +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 any need for -registering with username and password - all you need is an Ethereum keypair. +Furthermore, anyone can send coins to each other without a need for +registering with username and password — all you need is an Ethereum keypair. :: - pragma solidity ^0.4.21; + pragma solidity >0.4.99 <0.6.0; contract Coin { // The keyword "public" makes those variables - // readable from outside. + // easily readable from outside. address public minter; mapping (address => uint) public balances; - // Events allow light clients to react on + // Events allow light clients to react to // changes efficiently. event Sent(address from, address to, uint amount); // This is the constructor whose code is // run only when the contract is created. - function Coin() public { + constructor() public { minter = msg.sender; } function mint(address receiver, uint amount) public { - if (msg.sender != minter) return; + require(msg.sender == minter); + require(amount < 1e60); balances[receiver] += amount; } function send(address receiver, uint amount) public { - if (balances[msg.sender] < amount) return; + require(amount <= balances[msg.sender], "Insufficient balance."); balances[msg.sender] -= amount; balances[receiver] += amount; emit Sent(msg.sender, receiver, amount); @@ -116,15 +118,15 @@ 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 keypairs belonging to external +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 -to the following:: +to the following (ignore ``external`` and ``view`` for now):: - function minter() returns (address) { return minter; } + function minter() external view returns (address) { return minter; } Of course, adding a function exactly like that will not work because we would have a @@ -137,17 +139,17 @@ 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. Mappings can be seen as `hash tables `_ which are -virtually initialized such that every possible key exists and is mapped to a +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, -like this one. The :ref:`getter function` created by the ``public`` keyword +added to the mapping or use it in a context where this is not needed. +The :ref:`getter function` created by the ``public`` keyword is a bit more complex in this case. It roughly looks like the following:: - function balances(address _account) public view returns (uint) { + function balances(address _account) external view returns (uint) { return balances[_account]; } @@ -162,7 +164,9 @@ a so-called "event" which is emitted in the last line of the function 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 :: +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):: Coin.Sent().watch({}, '', function(error, result) { if (!error) { @@ -180,23 +184,34 @@ the user interface. .. index:: coin -The special function ``Coin`` is the -constructor which is run during creation of the contract and +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 magic global variable that +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 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. On the other hand, ``send`` can be used by anyone (who already -has some of these coins) to send coins to anyone else. Note that 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 -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 -a "blockchain explorer" that tracks transactions and balances of your new coin. +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. + +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. + +.. 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 + 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 + 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. .. _blockchain-basics: @@ -206,7 +221,7 @@ Blockchain Basics Blockchains as a concept are not too hard to understand for programmers. The reason is that most of the complications (mining, `hashing `_, `elliptic-curve cryptography `_, `peer-to-peer networks `_, etc.) -are just there to provide a certain set of features and promises. Once you accept these +are just there to provide a certain set of features and promises for the platform. Once you accept these features as given, you do not have to worry about the underlying technology - or do you have to know how Amazon's AWS works internally in order to use it? @@ -221,7 +236,7 @@ If you want to change something in the database, you have to create a so-called which has to be accepted by all others. The word transaction implies that the change you want to make (assume you want to change two values at the same time) is either not done at all or completely applied. Furthermore, -while your transaction is applied to the database, no other transaction can alter it. +while your transaction is being applied to the database, no other transaction can alter it. As an example, imagine a table that lists the balances of all accounts in an electronic currency. If a transfer from one account to another is requested, @@ -240,12 +255,13 @@ only the person holding the keys to the account can transfer money from it. Blocks ====== -One major obstacle to overcome is what, in Bitcoin terms, is called a "double-spend attack": -What happens if two transactions exist in the network that both want to empty an account, -a so-called conflict? +One major obstacle to overcome is what (in Bitcoin terms) is called a "double-spend attack": +What happens if two transactions exist in the network that both want to empty an account? +Only one of the transactions can be valid, typically the one that is accepted first. +The problem is that "first" is not an objective term in a peer-to-peer network. -The abstract answer to this is that you do not have to care. An order of the transactions -will be selected for you, the transactions will be bundled into what is called a "block" +The abstract answer to this is that you do not have to care. A globally accepted order of the transactions +will be selected for you, solving the conflict. The transactions will be bundled into what is called a "block" and then they will be executed and distributed among all participating nodes. If two transactions contradict each other, the one that ends up being second will be rejected and not become part of the block. @@ -256,10 +272,16 @@ Ethereum this is roughly every 17 seconds. As part of the "order selection mechanism" (which is called "mining") it may happen that blocks are reverted from time to time, but only at the "tip" of the chain. The more -blocks that are added on top, the less likely it is. So it might be that your transactions +blocks are added on top of a particular block, the less likely this block will be reverted. So it might be that your transactions are reverted and even removed from the blockchain, but the longer you wait, the less likely it will be. +.. note:: + Transactions are not guaranteed to be included in the next block or any specific future block, + since it is not up to the submitter of a transaction, but up to the miners to determine in which block the transaction is included. + + If you want to schedule future calls of your contract, you can use + the `alarm clock `_ or a similar oracle service. .. _the-ethereum-virtual-machine: @@ -301,7 +323,7 @@ Every account has a persistent key-value store mapping 256-bit words to 256-bit words called **storage**. Furthermore, every account has a **balance** in -Ether (in "Wei" to be exact) which can be modified by sending transactions that +Ether (in "Wei" to be exact, `1 ether` is `10**18 wei`) which can be modified by sending transactions that include Ether. .. index:: ! transaction @@ -310,19 +332,20 @@ Transactions ============ A transaction is a message that is sent from one account to another -account (which might be the same or the special zero-account, see below). -It can include binary data (its payload) and Ether. +account (which might be the same or empty, see below). +It can include binary data (which is called "payload") and Ether. If the target account contains code, that code is executed and the payload is provided as input data. -If the target account is the zero-account (the account with the -address ``0``), the transaction creates a **new contract**. +If the target account is not set (the transaction does not have +a recipient or the recipient is set to ``null``), the transaction +creates a **new contract**. As already mentioned, the address of that contract is not the zero address but an address derived from the sender and its number of transactions sent (the "nonce"). The payload of such a contract creation transaction is taken to be -EVM bytecode and executed. The output of this execution is +EVM bytecode and executed. The output data of this execution is permanently stored as the code of the contract. This means that in order to create a contract, you do not send the actual code of the contract, but in fact code that @@ -341,14 +364,14 @@ Gas Upon creation, each transaction is charged with a certain amount of **gas**, whose purpose is to limit the amount of work that is needed to execute -the transaction and to pay for this execution. While the EVM executes the +the transaction and to pay for this execution at the same time. While the EVM executes the transaction, the gas is gradually depleted according to specific rules. The **gas price** is a value set by the creator of the transaction, who has to pay ``gas_price * gas`` up front from the sending account. -If some gas is left after the execution, it is refunded in the same way. +If some gas is left after the execution, it is refunded to the creator in the same way. -If the gas is used up at any point (i.e. it is negative), +If the gas is used up at any point (i.e. it would be negative), an out-of-gas exception is triggered, which reverts all modifications made to the state in the current call frame. @@ -357,23 +380,27 @@ made to the state in the current call frame. Storage, Memory and the Stack ============================= -Each account has a persistent memory area which is called **storage**. -Storage is a key-value store that maps 256-bit words to 256-bit words. -It is not possible to enumerate storage from within a contract -and it is comparatively costly to read and even more so, to modify -storage. A contract can neither read nor write to any storage apart -from its own. +The Ethereum Virtual Machine has three areas where it can store data- +storage, memory and the stack, which are explained in the following +paragraphs. -The second memory area is called **memory**, of which a contract obtains +Each account has a data area called **storage**, which is persistent between function calls +and transactions. +Storage is a key-value store that maps 256-bit words to 256-bit words. +It is not possible to enumerate storage from within a contract and it is +comparatively costly to read, and even more to modify storage. +A contract can neither read nor write to any storage apart from its own. + +The second data area is called **memory**, of which a contract obtains a freshly cleared instance for each message call. Memory is linear and can be addressed at byte level, but reads are limited to a width of 256 bits, while writes can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when -accessing (either reading or writing) a previously untouched memory word (ie. any offset +accessing (either reading or writing) a previously untouched memory word (i.e. any offset within a word). At the time of expansion, the cost in gas must be paid. Memory is more costly the larger it grows (it scales quadratically). The EVM is not a register machine but a stack machine, so all -computations are performed on an area called the **stack**. It has a maximum size of +computations are performed on an data area called the **stack**. It has a maximum size of 1024 elements and contains words of 256 bits. Access to the stack is limited to the top end in the following way: It is possible to copy one of @@ -381,7 +408,8 @@ the topmost 16 elements to the top of the stack or swap the topmost element with one of the 16 elements below it. All other operations take the topmost two (or one, or more, depending on the operation) elements from the stack and push the result onto the stack. -Of course it is possible to move stack elements to storage or memory, +Of course it is possible to move stack elements to storage or memory +in order to get deeper access to the stack, but it is not possible to just access arbitrary elements deeper in the stack without first removing the top of the stack. @@ -391,13 +419,17 @@ Instruction Set =============== The instruction set of the EVM is kept minimal in order to avoid -incorrect implementations which could cause consensus problems. -All instructions operate on the basic data type, 256-bit words. +incorrect or inconsistent implementations which could cause consensus problems. +All instructions operate on the basic data type, 256-bit words or on slices of memory +(or other byte arrays). The usual arithmetic, bit, logical and comparison operations are present. Conditional and unconditional jumps are possible. Furthermore, contracts can access relevant properties of the current block like its number and timestamp. +For a complete list, please see the :ref:`list of opcodes ` as part of the inline +assembly documentation. + .. index:: ! message call, function;call Message Calls @@ -412,7 +444,7 @@ a top-level message call which in turn can create further message calls. A contract can decide how much of its remaining **gas** should be sent with the inner message call and how much it wants to retain. If an out-of-gas exception happens in the inner call (or any -other exception), this will be signalled by an error value put onto the stack. +other exception), this will be signaled by an error value put onto the stack. In this case, only the gas sent together with the call is used up. In Solidity, the calling contract causes a manual exception by default in such situations, so that exceptions "bubble up" the call stack. @@ -422,9 +454,12 @@ will receive a freshly cleared instance of memory and has access to the call payload - which will be provided in a separate area called the **calldata**. After it has finished execution, it can return data which will be stored at a location in the caller's memory preallocated by the caller. +All such calls are fully synchronous. Calls are **limited** to a depth of 1024, which means that for more complex -operations, loops should be preferred over recursive calls. +operations, loops should be preferred over recursive calls. Furthermore, +only 63/64th of the gas can be forwarded in a message call, which causes a +depth limit of a little less than 1000 in practice. .. index:: delegatecall, callcode, library @@ -442,7 +477,7 @@ refer to the calling contract, only the code is taken from the called address. This makes it possible to implement the "library" feature in Solidity: Reusable library code that can be applied to a contract's storage, e.g. in -order to implement a complex data structure. +order to implement a complex data structure. .. index:: log @@ -451,13 +486,13 @@ Logs It is possible to store data in a specially indexed data structure that maps all the way up to the block level. This feature called **logs** -is used by Solidity in order to implement **events**. +is used by Solidity in order to implement :ref:`events `. Contracts cannot access log data after it has been created, but they can be efficiently accessed from outside the blockchain. Since some part of the log data is stored in `bloom filters `_, it is possible to search for this data in an efficient and cryptographically secure way, so network peers that do not download the whole blockchain -("light clients") can still find these logs. +(so-called "light clients") can still find these logs. .. index:: contract creation @@ -465,26 +500,22 @@ Create ====== Contracts can even create other contracts using a special opcode (i.e. -they do not simply call the zero address). The only difference between +they do not simply call the zero address as a transaction would). The only difference between these **create calls** and normal message calls is that the payload data is executed and the result stored as code and the caller / creator receives the address of the new contract on the stack. -.. index:: selfdestruct +.. index:: selfdestruct, self-destruct, deactivate -Self-destruct -============= +Deactivate and Self-destruct +============================ -The only possibility that code is removed 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. +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's code does not contain a call to ``selfdestruct``, - it can still perform that operation using ``delegatecall`` or ``callcode``. +.. note:: + Even if a contract's code does not contain a call to ``selfdestruct``, it can still perform that operation using ``delegatecall`` or ``callcode``. -.. note:: The pruning of old contracts may or may not be implemented by Ethereum - clients. Additionally, archive nodes could choose to keep the contract storage - and code indefinitely. +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. -.. note:: Currently **external accounts** cannot be removed from the state. +.. 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/layout-of-source-files.rst b/docs/layout-of-source-files.rst index f9d197b7b..9a8bdc3e3 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -2,15 +2,29 @@ Layout of a Solidity Source File ******************************** -Source files can contain an arbitrary number of contract definitions, include directives -and pragma directives. +Source files can contain an arbitrary number of +:ref:`contract definitions`, import_ directives +and :ref:`pragma directives`. + +.. index:: ! pragma + +.. _pragma: + +Pragmas +======= + +The ``pragma`` keyword can be used to enable certain compiler features +or checks. A pragma directive is always local to a source file, so +you have to add the pragma to all your files if you want enable it +in all of your project. If you :ref:`import` another file, the pragma +from that file will not automatically apply to the importing file. .. index:: ! pragma, version .. _version_pragma: Version Pragma -============== +-------------- Source files can (and should) be annotated with a so-called version pragma to reject being compiled with future compiler versions that might introduce incompatible @@ -35,6 +49,53 @@ the exact version of the compiler, so that bugfix releases are still possible. It is possible to specify much more complex rules for the compiler version, the expression follows those used by `npm `_. +.. note:: + Using the version pragma will *not* change the version of the compiler. + It will also *not* enable or disable features of the compiler. It will just + instruct the compiler to check whether its version matches the one + required by the pragma. If it does not match, the compiler will issue + an error. + +.. index:: ! pragma, experimental + +.. _experimental_pragma: + +Experimental Pragma +------------------- + +The second pragma is the experimental pragma. It can be used to enable +features of the compiler or language that are not yet enabled by default. +The following experimental pragmas are currently supported: + + +ABIEncoderV2 +~~~~~~~~~~~~ + +The new ABI encoder is able to encode and decode arbitrarily nested +arrays and structs. It produces less optimal code (the optimizer +for this part of the code is still under development) and has not +received as much testing as the old encoder. You can activate it +using ``pragma experimental ABIEncoderV2;``. + +.. _smt_checker: + +SMTChecker +~~~~~~~~~~ + +This component has to be enabled when the Solidity compiler is built +and therefore it is not available in all Solidity binaries. +The :ref:`build instructions` explain how to activate this option. +It is activated for the Ubuntu PPA releases in most versions, +but not for solc-js, the Docker images, Windows binaries or the +statically-built Linux binaries. + +If you use +``pragma experimental SMTChecker;``, then you get additional +safety warnings which are obtained by querying an SMT solver. +The component does not yet support all features of the Solidity language +and likely outputs many warnings. In case it reports unsupported +features, the analysis may not be fully sound. + .. index:: source file, ! import .. _import: @@ -56,18 +117,27 @@ At a global level, you can use import statements of the following form: This statement imports all global symbols from "filename" (and symbols imported there) into the current global scope (different than in ES6 but backwards-compatible for Solidity). +This simple form is not recommended for use, because it pollutes the namespace in an +unpredictable way: If you add new top-level items inside "filename", they will automatically +appear in all files that import like this from "filename". It is better to import specific +symbols explicitly. + +The following example creates a new global symbol ``symbolName`` whose members are all +the global symbols from ``"filename"``. :: import * as symbolName from "filename"; -...creates a new global symbol ``symbolName`` whose members are all the global symbols from ``"filename"``. +If there is a naming collision, you can also rename symbols while importing. +This code +creates new global symbols ``alias`` and ``symbol2`` which reference ``symbol1`` and ``symbol2`` from inside ``"filename"``, respectively. :: import {symbol1 as alias, symbol2} from "filename"; -...creates new global symbols ``alias`` and ``symbol2`` which reference ``symbol1`` and ``symbol2`` from ``"filename"``, respectively. + Another syntax is not part of ES6, but probably convenient: @@ -77,6 +147,10 @@ Another syntax is not part of ES6, but probably convenient: which is equivalent to ``import * as symbolName from "filename";``. +.. note:: + If you use `import "filename.sol" as moduleName;`, you access a contract called `C` + from inside `"filename.sol"` as `moduleName.C` and not by using `C` directly. + Paths ----- @@ -93,47 +167,52 @@ It depends on the compiler (see below) how to actually resolve the paths. In general, the directory hierarchy does not need to strictly map onto your local filesystem, it can also map to resources discovered via e.g. ipfs, http or git. +.. note:: + Always use relative imports like ``import "./filename.sol";`` and avoid + using ``..`` in path specifiers. In the latter case, it is probably better to use + global paths and set up remappings as explained below. + Use in Actual Compilers ----------------------- -When the compiler is invoked, it is not only possible to specify how to -discover the first element of a path, but it is possible to specify path prefix -remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to -``/usr/local/dapp-bin/library`` and the compiler will read the files from there. -If multiple remappings can be applied, the one with the longest key is tried first. This -allows for a "fallback-remapping" with e.g. ``""`` maps to -``"/usr/local/include/solidity"``. Furthermore, these remappings can -depend on the context, which allows you to configure packages to -import e.g. different versions of a library of the same name. +When invoking the compiler, you can specify how to discover the first element +of a path, and also path prefix remappings. For +example you can setup a remapping so that everything imported from the virtual +directory ``github.com/ethereum/dapp-bin/library`` would actually be read from +your local directory ``/usr/local/dapp-bin/library``. +If multiple remappings apply, the one with the longest key is tried first. +An empty prefix is not allowed. The remappings can depend on a context, +which allows you to configure packages to import e.g., different versions of a +library of the same name. **solc**: -For solc (the commandline compiler), these remappings are provided as +For solc (the commandline compiler), you provide these path remappings as ``context:prefix=target`` arguments, where both the ``context:`` and the -``=target`` parts are optional (where target defaults to prefix in that +``=target`` parts are optional (``target`` defaults to ``prefix`` in this case). All remapping values that are regular files are compiled (including -their dependencies). This mechanism is completely backwards-compatible (as long -as no filename contains = or :) and thus not a breaking change. All imports -in files in or below the directory ``context`` that import a file that -starts with ``prefix`` are redirected by replacing ``prefix`` by ``target``. +their dependencies). -So as an example, if you clone -``github.com/ethereum/dapp-bin/`` locally to ``/usr/local/dapp-bin``, you can use -the following in your source file: +This mechanism is backwards-compatible (as long +as no filename contains ``=`` or ``:``) and thus not a breaking change. All +files in or below the ``context`` directory that import a file that starts with +``prefix`` are redirected by replacing ``prefix`` by ``target``. + +For example, if you clone ``github.com/ethereum/dapp-bin/`` locally to +``/usr/local/dapp-bin``, you can use the following in your source file: :: import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; -and then run the compiler as +Then run the compiler: .. code-block:: bash solc github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ source.sol -As a more complex example, suppose you rely on some module that uses a -very old version of dapp-bin. That old version of dapp-bin is checked -out at ``/usr/local/dapp-bin_old``, then you can use +As a more complex example, suppose you rely on a module that uses an old +version of dapp-bin that you checked out to ``/usr/local/dapp-bin_old``, then you can run: .. code-block:: bash @@ -141,28 +220,29 @@ out at ``/usr/local/dapp-bin_old``, then you can use module2:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin_old/ \ source.sol -so that all imports in ``module2`` point to the old version but imports -in ``module1`` get the new version. +This means that all imports in ``module2`` point to the old version but imports +in ``module1`` point to the new version. -Note that solc only allows you to include files from certain directories: -They have to be in the directory (or subdirectory) of one of the explicitly -specified source files or in the directory (or subdirectory) of a remapping -target. If you want to allow direct absolute includes, just add the -remapping ``=/``. +.. note:: + + ``solc`` only allows you to include files from certain directories. They have + to be in the directory (or subdirectory) of one of the explicitly specified + source files or in the directory (or subdirectory) of a remapping target. If + you want to allow direct absolute includes, add the remapping ``/=/``. If there are multiple remappings that lead to a valid file, the remapping with the longest common prefix is chosen. **Remix**: -`Remix `_ -provides an automatic remapping for github and will also automatically retrieve -the file over the network: -You can import the iterable mapping by e.g. -``import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;``. +`Remix `_ provides an automatic remapping for +GitHub and automatically retrieves the file over the network. You can import +the iterable mapping as above, e.g. -Other source code providers may be added in the future. +:: + import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; +Remix may add other source code providers in the future. .. index:: ! comment, natspec @@ -180,6 +260,11 @@ Single-line comments (``//``) and multi-line comments (``/*...*/``) are possible multi-line comment. */ +.. note:: + A single-line comment is terminated by any unicode line terminator + (LF, VF, FF, CR, NEL, LS or PS) in utf8 encoding. The terminator is still part of + the source code after the comment, so if it is not an ascii symbol + (these are NEL, LS and PS), it will lead to a parser error. Additionally, there is another type of comment called a natspec comment, for which the documentation is not yet written. They are written with a @@ -195,17 +280,17 @@ for the two input parameters and two returned values. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; /** @title Shape calculator. */ - contract shapeCalculator { + contract ShapeCalculator { /** @dev Calculates a rectangle's surface and perimeter. * @param w Width of the rectangle. * @param h Height of the rectangle. * @return s The calculated surface. * @return p The calculated perimeter. */ - function rectangle(uint w, uint h) returns (uint s, uint p) { + function rectangle(uint w, uint h) public pure returns (uint s, uint p) { s = w * h; p = 2 * (w + h); } diff --git a/docs/lll.rst b/docs/lll.rst new file mode 100644 index 000000000..d9409bf84 --- /dev/null +++ b/docs/lll.rst @@ -0,0 +1,14 @@ +### +LLL +### + +.. _lll: + +LLL is a low-level language for the EVM with an s-expressions syntax. + +The Solidity repository contains an LLL compiler, which shares the assembler subsystem with Solidity. +However, apart from maintaining that it still compiles, no other improvements are made to it. + +.. warning:: + + The LLL codebase is deprecated and will be removed from the Solidity repository in the future. diff --git a/docs/make.bat b/docs/make.bat index de2bccf75..bc06e706e 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,242 +1,242 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -set I18NSPHINXOPTS=%SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Solidity.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Solidity.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Solidity.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Solidity.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/metadata.rst b/docs/metadata.rst index 5e37219e1..c0613809a 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -4,28 +4,28 @@ Contract Metadata .. index:: metadata, contract verification -The Solidity compiler automatically generates a JSON file, the -contract metadata, that contains information about the current contract. -It can be used to query the compiler version, the sources used, the ABI -and NatSpec documentation in order to more safely interact with the contract -and to verify its source code. +The Solidity compiler automatically generates a JSON file, the contract +metadata, that contains information about the current contract. You can use +this file to query the compiler version, the sources used, the ABI and NatSpec +documentation to more safely interact with the contract and verify its source +code. The compiler appends a Swarm hash of the metadata file to the end of the bytecode (for details, see below) of each contract, so that you can retrieve the file in an authenticated way without having to resort to a centralized data provider. -Of course, you have to publish the metadata file to Swarm (or some other service) -so that others can access it. The file can be output by using ``solc --metadata`` -and the file will be called ``ContractName_meta.json``. -It will contain Swarm references to the source code, so you have to upload -all source files and the metadata file. +You have to publish the metadata file to Swarm (or another service) so that +others can access it. You create the file by using the ``solc --metadata`` +command that generates a file called ``ContractName_meta.json``. It contains +Swarm references to the source code, so you have to upload all source files and +the metadata file. The metadata file has the following format. The example below is presented in a human-readable way. Properly formatted metadata should use quotes correctly, reduce whitespace to a minimum and sort the keys of all objects to arrive at a -unique formatting. -Comments are of course also not permitted and used here only for explanatory purposes. +unique formatting. Comments are not permitted and used here only for +explanatory purposes. .. code-block:: none @@ -93,14 +93,15 @@ Comments are of course also not permitted and used here only for explanatory pur } } -.. note:: - Note the ABI definition above has no fixed order. It can change with compiler versions. +.. warning:: + Since the bytecode of the resulting contract contains the metadata hash, any + change to the metadata results in a change of the bytecode. This includes + changes to a filename or path, and since the metadata includes a hash of all the + sources used, a single whitespace change results in different metadata, and + different bytecode. .. note:: - Since the bytecode of the resulting contract contains the metadata hash, any change to - the metadata will result in a change of the bytecode. Furthermore, since the metadata - includes a hash of all the sources used, a single whitespace change in any of the source - codes will result in a different metadata, and subsequently a different bytecode. + Note the ABI definition above has no fixed order. It can change with compiler versions. Encoding of the Metadata Hash in the Bytecode ============================================= @@ -117,21 +118,30 @@ to the end of the deployed bytecode:: So in order to retrieve the data, the end of the deployed bytecode can be checked to match that pattern and use the Swarm hash to retrieve the file. +.. note:: + The compiler currently uses the "swarm version 0" hash of the metadata, + but this might change in the future, so do not rely on this sequence + to start with ``0xa1 0x65 'b' 'z' 'z' 'r' '0'``. We might also + add additional data to this CBOR structure, so the + best option is to use a proper CBOR parser. + + Usage for Automatic Interface Generation and NatSpec ==================================================== The metadata is used in the following way: A component that wants to interact -with a contract (e.g. Mist) retrieves the code of the contract, from that +with a contract (e.g. Mist or any wallet) retrieves the code of the contract, from that the Swarm hash of a file which is then retrieved. That file is JSON-decoded into a structure like above. The component can then use the ABI to automatically generate a rudimentary user interface for the contract. -Furthermore, Mist can use the userdoc to display a confirmation message to the user -whenever they interact with the contract. +Furthermore, the wallet can use the NatSpec user documentation to display a confirmation message to the user +whenever they interact with the contract, together with requesting +authorization for the transaction signature. -Additional information about Ethereum Natural Specification (NatSpec) can be found `here `_. +Additional information about Ethereum Natural Specification (NatSpec) can be found `here `_. Usage for Source Code Verification ================================== diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index c7c325285..21978ded0 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -32,23 +32,33 @@ Statically-sized variables (everything except mapping and dynamically-sized arra ``uint128, uint256, uint128``, as the former will only take up two slots of storage whereas the latter will take up three. + .. note:: + The layout of state variables in storage is considered to be part of the external interface + of Solidity due to the fact that storage pointers can be passed to libraries. This means that + any change to the rules outlined in this section is considered a breaking change + of the language and due to its critical nature should be considered very carefully before + being executed. + + The elements of structs and arrays are stored after each other, just as if they were given explicitly. +Mappings and Dynamic Arrays +=========================== + Due to their unpredictable size, mapping and dynamically-sized array types use a Keccak-256 hash computation to find the starting position of the value or the array data. These starting positions are always full stack slots. -The mapping or the dynamic array itself -occupies an (unfilled) slot in storage at some position ``p`` according to the above rule (or by -recursively applying this rule for mappings to mappings or arrays of arrays). For a dynamic array, this slot stores the number of elements in the array (byte arrays and strings are an exception here, see below). For a mapping, the slot is unused (but it is needed so that two equal mappings after each other will use a different hash distribution). -Array data is located at ``keccak256(p)`` and the value corresponding to a mapping key +The mapping or the dynamic array itself occupies a slot in storage at some position ``p`` +according to the above rule (or by recursively applying this rule for mappings of mappings or arrays of arrays). For dynamic arrays, +this slot stores the number of elements in the array (byte arrays and strings are an exception, see :ref:`below `). +For mappings, the slot is unused (but it is needed so that two equal mappings after each other will use a different +hash distribution). Array data is located at ``keccak256(p)`` and the value corresponding to a mapping key ``k`` is located at ``keccak256(k . p)`` where ``.`` is concatenation. If the value is again a non-elementary type, the positions are found by adding an offset of ``keccak256(k . p)``. -``bytes`` and ``string`` store their data in the same slot where also the length is stored if they are short. In particular: If the data is at most ``31`` bytes long, it is stored in the higher-order bytes (left aligned) and the lowest-order byte stores ``length * 2``. If it is longer, the main slot stores ``length * 2 + 1`` and the data is stored as usual in ``keccak256(slot)``. - So for the following contract snippet:: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { struct s { uint a; uint b; } @@ -58,27 +68,43 @@ So for the following contract snippet:: The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``. +.. _bytes-and-string: + +``bytes`` and ``string`` +------------------------ + +``bytes`` and ``string`` are encoded identically. For short byte arrays, they store their data in the same +slot where the length is also stored. In particular: if the data is at most ``31`` bytes long, it is stored +in the higher-order bytes (left aligned) and the lowest-order byte stores ``length * 2``. +For byte arrays that store data which is ``32`` or more bytes long, the main slot stores ``length * 2 + 1`` and the data is +stored as usual in ``keccak256(slot)``. This means that you can distinguish a short array from a long array +by checking if the lowest bit is set: short (not set) and long (set). + +.. note:: + Handling invalidly encoded slots is currently not supported but may be added in the future. + .. index: memory layout **************** Layout in Memory **************** -Solidity reserves four 32 byte slots: +Solidity reserves four 32-byte slots, with specific byte ranges (inclusive of endpoints) being used as follows: -- ``0x00`` - ``0x3f``: scratch space for hashing methods -- ``0x40`` - ``0x5f``: currently allocated memory size (aka. free memory pointer) -- ``0x60`` - ``0x7f``: zero slot +- ``0x00`` - ``0x3f`` (64 bytes): scratch space for hashing methods +- ``0x40`` - ``0x5f`` (32 bytes): currently allocated memory size (aka. free memory pointer) +- ``0x60`` - ``0x7f`` (32 bytes): zero slot -Scratch space can be used between statements (ie. within inline assembly). The zero slot +Scratch space can be used between statements (i.e. within inline assembly). The zero slot is used as initial value for dynamic memory arrays and should never be written to (the free memory pointer points to ``0x80`` initially). Solidity always places new objects at the free memory pointer and memory is never freed (this might change in the future). .. warning:: - There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifecycle, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one shouldn't expect the free memory to be zeroed out. + There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifetime, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one shouldn't expect the free memory to point to zeroed out memory. + While it may seem like a good idea to use ``msize`` to arrive at a definitely zeroed out memory area, using such a pointer non-temporarily without updating the free memory pointer can have adverse results. .. index: calldata layout @@ -86,10 +112,14 @@ Solidity always places new objects at the free memory pointer and memory is neve Layout of Call Data ******************* -When a Solidity contract is deployed and when it is called from an -account, the input data is assumed to be in the format in :ref:`the ABI -specification `. The ABI specification requires arguments to be padded to multiples of 32 -bytes. The internal function calls use a different convention. +The input data for a function call is assumed to be in the format defined by the :ref:`ABI +specification `. Among others, the ABI specification requires arguments to be padded to multiples of 32 +bytes. The internal function calls use a different convention. + +Arguments for the constructor of a contract are directly appended at the end of the +contract's code, also in ABI encoding. The constructor will access them through a hard-coded offset, and +not by using the ``codesize`` opcode, since this of course changes when appending +data to the code. .. index: variable cleanup @@ -143,35 +173,34 @@ Different types have different rules for cleaning up invalid values: .. index:: optimizer, common subexpression elimination, constant propagation ************************* -Internals - The Optimizer +Internals - The Optimiser ************************* -The Solidity optimizer operates on assembly, so it can be and also is used by other languages. It splits the sequence of instructions into basic blocks at ``JUMPs`` and ``JUMPDESTs``. Inside these blocks, the instructions are analysed and every modification to the stack, to memory or storage is recorded as an expression which consists of an instruction and a list of arguments which are essentially pointers to other expressions. The main idea is now to find expressions that are always equal (on every input) and combine them into an expression class. The optimizer first tries to find each new expression in a list of already known expressions. If this does not work, the expression is simplified according to rules like ``constant + constant = sum_of_constants`` or ``X * 1 = X``. Since this is done recursively, we can also apply the latter rule if the second factor is a more complex expression where we know that it will always evaluate to one. Modifications to storage and memory locations have to erase knowledge about storage and memory locations which are not known to be different: If we first write to location x and then to location y and both are input variables, the second could overwrite the first, so we actually do not know what is stored at x after we wrote to y. On the other hand, if a simplification of the expression x - y evaluates to a non-zero constant, we know that we can keep our knowledge about what is stored at x. +The Solidity optimiser operates on assembly so that other languages can use it. It splits the sequence of instructions into basic blocks at ``JUMPs`` and ``JUMPDESTs``. Inside these blocks, the optimiser analyses the instructions and records every modification to the stack, memory, or storage as an expression which consists of an instruction and a list of arguments which are pointers to other expressions. The optimiser uses a component called "CommonSubexpressionEliminator" that amongst other tasks, finds expressions that are always equal (on every input) and combines them into an expression class. The optimiser first tries to find each new expression in a list of already known expressions. If this does not work, it simplifies the expression according to rules like ``constant + constant = sum_of_constants`` or ``X * 1 = X``. Since this is a recursive process, we can also apply the latter rule if the second factor is a more complex expression where we know that it always evaluates to one. Modifications to storage and memory locations have to erase knowledge about storage and memory locations which are not known to be different. If we first write to location x and then to location y and both are input variables, the second could overwrite the first, so we do not know what is stored at x after we wrote to y. If simplification of the expression x - y evaluates to a non-zero constant, we know that we can keep our knowledge about what is stored at x. -At the end of this process, we know which expressions have to be on the stack in the end and have a list of modifications to memory and storage. This information is stored together with the basic blocks and is used to link them. Furthermore, knowledge about the stack, storage and memory configuration is forwarded to the next block(s). If we know the targets of all ``JUMP`` and ``JUMPI`` instructions, we can build a complete control flow graph of the program. If there is only one target we do not know (this can happen as in principle, jump targets can be computed from inputs), we have to erase all knowledge about the input state of a block as it can be the target of the unknown ``JUMP``. If a ``JUMPI`` is found whose condition evaluates to a constant, it is transformed to an unconditional jump. +After this process, we know which expressions have to be on the stack at the end, and have a list of modifications to memory and storage. This information is stored together with the basic blocks and is used to link them. Furthermore, knowledge about the stack, storage and memory configuration is forwarded to the next block(s). If we know the targets of all ``JUMP`` and ``JUMPI`` instructions, we can build a complete control flow graph of the program. If there is only one target we do not know (this can happen as in principle, jump targets can be computed from inputs), we have to erase all knowledge about the input state of a block as it can be the target of the unknown ``JUMP``. If the optimiser finds a ``JUMPI`` whose condition evaluates to a constant, it transforms it to an unconditional jump. -As the last step, the code in each block is completely re-generated. A dependency graph is created from the expressions on the stack at the end of the block and every operation that is not part of this graph is essentially dropped. Now code is generated that applies the modifications to memory and storage in the order they were made in the original code (dropping modifications which were found not to be needed) and finally, generates all values that are required to be on the stack in the correct place. +As the last step, the code in each block is re-generated. The optimiser creates a dependency graph from the expressions on the stack at the end of the block, and it drops every operation that is not part of this graph. It generates code that applies the modifications to memory and storage in the order they were made in the original code (dropping modifications which were found not to be needed). Finally, it generates all values that are required to be on the stack in the correct place. -These steps are applied to each basic block and the newly generated code is used as replacement if it is smaller. If a basic block is split at a ``JUMPI`` and during the analysis, the condition evaluates to a constant, the ``JUMPI`` is replaced depending on the value of the constant, and thus code like +These steps are applied to each basic block and the newly generated code is used as replacement if it is smaller. If a basic block is split at a ``JUMPI`` and during the analysis, the condition evaluates to a constant, the ``JUMPI`` is replaced depending on the value of the constant. Thus code like :: - var x = 7; + uint x = 7; data[7] = 9; if (data[x] != x + 2) return 2; else return 1; -is simplified to code which can also be compiled from +still simplifies to code which you can compile even though the instructions contained +a jump in the beginning of the process: :: data[7] = 9; return 1; -even though the instructions contained a jump in the beginning. - .. index:: source mappings *************** @@ -190,7 +219,7 @@ important for static analysis tools that operate on bytecode level and for displaying the current position in the source code inside a debugger or for breakpoint handling. -Both kinds of source mappings use integer indentifiers to refer to source files. +Both kinds of source mappings use integer identifiers to refer to source files. These are regular array indices into a list of source files usually called ``"sourceList"``, which is part of the combined-json and the output of the json / npm compiler. @@ -237,7 +266,6 @@ Tips and Tricks * 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. * If you end up checking conditions on input or state a lot at the beginning of your functions, try using :ref:`modifiers`. -* If your contract has a function called ``send`` but you want to use the built-in send-function, use ``address(contractVariable).send(amount)``. * Initialize storage structs with a single assignment: ``x = MyStruct({a: 1, b: 2});`` .. note:: @@ -273,7 +301,7 @@ The following is the order of precedence for operators, listed in order of evalu +------------+-------------------------------------+--------------------------------------------+ | *2* | Prefix increment and decrement | ``++``, ``--`` | + +-------------------------------------+--------------------------------------------+ -| | Unary plus and minus | ``+``, ``-`` | +| | Unary minus | ``-`` | + +-------------------------------------+--------------------------------------------+ | | Unary operations | ``delete`` | + +-------------------------------------+--------------------------------------------+ @@ -317,45 +345,42 @@ The following is the order of precedence for operators, listed in order of evalu Global Variables ================ -- ``abi.encode(...) returns (bytes)``: :ref:`ABI `-encodes the given arguments -- ``abi.encodePacked(...) returns (bytes)``: Performes :ref:`packed encoding ` of the given arguments -- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: :ref:`ABI `-encodes the given arguments +- ``abi.decode(bytes memory encodedData, (...)) returns (...)``: :ref:`ABI `-decodes the provided data. The types are given in parentheses as second argument. Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))`` +- ``abi.encode(...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments +- ``abi.encodePacked(...) returns (bytes memory)``: Performs :ref:`packed encoding ` of the given arguments +- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments starting from the second and prepends the given four-byte selector -- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)``` -- ``block.blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by ``blockhash(uint blockNumber)``. -- ``block.coinbase`` (``address``): current block miner's address +- ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``` +- ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number - ``block.timestamp`` (``uint``): current block timestamp - ``gasleft() returns (uint256)``: remaining gas - ``msg.data`` (``bytes``): complete calldata -- ``msg.gas`` (``uint``): remaining gas - deprecated in version 0.4.21 and to be replaced by ``gasleft()`` -- ``msg.sender`` (``address``): sender of the message (current call) +- ``msg.sender`` (``address payable``): sender of the message (current call) - ``msg.value`` (``uint``): number of wei sent with the message - ``now`` (``uint``): current block timestamp (alias for ``block.timestamp``) - ``tx.gasprice`` (``uint``): gas price of the transaction -- ``tx.origin`` (``address``): sender of the transaction (full call chain) +- ``tx.origin`` (``address payable``): sender of the transaction (full call chain) - ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error) - ``require(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component) -- ``require(bool condition, string message)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component). Also provide error message. +- ``require(bool condition, string memory message)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component). Also provide error message. - ``revert()``: abort execution and revert state changes -- ``revert(string message)``: abort execution and revert state changes providing an explanatory string +- ``revert(string memory message)``: abort execution and revert state changes providing an explanatory string - ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks -- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments ` -- ``sha3(...) returns (bytes32)``: an alias to ``keccak256`` -- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the :ref:`(tightly packed) arguments ` -- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the :ref:`(tightly packed) arguments ` +- ``keccak256(bytes memory) returns (bytes32)``: compute the Keccak-256 hash of the input +- ``sha256(bytes memory) returns (bytes32)``: compute the SHA-256 hash of the input +- ``ripemd160(bytes memory) returns (bytes20)``: compute the RIPEMD-160 hash of the input - ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error - ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. -- ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` +- ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` or ``address payable`` - ``super``: the contract one level higher in the inheritance hierarchy -- ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address -- ``suicide(address recipient)``: a deprecated alias to ``selfdestruct`` +- ``selfdestruct(address payable recipient)``: destroy the current contract, sending its funds to the given address - ``
.balance`` (``uint256``): balance of the :ref:`address` in Wei -- ``
.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure -- ``
.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure +- ``
.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure +- ``
.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure .. note:: Do not rely on ``block.timestamp``, ``now`` and ``blockhash`` as a source of randomness, @@ -374,6 +399,11 @@ Global Variables You can only access the hashes of the most recent 256 blocks, all other values will be zero. +.. note:: + In version 0.5.0, the following aliases were removed: ``suicide`` as alias for ``selfdestruct``, + ``msg.gas`` as alias for ``gasleft``, ``block.blockhash`` as alias for ``blockhash`` and + ``sha3`` as alias for ``keccak256``. + .. index:: visibility, public, private, external, internal Function Visibility Specifiers @@ -396,11 +426,10 @@ Function Visibility Specifiers Modifiers ========= -- ``pure`` for functions: Disallows modification or access of state - this is not enforced yet. -- ``view`` for functions: Disallows modification of state - this is not enforced yet. +- ``pure`` for functions: Disallows modification or access of state. +- ``view`` for functions: Disallows modification of state. - ``payable`` for functions: Allows them to receive Ether together with a call. - ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot. -- ``constant`` for functions: Same as ``view``. - ``anonymous`` for events: Does not store event signature as topic. - ``indexed`` for event parameters: Stores the parameter as topic. @@ -409,8 +438,11 @@ Reserved Keywords These keywords are reserved in Solidity. They might become part of the syntax in the future: -``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``let``, ``match``, ``null``, -``of``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``. +``abstract``, ``after``, ``alias``, ``apply``, ``auto``, ``case``, ``catch``, ``copyof``, ``default``, +``define``, ``final``, ``immutable``, ``implements``, ``in``, ``inline``, ``let``, ``macro``, ``match``, +``mutable``, ``null``, ``of``, ``override``, ``partial``, ``promise``, ``reference``, ``relocatable``, +``sealed``, ``sizeof``, ``static``, ``supports``, ``switch``, ``try``, ``type``, ``typedef``, ``typeof``, +``unchecked``. Language Grammar ================ diff --git a/docs/requirements.txt b/docs/requirements.txt index 0607b1efa..5fba631c7 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1,2 @@ sphinx_rtd_theme>=0.3.1 +pygments-lexer-solidity>=0.3.1 diff --git a/docs/resources.rst b/docs/resources.rst new file mode 100644 index 000000000..e9e656922 --- /dev/null +++ b/docs/resources.rst @@ -0,0 +1,132 @@ +Resources +--------- + +General +~~~~~~~ + +* `Ethereum `_ + +* `Changelog `_ + +* `Source Code `_ + +* `Ethereum Stackexchange `_ + +* `Language Users Chat `_ + +* `Compiler Developers Chat `_ + +Solidity Integrations +~~~~~~~~~~~~~~~~~~~~~ + +* Generic: + + + * `EthFiddle `_ + Solidity IDE in the Browser. Write and share your solidity code. Uses server-side components. + + * `Remix `_ + Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. + + * `Solium `_ + Linter to identify and fix style and security issues in Solidity. + + * `Solhint `_ + Solidity linter that provides security, style guide and best practice rules for smart contract validation. + +* Atom: + + * `Etheratom `_ + Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible). + + * `Atom Solidity Linter `_ + Plugin for the Atom editor that provides Solidity linting. + + * `Atom Solium Linter `_ + Configurable Solidty linter for Atom using Solium as a base. + +* Eclipse: + + * `YAKINDU Solidity Tools `_ + Eclipse based IDE. Features context sensitive code completion and help, code navigation, syntax coloring, built in compiler, quick fixes and templates. + +* Emacs: + + * `Emacs Solidity `_ + Plugin for the Emacs editor providing syntax highlighting and compilation error reporting. + +* IntelliJ: + + * `IntelliJ IDEA plugin `_ + Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs) + +* Sublime: + + * `Package for SublimeText - Solidity language syntax `_ + Solidity syntax highlighting for SublimeText editor. + +* Vim: + + * `Vim Solidity `_ + Plugin for the Vim editor providing syntax highlighting. + + * `Vim Syntastic `_ + Plugin for the Vim editor providing compile checking. + +* Visual Studio Code: + + * `Visual Studio Code extension `_ + Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. + +Discontinued: + +* `Mix IDE `_ + Qt based IDE for designing, debugging and testing solidity smart contracts. + +* `Ethereum Studio `_ + Specialized web IDE that also provides shell access to a complete Ethereum environment. + +* `Visual Studio Extension `_ + Solidity plugin for Microsoft Visual Studio that includes the Solidity compiler. + +Solidity Tools +~~~~~~~~~~~~~~ + +* `Dapp `_ + Build tool, package manager, and deployment assistant for Solidity. + +* `Solidity REPL `_ + Try Solidity instantly with a command-line Solidity console. + +* `solgraph `_ + Visualize Solidity control flow and highlight potential security vulnerabilities. + +* `Doxity `_ + Documentation Generator for Solidity. + +* `evmdis `_ + EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. + +* `ABI to solidity interface converter `_ + A script for generating contract interfaces from the ABI of a smart contract. + +* `Securify `_ + Fully automated online static analyzer for smart contracts, providing a security report based on vulnerability patterns. + +* `Sūrya `_ + Utility tool for smart contract systems, offering a number of visual outputs and information about the contracts' structure. Also supports querying the function call graph. + +* `EVM Lab `_ + Rich tool package to interact with the EVM. Includes a VM, Etherchain API, and a trace-viewer with gas cost display. + +.. note:: + Information like variable names, comments, and source code formatting is lost in the compilation process and it is not possible to completely recover the original source code. Decompiling smart contracts to view the original source code might not be possible, or the end result that useful. + +Third-Party Solidity Parsers and Grammars +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* `solidity-parser `_ + Solidity parser for JavaScript + +* `Solidity Grammar for ANTLR 4 `_ + Solidity grammar for the ANTLR 4 parser generator diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 4133edb14..bd06276b4 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -55,7 +55,7 @@ complete contract): :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract Fund { @@ -78,7 +78,7 @@ as it uses ``call`` which forwards all remaining gas by default: :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract Fund { @@ -86,7 +86,8 @@ as it uses ``call`` which forwards all remaining gas by default: mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { - if (msg.sender.call.value(shares[msg.sender])()) + (bool success,) = msg.sender.call.value(shares[msg.sender])(""); + if (success) shares[msg.sender] = 0; } } @@ -96,14 +97,14 @@ outlined further below: :: - pragma solidity ^0.4.11; + pragma solidity >=0.4.11 <0.6.0; contract Fund { /// Mapping of ether shares of the contract. mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { - var share = shares[msg.sender]; + uint share = shares[msg.sender]; shares[msg.sender] = 0; msg.sender.transfer(share); } @@ -135,15 +136,16 @@ Sending and Receiving Ether - If a contract receives Ether (without a function being called), the fallback function is executed. If it does not have a fallback function, the Ether will be rejected (by throwing an exception). During the execution of the fallback function, the contract can only rely - on the "gas stipend" (2300 gas) being available to it at that time. This stipend is not enough to access storage in any way. + on the "gas stipend" it is passed (2300 gas) being available to it at that time. This stipend is not enough to modify storage + (do not take this for granted though, the stipend might change with future hard forks). To be sure that your contract can receive Ether in that way, check the gas requirements of the fallback function (for example in the "details" section in Remix). - There is a way to forward more gas to the receiving contract using - ``addr.call.value(x)()``. This is essentially the same as ``addr.transfer(x)``, + ``addr.call.value(x)("")``. This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas and opens up the ability for the - recipient to perform more expensive actions (and it only returns a failure code - and does not automatically propagate the error). This might include calling back + recipient to perform more expensive actions (and it returns a failure code + instead of automatically propagating the error). This might include calling back into the sending contract or other state changes you might not have thought of. So it allows for great flexibility for honest users but also for malicious actors. @@ -171,7 +173,8 @@ before they interact with your contract. Note that ``.send()`` does **not** throw an exception if the call stack is depleted but rather returns ``false`` in that case. The low-level functions -``.call()``, ``.callcode()`` and ``.delegatecall()`` behave in the same way. +``.call()``, ``.callcode()``, ``.delegatecall()`` and ``.staticcall()`` behave +in the same way. tx.origin ========= @@ -180,17 +183,17 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like :: - pragma solidity ^0.4.11; + pragma solidity >0.4.99 <0.6.0; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract TxUserWallet { address owner; - function TxUserWallet() public { + constructor() public { owner = msg.sender; } - function transferTo(address dest, uint amount) public { + function transferTo(address payable dest, uint amount) public { require(tx.origin == owner); dest.transfer(amount); } @@ -200,20 +203,20 @@ Now someone tricks you into sending ether to the address of this attack wallet: :: - pragma solidity ^0.4.11; + pragma solidity >0.4.99 <0.6.0; interface TxUserWallet { - function transferTo(address dest, uint amount) public; + function transferTo(address payable dest, uint amount) external; } contract TxAttackWallet { - address owner; + address payable owner; - function TxAttackWallet() public { + constructor() public { owner = msg.sender; } - function() public { + function() external { TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance); } } @@ -221,10 +224,29 @@ Now someone tricks you into sending ether to the address of this attack wallet: If your wallet had checked ``msg.sender`` for authorization, it would get the address of the attack wallet, instead of the owner address. But by checking ``tx.origin``, it gets the original address that kicked off the transaction, which is still the owner address. The attack wallet instantly drains all your funds. + +Two's Complement / Underflows / Overflows +========================================= + +As in many programming languages, Solidity's integer types are not actually integers. +They resemble integers when the values are small, but behave differently if the numbers are larger. +For example, the following is true: ``uint8(255) + uint8(1) == 0``. This situation is called +an *overflow*. It occurs when an operation is performed that requires a fixed size variable +to store a number (or piece of data) that is outside the range of the variable's data type. +An *underflow* is the converse situation: ``uint8(0) - uint8(1) == 255``. + +In general, read about the limits of two's complement representation, which even has some +more special edge cases for signed numbers. + +Try to use ``require`` to limit the size of inputs to a reasonable range and use the +:ref:`SMT checker` to find potential overflows, or +use a library like +`SafeMath` +if you want all overflows to cause a revert. + Minor Details ============= -- In ``for (var i = 0; i < arrayName.length; i++) { ... }``, the type of ``i`` will be ``uint8``, because this is the smallest type that is required to hold the value ``0``. If the array has more than 255 elements, the loop will not terminate. - Types that do not occupy the full 32 bytes might contain "dirty higher order bits". This is especially important if you access ``msg.data`` - it poses a malleability risk: You can craft transactions that call a function ``f(uint8 x)`` with a raw byte argument @@ -245,12 +267,8 @@ implications, there might be another issue buried beneath it. Any compiler warning we issue can be silenced by slight changes to the code. -Also try to enable the "0.5.0" safety features as early as possible -by adding ``pragma experimental "v0.5.0";``. Note that in this case, -the word ``experimental`` does not mean that the safety features are in any -way risky, it is just a way to enable some features that are -not yet part of the latest version of Solidity due to backwards -compatibility. +Always use the latest version of the compiler to be notified about all recently +introduced warnings. Restrict the Amount of Ether ============================ @@ -304,6 +322,12 @@ of "failsafe" mode, which, for example, disables most of the features, hands ove control to a fixed and trusted third party or just converts the contract into a simple "give me back my money" contract. +Ask for Peer Review +=================== + +The more people examine a piece of code, the more issues are found. +Asking people to review your code also helps as a cross-check to find out whether your code +is easy to understand - a very important criterion for good smart contracts. ******************* Formal Verification diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 2b3d4b484..752e86418 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -36,7 +36,7 @@ of votes. :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; /// @title Voting with delegation. contract Ballot { @@ -66,7 +66,7 @@ of votes. Proposal[] public proposals; /// Create a new ballot to choose one of `proposalNames`. - constructor(bytes32[] proposalNames) public { + constructor(bytes32[] memory proposalNames) public { chairperson = msg.sender; voters[chairperson].weight = 1; @@ -90,7 +90,7 @@ of votes. // If the first argument of `require` evaluates // to `false`, execution terminates and all // changes to the state and to Ether balances - // are reverted. + // are reverted. // This used to consume all gas in old EVM versions, but // not anymore. // It is often a good idea to use `require` to check if @@ -152,6 +152,7 @@ of votes. /// to proposal `proposals[proposal].name`. function vote(uint proposal) public { Voter storage sender = voters[msg.sender]; + require(sender.weight != 0, "Has no right to vote"); require(!sender.voted, "Already voted."); sender.voted = true; sender.vote = proposal; @@ -220,19 +221,19 @@ bid. If the highest bid is raised, the previously highest bidder gets her money back. After the end of the bidding period, the contract has to be called manually for the -beneficiary to receive his money - contracts cannot +beneficiary to receive their money - contracts cannot activate themselves. :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract SimpleAuction { // Parameters of the auction. Times are either // absolute unix timestamps (seconds since 1970-01-01) // or time periods in seconds. - address public beneficiary; - uint public auctionEnd; + address payable public beneficiary; + uint public auctionEndTime; // Current state of the auction. address public highestBidder; @@ -241,10 +242,11 @@ activate themselves. // Allowed withdrawals of previous bids mapping(address => uint) pendingReturns; - // Set to true at the end, disallows any change + // Set to true at the end, disallows any change. + // By default initialized to `false`. bool ended; - // Events that will be fired on changes. + // Events that will be emitted on changes. event HighestBidIncreased(address bidder, uint amount); event AuctionEnded(address winner, uint amount); @@ -258,10 +260,10 @@ activate themselves. /// beneficiary address `_beneficiary`. constructor( uint _biddingTime, - address _beneficiary + address payable _beneficiary ) public { beneficiary = _beneficiary; - auctionEnd = now + _biddingTime; + auctionEndTime = now + _biddingTime; } /// Bid on the auction with the value sent @@ -278,7 +280,7 @@ activate themselves. // Revert the call if the bidding // period is over. require( - now <= auctionEnd, + now <= auctionEndTime, "Auction already ended." ); @@ -337,7 +339,7 @@ activate themselves. // external contracts. // 1. Conditions - require(now >= auctionEnd, "Auction not yet ended."); + require(now >= auctionEndTime, "Auction not yet ended."); require(!ended, "auctionEnd has already been called."); // 2. Effects @@ -372,7 +374,7 @@ is the same as the one provided during the bidding period. Another challenge is how to make the auction **binding and blind** at the same time: The only way to prevent the bidder from just not sending the money -after he won the auction is to make her send it +after they won the auction is to make her send it together with the bid. Since value transfers cannot be blinded in Ethereum, anyone can see the value. @@ -388,7 +390,7 @@ high or low invalid bids. :: - pragma solidity >0.4.23 <0.5.0; + pragma solidity >0.4.23 <0.6.0; contract BlindAuction { struct Bid { @@ -396,7 +398,7 @@ high or low invalid bids. uint deposit; } - address public beneficiary; + address payable public beneficiary; uint public biddingEnd; uint public revealEnd; bool public ended; @@ -421,15 +423,15 @@ high or low invalid bids. constructor( uint _biddingTime, uint _revealTime, - address _beneficiary + address payable _beneficiary ) public { beneficiary = _beneficiary; biddingEnd = now + _biddingTime; revealEnd = biddingEnd + _revealTime; } - /// Place a blinded bid with `_blindedBid` = keccak256(value, - /// fake, secret). + /// Place a blinded bid with `_blindedBid` = + /// keccak256(abi.encodePacked(value, fake, secret)). /// The sent ether is only refunded if the bid is correctly /// revealed in the revealing phase. The bid is valid if the /// ether sent together with the bid is at least "value" and @@ -452,9 +454,9 @@ high or low invalid bids. /// correctly blinded invalid bids and for all bids except for /// the totally highest. function reveal( - uint[] _values, - bool[] _fake, - bytes32[] _secret + uint[] memory _values, + bool[] memory _fake, + bytes32[] memory _secret ) public onlyAfter(biddingEnd) @@ -467,22 +469,22 @@ high or low invalid bids. uint refund; for (uint i = 0; i < length; i++) { - Bid storage bid = bids[msg.sender][i]; + Bid storage bidToCheck = bids[msg.sender][i]; (uint value, bool fake, bytes32 secret) = (_values[i], _fake[i], _secret[i]); - if (bid.blindedBid != keccak256(value, fake, secret)) { + if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) { // Bid was not actually revealed. // Do not refund deposit. continue; } - refund += bid.deposit; - if (!fake && bid.deposit >= value) { + refund += bidToCheck.deposit; + if (!fake && bidToCheck.deposit >= value) { if (placeBid(msg.sender, value)) refund -= value; } // Make it impossible for the sender to re-claim // the same deposit. - bid.blindedBid = bytes32(0); + bidToCheck.blindedBid = bytes32(0); } msg.sender.transfer(refund); } @@ -496,7 +498,7 @@ high or low invalid bids. if (value <= highestBid) { return false; } - if (highestBidder != 0) { + if (highestBidder != address(0)) { // Refund the previously highest bidder. pendingReturns[highestBidder] += highestBid; } @@ -541,12 +543,12 @@ Safe Remote Purchase :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract Purchase { uint public value; - address public seller; - address public buyer; + address payable public seller; + address payable public buyer; enum State { Created, Locked, Inactive } State public state; @@ -645,4 +647,489 @@ Safe Remote Purchase Micropayment Channel ******************** -To be written. +In this section we will learn how to build a simple implementation +of a payment channel. It use cryptographics signatures to make +repeated transfers of Ether between the same parties secure, instantaneous, and +without transaction fees. To do it we need to understand how to +sign and verify signatures, and setup the payment channel. + +Creating and verifying signatures +================================= + +Imagine Alice wants to send a quantity of Ether to Bob, i.e. +Alice is the sender and the Bob is the recipient. +Alice only needs to send cryptographically signed messages off-chain +(e.g. via email) to Bob and it will be very similar to writing checks. + +Signatures are used to authorize transactions, +and they are a general tool that is available to +smart contracts. Alice will build a simple +smart contract that lets her transmit Ether, but +in a unusual way, instead of calling a function herself +to initiate a payment, she will let Bob +do that, and therefore pay the transaction fee. +The contract will work as follows: + + 1. Alice deploys the ``ReceiverPays`` contract, attaching enough Ether to cover the payments that will be made. + 2. Alice authorizes a payment by signing a message with their private key. + 3. Alice sends the cryptographically signed message to Bob. The message does not need to be kept secret + (you will understand it later), and the mechanism for sending it does not matter. + 4. Bob claims their payment by presenting the signed message to the smart contract, it verifies the + authenticity of the message and then releases the funds. + +Creating the signature +---------------------- + +Alice does not need to interact with Ethereum network to +sign the transaction, the process is completely offline. +In this tutorial, we will sign messages in the browser +using ``web3.js`` and ``MetaMask``. +In particular, we will use the standard way described in `EIP-762 `_, +as it provides a number of other security benefits. + +:: + + /// Hashing first makes a few things easier + var hash = web3.sha3("message to sign"); + web3.personal.sign(hash, web3.eth.defaultAccount, function () {...}); + + +Note that the ``web3.personal.sign`` prepends the length of the message to the signed data. +Since we hash first, the message will always be exactly 32 bytes long, +and thus this length prefix is always the same, making everything easier. + +What to Sign +------------ + +For a contract that fulfills payments, the signed message must include: + + 1. The recipient's address + 2. The amount to be transferred + 3. Protection against replay attacks + +A replay attack is when a signed message is reused to claim authorization for +a second action. +To avoid replay attacks we will use the same as in Ethereum transactions +themselves, a so-called nonce, which is the number of transactions sent by an +account. +The smart contract will check if a nonce is used multiple times. + +There is another type of replay attacks, it occurs when the +owner deploys a ``ReceiverPays`` smart contract, performs some payments, +and then destroy the contract. Later, she decides to deploy the +``RecipientPays`` smart contract again, but the new contract does not +know the nonces used in the previous deployment, so the attacker +can use the old messages again. + +Alice can protect against it including +the contract's address in the message, and only +messages containing contract's address itself will be accepted. +This functionality can be found in the first two lines of the ``claimPayment()`` function in the full contract +at the end of this chapter. + +Packing arguments +----------------- + +Now that we have identified what information to include in the +signed message, we are ready to put the message together, hash it, +and sign it. For simplicity, we just concatenate the data. +The +`ethereumjs-abi `_ library provides +a function called ``soliditySHA3`` that mimics the behavior +of Solidity's ``keccak256`` function applied to arguments encoded +using ``abi.encodePacked``. +Putting it all together, here is a JavaScript function that +creates the proper signature for the ``ReceiverPays`` example: + +:: + + // recipient is the address that should be paid. + // amount, in wei, specifies how much ether should be sent. + // nonce can be any unique number to prevent replay attacks + // contractAddress is used to prevent cross-contract replay attacks + function signPayment(recipient, amount, nonce, contractAddress, callback) { + var hash = "0x" + ethereumjs.ABI.soliditySHA3( + ["address", "uint256", "uint256", "address"], + [recipient, amount, nonce, contractAddress] + ).toString("hex"); + + web3.personal.sign(hash, web3.eth.defaultAccount, callback); + } + +Recovering the Message Signer in Solidity +----------------------------------------- + +In general, ECDSA signatures consist of two parameters, ``r`` and ``s``. +Signatures in Ethereum include a third parameter called ``v``, that can be used +to recover which account's private key was used to sign in the message, +the transaction's sender. Solidity provides a built-in function +`ecrecover `_ +that accepts a message along with the ``r``, ``s`` and ``v`` parameters and +returns the address that was used to sign the message. + +Extracting the Signature Parameters +----------------------------------- + +Signatures produced by web3.js are the concatenation of ``r``, ``s`` and ``v``, +so the first step is splitting those parameters back out. It can be done on the client, +but doing it inside the smart contract means only one signature parameter +needs to be sent rather than three. +Splitting apart a byte array into component parts is a little messy. +We will use `inline assembly `_ to do the job +in the ``splitSignature`` function (the third function in the full contract +at the end of this chapter). + +Computing the Message Hash +-------------------------- + +The smart contract needs to know exactly what parameters were signed, +and so it must recreate the message from the parameters and use that +for signature verification. The functions ``prefixed`` and +``recoverSigner`` do this and their use can be found in the +``claimPayment`` function. + + +The full contract +----------------- + +:: + + pragma solidity >=0.4.24 <0.6.0; + + contract ReceiverPays { + address owner = msg.sender; + + mapping(uint256 => bool) usedNonces; + + constructor() public payable {} + + function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) public { + require(!usedNonces[nonce]); + usedNonces[nonce] = true; + + // this recreates the message that was signed on the client + bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this))); + + require(recoverSigner(message, signature) == owner); + + msg.sender.transfer(amount); + } + + /// destroy the contract and reclaim the leftover funds. + function kill() public { + require(msg.sender == owner); + selfdestruct(msg.sender); + } + + /// signature methods. + function splitSignature(bytes memory sig) + internal + pure + returns (uint8 v, bytes32 r, bytes32 s) + { + require(sig.length == 65); + + assembly { + // first 32 bytes, after the length prefix. + r := mload(add(sig, 32)) + // second 32 bytes. + s := mload(add(sig, 64)) + // final byte (first byte of the next 32 bytes). + v := byte(0, mload(add(sig, 96))) + } + + return (v, r, s); + } + + function recoverSigner(bytes32 message, bytes memory sig) + internal + pure + returns (address) + { + (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); + + return ecrecover(message, v, r, s); + } + + /// builds a prefixed hash to mimic the behavior of eth_sign. + function prefixed(bytes32 hash) internal pure returns (bytes32) { + return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + } + } + + +Writing a Simple Payment Channel +================================ + +Alice will now build a simple but complete implementation of a payment channel. +Payment channels use cryptographic signatures to make repeated transfers +of Ether securely, instantaneously, and without transaction fees. + +What is a Payment Channel? +-------------------------- + +Payment channels allow participants to make repeated transfers of Ether without +using transactions. This means that the delays and fees associated with transactions +can be avoided. We are going to explore a simple unidirectional payment channel between +two parties (Alice and Bob). Using it involves three steps: + + 1. Alice funds a smart contract with Ether. This "opens" the payment channel. + 2. Alice signs messages that specify how much of that Ether is owed to the recipient. This step is repeated for each payment. + 3. Bob "closes" the payment channel, withdrawing their portion of the Ether and sending the remainder back to the sender. + +Note that only steps 1 and 3 require Ethereum transactions, step 2 means that +the sender transmits a cryptographically signed message to the recipient via off chain ways (e.g. email). +This means only two transactions are required to support any number of transfers. + +Bob is guaranteed to receive their funds because the smart contract escrows +the Ether and honors a valid signed message. The smart contract also enforces a timeout, +so Alice is guaranteed to eventually recover their funds even if the recipient refuses +to close the channel. +It is up to the participants in a payment channel to decide how long to keep it open. +For a short-lived transaction, such as paying an internet cafe for each minute of network access, +or for a longer relationship, such as paying an employee an hourly wage, a payment could last for months or years. + +Opening the Payment Channel +--------------------------- + +To open the payment channel, Alice deploys the smart contract, +attaching the Ether to be escrowed and specifying the intendend recipient +and a maximum duration for the channel to exist. It is the function +``SimplePaymentChannel`` in the contract, that is at the end of this chapter. + +Making Payments +--------------- + +Alice makes payments by sending signed messages to Bob. +This step is performed entirely outside of the Ethereum network. +Messages are cryptographically signed by the sender and then transmitted directly to the recipient. + +Each message includes the following information: + + * The smart contract's address, used to prevent cross-contract replay attacks. + * The total amount of Ether that is owed the recipient so far. + +A payment channel is closed just once, at the end of a series of transfers. +Because of this, only one of the messages sent will be redeemed. This is why +each message specifies a cumulative total amount of Ether owed, rather than the +amount of the individual micropayment. The recipient will naturally choose to +redeem the most recent message because that is the one with the highest total. +The nonce per-message is not needed anymore, because the smart contract will +only honor a single message. The address of the smart contract is still used +to prevent a message intended for one payment channel from being used for a different channel. + +Here is the modified javascript code to cryptographically sign a message from the previous chapter: + +:: + + function constructPaymentMessage(contractAddress, amount) { + return ethereumjs.ABI.soliditySHA3( + ["address", "uint256"], + [contractAddress, amount] + ); + } + + function signMessage(message, callback) { + web3.personal.sign( + "0x" + message.toString("hex"), + web3.eth.defaultAccount, + callback + ); + } + + // contractAddress is used to prevent cross-contract replay attacks. + // amount, in wei, specifies how much Ether should be sent. + + function signPayment(contractAddress, amount, callback) { + var message = constructPaymentMessage(contractAddress, amount); + signMessage(message, callback); + } + + +Closing the Payment Channel +--------------------------- + +When Bob is ready to receive their funds, it is time to +close the payment channel by calling a ``close`` function on the smart contract. +Closing the channel pays the recipient the Ether they are owed and destroys the contract, +sending any remaining Ether back to Alice. +To close the channel, Bob needs to provide a message signed by Alice. + +The smart contract must verify that the message contains a valid signature from the sender. +The process for doing this verification is the same as the process the recipient uses. +The Solidity functions ``isValidSignature`` and ``recoverSigner`` work just like their +JavaScript counterparts in the previous section. The latter is borrowed from the +``ReceiverPays`` contract in the previous chapter. + +The ``close`` function can only be called by the payment channel recipient, +who will naturally pass the most recent payment message because that message +carries the highest total owed. If the sender were allowed to call this function, +they could provide a message with a lower amount and cheat the recipient out of what they are owed. + +The function verifies the signed message matches the given parameters. +If everything checks out, the recipient is sent their portion of the Ether, +and the sender is sent the rest via a ``selfdestruct``. +You can see the ``close`` function in the full contract. + +Channel Expiration +------------------- + +Bob can close the payment channel at any time, but if they fail to do so, +Alice needs a way to recover their escrowed funds. An *expiration* time was set +at the time of contract deployment. Once that time is reached, Alice can call +``claimTimeout`` to recover their funds. You can see the ``claimTimeout`` function in the +full contract. + +After this function is called, Bob can no longer receive any Ether, +so it is important that Bob closes the channel before the expiration is reached. + + +The full contract +----------------- + +:: + + pragma solidity >=0.4.24 <0.6.0; + + contract SimplePaymentChannel { + address payable public sender; // The account sending payments. + address payable public recipient; // The account receiving the payments. + uint256 public expiration; // Timeout in case the recipient never closes. + + constructor (address payable _recipient, uint256 duration) + public + payable + { + sender = msg.sender; + recipient = _recipient; + expiration = now + duration; + } + + function isValidSignature(uint256 amount, bytes memory signature) + internal + view + returns (bool) + { + bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount))); + + // check that the signature is from the payment sender + return recoverSigner(message, signature) == sender; + } + + /// the recipient can close the channel at any time by presenting a + /// signed amount from the sender. the recipient will be sent that amount, + /// and the remainder will go back to the sender + function close(uint256 amount, bytes memory signature) public { + require(msg.sender == recipient); + require(isValidSignature(amount, signature)); + + recipient.transfer(amount); + selfdestruct(sender); + } + + /// the sender can extend the expiration at any time + function extend(uint256 newExpiration) public { + require(msg.sender == sender); + require(newExpiration > expiration); + + expiration = newExpiration; + } + + /// if the timeout is reached without the recipient closing the channel, + /// then the Ether is released back to the sender. + function claimTimeout() public { + require(now >= expiration); + selfdestruct(sender); + } + + /// All functions below this are just taken from the chapter + /// 'creating and verifying signatures' chapter. + + function splitSignature(bytes memory sig) + internal + pure + returns (uint8 v, bytes32 r, bytes32 s) + { + require(sig.length == 65); + + assembly { + // first 32 bytes, after the length prefix + r := mload(add(sig, 32)) + // second 32 bytes + s := mload(add(sig, 64)) + // final byte (first byte of the next 32 bytes) + v := byte(0, mload(add(sig, 96))) + } + + return (v, r, s); + } + + function recoverSigner(bytes32 message, bytes memory sig) + internal + pure + returns (address) + { + (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); + + return ecrecover(message, v, r, s); + } + + /// builds a prefixed hash to mimic the behavior of eth_sign. + function prefixed(bytes32 hash) internal pure returns (bytes32) { + return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + } + } + + +Note: The function ``splitSignature`` is very simple and does not use all security checks. +A real implementation should use a more rigorously tested library, such as +openzepplin's `version `_ of this code. + + + +Verifying Payments +------------------ + +Unlike in our previous chapter, messages in a payment channel aren't +redeemed right away. The recipient keeps track of the latest message and +redeems it when it's time to close the payment channel. This means it's +critical that the recipient perform their own verification of each message. +Otherwise there is no guarantee that the recipient will be able to get paid +in the end. + +The recipient should verify each message using the following process: + + 1. Verify that the contact address in the message matches the payment channel. + 2. Verify that the new total is the expected amount. + 3. Verify that the new total does not exceed the amount of Ether escrowed. + 4. Verify that the signature is valid and comes from the payment channel sender. + +We'll use the `ethereumjs-util `_ +library to write this verifications. The final step can be done a number of ways, +but if it's being done in **JavaScript**. +The following code borrows the `constructMessage` function from the signing **JavaScript code** +above: + +:: + + // this mimics the prefixing behavior of the eth_sign JSON-RPC method. + function prefixed(hash) { + return ethereumjs.ABI.soliditySHA3( + ["string", "bytes32"], + ["\x19Ethereum Signed Message:\n32", hash] + ); + } + + function recoverSigner(message, signature) { + var split = ethereumjs.Util.fromRpcSig(signature); + var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s); + var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex"); + return signer; + } + + function isValidSignature(contractAddress, amount, signature, expectedSigner) { + var message = prefixed(constructPaymentMessage(contractAddress, amount)); + var signer = recoverSigner(message, signature); + return signer.toLowerCase() == + ethereumjs.Util.stripHexPrefix(expectedSigner).toLowerCase(); + } diff --git a/docs/solidity-in-depth.rst b/docs/solidity-in-depth.rst index b6217b479..ddfddb77b 100644 --- a/docs/solidity-in-depth.rst +++ b/docs/solidity-in-depth.rst @@ -4,7 +4,7 @@ Solidity in Depth This section should provide you with all you need to know about Solidity. If something is missing here, please contact us on -`Gitter `_ or make a pull request on +`Gitter `_ or create a pull request on `Github `_. .. toctree:: @@ -18,3 +18,4 @@ If something is missing here, please contact us on contracts.rst assembly.rst miscellaneous.rst + 050-breaking-changes.rst diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index 7a6317eba..582e53381 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -11,16 +11,22 @@ Each contract can contain declarations of :ref:`structure-state-variables`, :ref :ref:`structure-function-modifiers`, :ref:`structure-events`, :ref:`structure-struct-types` and :ref:`structure-enum-types`. Furthermore, contracts can inherit from other contracts. +There are also special kinds of contracts called :ref:`libraries` and :ref:`interfaces`. + +The section about :ref:`contracts` contains more details than this section, +which serves to provide a quick overview. + .. _structure-state-variables: State Variables =============== -State variables are values which are permanently stored in contract storage. +State variables are variables whose values are permanently stored in contract +storage. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract SimpleStorage { uint storedData; // State variable @@ -40,7 +46,7 @@ Functions are the executable units of code within a contract. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract SimpleAuction { function bid() public payable { // Function @@ -49,7 +55,7 @@ Functions are the executable units of code within a contract. } :ref:`function-calls` can happen internally or externally -and have different levels of visibility (:ref:`visibility-and-getters`) +and have different levels of :ref:`visibility` towards other contracts. .. _structure-function-modifiers: @@ -58,11 +64,11 @@ Function Modifiers ================== Function modifiers can be used to amend the semantics of functions in a declarative way -(see :ref:`modifiers` in contracts section). +(see :ref:`modifiers` in the contracts section). :: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract Purchase { address public seller; @@ -75,7 +81,7 @@ Function modifiers can be used to amend the semantics of functions in a declarat _; } - function abort() public onlySeller { // Modifier usage + function abort() public view onlySeller { // Modifier usage // ... } } @@ -89,7 +95,7 @@ Events are convenience interfaces with the EVM logging facilities. :: - pragma solidity ^0.4.21; + pragma solidity >=0.4.21 <0.6.0; contract SimpleAuction { event HighestBidIncreased(address bidder, uint amount); // Event @@ -113,7 +119,7 @@ Structs are custom defined types that can group several variables (see :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract Ballot { struct Voter { // Struct @@ -134,7 +140,7 @@ Enums can be used to create custom types with a finite set of 'constant values' :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract Purchase { enum State { Created, Locked, Inactive } // Enum diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 6b28f2ab5..7b48ccada 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -52,31 +52,35 @@ Surround top level declarations in solidity source with two blank lines. Yes:: + pragma solidity >=0.4.0 <0.6.0; + contract A { - ... + // ... } contract B { - ... + // ... } contract C { - ... + // ... } No:: + pragma solidity >=0.4.0 <0.6.0; + contract A { - ... + // ... } contract B { - ... + // ... } contract C { - ... + // ... } Within a contract surround function declarations with a single blank line. @@ -85,44 +89,48 @@ Blank lines may be omitted between groups of related one-liners (such as stub fu Yes:: + pragma solidity >=0.4.0 <0.6.0; + contract A { - function spam() public; - function ham() public; + function spam() public pure; + function ham() public pure; } contract B is A { - function spam() public { - ... + function spam() public pure { + // ... } - function ham() public { - ... + function ham() public pure { + // ... } } No:: + pragma solidity >=0.4.0 <0.6.0; + contract A { - function spam() public { - ... + function spam() public pure { + // ... } - function ham() public { - ... + function ham() public pure { + // ... } } .. _maximum_line_length: -Maximum Line Length +Maximum Line Length =================== -Keeping lines under the `PEP 8 recommendation `_ to a maximum of 79 (or 99) +Keeping lines under the `PEP 8 recommendation `_ to a maximum of 79 (or 99) characters helps readers easily parse the code. Wrapped lines should conform to the following guidelines. -1. The first argument should not be attached to the opening parenthesis. +1. The first argument should not be attached to the opening parenthesis. 2. One, and only one, indent should be used. 3. Each argument should fall on its own line. 4. The terminating element, :code:`);`, should be placed on the final line by itself. @@ -132,38 +140,38 @@ Function Calls Yes:: thisFunctionCallIsReallyLong( - longArgument1, - longArgument2, + longArgument1, + longArgument2, longArgument3 ); No:: - thisFunctionCallIsReallyLong(longArgument1, - longArgument2, + thisFunctionCallIsReallyLong(longArgument1, + longArgument2, longArgument3 ); - - thisFunctionCallIsReallyLong(longArgument1, - longArgument2, + + thisFunctionCallIsReallyLong(longArgument1, + longArgument2, longArgument3 - ); - + ); + thisFunctionCallIsReallyLong( longArgument1, longArgument2, longArgument3 - ); + ); thisFunctionCallIsReallyLong( - longArgument1, - longArgument2, + longArgument1, + longArgument2, longArgument3 ); thisFunctionCallIsReallyLong( - longArgument1, - longArgument2, - longArgument3); + longArgument1, + longArgument2, + longArgument3); Assignment Statements @@ -188,8 +196,8 @@ Event Definitions and Event Emitters Yes:: event LongAndLotsOfArgs( - adress sender, - adress recipient, + address sender, + address recipient, uint256 publicKey, uint256 amount, bytes32[] options @@ -205,8 +213,8 @@ Yes:: No:: - event LongAndLotsOfArgs(adress sender, - adress recipient, + event LongAndLotsOfArgs(address sender, + address recipient, uint256 publicKey, uint256 amount, bytes32[] options); @@ -215,7 +223,7 @@ No:: recipient, publicKey, amount, - options); + options); Source File Encoding ==================== @@ -229,30 +237,32 @@ Import statements should always be placed at the top of the file. Yes:: - import "owned"; + pragma solidity >=0.4.0 <0.6.0; + import "./Owned.sol"; contract A { - ... + // ... } - - contract B is owned { - ... + contract B is Owned { + // ... } No:: + pragma solidity >=0.4.0 <0.6.0; + contract A { - ... + // ... } - import "owned"; + import "./Owned.sol"; - contract B is owned { - ... + contract B is Owned { + // ... } Order of Functions @@ -273,13 +283,15 @@ Within a grouping, place the ``view`` and ``pure`` functions last. Yes:: + pragma solidity >=0.4.0 <0.6.0; + contract A { - function A() public { - ... + constructor() public { + // ... } - function() public { - ... + function() external { + // ... } // External functions @@ -303,23 +315,25 @@ Yes:: No:: + pragma solidity >=0.4.0 <0.6.0; + contract A { // External functions // ... + function() external { + // ... + } + // Private functions // ... // Public functions // ... - function A() public { - ... - } - - function() public { - ... + constructor() public { + // ... } // Internal functions @@ -374,13 +388,13 @@ Don't include a whitespace in the fallback function: Yes:: - function() public { + function() external { ... } No:: - function () public { + function () external { ... } @@ -397,6 +411,8 @@ should: Yes:: + pragma solidity >=0.4.0 <0.6.0; + contract Coin { struct Bank { address owner; @@ -406,6 +422,8 @@ Yes:: No:: + pragma solidity >=0.4.0 <0.6.0; + contract Coin { struct Bank { @@ -529,7 +547,7 @@ No:: function increment(uint x) public pure returns (uint) { return x + 1;} -You should explicitly label the visibility of all functions, including constructors. +You should explicitly label the visibility of all functions, including constructors. Yes:: @@ -540,7 +558,7 @@ Yes:: No:: function implicitlyPublic(uint val) { - doSomething(); + doSomething(); } The visibility modifier for a function should come before any custom @@ -663,19 +681,19 @@ Yes:: address a, address b, address c - ) - public + ) + public returns ( - address someAddressName, - uint256 LongArgument, + address someAddressName, + uint256 LongArgument, uint256 Argument ) - { + { doSomething() - + return ( - veryLongReturnArg1, - veryLongReturnArg2, + veryLongReturnArg1, + veryLongReturnArg2, veryLongReturnArg3 ); } @@ -686,16 +704,16 @@ No:: address a, address b, address c - ) - public - returns (address someAddressName, - uint256 LongArgument, + ) + public + returns (address someAddressName, + uint256 LongArgument, uint256 Argument) - { + { doSomething() - - return (veryLongReturnArg1, - veryLongReturnArg1, + + return (veryLongReturnArg1, + veryLongReturnArg1, veryLongReturnArg1); } @@ -705,37 +723,76 @@ manner as modifiers if the function declaration is long or hard to read. Yes:: + pragma solidity >=0.4.0 <0.6.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 { - function A(uint param1, uint param2, uint param3, uint param4, uint param5) + uint x; + + constructor(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { // do something with param5 + x = param5; } } No:: + pragma solidity >=0.4.0 <0.6.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 { - function A(uint param1, uint param2, uint param3, uint param4, uint param5) + uint x; + + constructor(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { - // do something with param5 + x = param5; } } - contract A is B, C, D { - function A(uint param1, uint param2, uint param3, uint param4, uint param5) + contract X is B, C, D { + uint x; + + constructor(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { - // do something with param5 + x = param5; } } @@ -817,6 +874,29 @@ No:: x = y+z; x +=1; +*************** +Order of Layout +*************** + +Layout contract elements in the following order: + +1. Pragma statements +2. Import statements +3. Interfaces +4. Libraries +5. Contracts + +Inside each contract, library or interface, use the following order: + +1. Type declarations +2. State variables +3. Events +4. Functions + +.. note:: + + It might be clearer to declare types close to their use in events or state + variables. ****************** Naming Conventions @@ -830,7 +910,7 @@ The naming recommendations given here are intended to improve the readability, and thus they are not rules, but rather guidelines to try and help convey the most information through the names of things. -Lastly, consistency within a codebase should always supercede any conventions +Lastly, consistency within a codebase should always supersede any conventions outlined in this document. @@ -867,7 +947,69 @@ indistinguishable from the numerals one and zero. Contract and Library Names ========================== -Contracts and libraries should be named using the CapWords style. Examples: ``SimpleToken``, ``SmartBank``, ``CertificateHashRepository``, ``Player``. +* Contracts and libraries should be named using the CapWords style. Examples: ``SimpleToken``, ``SmartBank``, ``CertificateHashRepository``, ``Player``, ``Congress``, ``Owned``. +* Contract and library names should also match their filenames. +* If a contract file includes multiple contracts and/or libraries, then the filename should match the *core contract*. This is not recommended however if it can be avoided. + +As shown in the example below, if the contract name is `Congress` and the library name is `Owned`, then their associated filenames should be `Congress.sol` and `Owned.sol`. + +Yes:: + + pragma solidity >=0.4.0 <0.6.0; + + // Owned.sol + contract Owned { + address public owner; + + constructor() public { + owner = msg.sender; + } + + modifier onlyOwner { + require(msg.sender == owner); + _; + } + + function transferOwnership(address newOwner) public onlyOwner { + owner = newOwner; + } + } + + // Congress.sol + import "./Owned.sol"; + + contract Congress is Owned, TokenRecipient { + //... + } + +No:: + + pragma solidity >=0.4.0 <0.6.0; + + // owned.sol + contract owned { + address public owner; + + constructor() public { + owner = msg.sender; + } + + modifier onlyOwner { + require(msg.sender == owner); + _; + } + + function transferOwnership(address newOwner) public onlyOwner { + owner = newOwner; + } + } + + // Congress.sol + import "./owned.sol"; + + contract Congress is owned, tokenRecipient { + //... + } Struct Names diff --git a/docs/types.rst b/docs/types.rst index 5c20dc679..34b94b88e 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -7,10 +7,8 @@ Types ***** Solidity is a statically typed language, which means that the type of each -variable (state and local) needs to be specified (or at least known - -see :ref:`type-deduction` below) at -compile-time. Solidity provides several elementary types which can be combined -to form complex types. +variable (state and local) needs to be specified. +Solidity provides several elementary types which can be combined to form complex types. In addition, types can interact with each other in expressions containing operators. For a quick reference of the various operators, see :ref:`order`. @@ -52,23 +50,91 @@ Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) * Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) -* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation), ``<<`` (left shift), ``>>`` (right shift) +* Shift operators: ``<<`` (left shift), ``>>`` (right shift) +* Arithmetic operators: ``+``, ``-``, unary ``-``, ``*``, ``/``, ``%`` (modulo), ``**`` (exponentiation) -Division always truncates (it is just compiled to the ``DIV`` opcode of the EVM), but it does not truncate if both -operators are :ref:`literals` (or literal expressions). -Division by zero and modulus with zero throws a runtime exception. +Comparisons +^^^^^^^^^^^ -The result of a shift operation is the type of the left operand. The -expression ``x << y`` is equivalent to ``x * 2**y``, and ``x >> y`` is -equivalent to ``x / 2**y``. This means that shifting negative numbers -sign extends. Shifting by a negative amount throws a runtime exception. +The value of a comparison is the one obtained by comparing the integer value. + +Bit operations +^^^^^^^^^^^^^^ + +Bit operations are performed on the two's complement representation of the number. +This means that, for example ``~int256(0) == int256(-1)``. + +Shifts +^^^^^^ + +The result of a shift operation has the type of the left operand. The +expression ``x << y`` is equivalent to ``x * 2**y``, and, for positive integers, +``x >> y`` is equivalent to ``x / 2**y``. For negative ``x``, ``x >> y`` +is equivalent to dividing by a power of ``2`` while rounding down (towards negative infinity). +Shifting by a negative amount throws a runtime exception. .. warning:: - The results produced by shift right of negative values of signed integer types is different from those produced - by other programming languages. In Solidity, shift right maps to division so the shifted negative values - are going to be rounded towards zero (truncated). In other programming languages the shift right of negative values - works like division with rounding down (towards negative infinity). + Before version ``0.5.0`` a right shift ``x >> y`` for negative ``x`` was equivalent to ``x / 2**y``, + i.e. right shifts used rounding towards zero instead of rounding towards negative infinity. + +Addition, Subtraction and Multiplication +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Addition, subtraction and multiplication have the usual semantics. +They wrap in two's complement representation, meaning that +for example ``uint256(0) - uint256(1) == 2**256 - 1``. You have to take these overflows +into account when designing safe smart contracts. + +The expression ``-x`` is equivalent to ``(T(0) - x)`` where +``T`` is the type of ``x``. This means that ``-x`` will not be negative +if the type of ``x`` is an unsigned integer type. Also, ``-x`` can be +positive if ``x`` is negative. There is another caveat also resulting +from two's complement representation:: + + int x = -2**255; + assert(-x == x); + +This means that even if a number is negative, you cannot assume that +its negation will be positive. + + +Division +^^^^^^^^ + +Since the type of the result of an operation is always the type of one of +the operands, division on integers always results in an integer. +In Solidity, division rounds towards zero. This mean that ``int256(-5) / int256(2) == int256(-2)``. + +Note that in contrast, division on :ref:`literals` results in fractional values +of arbitrary precision. + +.. note:: + Division by zero causes a failing assert. + +Modulo +^^^^^^ + +The modulo operation ``a % n`` yields the remainder ``r`` after the division of the operand ``a`` +by the operand ``n``, where ``q = int(a / n)`` and ``r = a - (n * q)``. This means that modulo +results in the same sign as its left operand (or zero) and ``a % n == -(abs(a) % n)`` holds for negative ``a``: + + * ``int256(5) % int256(2) == int256(1)`` + * ``int256(5) % int256(-2) == int256(1)`` + * ``int256(-5) % int256(2) == int256(-1)`` + * ``int256(-5) % int256(-2) == int256(-1)`` + +.. note:: + Modulo with zero causes a failing assert. + +Exponentiation +^^^^^^^^^^^^^^ + +Exponentiation is only available for unsigned types. Please take care that the types +you are using are large enough to hold the result and prepare for potential wrapping behaviour. + +.. note:: + Note that ``0**0`` is defined by the EVM as ``1``. .. index:: ! ufixed, ! fixed, ! fixed point number @@ -86,7 +152,7 @@ the type and ``N`` represents how many decimal points are available. ``M`` must Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) -* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder) +* Arithmetic operators: ``+``, ``-``, unary ``-``, ``*``, ``/``, ``%`` (modulo) .. note:: The main difference between floating point (``float`` and ``double`` in many languages, more precisely IEEE 754 numbers) and fixed point numbers is @@ -94,42 +160,83 @@ Operators: defined in the latter. Generally, in floating point almost the entire space is used to represent the number, while only a small number of bits define where the decimal point is. -.. index:: address, balance, send, call, callcode, delegatecall, transfer +.. index:: address, balance, send, call, callcode, delegatecall, staticcall, transfer .. _address: Address ------- -``address``: Holds a 20 byte value (size of an Ethereum address). Address types also have members and serve as a base for all contracts. +The address type comes in two flavours, which are largely identical: + + - ``address``: Holds a 20 byte value (size of an Ethereum address). + - ``address payable``: Same as ``address``, but with the additional members ``transfer`` and ``send``. + +The idea behind this distinction is that ``address payable`` is an address you can send Ether to, +while a plain ``address`` cannot be sent Ether. + +Type conversions: + +Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable`` are +not possible (the only way to perform such a conversion is by using an intermediate conversion to ``uint160``). + +:ref:`Address literals` can be implicitly converted to ``address payable``. + +Explicit conversions to and from ``address`` are allowed for integers, integer literals, ``bytes20`` and contract types with the following +caveat: +Conversions of the form ``address payable(x)`` are not allowed. Instead the result of a conversion of the form ``address(x)`` +has the type ``address payable``, if ``x`` is of integer or fixed bytes type, a literal or a contract with a payable fallback function. +If ``x`` is a contract without payable fallback function, then ``address(x)`` will be of type ``address``. +In external function signatures ``address`` is used for both the ``address`` and the ``address payable`` type. + +.. note:: + It might very well be that you do not need to care about the distinction between ``address`` + and ``address payable`` and just use ``address`` everywhere. For example, + if you are using the :ref:`withdrawal pattern`, you can (and should) store the + address itself as ``address``, because you invoke the ``transfer`` function on + ``msg.sender``, which is an ``address payable``. Operators: * ``<=``, ``<``, ``==``, ``!=``, ``>=`` and ``>`` +.. warning:: + If you convert a type that uses a larger byte size to an ``address``, for example ``bytes32``, then the ``address`` is truncated. + To reduce conversion ambiguity version 0.4.24 and higher of the compiler force you make the truncation explicit in the conversion. + Take for example the address ``0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC``. + + You can use ``address(uint160(bytes20(b)))``, which results in ``0x111122223333444455556666777788889999aAaa``, + or you can use ``address(uint160(uint256(b)))``, which results in ``0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc``. + .. note:: - Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address. + The distinction between ``address`` and ``address payable`` was introduced with version 0.5.0. + Also starting from that version, contracts do not derive from the address type, but can still be explicitly converted to + ``address`` or to ``address payable``, if they have a payable fallback function. .. _members-of-addresses: Members of Addresses ^^^^^^^^^^^^^^^^^^^^ +For a quick reference of all members of address, see :ref:`address_related`. + * ``balance`` and ``transfer`` -For a quick reference, see :ref:`address_related`. - It is possible to query the balance of an address using the property ``balance`` -and to send Ether (in units of wei) to an address using the ``transfer`` function: +and to send Ether (in units of wei) to a payable address using the ``transfer`` function: :: - address x = 0x123; - address myAddress = this; + address payable x = address(0x123); + address myAddress = address(this); if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); +The ``transfer`` function fails if the balance of the current contract is not large enough +or if the Ether transfer is rejected by the receiving account. The ``transfer`` function +reverts on failure. + .. note:: - If ``x`` is a contract address, its code (more specifically: its fallback function, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. + If ``x`` is a contract address, its code (more specifically: its :ref:`fallback-function`, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. * ``send`` @@ -141,40 +248,56 @@ Send is the low-level counterpart of ``transfer``. If the execution fails, the c to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: use a pattern where the recipient withdraws the money. -* ``call``, ``callcode`` and ``delegatecall`` +* ``call``, ``delegatecall`` and ``staticcall`` -Furthermore, to interface with contracts that do not adhere to the ABI, -the function ``call`` is provided which takes an arbitrary number of arguments of any type. These arguments are padded to 32 bytes and concatenated. One exception is the case where the first argument is encoded to exactly four bytes. In this case, it is not padded to allow the use of function signatures here. +In order to interface with contracts that do not adhere to the ABI, +or to get more direct control over the encoding, +the functions ``call``, ``delegatecall`` and ``staticcall`` are provided. +They all take a single ``bytes memory`` argument as input and +return the success condition (as a ``bool``) and the returned data +(``bytes memory``). +The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` +and ``abi.encodeWithSignature`` can be used to encode structured data. -:: +Example:: - address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2; - nameReg.call("register", "MyName"); - nameReg.call(bytes4(keccak256("fun(uint256)")), a); + bytes memory payload = abi.encodeWithSignature("register(string)", "MyName"); + (bool success, bytes memory returnData) = address(nameReg).call(payload); + require(success); -``call`` returns a boolean indicating whether the invoked function terminated (``true``) or caused an EVM exception (``false``). It is not possible to access the actual data returned (for this we would need to know the encoding and size in advance). +.. warning:: + All these functions are low-level functions and should be used with care. + Specifically, any unknown contract might be malicious and if you call it, you + hand over control to that contract which could in turn call back into + your contract, so be prepared for changes to your state variables + when the call returns. The regular way to interact with other contracts + is to call a function on a contract object (``x.f()``). + +:: note:: + Previous versions of Solidity allowed these functions to receive + arbitrary arguments and would also handle a first argument of type + ``bytes4`` differently. These edge cases were removed in version 0.5.0. It is possible to adjust the supplied gas with the ``.gas()`` modifier:: - namReg.call.gas(1000000)("register", "MyName"); + namReg.call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); Similarly, the supplied Ether value can be controlled too:: - nameReg.call.value(1 ether)("register", "MyName"); + nameReg.call.value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); Lastly, these modifiers can be combined. Their order does not matter:: - nameReg.call.gas(1000000).value(1 ether)("register", "MyName"); + nameReg.call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); + +In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. .. note:: - It is not yet possible to use the gas or value modifiers on overloaded functions. + Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. This function was removed in version 0.5.0. - A workaround is to introduce a special case for gas and value and just re-check - whether they are present at the point of overload resolution. +Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert if the called function modifies the state in any way. -In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. - -All three functions ``call``, ``delegatecall`` and ``callcode`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. +All three functions ``call``, ``delegatecall`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. The ``.gas()`` option is available on all three methods, while the ``.value()`` option is not supported for ``delegatecall``. @@ -182,41 +305,72 @@ The ``.gas()`` option is available on all three methods, while the ``.value()`` All contracts can be converted to ``address`` type, so it is possible to query the balance of the current contract using ``address(this).balance``. -.. note:: - The use of ``callcode`` is discouraged and will be removed in the future. +.. index:: ! contract type, ! type; contract -.. warning:: - All these functions are low-level functions and should be used with care. - Specifically, any unknown contract might be malicious and if you call it, you - hand over control to that contract which could in turn call back into - your contract, so be prepared for changes to your state variables - when the call returns. +.. _contract_types: + +Contract Types +-------------- + +Every :ref:`contract` defines its own type. +You can implicitly convert contracts to contracts they inherit from. +Contracts can be explicitly converted to and from all other contract types +and the ``address`` type. + +Explicit conversion to and from the ``address payable`` type +is only possible if the contract type has a payable fallback function. +The conversion is still performed using ``address(x)`` and not +using ``address payable(x)``. You can find more information in the section about +the :ref:`address type
`. + +.. note:: + Before version 0.5.0, contracts directly derived from the address type + and there was no distinction between ``address`` and ``address payable``. + +If you declare a local variable of contract type (`MyContract c`), you can call +functions on that contract. Take care to assign it from somewhere that is the +same contract type. + +You can also instantiate contracts (which means they are newly created). You +can find more details in the :ref:`'Contracts via new'` +section. + +The data representation of a contract is identical to that of the ``address`` +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. .. index:: byte array, bytes32 - Fixed-size byte arrays ---------------------- -``bytes1``, ``bytes2``, ``bytes3``, ..., ``bytes32``. ``byte`` is an alias for ``bytes1``. +The value types ``bytes1``, ``bytes2``, ``bytes3``, ..., ``bytes32`` +hold a sequence of bytes from one to up to 32. +``byte`` is an alias for ``bytes1``. Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) -* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift) +* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) +* Shift operators: ``<<`` (left shift), ``>>`` (right shift) * Index access: If ``x`` is of type ``bytesI``, then ``x[k]`` for ``0 <= k < I`` returns the ``k`` th byte (read-only). -The shifting operator works with any integer type as right operand (but will -return the type of the left operand), which denotes the number of bits to shift by. -Shifting by a negative amount will cause a runtime exception. +The shifting operator works with any integer type as right operand (but +returns the type of the left operand), which denotes the number of bits to shift by. +Shifting by a negative amount causes a runtime exception. Members: * ``.length`` yields the fixed length of the byte array (read-only). .. note:: - It is possible to use an array of bytes as ``byte[]``, but it is wasting a lot of space, 31 bytes every element, - to be exact, when passing in calls. It is better to use ``bytes``. + The type ``byte[]`` is an array of bytes, but due to padding rules, it wastes + 31 bytes of space for each element (except in storage). It is better to use the ``bytes`` + type instead. Dynamically-sized byte array ---------------------------- @@ -226,10 +380,6 @@ Dynamically-sized byte array ``string``: Dynamically-sized UTF-8-encoded string, see :ref:`arrays`. Not a value-type! -As a rule of thumb, use ``bytes`` for arbitrary-length raw byte data and ``string`` -for arbitrary-length string (UTF-8) data. If you can limit the length to a certain -number of bytes, always use one of ``bytes1`` to ``bytes32`` because they are much cheaper. - .. index:: address, literal;address .. _address_literals: @@ -238,7 +388,7 @@ Address Literals ---------------- Hexadecimal literals that pass the address checksum test, for example -``0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`` are of ``address`` type. +``0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`` are of ``address payable`` type. Hexadecimal literals that are between 39 and 41 digits long and do not pass the checksum test produce a warning and are treated as regular rational number literals. @@ -263,8 +413,14 @@ one side. Examples include ``1.``, ``.1`` and ``1.3``. Scientific notation is also supported, where the base can have fractions, while the exponent cannot. Examples include ``2e10``, ``-2e10``, ``2e-10``, ``2.5e1``. +Underscores can be used to separate the digits of a numeric literal to aid readability. +For example, decimal ``123_000``, hexadecimal ``0x2eff_abde``, scientific decimal notation ``1_2e345_678`` are all valid. +Underscores are only allowed between two digits and only one consecutive underscore is allowed. +There is no additional semantic meaning added to a number literal containing underscores, +the underscores are ignored. + Number literal expressions retain arbitrary precision until they are converted to a non-literal type (i.e. by -using them together with a non-literal expression). +using them together with a non-literal expression or by explicit conversion). This means that computations do not overflow and divisions do not truncate in number literal expressions. @@ -286,14 +442,15 @@ a non-rational number). belong to the same number literal type for the rational number three. .. warning:: - Division on integer literals used to truncate in earlier versions, but it will now convert into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``. + 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 - expressions. Even though we know that the value of the - expression assigned to ``b`` in the following example evaluates to - an integer, but the partial expression ``2.5 + a`` does not type check so the code - does not compile + expressions. Disregarding types, the value of the expression assigned to ``b`` + below evaluates to an integer. Because ``a`` is of type ``uint128``, the + expression ``2.5 + a`` has to have a proper type, though. Since there is no common type + for the type of ``2.5`` and ``uint128``, the Solidity compiler does not accept + this code. :: @@ -301,22 +458,51 @@ a non-rational number). uint128 b = 2.5 + a + 0.5; .. index:: literal, literal;string, string +.. _string_literals: String Literals --------------- -String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; ``"foo"`` represents three bytes not four. As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``. +String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; ``"foo"`` represents three bytes, not four. As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``. -String literals support escape characters, such as ``\n``, ``\xNN`` and ``\uNNNN``. ``\xNN`` takes a hex value and inserts the appropriate byte, while ``\uNNNN`` takes a Unicode codepoint and inserts an UTF-8 sequence. +String literals support the following escape characters: + + - ``\`` (escapes an actual newline) + - ``\\`` (backslash) + - ``\'`` (single quote) + - ``\"`` (double quote) + - ``\b`` (backspace) + - ``\f`` (form feed) + - ``\n`` (newline) + - ``\r`` (carriage return) + - ``\t`` (tab) + - ``\v`` (vertical tab) + - ``\xNN`` (hex escape, see below) + - ``\uNNNN`` (unicode escape, see below) + +``\xNN`` takes a hex value and inserts the appropriate byte, while ``\uNNNN`` takes a Unicode codepoint and inserts an UTF-8 sequence. + +The string in the following example has a length of ten bytes. +It starts with a newline byte, followed by a double quote, a single +quote a backslash character and then (without separator) the +character sequence ``abcdef``. + +:: + + "\n\"\'\\abc\ + def" + +Any unicode line terminator which is not a newline (i.e. LF, VF, FF, CR, NEL, LS, PS) is considered to +terminate the string literal. Newline only terminates the string literal if it is not preceded by a ``\``. .. index:: literal, bytes Hexadecimal Literals -------------------- -Hexademical Literals are prefixed with the keyword ``hex`` and are enclosed in double or single-quotes (``hex"001122FF"``). Their content must be a hexadecimal string and their value will be the binary representation of those values. +Hexadecimal literals are prefixed with the keyword ``hex`` and are enclosed in double or single-quotes (``hex"001122FF"``). Their content must be a hexadecimal string and their value will be the binary representation of those values. -Hexademical Literals behave like String Literals and have the same convertibility restrictions. +Hexadecimal literals behave like :ref:`string literals ` and have the same convertibility restrictions. .. index:: enum @@ -326,12 +512,17 @@ 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 conversions -check the value ranges at runtime and a failure causes an exception. Enums needs at least one member. +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. + +The data representation is the same as for enums in C: The options are represented by +subsequent unsigned integer values starting from ``0``. + :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract test { enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } @@ -345,7 +536,7 @@ check the value ranges at runtime and a failure causes an exception. Enums need // Since enum types are not part of the ABI, the signature of "getChoice" // will automatically be changed to "getChoice() returns (uint8)" // for all matters external to Solidity. The integer type used is just - // large enough to hold all enum values, i.e. if you have more values, + // large enough to hold all enum values, i.e. if you have more than 256 values, // `uint16` will be used and so on. function getChoice() public view returns (ActionChoices) { return choice; @@ -380,22 +571,41 @@ be passed via and returned from external function calls. Function types are notated as follows:: - function () {internal|external} [pure|constant|view|payable] [returns ()] + function () {internal|external} [pure|view|payable] [returns ()] In contrast to the parameter types, the return types cannot be empty - if the function type should not return anything, the whole ``returns ()`` part has to be omitted. By default, function types are internal, so the ``internal`` keyword can be -omitted. In contrast, contract functions themselves are public by default, -only when used as the name of a type, the default is internal. +omitted. Note that this only applies to function types. Visibility has +to be specified explicitly for functions defined in contracts, they +do not have a default. -There are two ways to access a function in the current contract: Either directly -by its name, ``f``, or using ``this.f``. The former will result in an internal -function, the latter in an external function. +Conversions: -If a function type variable is not initialized, calling it will result -in an exception. The same happens if you call a function after using ``delete`` +A value of external function type can be explicitly converted to ``address`` +resulting in the address of the contract of the function. + +A function type ``A`` is implicitly convertible to a function type ``B`` if and only if +their parameter types are identical, their return types are identical, +their internal/external property is identical and the state mutability of ``A`` +is not more restrictive than the state mutability of ``B``. In particular: + + - ``pure`` functions can be converted to ``view`` and ``non-payable`` functions + - ``view`` functions can be converted to ``non-payable`` functions + - ``payable`` functions can be converted to ``non-payable`` functions + +No other conversions between function types are possible. + +The rule about ``payable`` and ``non-payable`` might be a little +confusing, but in essence, if a function is ``payable``, this means that it +also accepts a payment of zero Ether, so it also is ``non-payable``. +On the other hand, a ``non-payable`` function will reject Ether sent to it, +so ``non-payable`` functions cannot be converted to ``payable`` functions. + +If a function type variable is not initialised, calling it results +in a failed assertion. The same happens if you call a function after using ``delete`` on it. If external function types are used outside of the context of Solidity, @@ -406,20 +616,22 @@ Note that public functions of the current contract can be used both as an internal and as an external function. To use ``f`` as an internal function, just use ``f``, if you want to use its external form, use ``this.f``. -Additionally, public (or external) functions also have a special member called ``selector``, +Members: + +Public (or external) functions also have a special member called ``selector``, which returns the :ref:`ABI function selector `:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract Selector { - function f() public view returns (bytes4) { + function f() public pure returns (bytes4) { return this.f.selector; } } Example that shows how to use internal function types:: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; library ArrayUtils { // internal functions can be used in internal library functions because @@ -470,20 +682,20 @@ Example that shows how to use internal function types:: Another example that uses external function types:: - pragma solidity ^0.4.22; + pragma solidity >=0.4.22 <0.6.0; contract Oracle { struct Request { bytes data; - function(bytes memory) external callback; + function(uint) external callback; } Request[] requests; event NewRequest(uint); - function query(bytes data, function(bytes memory) external callback) public { + function query(bytes memory data, function(uint) external callback) public { requests.push(Request(data, callback)); emit NewRequest(requests.length - 1); } - function reply(uint requestID, bytes response) public { + function reply(uint requestID, uint response) public { // Here goes the check that the reply comes from a trusted source requests[requestID].callback(response); } @@ -491,15 +703,16 @@ Another example that uses external function types:: contract OracleUser { Oracle constant oracle = Oracle(0x1234567); // known contract - function buySomething() { + uint exchangeRate; + function buySomething() public { oracle.query("USD", this.oracleResponse); } - function oracleResponse(bytes response) public { + function oracleResponse(uint response) public { require( msg.sender == address(oracle), "Only oracle can call this." ); - // Use the data + exchangeRate = response; } } @@ -509,48 +722,58 @@ Another example that uses external function types:: .. index:: ! type;reference, ! reference type, storage, memory, location, array, struct Reference Types -================== +=============== -Complex types, i.e. types which do not always fit into 256 bits have to be handled -more carefully than the value-types we have already seen. Since copying -them can be quite expensive, we have to think about whether we want them to be -stored in **memory** (which is not persisting) or **storage** (where the state -variables are held). +Values of reference type can be modified through multiple different names. +Contrast this with value types where you get an independent copy whenever +a variable of value type is used. Because of that, reference types have to be handled +more carefully than value types. Currently, reference types comprise structs, +arrays and mappings. If you use a reference type, you always have to explicitly +provide the data area where the type is stored: ``memory`` (whose lifetime is limited +to a function call), ``storage`` (the location where the state variables are stored) +or ``calldata`` (special data location that contains the function arguments, +only available for external function call parameters). + +An assignment or type conversion that changes the data location will always incur an automatic copy operation, +while assignments inside the same data location only copy in some cases for storage types. + +.. _data-location: Data location ------------- -Every complex type, i.e. *arrays* and *structs*, has an additional -annotation, the "data location", about whether it is stored in memory or in storage. Depending on the -context, there is always a default, but it can be overridden by appending -either ``storage`` or ``memory`` to the type. The default for function parameters (including return parameters) is ``memory``, the default for local variables is ``storage`` and the location is forced -to ``storage`` for state variables (obviously). +Every reference type, i.e. *arrays* and *structs*, has an additional +annotation, the "data location", about where it is stored. There are three data locations: +``memory``, ``storage`` and ``calldata``. Calldata is only valid for parameters of external contract +functions and is required for this type of parameter. Calldata is a non-modifiable, +non-persistent area where function arguments are stored, and behaves mostly like memory. -There is also a third data location, ``calldata``, which is a non-modifiable, -non-persistent area where function arguments are stored. Function parameters -(not return parameters) of external functions are forced to ``calldata`` and -behave mostly like ``memory``. -Data locations are important because they change how assignments behave: -assignments between storage and memory and also to a state variable (even from other state variables) -always create an independent copy. -Assignments to local storage variables only assign a reference though, and -this reference always points to the state variable even if the latter is changed -in the meantime. -On the other hand, assignments from a memory stored reference type to another -memory-stored reference type do not create a copy. +.. note:: + Prior to version 0.5.0 the data location could be omitted, and would default to different locations + depending on the kind of variable, function type, etc., but all complex types must now give an explicit + data location. + +Data locations are not only relevant for persistency of data, but also for the semantics of assignments: +assignments between storage and memory (or from calldata) always create an independent copy. +Assignments from memory to memory only create references. This means that changes to one memory variable +are also visible in all other memory variables that refer to the same data. +Assignments from storage to a local storage variables also only assign a reference. +In contrast, all other assignments to storage always copy. Examples for this case +are assignments to state variables or to members of local variables of storage struct type, even +if the local variable itself is just a reference. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract C { uint[] x; // the data location of x is storage // the data location of memoryArray is memory - function f(uint[] memoryArray) public { + function f(uint[] memory memoryArray) public { x = memoryArray; // works, copies the whole array to storage - var y = x; // works, assigns a pointer, data location of y is storage + uint[] storage y = x; // works, assigns a pointer, data location of y is storage y[7]; // fine, returns the 8th element y.length = 2; // fine, modifies x through y delete x; // fine, clears the array, also modifies y @@ -564,21 +787,10 @@ memory-stored reference type do not create a copy. h(x); // calls h and creates an independent, temporary copy in memory } - function g(uint[] storage storageArray) internal {} - function h(uint[] memoryArray) public {} + function g(uint[] storage) internal pure {} + function h(uint[] memory) public pure {} } -Summary -^^^^^^^ - -Forced data location: - - parameters (not return) of external functions: calldata - - state variables: storage - -Default data location: - - parameters (also return) of functions: memory - - all other local variables: storage - .. index:: ! array .. _arrays: @@ -587,9 +799,10 @@ Arrays ------ Arrays can have a compile-time fixed size or they can be dynamic. -For storage arrays, the element type can be arbitrary (i.e. also other -arrays, mappings or structs). For memory arrays, it cannot be a mapping and -has to be an ABI type if it is an argument of a publicly-visible function. +The are few restrictions for the element, it can also be +another array, a mapping or a struct. The general restrictions for +types apply, though, in that mappings can only be used in storage +and publicly-visible functions need parameters that are :ref:`ABI types `. An array of fixed size ``k`` and element type ``T`` is written as ``T[k]``, an array of dynamic size as ``T[]``. As an example, an array of 5 dynamic @@ -599,11 +812,17 @@ third dynamic array, you use ``x[2][1]`` (indices are zero-based and access works in the opposite way of the declaration, i.e. ``x[2]`` shaves off one level in the type from the right). -Variables of type ``bytes`` and ``string`` are special arrays. A ``bytes`` is similar to ``byte[]``, -but it is packed tightly in calldata. ``string`` is equal to ``bytes`` but does not allow -length or index access (for now). +Accessing an array past its end causes a revert. If you want to add +new elements, you have to use ``.push()`` or increase the ``.length`` +member (see below). +Variables of type ``bytes`` and ``string`` are special arrays. A ``bytes`` is similar to ``byte[]``, +but it is packed tightly in calldata and memory. ``string`` is equal to ``bytes`` but does not allow +length or index access. So ``bytes`` should always be preferred over ``byte[]`` because it is cheaper. +As a rule of thumb, use ``bytes`` for arbitrary-length raw byte data and ``string`` +for arbitrary-length string (UTF-8) data. If you can limit the length to a certain +number of bytes, always use one of ``bytes1`` to ``bytes32`` because they are much cheaper. .. note:: If you want to access the byte-representation of a string ``s``, use @@ -619,19 +838,21 @@ The numeric index will become a required parameter for the getter. Allocating Memory Arrays ^^^^^^^^^^^^^^^^^^^^^^^^ -Creating arrays with variable length in memory can be done using the ``new`` keyword. -As opposed to storage arrays, it is **not** possible to resize memory arrays by assigning to -the ``.length`` member. +You can use the ``new`` keyword to create arrays with a runtime-dependent length in memory. +As opposed to storage arrays, it is **not** possible to resize memory arrays (e.g. by assigning to +the ``.length`` member). You either have to calculate the required size in advance +or create a new memory array and copy every element. :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { function f(uint len) public pure { uint[] memory a = new uint[](7); bytes memory b = new bytes(len); - // Here we have a.length == 7 and b.length == len + assert(a.length == 7); + assert(b.length == len); a[6] = 8; } } @@ -646,13 +867,13 @@ assigned to a variable right away. :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract C { function f() public pure { g([uint(1), 2, 3]); } - function g(uint[3] _data) public pure { + function g(uint[3] memory) public pure { // ... } } @@ -660,68 +881,103 @@ assigned to a variable right away. The type of an array literal is a memory array of fixed size whose base type is the common type of the given elements. The type of ``[1, 2, 3]`` is ``uint8[3] memory``, because the type of each of these constants is ``uint8``. -Because of that, it was necessary to convert the first element in the example +Because of that, it is necessary to convert the first element in the example above to ``uint``. Note that currently, fixed size memory arrays cannot be assigned to dynamically-sized memory arrays, i.e. the following is not possible: :: + pragma solidity >=0.4.0 <0.6.0; + // This will not compile. - - pragma solidity ^0.4.0; - contract C { function f() public { // The next line creates a type error because uint[3] memory // cannot be converted to uint[] memory. - uint[] x = [uint(1), 3, 4]; + uint[] memory x = [uint(1), 3, 4]; } } It is planned to remove this restriction in the future but currently creates some complications because of how arrays are passed in the ABI. -.. index:: ! array;length, length, push, !array;push +.. index:: ! array;length, length, push, pop, !array;push, !array;pop Members ^^^^^^^ **length**: - Arrays have a ``length`` member to hold their number of elements. - Dynamic arrays can be resized in storage (not in memory) by changing the - ``.length`` member. This does not happen automatically when attempting to access elements outside the current length. The size of memory arrays is fixed (but dynamic, i.e. it can depend on runtime parameters) once they are created. + Arrays have a ``length`` member that contains their number of elements. + The length of memory arrays is fixed (but dynamic, i.e. it can depend on runtime parameters) once they are created. + For dynamically-sized arrays (only available for storage), this member can be assigned to resize the array. + Accessing elements outside the current length does not automatically resize the array and instead causes a failing assertion. + Increasing the length adds new zero-initialised elements to the array. + Reducing the length performs an implicit :ref:``delete`` on each of the removed elements. **push**: - Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push`` that can be used to append an element at the end of the array. The function returns the new length. + Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push`` that you can use to append an element at the end of the array. The element will be zero-initialised. The function returns the new length. +**pop**: + Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``pop`` that you can use to remove an element from the end of the array. This also implicitly calls :ref:``delete`` on the removed element. .. warning:: - It is not yet possible to use arrays of arrays in external functions. + If you use ``.length--`` on an empty array, it causes an underflow and + thus sets the length to ``2**256-1``. -.. warning:: - Due to limitations of the EVM, it is not possible to return - dynamic content from external function calls. The function ``f`` in - ``contract C { function f() returns (uint[]) { ... } }`` will return - something if called from web3.js, but not if called from Solidity. +.. note:: + Increasing the length of a storage array has constant gas costs because + storage is assumed to be zero-initialised, while decreasing + the length has at least linear cost (but in most cases worse than linear), + because it includes explicitly clearing the removed + elements similar to calling :ref:``delete`` on them. - The only workaround for now is to use large statically-sized arrays. +.. note:: + It is not yet possible to use arrays of arrays in external functions + (but they are supported in public functions). +.. note:: + In EVM versions before Byzantium, it was not possible to access + dynamic arrays return from function calls. If you call functions + that return dynamic arrays, make sure to use an EVM that is set to + Byzantium mode. :: - pragma solidity ^0.4.16; + pragma solidity >=0.4.16 <0.6.0; contract ArrayContract { uint[2**20] m_aLotOfIntegers; // Note that the following is not a pair of dynamic arrays but a // dynamic array of pairs (i.e. of fixed size arrays of length two). + // Because of that, T[] is always a dynamic array of T, even if T + // itself is an array. + // Data location for all state variables is storage. bool[2][] m_pairsOfFlags; - // newPairs is stored in memory - the default for function arguments - function setAllFlagPairs(bool[2][] newPairs) public { - // assignment to a storage array replaces the complete array + // newPairs is stored in memory - the only possibility + // for public contract function arguments + function setAllFlagPairs(bool[2][] memory newPairs) public { + // assignment to a storage array performs a copy of ``newPairs`` and + // replaces the complete array ``m_pairsOfFlags``. m_pairsOfFlags = newPairs; } + struct StructType { + uint[] contents; + uint moreInfo; + } + StructType s; + + function f(uint[] memory c) public { + // stores a reference to ``s`` in ``g`` + StructType storage g = s; + // also changes ``s.moreInfo``. + g.moreInfo = 2; + // assigns a copy because ``g.contents`` + // is not a local variable, but a member of + // a local variable. + g.contents = c; + } + function setFlagPair(uint index, bool flagA, bool flagB) public { // access to a non-existing index will throw an exception m_pairsOfFlags[index][0] = flagA; @@ -743,26 +999,31 @@ Members bytes m_byteData; - function byteArrays(bytes data) public { + function byteArrays(bytes memory data) public { // byte arrays ("bytes") are different as they are stored without padding, // but can be treated identical to "uint8[]" m_byteData = data; m_byteData.length += 7; - m_byteData[3] = byte(8); + m_byteData[3] = 0x08; delete m_byteData[2]; } - function addFlag(bool[2] flag) public returns (uint) { + function addFlag(bool[2] memory flag) public returns (uint) { return m_pairsOfFlags.push(flag); } - function createMemoryArray(uint size) public pure returns (bytes) { + function createMemoryArray(uint size) public pure returns (bytes memory) { // Dynamic memory arrays are created using `new`: uint[2][] memory arrayOfPairs = new uint[2][](size); + + // Inline arrays are always statically-sized and if you only + // use literals, you have to provide at least one type. + arrayOfPairs[0] = [uint(1), 2]; + // Create a dynamic byte array: bytes memory b = new bytes(200); for (uint i = 0; i < b.length; i++) - b[i] = byte(i); + b[i] = byte(uint8(i)); return b; } } @@ -780,7 +1041,7 @@ shown in the following example: :: - pragma solidity ^0.4.11; + pragma solidity >=0.4.11 <0.6.0; contract CrowdFunding { // Defines a new type with two fields. @@ -790,7 +1051,7 @@ shown in the following example: } struct Campaign { - address beneficiary; + address payable beneficiary; uint fundingGoal; uint numFunders; uint amount; @@ -800,9 +1061,12 @@ shown in the following example: uint numCampaigns; mapping (uint => Campaign) campaigns; - function newCampaign(address beneficiary, uint goal) public returns (uint campaignID) { + function newCampaign(address payable beneficiary, uint goal) public returns (uint campaignID) { campaignID = numCampaigns++; // campaignID is return variable - // Creates new struct and saves in storage. We leave out the mapping type. + // Creates new struct in memory and copies it to storage. + // We leave out the mapping type, because it is not valid in memory. + // If structs are copied (even from storage to storage), mapping types + // are always omitted, because they cannot be enumerated. campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0); } @@ -832,11 +1096,12 @@ Struct types can be used inside mappings and arrays and they can itself contain mappings and arrays. It is not possible for a struct to contain a member of its own type, -although the struct itself can be the value type of a mapping member. +although the struct itself can be the value type of a mapping member +or it can contain a dynamically-sized array of its type. This restriction is necessary, as the size of the struct has to be finite. Note how in all the functions, a struct type is assigned to a local variable -(of the default storage data location). +with data location ``storage``. This does not copy the struct but only stores a reference so that assignments to members of the local variable actually write to the state. @@ -847,32 +1112,39 @@ assigning it to a local variable, as in .. index:: !mapping Mappings -======== +-------- -Mapping types are declared as ``mapping(_KeyType => _ValueType)``. -Here ``_KeyType`` can be almost any type except for a mapping, a dynamically sized array, a contract, an enum and a struct. -``_ValueType`` can actually be any type, including mappings. +You declare mapping types with the syntax ``mapping(_KeyType => _ValueType)``. +The ``_KeyType`` can be any elementary type. This means it can be any of +the built-in value types plus ``bytes`` and ``string``. User-defined +or complex types like contract types, enums, mappings, structs and any array type +apart from ``bytes`` and ``string`` are not allowed. +``_ValueType`` can be any type, including mappings. -Mappings can be seen as `hash tables `_ which are virtually initialized such that -every possible key exists and is mapped to a value whose byte-representation is -all zeros: a type's :ref:`default value `. The similarity ends here, though: The key data is not actually stored -in a mapping, only its ``keccak256`` hash used to look up the value. +You can think of mappings as `hash tables `_, which are virtually initialised +such that every possible key exists and is mapped to a value whose +byte-representation is all zeros, a type's :ref:`default value `. The similarity ends there, the key data is not stored in a +mapping, only its ``keccak256`` hash is used to look up the value. -Because of this, mappings do not have a length or a concept of a key or value being "set". +Because of this, mappings do not have a length or a concept of a key or +value being set. -Mappings are only allowed for state variables (or as storage reference types -in internal functions). +Mappings can only have a data location of ``storage`` and thus +are allowed for state variables, as storage reference types +in functions, or as parameters for library functions. +They cannot be used as parameters or return parameters +of contract functions that are publicly visible. -It is possible to mark mappings ``public`` and have Solidity create a :ref:`getter `. -The ``_KeyType`` will become a required parameter for the getter and it will -return ``_ValueType``. - -The ``_ValueType`` can be a mapping too. The getter will have one parameter -for each ``_KeyType``, recursively. +You can mark 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``. +If ``_ValueType`` is an array or a mapping, the getter has one parameter for +each ``_KeyType``, recursively. For example with a mapping: :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract MappingExample { mapping(address => uint) public balances; @@ -886,14 +1158,14 @@ for each ``_KeyType``, recursively. function f() public returns (uint) { MappingExample m = new MappingExample(); m.update(100); - return m.balances(this); + return m.balances(address(this)); } } .. note:: - Mappings are not iterable, but it is possible to implement a data structure on top of them. - For an example, see `iterable mapping `_. + Mappings are not iterable, but it is possible to implement a data structure + on top of them. For an example, see `iterable mapping `_. .. index:: assignment, ! delete, lvalue @@ -907,15 +1179,17 @@ If ``a`` is an LValue (i.e. a variable or something that can be assigned to), th delete ------ -``delete a`` assigns the initial value for the type to ``a``. I.e. for integers it is equivalent to ``a = 0``, but it can also be used on arrays, where it assigns a dynamic array of length zero or a static array of the same length with all elements reset. For structs, it assigns a struct with all members reset. +``delete a`` assigns the initial value for the type to ``a``. I.e. for integers it is equivalent to ``a = 0``, but it can also be used on arrays, where it assigns a dynamic array of length zero or a static array of the same length with all elements reset. For structs, it assigns a struct with all members reset. In other words, the value of ``a`` after ``delete a`` is the same as if ``a`` would be declared without assignment, with the following caveat: -``delete`` has no effect on whole mappings (as the keys of mappings may be arbitrary and are generally unknown). So if you delete a struct, it will reset all members that are not mappings and also recurse into the members unless they are mappings. However, individual keys and what they map to can be deleted. +``delete`` has no effect on mappings (as the keys of mappings may be arbitrary and are generally unknown). So if you delete a struct, it will reset all members that are not mappings and also recurse into the members unless they are mappings. However, individual keys and what they map to can be deleted: If ``a`` is a mapping, then ``delete a[x]`` will delete the value stored at ``x``. It is important to note that ``delete a`` really behaves like an assignment to ``a``, i.e. it stores a new object in ``a``. +This distinction is visible when ``a`` is reference variable: It will only reset ``a`` itself, not the +value it referred to previously. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; contract DeleteExample { uint data; @@ -924,17 +1198,20 @@ It is important to note that ``delete a`` really behaves like an assignment to ` function f() public { uint x = data; delete x; // sets x to 0, does not affect data - delete data; // sets data to 0, does not affect x which still holds a copy + delete data; // sets data to 0, does not affect x uint[] storage y = dataArray; delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also // y is affected which is an alias to the storage object // On the other hand: "delete y" is not valid, as assignments to local variables // referencing storage objects can only be made from existing storage objects. + assert(y.length == 0); } } .. index:: ! type;conversion, ! cast +.. _types-conversion-elementary-types: + Conversions between Elementary Types ==================================== @@ -948,16 +1225,16 @@ 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``). -Furthermore, unsigned integers can be converted to bytes of the same or larger -size, but not vice-versa. Any type that can be converted to ``uint160`` can also -be converted to ``address``. + +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 so be sure to test to ensure that the +give you some 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 ``int8`` to a ``uint``: @@ -969,32 +1246,92 @@ a negative ``int8`` to a ``uint``: At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex characters), which is -3 in the two's complement representation of 256 bits. -If a type is explicitly converted to a smaller type, higher-order bits are +If an integer is explicitly converted to a smaller type, higher-order bits are cut off:: uint32 a = 0x12345678; uint16 b = uint16(a); // b will be 0x5678 now -.. index:: ! type;deduction, ! var +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. -.. _type-deduction: + uint16 a = 0x1234; + uint32 b = uint32(a); // b will be 0x00001234 now + assert(a == b); -Type Deduction -============== +Fixed-size bytes types behave differently during conversions. They can be thought of as +sequences of individual bytes and converting to a smaller type will cut off the +sequence:: -For convenience, it is not always necessary to explicitly specify the type of a -variable, the compiler automatically infers it from the type of the first -expression that is assigned to the variable:: + bytes2 a = 0x1234; + bytes1 b = bytes1(a); // b will be 0x12 - uint24 x = 0x123; - var y = x; +If a fixed-size bytes type is explicitly converted to a larger type, it is padded on +the right. Accessing the byte at a fixed index will result in the same value before and +after the conversion (if the index is still in range):: -Here, the type of ``y`` will be ``uint24``. Using ``var`` is not possible for function -parameters or return parameters. + bytes2 a = 0x1234; + bytes4 b = bytes4(a); // b will be 0x12340000 + assert(a[0] == b[0]); + assert(a[1] == b[1]); -.. warning:: - The type is only deduced from the first assignment, so - the loop in the following snippet is infinite, as ``i`` will have the type - ``uint8`` and the highest value of this type is smaller than ``2000``. - ``for (var i = 0; i < 2000; i++) { ... }`` +Since integers and fixed-size byte arrays behave differently when truncating or +padding, explicit conversions between integers and fixed-size byte arrays are only allowed, +if both have the same size. If you want to convert between integers and fixed-size byte arrays of +different size, you have to use intermediate conversions that make the desired truncation and padding +rules explicit:: + bytes2 a = 0x1234; + uint32 b = uint16(a); // b will be 0x00001234 + uint32 c = uint32(bytes4(a)); // c will be 0x12340000 + uint8 d = uint8(uint16(a)); // d will be 0x34 + uint8 e = uint8(bytes1(a)); // d will be 0x12 + +.. _types-conversion-literals: + +Conversions between Literals and Elementary Types +================================================= + +Integer Types +------------- + +Decimal and hexadecimal number literals can be implicitly converted to any integer type +that is large enough to represent it without truncation:: + + uint8 a = 12; // fine + uint32 b = 1234; // fine + uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456 + +Fixed-Size Byte Arrays +---------------------- + +Decimal number literals cannot be implicitly converted to fixed-size byte arrays. Hexadecimal +number literals can be, but only if the number of hex digits exactly fits the size of the bytes +type. As an exception both decimal and hexadecimal literals which have a value of zero can be +converted to any fixed-size bytes type:: + + bytes2 a = 54321; // not allowed + bytes2 b = 0x12; // not allowed + bytes2 c = 0x123; // not allowed + bytes2 d = 0x1234; // fine + bytes2 e = 0x0012; // fine + bytes4 f = 0; // fine + bytes4 g = 0x0; // fine + +String literals and hex string literals can be implicitly converted to fixed-size byte arrays, +if their number of characters matches the size of the bytes type:: + + bytes2 a = hex"1234"; // fine + bytes2 b = "xy"; // fine + bytes2 c = hex"12"; // not allowed + bytes2 d = hex"123"; // not allowed + bytes2 e = "x"; // not allowed + bytes2 f = "xyz"; // not allowed + +Addresses +--------- + +As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum +test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type. + +Explicit conversions from ``bytes20`` or any integer type to ``address`` result in ``address payable``. diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index a6f8ca874..7f62e71e6 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -7,15 +7,25 @@ Units and Globally Available Variables Ether Units =========== -A literal number can take a suffix of ``wei``, ``finney``, ``szabo`` or ``ether`` to convert between the subdenominations of Ether, where Ether currency numbers without a postfix are assumed to be Wei, e.g. ``2 ether == 2000 finney`` evaluates to ``true``. +A literal number can take a suffix of ``wei``, ``finney``, ``szabo`` or ``ether`` to specify a subdenomination of Ether, where Ether numbers without a postfix are assumed to be Wei. + +:: + + assert(1 wei == 1); + assert(1 szabo == 1e12); + assert(1 finney == 1e15); + assert(1 ether == 1e18); + +The only effect of the subdenomination suffix is a multiplication by a power of ten. + .. index:: time, seconds, minutes, hours, days, weeks, years Time Units ========== -Suffixes like ``seconds``, ``minutes``, ``hours``, ``days``, ``weeks`` and -``years`` after literal numbers can be used to convert between units of time where seconds are the base +Suffixes like ``seconds``, ``minutes``, ``hours``, ``days`` and ``weeks`` +after literal numbers can be used to specify units of time where seconds are the base unit and units are considered naively in the following way: * ``1 == 1 seconds`` @@ -23,7 +33,6 @@ unit and units are considered naively in the following way: * ``1 hours == 60 minutes`` * ``1 days == 24 hours`` * ``1 weeks == 7 days`` - * ``1 years == 365 days`` Take care if you perform calendar calculations using these units, because not every year equals 365 days and not even every day has 24 hours @@ -32,7 +41,7 @@ Due to the fact that leap seconds cannot be predicted, an exact calendar library has to be updated by an external oracle. .. note:: - The suffix ``years`` has been deprecated due to the reasons above. + The suffix ``years`` has been removed in version 0.5.0 due to the reasons above. These suffixes cannot be applied to variables. If you want to interpret some input variable in e.g. days, you can do it in the following way:: @@ -56,21 +65,20 @@ or are general-use utility functions. Block and Transaction Properties -------------------------------- -- ``block.blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by ``blockhash(uint blockNumber)``. -- ``block.coinbase`` (``address``): current block miner's address +- ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks +- ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number - ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch - ``gasleft() returns (uint256)``: remaining gas -- ``msg.data`` (``bytes``): complete calldata -- ``msg.gas`` (``uint``): remaining gas - deprecated in version 0.4.21 and to be replaced by ``gasleft()`` -- ``msg.sender`` (``address``): sender of the message (current call) +- ``msg.data`` (``bytes calldata``): complete calldata +- ``msg.sender`` (``address payable``): sender of the message (current call) - ``msg.sig`` (``bytes4``): first four bytes of the calldata (i.e. function identifier) - ``msg.value`` (``uint``): number of wei sent with the message - ``now`` (``uint``): current block timestamp (alias for ``block.timestamp``) - ``tx.gasprice`` (``uint``): gas price of the transaction -- ``tx.origin`` (``address``): sender of the transaction (full call chain) +- ``tx.origin`` (``address payable``): sender of the transaction (full call chain) .. note:: The values of all members of ``msg``, including ``msg.sender`` and @@ -94,22 +102,30 @@ Block and Transaction Properties You can only access the hashes of the most recent 256 blocks, all other values will be zero. -.. index:: abi, encoding, packed - -ABI Encoding Functions ----------------------- - -- ``abi.encode(...) returns (bytes)``: ABI-encodes the given arguments -- ``abi.encodePacked(...) returns (bytes)``: Performes packed encoding of the given arguments -- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: ABI-encodes the given arguments - starting from the second and prepends the given four-byte selector -- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)``` +.. note:: + The function ``blockhash`` was previously known as ``block.blockhash``. It was deprecated in + version 0.4.22 and removed in version 0.5.0. .. note:: - These encoding functions can be used to craft data for function calls without actually - calling a function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a more - explicit way to compute ``keccak256(a, b)``, which will be deprecated in future - versions. + The function ``gasleft`` was previously known as ``msg.gas``. It was deprecated in + version 0.4.21 and removed in version 0.5.0. + +.. index:: abi, encoding, packed + +ABI Encoding and Decoding Functions +----------------------------------- + +- ``abi.decode(bytes memory encodedData, (...)) returns (...)``: ABI-decodes the given data, while the types are given in parentheses as second argument. Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))`` +- ``abi.encode(...) returns (bytes memory)``: ABI-encodes the given arguments +- ``abi.encodePacked(...) returns (bytes memory)``: Performs :ref:`packed encoding ` of the given arguments +- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: ABI-encodes the given arguments starting from the second and prepends the given four-byte selector +- ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)``` + +.. note:: + These encoding functions can be used to craft data for external function calls without actually + calling an external function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a way + to compute the hash of structured data (although be aware that it is possible to + craft a "hash collision" using different inputs types). See the documentation about the :ref:`ABI ` and the :ref:`tightly packed encoding ` for details about the encoding. @@ -119,15 +135,18 @@ See the documentation about the :ref:`ABI ` and the Error Handling -------------- +See the dedicated section on :ref:`assert and require` for +more details on error handling and when to use which function. + ``assert(bool condition)``: - invalidates the transaction if the condition is not met - to be used for internal errors. + causes an invalid opcode and thus state change reversion if the condition is not met - to be used for internal errors. ``require(bool condition)``: reverts if the condition is not met - to be used for errors in inputs or external components. -``require(bool condition, string message)``: +``require(bool condition, string memory message)``: reverts if the condition is not met - to be used for errors in inputs or external components. Also provides an error message. ``revert()``: abort execution and revert state changes -``revert(string reason)``: +``revert(string memory reason)``: abort execution and revert state changes, providing an explanatory string .. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, @@ -139,54 +158,44 @@ Mathematical and Cryptographic Functions compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. -``keccak256(...) returns (bytes32)``: - compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments ` -``sha256(...) returns (bytes32)``: - compute the SHA-256 hash of the :ref:`(tightly packed) arguments ` -``sha3(...) returns (bytes32)``: - alias to ``keccak256`` -``ripemd160(...) returns (bytes20)``: - compute RIPEMD-160 hash of the :ref:`(tightly packed) arguments ` +``keccak256(bytes memory) returns (bytes32)``: + compute the Keccak-256 hash of the input +``sha256(bytes memory) returns (bytes32)``: + compute the SHA-256 hash of the input +``ripemd160(bytes memory) returns (bytes20)``: + compute RIPEMD-160 hash of the input ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover the address associated with the public key from elliptic curve signature or return zero on error (`example usage `_) -In the above, "tightly packed" means that the arguments are concatenated without padding. -This means that the following are all identical:: - - keccak256("ab", "c") - keccak256("abc") - keccak256(0x616263) - keccak256(6382179) - keccak256(97, 98, 99) - -If padding is needed, explicit type conversions can be used: ``keccak256("\x00\x12")`` is the -same as ``keccak256(uint16(0x12))``. - -Note that constants will be packed using the minimum number of bytes required to store them. -This means that, for example, ``keccak256(0) == keccak256(uint8(0))`` and -``keccak256(0x12345678) == keccak256(uint32(0x12345678))``. +.. note:: + Function ``ecrecover`` returns an ``address``, and not an ``address + payable``. See :ref:`address payable
` for conversion, in case you need + to transfer funds to the recovered address. It might be that you run into Out-of-Gas for ``sha256``, ``ripemd160`` or ``ecrecover`` on a *private blockchain*. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net. -.. index:: balance, send, transfer, call, callcode, delegatecall +.. note:: + There used to be an alias for ``keccak256`` called ``sha3``, which was removed in version 0.5.0. + +.. index:: balance, send, transfer, call, callcode, delegatecall, staticcall .. _address_related: -Address Related ---------------- +Members of Address Types +------------------------ ``
.balance`` (``uint256``): balance of the :ref:`address` in Wei -``
.transfer(uint256 amount)``: - send given amount of Wei to :ref:`address`, throws on failure, forwards 2300 gas stipend, not adjustable -``
.send(uint256 amount) returns (bool)``: +``
.transfer(uint256 amount)``: + send given amount of Wei to :ref:`address`, reverts on failure, forwards 2300 gas stipend, not adjustable +``
.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure, forwards 2300 gas stipend, not adjustable -``
.call(...) returns (bool)``: - issue low-level ``CALL``, returns ``false`` on failure, forwards all available gas, adjustable -``
.callcode(...) returns (bool)``: - issue low-level ``CALLCODE``, returns ``false`` on failure, forwards all available gas, adjustable -``
.delegatecall(...) returns (bool)``: - issue low-level ``DELEGATECALL``, returns ``false`` on failure, forwards all available gas, adjustable +``
.call(bytes memory) returns (bool, bytes memory)``: + issue low-level ``CALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable +``
.delegatecall(bytes memory) returns (bool, bytes memory)``: + issue low-level ``DELEGATECALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable +``
.staticcall(bytes memory) returns (bool, bytes memory)``: + issue low-level ``STATICCALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable For more information, see the section on :ref:`address`. @@ -197,14 +206,23 @@ For more information, see the section on :ref:`address`. Use a pattern where the recipient withdraws the money. .. note:: - If storage variables are accessed via a low-level delegatecall, the storage layout of the two contracts + Prior to version 0.5.0, Solidity allowed address members to be accessed by a contract instance, for example ``this.balance``. + This is now forbidden and an explicit conversion to address must be done: ``address(this).balance``. + +.. note:: + If state variables are accessed via a low-level delegatecall, the storage layout of the two contracts must align in order for the called contract to correctly access the storage variables of the calling contract by name. This is of course not the case if storage pointers are passed as function arguments as in the case for the high-level libraries. - - + .. note:: - The use of ``callcode`` is discouraged and will be removed in the future. + Prior to version 0.5.0, ``.call``, ``.delegatecall`` and ``.staticcall`` only returned the + success condition and not the return data. + +.. note:: + Prior to version 0.5.0, there was a member called ``callcode`` with similar but slightly different + semantics than ``delegatecall``. + .. index:: this, selfdestruct @@ -214,11 +232,12 @@ Contract Related ``this`` (current contract's type): the current contract, explicitly convertible to :ref:`address` -``selfdestruct(address recipient)``: +``selfdestruct(address payable recipient)``: destroy the current contract, sending its funds to the given :ref:`address` -``suicide(address recipient)``: - deprecated alias to ``selfdestruct`` - Furthermore, all functions of the current contract are callable directly including the current function. +.. note:: + Prior to version 0.5.0, there was a function called ``suicide`` with the same + semantics as ``selfdestruct``. + diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 1d7cb97b0..9ba6caa5f 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -10,50 +10,127 @@ Using the Commandline Compiler ****************************** .. note:: - This section doesn't apply to :ref:`solcjs `. + This section does not apply to :ref:`solcjs `, not even if it is used in commandline mode. One of the build targets of the Solidity repository is ``solc``, the solidity commandline compiler. Using ``solc --help`` provides you with an explanation of all options. The compiler can produce various outputs, ranging from simple binaries and assembly over an abstract syntax tree (parse tree) to estimations of gas usage. If you only want to compile a single file, you run it as ``solc --bin sourceFile.sol`` and it will print the binary. If you want to get some of the more advanced output variants of ``solc``, it is probably better to tell it to output everything to separate files using ``solc -o outputDirectory --bin --ast --asm sourceFile.sol``. -Before you deploy your contract, activate the optimizer while compiling using ``solc --optimize --bin sourceFile.sol``. By default, the optimizer will optimize the contract for 200 runs. If you want to optimize for initial contract deployment and get the smallest output, set it to ``--runs=1``. If you expect many transactions and don't care for higher deployment cost and output size, set ``--runs`` to a high number. +Before you deploy your contract, activate the optimizer when compiling using ``solc --optimize --bin sourceFile.sol``. +By default, the optimizer will optimize the contract assuming it is called 200 times across its lifetime. +If you want the initial contract deployment to be cheaper and the later function executions to be more expensive, +set it to ``--runs=1``. If you expect many transactions and do not care for higher deployment cost and +output size, set ``--runs`` to a high number. The commandline compiler will automatically read imported files from the filesystem, but it is also possible to provide path redirects using ``prefix=path`` in the following way: :: - solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol + solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ file.sol This essentially instructs the compiler to search for anything starting with -``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin`` and if it does not -find the file there, it will look at ``/usr/local/lib/fallback`` (the empty prefix -always matches). ``solc`` will not read files from the filesystem that lie outside of +``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin``. +``solc`` will not read files from the filesystem that lie outside of the remapping targets and outside of the directories where explicitly specified source -files reside, so things like ``import "/etc/passwd";`` only work if you add ``=/`` as a remapping. +files reside, so things like ``import "/etc/passwd";`` only work if you add ``/=/`` as a remapping. + +An empty remapping prefix is not allowed. If there are multiple matches due to remappings, the one with the longest common prefix is selected. For security reasons the compiler has restrictions what directories it can access. Paths (and their subdirectories) of source files specified on the commandline and paths defined by remappings are allowed for import statements, but everything else is rejected. Additional paths (and their subdirectories) can be allowed via the ``--allow-paths /sample/path,/another/sample/path`` switch. -If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__LibraryName______``. You can use ``solc`` as a linker meaning that it will insert the library addresses for you at those points: +If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__$53aea86b7d70b31448b230b20ae141a537$__``. These are placeholders for the actual library addresses. +The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name. +The bytecode file will also contain lines of the form ``// -> `` at the end to help +identify which libraries the placeholders represent. Note that the fully qualified library name +is the path of its source file and the library name separated by ``:``. +You can use ``solc`` as a linker meaning that it will insert the library addresses for you at those points: -Either add ``--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"`` to your command to provide an address for each library or store the string in a file (one library per line) and run ``solc`` using ``--libraries fileName``. +Either add ``--libraries "file.sol:Math:0x1234567890123456789012345678901234567890 file.sol:Heap:0xabCD567890123456789012345678901234567890"`` to your command to provide an address for each library or store the string in a file (one library per line) and run ``solc`` using ``--libraries fileName``. -If ``solc`` is called with the option ``--link``, all input files are interpreted to be unlinked binaries (hex-encoded) in the ``__LibraryName____``-format given above and are linked in-place (if the input is read from stdin, it is written to stdout). All options except ``--libraries`` are ignored (including ``-o``) in this case. +If ``solc`` is called with the option ``--link``, all input files are interpreted to be unlinked binaries (hex-encoded) in the ``__$53aea86b7d70b31448b230b20ae141a537$__``-format given above and are linked in-place (if the input is read from stdin, it is written to stdout). All options except ``--libraries`` are ignored (including ``-o``) in this case. -If ``solc`` is called with the option ``--standard-json``, it will expect a JSON input (as explained below) on the standard input, and return a JSON output on the standard output. +If ``solc`` is called with the option ``--standard-json``, it will expect a JSON input (as explained below) on the standard input, and return a JSON output on the standard output. This is the recommended interface for more complex and especially automated uses. + +.. note:: + The library placeholder used to be the fully qualified name of the library itself + instead of the hash of it. This format is still supported by ``solc --link`` but + the compiler will no longer output it. This change was made to reduce + the likelihood of a collision between libraries, since only the first 36 characters + of the fully qualified library name could be used. + +.. _evm-version: +.. index:: ! EVM version, compile target + +Setting the EVM version to target +********************************* + +When you compile your contract code you can specify the Ethereum virtual machine +version to compile for to avoid particular features or behaviours. + +.. warning:: + + Compiling for the wrong EVM version can result in wrong, strange and failing + behaviour. Please ensure, especially if running a private chain, that you + use matching EVM versions. + +On the command line, you can select the EVM version as follows: + +.. code-block:: shell + + solc --evm-version contract.sol + +In the :ref:`standard JSON interface `, use the ``"evmVersion"`` +key in the ``"settings"`` field: + +.. code-block:: none + + { + "sources": { ... }, + "settings": { + "optimizer": { ... }, + "evmVersion": "" + } + } + +Target options +-------------- + +Below is a list of target EVM versions and the compiler-relevant changes introduced +at each version. Backward compatibility is not guaranteed between each version. + +- ``homestead`` (oldest version) +- ``tangerineWhistle`` + - gas cost for access to other accounts increased, relevant for gas estimation and the optimizer. + - all gas sent by default for external calls, previously a certain amount had to be retained. +- ``spuriousDragon`` + - gas cost for the ``exp`` opcode increased, relevant for gas estimation and the optimizer. +- ``byzantium`` (**default**) + - opcodes ``returndatacopy``, ``returndatasize`` and ``staticcall`` are available in assembly. + - the ``staticcall`` opcode is used when calling non-library view or pure functions, which prevents the functions from modifying state at the EVM level, i.e., even applies when you use invalid type conversions. + - it is possible to access dynamic data returned from function calls. + - ``revert`` opcode introduced, which means that ``revert()`` will not waste gas. +- ``constantinople`` (still in progress) + - opcodes ``shl``, ``shr`` and ``sar`` are available in assembly. + - shifting operators use shifting opcodes and thus need less gas. .. _compiler-api: Compiler Input and Output JSON Description ****************************************** -These JSON formats are used by the compiler API as well as are available through ``solc``. These are subject to change, -some fields are optional (as noted), but it is aimed at to only make backwards compatible changes. +The recommended way to interface with the Solidity compiler especially for +more complex and automated setups is the so-called JSON-input-output interface. +The same interface is provided by all distributions of the compiler. + +The fields are generally subject to change, +some are optional (as noted), but we try to only make backwards compatible changes. The compiler API expects a JSON formatted input and outputs the compilation result in a JSON formatted output. +The following subsections describe the format through an example. Comments are of course not permitted and used here only for explanatory purposes. Input Description @@ -62,7 +139,7 @@ Input Description .. code-block:: none { - // Required: Source code language, such as "Solidity", "serpent", "lll", "assembly", etc. + // Required: Source code language, such as "Solidity", "Vyper", "lll", "assembly", etc. language: "Solidity", // Required sources: @@ -82,6 +159,8 @@ Input Description [ "bzzr://56ab...", "ipfs://Qma...", + // If files are used, their directories should be added to the command line via + // `--allow-paths `. "file:///tmp/path/to/file.sol" ] }, diff --git a/docs/utils/SolidityLexer.py b/docs/utils/SolidityLexer.py deleted file mode 100644 index 50f51cf4f..000000000 --- a/docs/utils/SolidityLexer.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import copy - -from pygments.lexer import RegexLexer, ExtendedRegexLexer, bygroups, using, \ - include, this -from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ - Number, Other, Punctuation, Literal - -__all__ = ['SolidityLexer'] - -class SolidityLexer(RegexLexer): - name = "Solidity" - aliases = ['sol', 'solidity'] - filenames = ['*.sol'] - mimetypes = [] - flags = re.DOTALL - tokens = { - 'commentsandwhitespace': [ - (r'\s+', Text), - (r' time - * Start Clift Vesting - */ - function calculateVestedTokens( - uint256 tokens, - uint256 time, - uint256 start, - uint256 cliff, - uint256 vesting) constant returns (uint256) - { - // Shortcuts for before cliff and after vesting cases. - if (time < cliff) return 0; - if (time >= vesting) return tokens; - - // Interpolate all vested tokens. - // As before cliff the shortcut returns 0, we can use just calculate a value - // in the vesting rect (as shown in above's figure) - - // vestedTokens = tokens * (time - start) / (vesting - start) - uint256 vestedTokens = SafeMath.div( - SafeMath.mul( - tokens, - SafeMath.sub(time, start) - ), - SafeMath.sub(vesting, start) - ); - - return vestedTokens; - } - - /** - * @dev Get all information about a specifc grant. - * @param _holder The address which will have its tokens revoked. - * @param _grantId The id of the token grant. - * @return Returns all the values that represent a TokenGrant(address, value, start, cliff, - * revokability, burnsOnRevoke, and vesting) plus the vested value at the current time. - */ - function tokenGrant(address _holder, uint256 _grantId) constant returns (address granter, uint256 value, uint256 vested, uint64 start, uint64 cliff, uint64 vesting, bool revokable, bool burnsOnRevoke) { - TokenGrant grant = grants[_holder][_grantId]; - - granter = grant.granter; - value = grant.value; - start = grant.start; - cliff = grant.cliff; - vesting = grant.vesting; - revokable = grant.revokable; - burnsOnRevoke = grant.burnsOnRevoke; - - vested = vestedTokens(grant, uint64(now)); - } - - /** - * @dev Get the amount of vested tokens at a specific time. - * @param grant TokenGrant The grant to be checked. - * @param time The time to be checked - * @return An uint256 representing the amount of vested tokens of a specific grant at a specific time. - */ - function vestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) { - return calculateVestedTokens( - grant.value, - uint256(time), - uint256(grant.start), - uint256(grant.cliff), - uint256(grant.vesting) - ); - } - - /** - * @dev Calculate the amount of non vested tokens at a specific time. - * @param grant TokenGrant The grant to be checked. - * @param time uint64 The time to be checked - * @return An uint256 representing the amount of non vested tokens of a specifc grant on the - * passed time frame. - */ - function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) { - return grant.value.sub(vestedTokens(grant, time)); - } - - /** - * @dev Calculate the date when the holder can trasfer all its tokens - * @param holder address The address of the holder - * @return An uint256 representing the date of the last transferable tokens. - */ - function lastTokenIsTransferableDate(address holder) constant public returns (uint64 date) { - date = uint64(now); - uint256 grantIndex = grants[holder].length; - for (uint256 i = 0; i < grantIndex; i++) { - date = Math.max64(grants[holder][i].vesting, date); - } - } -} diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index 5e4991e2c..eb274c095 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -40,23 +40,23 @@ namespace { static char const* registrarCode = R"DELIMITER( -pragma solidity ^0.4.0; +pragma solidity >=0.4.0 <0.6.0; contract NameRegister { - function addr(string _name) constant returns (address o_owner); - function name(address _owner) constant returns (string o_name); + function addr(string memory _name) public view returns (address o_owner); + function name(address _owner) public view returns (string memory o_name); } contract Registrar is NameRegister { event Changed(string indexed name); event PrimaryChanged(string indexed name, address indexed addr); - function owner(string _name) constant returns (address o_owner); - function addr(string _name) constant returns (address o_address); - function subRegistrar(string _name) constant returns (address o_subRegistrar); - function content(string _name) constant returns (bytes32 o_content); + function owner(string memory _name) public view returns (address o_owner); + function addr(string memory _name) public view returns (address o_address); + function subRegistrar(string memory _name) public view returns (address o_subRegistrar); + function content(string memory _name) public view returns (bytes32 o_content); - function name(address _owner) constant returns (string o_name); + function name(address _owner) public view returns (string memory o_name); } contract AuctionSystem { @@ -64,13 +64,13 @@ contract AuctionSystem { event NewBid(string indexed _name, address _bidder, uint _value); /// Function that is called once an auction ends. - function onAuctionEnd(string _name) internal; + function onAuctionEnd(string memory _name) internal; - function bid(string _name, address _bidder, uint _value) internal { - var auction = m_auctions[_name]; + function bid(string memory _name, address payable _bidder, uint _value) internal { + Auction storage auction = m_auctions[_name]; if (auction.endDate > 0 && now > auction.endDate) { - AuctionEnded(_name, auction.highestBidder); + emit AuctionEnded(_name, auction.highestBidder); onAuctionEnd(_name); delete m_auctions[_name]; return; @@ -84,14 +84,14 @@ contract AuctionSystem { auction.highestBidder = _bidder; auction.endDate = now + c_biddingTime; - NewBid(_name, _bidder, _value); + emit NewBid(_name, _bidder, _value); } } uint constant c_biddingTime = 7 days; struct Auction { - address highestBidder; + address payable highestBidder; uint highestBid; uint secondHighestBid; uint sumOfBids; @@ -102,91 +102,91 @@ contract AuctionSystem { contract GlobalRegistrar is Registrar, AuctionSystem { struct Record { - address owner; + address payable owner; address primary; address subRegistrar; bytes32 content; uint renewalDate; } - uint constant c_renewalInterval = 1 years; + uint constant c_renewalInterval = 365 days; uint constant c_freeBytes = 12; - function Registrar() { + function Registrar() public { // TODO: Populate with hall-of-fame. } - function onAuctionEnd(string _name) internal { - var auction = m_auctions[_name]; - var record = m_toRecord[_name]; - var previousOwner = record.owner; + function onAuctionEnd(string memory _name) internal { + Auction storage auction = m_auctions[_name]; + Record storage record = m_toRecord[_name]; + address previousOwner = record.owner; record.renewalDate = now + c_renewalInterval; record.owner = auction.highestBidder; - Changed(_name); - if (previousOwner != 0) { + emit Changed(_name); + if (previousOwner != 0x0000000000000000000000000000000000000000) { if (!record.owner.send(auction.sumOfBids - auction.highestBid / 100)) - throw; + revert(); } else { if (!auction.highestBidder.send(auction.highestBid - auction.secondHighestBid)) - throw; + revert(); } } - function reserve(string _name) external payable { + function reserve(string calldata _name) external payable { if (bytes(_name).length == 0) - throw; + revert(); bool needAuction = requiresAuction(_name); if (needAuction) { if (now < m_toRecord[_name].renewalDate) - throw; + revert(); bid(_name, msg.sender, msg.value); } else { - Record record = m_toRecord[_name]; - if (record.owner != 0) - throw; + Record storage record = m_toRecord[_name]; + if (record.owner != 0x0000000000000000000000000000000000000000) + revert(); m_toRecord[_name].owner = msg.sender; - Changed(_name); + emit Changed(_name); } } - function requiresAuction(string _name) internal returns (bool) { + function requiresAuction(string memory _name) internal returns (bool) { return bytes(_name).length < c_freeBytes; } - modifier onlyrecordowner(string _name) { if (m_toRecord[_name].owner == msg.sender) _; } + modifier onlyrecordowner(string memory _name) { if (m_toRecord[_name].owner == msg.sender) _; } - function transfer(string _name, address _newOwner) onlyrecordowner(_name) { + function transfer(string memory _name, address payable _newOwner) onlyrecordowner(_name) public { m_toRecord[_name].owner = _newOwner; - Changed(_name); + emit Changed(_name); } - function disown(string _name) onlyrecordowner(_name) { + function disown(string memory _name) onlyrecordowner(_name) public { if (stringsEqual(m_toName[m_toRecord[_name].primary], _name)) { - PrimaryChanged(_name, m_toRecord[_name].primary); + emit PrimaryChanged(_name, m_toRecord[_name].primary); m_toName[m_toRecord[_name].primary] = ""; } delete m_toRecord[_name]; - Changed(_name); + emit Changed(_name); } - function setAddress(string _name, address _a, bool _primary) onlyrecordowner(_name) { + function setAddress(string memory _name, address _a, bool _primary) onlyrecordowner(_name) public { m_toRecord[_name].primary = _a; if (_primary) { - PrimaryChanged(_name, _a); + emit PrimaryChanged(_name, _a); m_toName[_a] = _name; } - Changed(_name); + emit Changed(_name); } - function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) { + function setSubRegistrar(string memory _name, address _registrar) onlyrecordowner(_name) public { m_toRecord[_name].subRegistrar = _registrar; - Changed(_name); + emit Changed(_name); } - function setContent(string _name, bytes32 _content) onlyrecordowner(_name) { + function setContent(string memory _name, bytes32 _content) onlyrecordowner(_name) public { m_toRecord[_name].content = _content; - Changed(_name); + emit Changed(_name); } function stringsEqual(string storage _a, string memory _b) internal returns (bool) { @@ -201,11 +201,11 @@ contract GlobalRegistrar is Registrar, AuctionSystem { return true; } - function owner(string _name) constant returns (address) { return m_toRecord[_name].owner; } - function addr(string _name) constant returns (address) { return m_toRecord[_name].primary; } - function subRegistrar(string _name) constant returns (address) { return m_toRecord[_name].subRegistrar; } - function content(string _name) constant returns (bytes32) { return m_toRecord[_name].content; } - function name(address _addr) constant returns (string o_name) { return m_toName[_addr]; } + function owner(string memory _name) public view returns (address) { return m_toRecord[_name].owner; } + function addr(string memory _name) public view returns (address) { return m_toRecord[_name].primary; } + function subRegistrar(string memory _name) public view returns (address) { return m_toRecord[_name].subRegistrar; } + function content(string memory _name) public view returns (bytes32) { return m_toRecord[_name].content; } + function name(address _addr) public view returns (string memory o_name) { return m_toName[_addr]; } mapping (address => string) m_toName; mapping (string => Record) m_toRecord; @@ -223,6 +223,7 @@ protected: s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "GlobalRegistrar"))); sendMessage(*s_compiledRegistrar, true); + BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index a3a27c377..e82f389fc 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -53,15 +53,15 @@ static char const* registrarCode = R"DELIMITER( // @authors: // Gav Wood -pragma solidity ^0.4.0; +pragma solidity >=0.4.0 <0.6.0; contract Registrar { event Changed(string indexed name); - function owner(string _name) constant returns (address o_owner); - function addr(string _name) constant returns (address o_address); - function subRegistrar(string _name) constant returns (address o_subRegistrar); - function content(string _name) constant returns (bytes32 o_content); + function owner(string memory _name) public view returns (address o_owner); + function addr(string memory _name) public view returns (address o_address); + function subRegistrar(string memory _name) public view returns (address o_subRegistrar); + function content(string memory _name) public view returns (bytes32 o_content); } contract FixedFeeRegistrar is Registrar { @@ -72,53 +72,53 @@ contract FixedFeeRegistrar is Registrar { address owner; } - modifier onlyrecordowner(string _name) { if (m_record(_name).owner == msg.sender) _; } + modifier onlyrecordowner(string memory _name) { if (m_record(_name).owner == msg.sender) _; } - function reserve(string _name) payable { - Record rec = m_record(_name); - if (rec.owner == 0 && msg.value >= c_fee) { + function reserve(string memory _name) public payable { + Record storage rec = m_record(_name); + if (rec.owner == 0x0000000000000000000000000000000000000000 && msg.value >= c_fee) { rec.owner = msg.sender; - Changed(_name); + emit Changed(_name); } } - function disown(string _name, address _refund) onlyrecordowner(_name) { - delete m_recordData[uint(keccak256(_name)) / 8]; + function disown(string memory _name, address payable _refund) onlyrecordowner(_name) public { + delete m_recordData[uint(keccak256(bytes(_name))) / 8]; if (!_refund.send(c_fee)) - throw; - Changed(_name); + revert(); + emit Changed(_name); } - function transfer(string _name, address _newOwner) onlyrecordowner(_name) { + function transfer(string memory _name, address _newOwner) onlyrecordowner(_name) public { m_record(_name).owner = _newOwner; - Changed(_name); + emit Changed(_name); } - function setAddr(string _name, address _a) onlyrecordowner(_name) { + function setAddr(string memory _name, address _a) onlyrecordowner(_name) public { m_record(_name).addr = _a; - Changed(_name); + emit Changed(_name); } - function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) { + function setSubRegistrar(string memory _name, address _registrar) onlyrecordowner(_name) public { m_record(_name).subRegistrar = _registrar; - Changed(_name); + emit Changed(_name); } - function setContent(string _name, bytes32 _content) onlyrecordowner(_name) { + function setContent(string memory _name, bytes32 _content) onlyrecordowner(_name) public { m_record(_name).content = _content; - Changed(_name); + emit Changed(_name); } - function record(string _name) constant returns (address o_addr, address o_subRegistrar, bytes32 o_content, address o_owner) { - Record rec = m_record(_name); + function record(string memory _name) public view returns (address o_addr, address o_subRegistrar, bytes32 o_content, address o_owner) { + Record storage rec = m_record(_name); o_addr = rec.addr; o_subRegistrar = rec.subRegistrar; o_content = rec.content; o_owner = rec.owner; } - function addr(string _name) constant returns (address) { return m_record(_name).addr; } - function subRegistrar(string _name) constant returns (address) { return m_record(_name).subRegistrar; } - function content(string _name) constant returns (bytes32) { return m_record(_name).content; } - function owner(string _name) constant returns (address) { return m_record(_name).owner; } + function addr(string memory _name) public view returns (address) { return m_record(_name).addr; } + function subRegistrar(string memory _name) public view returns (address) { return m_record(_name).subRegistrar; } + function content(string memory _name) public view returns (bytes32) { return m_record(_name).content; } + function owner(string memory _name) public view returns (address) { return m_record(_name).owner; } Record[2**253] m_recordData; - function m_record(string _name) constant internal returns (Record storage o_record) { - return m_recordData[uint(keccak256(_name)) / 8]; + function m_record(string memory _name) view internal returns (Record storage o_record) { + return m_recordData[uint(keccak256(bytes(_name))) / 8]; } uint constant c_fee = 69 ether; } @@ -135,6 +135,7 @@ protected: s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "FixedFeeRegistrar"))); sendMessage(*s_compiledRegistrar, true); + BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } u256 const m_fee = u256("69000000000000000000"); diff --git a/test/contracts/LLL_ENS.cpp b/test/contracts/LLL_ENS.cpp index 028d58c87..cfd6970cc 100644 --- a/test/contracts/LLL_ENS.cpp +++ b/test/contracts/LLL_ENS.cpp @@ -28,7 +28,7 @@ #define ACCOUNT(n) h256(account(n), h256::AlignRight) using namespace std; -using namespace dev::eth; +using namespace dev::lll; namespace dev { @@ -349,6 +349,7 @@ protected: BOOST_REQUIRE(errors.empty()); } sendMessage(*s_compiledEns, true); + BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } diff --git a/test/contracts/LLL_ERC20.cpp b/test/contracts/LLL_ERC20.cpp index 60b43e4f9..6c6762dd0 100644 --- a/test/contracts/LLL_ERC20.cpp +++ b/test/contracts/LLL_ERC20.cpp @@ -33,7 +33,7 @@ #define SUCCESS encodeArgs(1) using namespace std; -using namespace dev::eth; +using namespace dev::lll; namespace dev { @@ -400,6 +400,7 @@ protected: BOOST_REQUIRE(errors.empty()); } sendMessage(*s_compiledErc20, true); + BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } @@ -629,18 +630,22 @@ BOOST_AUTO_TEST_CASE(bad_data) // Correct data: transfer(address _to, 1). sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a123456789a") + encodeArgs(1), false, 0); + BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(m_output == SUCCESS); // Too little data (address is truncated by one byte). sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a12345678") + encodeArgs(1), false, 0); + BOOST_CHECK(!m_transactionSuccessful); BOOST_CHECK(m_output != SUCCESS); // Too much data (address is extended with a zero byte). sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a123456789a00") + encodeArgs(1), false, 0); + BOOST_CHECK(!m_transactionSuccessful); BOOST_CHECK(m_output != SUCCESS); // Invalid address (a bit above the 160th is set). sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000100123456789a123456789a123456789a123456789a") + encodeArgs(1), false, 0); + BOOST_CHECK(!m_transactionSuccessful); BOOST_CHECK(m_output != SUCCESS); } diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 1031e8f19..9fe02e463 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -56,7 +56,7 @@ static char const* walletCode = R"DELIMITER( // some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the // interior is executed. -pragma solidity ^0.4.0; +pragma solidity >=0.4.0 <0.6.0; contract multiowned { @@ -101,7 +101,7 @@ contract multiowned { // constructor is given number of sigs required to do protected "onlymanyowners" transactions // as well as the selection of addresses capable of confirming them. - function multiowned(address[] _owners, uint _required) { + constructor(address[] memory _owners, uint _required) public { m_numOwners = _owners.length + 1; m_owners[1] = uint(msg.sender); m_ownerIndex[uint(msg.sender)] = 1; @@ -119,11 +119,11 @@ contract multiowned { // make sure they're an owner if (ownerIndex == 0) return; uint ownerIndexBit = 2**ownerIndex; - var pending = m_pending[_operation]; + PendingState storage pending = m_pending[_operation]; if (pending.ownersDone & ownerIndexBit > 0) { pending.yetNeeded++; pending.ownersDone -= ownerIndexBit; - Revoke(msg.sender, _operation); + emit Revoke(msg.sender, _operation); } } @@ -137,7 +137,7 @@ contract multiowned { m_owners[ownerIndex] = uint(_to); m_ownerIndex[uint(_from)] = 0; m_ownerIndex[uint(_to)] = ownerIndex; - OwnerChanged(_from, _to); + emit OwnerChanged(_from, _to); } function addOwner(address _owner) onlymanyowners(keccak256(msg.data)) external { @@ -151,7 +151,7 @@ contract multiowned { m_numOwners++; m_owners[m_numOwners] = uint(_owner); m_ownerIndex[uint(_owner)] = m_numOwners; - OwnerAdded(_owner); + emit OwnerAdded(_owner); } function removeOwner(address _owner) onlymanyowners(keccak256(msg.data)) external { @@ -163,22 +163,22 @@ contract multiowned { m_ownerIndex[uint(_owner)] = 0; clearPending(); reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot - OwnerRemoved(_owner); + emit OwnerRemoved(_owner); } function changeRequirement(uint _newRequired) onlymanyowners(keccak256(msg.data)) external { if (_newRequired > m_numOwners) return; m_required = _newRequired; clearPending(); - RequirementChanged(_newRequired); + emit RequirementChanged(_newRequired); } - function isOwner(address _addr) returns (bool) { + function isOwner(address _addr) public returns (bool) { return m_ownerIndex[uint(_addr)] > 0; } - function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { - var pending = m_pending[_operation]; + function hasConfirmed(bytes32 _operation, address _owner) public view returns (bool) { + PendingState storage pending = m_pending[_operation]; uint ownerIndex = m_ownerIndex[uint(_owner)]; // make sure they're an owner @@ -199,9 +199,9 @@ contract multiowned { // determine what index the present sender is: uint ownerIndex = m_ownerIndex[uint(msg.sender)]; // make sure they're an owner - if (ownerIndex == 0) return; + if (ownerIndex == 0) return false; - var pending = m_pending[_operation]; + PendingState storage pending = m_pending[_operation]; // if we're not yet working on this operation, switch over and reset the confirmation status. if (pending.yetNeeded == 0) { // reset count of confirmations needed. @@ -215,7 +215,7 @@ contract multiowned { uint ownerIndexBit = 2**ownerIndex; // make sure we (the message sender) haven't confirmed this operation previously. if (pending.ownersDone & ownerIndexBit == 0) { - Confirmation(msg.sender, _operation); + emit Confirmation(msg.sender, _operation); // ok - check if count is enough to go ahead. if (pending.yetNeeded <= 1) { // enough confirmations: reset and run interior. @@ -228,6 +228,7 @@ contract multiowned { // not enough: record that this owner in particular confirmed. pending.yetNeeded--; pending.ownersDone |= ownerIndexBit; + return false; } } } @@ -288,7 +289,7 @@ contract daylimit is multiowned { // METHODS // constructor - stores initial daily limit and records the present day's index. - function daylimit(uint _limit) { + constructor(uint _limit) public { m_dailyLimit = _limit; m_lastDay = today(); } @@ -319,7 +320,7 @@ contract daylimit is multiowned { return false; } // determines today's index. - function today() private constant returns (uint) { return now / 1 days; } + function today() private view returns (uint) { return now / 1 days; } // FIELDS @@ -347,8 +348,8 @@ contract multisig { // TODO: document function changeOwner(address _from, address _to) external; - function execute(address _to, uint _value, bytes _data) external returns (bytes32); - function confirm(bytes32 _h) returns (bool); + function execute(address _to, uint _value, bytes calldata _data) external returns (bytes32); + function confirm(bytes32 _h) public returns (bool); } // usage: @@ -369,50 +370,50 @@ contract Wallet is multisig, multiowned, daylimit { // constructor - just pass on the owner array to the multiowned and // the limit to daylimit - function Wallet(address[] _owners, uint _required, uint _daylimit) payable + constructor(address[] memory _owners, uint _required, uint _daylimit) public payable multiowned(_owners, _required) daylimit(_daylimit) { } // destroys the contract sending everything to `_to`. - function kill(address _to) onlymanyowners(keccak256(msg.data)) external { + function kill(address payable _to) onlymanyowners(keccak256(msg.data)) external { selfdestruct(_to); } // gets called when no other function matches - function() payable { + function() external payable { // just being sent some cash? if (msg.value > 0) - Deposit(msg.sender, msg.value); + emit Deposit(msg.sender, msg.value); } - // Outside-visible transact entry point. Executes transacion immediately if below daily spend limit. + // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit. // If not, goes into multisig process. We provide a hash on return to allow the sender to provide // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value // and _data arguments). They still get the option of using them if they want, anyways. - function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 _r) { + function execute(address _to, uint _value, bytes calldata _data) external onlyowner returns (bytes32 _r) { // first, take the opportunity to check that we're under the daily limit. if (underLimit(_value)) { - SingleTransact(msg.sender, _value, _to, _data); + emit SingleTransact(msg.sender, _value, _to, _data); // yes - just execute the call. _to.call.value(_value)(_data); return 0; } // determine our operation hash. - _r = keccak256(msg.data, block.number); - if (!confirm(_r) && m_txs[_r].to == 0) { + _r = keccak256(abi.encodePacked(msg.data, block.number)); + if (!confirm(_r) && m_txs[_r].to == 0x0000000000000000000000000000000000000000) { m_txs[_r].to = _to; m_txs[_r].value = _value; m_txs[_r].data = _data; - ConfirmationNeeded(_r, msg.sender, _value, _to, _data); + emit ConfirmationNeeded(_r, msg.sender, _value, _to, _data); } } // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order // to determine the body of the transaction from the hash provided. - function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) { - if (m_txs[_h].to != 0) { + function confirm(bytes32 _h) onlymanyowners(_h) public returns (bool) { + if (m_txs[_h].to != 0x0000000000000000000000000000000000000000) { m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data); - MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data); + emit MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data); delete m_txs[_h]; return true; } @@ -451,6 +452,7 @@ protected: bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners); sendMessage(*s_compiledWallet + args, true, _value); + BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } }; diff --git a/test/externalTests.sh b/test/externalTests.sh index cd6deb754..935819257 100755 --- a/test/externalTests.sh +++ b/test/externalTests.sh @@ -40,21 +40,52 @@ function test_truffle { name="$1" repo="$2" + branch="$3" echo "Running $name tests..." DIR=$(mktemp -d) ( - git clone --depth 1 "$repo" "$DIR" - cd "$DIR" - npm install - find . -name soljson.js -exec cp "$SOLJSON" {} \; - if [ "$name" == "Gnosis" ]; then - # Replace fixed-version pragmas in Gnosis (part of Consensys best practice) - find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity 0/pragma solidity ^0/' + if [ -n "$branch" ] + then + echo "Cloning $branch of $repo..." + git clone --depth 1 "$repo" -b "$branch" "$DIR" + else + echo "Cloning $repo..." + git clone --depth 1 "$repo" "$DIR" fi + cd "$DIR" + echo "Current commit hash: `git rev-parse HEAD`" + npm install + # Replace solc package by master + for d in node_modules node_modules/truffle/node_modules + do + ( + cd $d + rm -rf solc + git clone --depth 1 https://github.com/ethereum/solc-js.git solc + cp "$SOLJSON" solc/ + ) + done + if [ "$name" == "Zeppelin" -o "$name" == "Gnosis" ]; then + echo "Replaced fixed-version pragmas..." + # Replace fixed-version pragmas in Gnosis (part of Consensys best practice) + find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity [\^0-9\.]*/pragma solidity >=0.0/' + fi + assertsol="node_modules/truffle/build/Assert.sol" + if [ -f "$assertsol" ] + then + echo "Replace Truffle's Assert.sol with a known good version" + rm "$assertsol" + wget https://raw.githubusercontent.com/trufflesuite/truffle-core/ef31bcaa15dbd9bd0f6a0070a5c63f271cde2dbc/lib/testing/Assert.sol -o "$assertsol" + fi + # Change "compileStandard" to "compile" + sed -i s/solc.compileStandard/solc.compile/ "node_modules/truffle/build/cli.bundled.js" npm run test ) rm -rf "$DIR" } -test_truffle Gnosis https://github.com/gnosis/gnosis-contracts.git -test_truffle Zeppelin https://github.com/OpenZeppelin/zeppelin-solidity.git +# Using our temporary fork here. Hopefully to be merged into upstream after the 0.5.0 release. +test_truffle Zeppelin https://github.com/axic/openzeppelin-solidity.git solidity-050 + +# Disabled temporarily as it needs to be updated to latest Truffle first. +#test_truffle Gnosis https://github.com/axic/pm-contracts.git solidity-050 diff --git a/test/libdevcore/IterateReplacing.cpp b/test/libdevcore/IterateReplacing.cpp new file mode 100644 index 000000000..08cd1e22f --- /dev/null +++ b/test/libdevcore/IterateReplacing.cpp @@ -0,0 +1,97 @@ +/* + 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 . +*/ +/** + * Unit tests for the iterateReplacing function + */ + +#include + +#include + +using namespace std; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(IterateReplacing) + +BOOST_AUTO_TEST_CASE(no_replacement) +{ + vector v{"abc", "def", "ghi"}; + function>(string&)> f = [](string&) -> boost::optional> { return {}; }; + iterateReplacing(v, f); + vector expectation{"abc", "def", "ghi"}; + BOOST_CHECK(v == expectation); +} + +BOOST_AUTO_TEST_CASE(empty_input) +{ + vector v; + function>(string&)> f = [](string&) -> boost::optional> { return {}; }; + iterateReplacing(v, f); + vector expectation; + BOOST_CHECK(v == expectation); +} + +BOOST_AUTO_TEST_CASE(delete_some) +{ + vector v{"abc", "def", "ghi"}; + function>(string&)> f = [](string& _s) -> boost::optional> { + if (_s == "def") + return vector(); + else + return {}; + }; + iterateReplacing(v, f); + vector expectation{"abc", "ghi"}; + BOOST_CHECK(v == expectation); +} + +BOOST_AUTO_TEST_CASE(inject_some_start) +{ + vector v{"abc", "def", "ghi"}; + function>(string&)> f = [](string& _s) -> boost::optional> { + if (_s == "abc") + return vector{"x", "y"}; + else + return {}; + }; + iterateReplacing(v, f); + vector expectation{"x", "y", "def", "ghi"}; + BOOST_CHECK(v == expectation); +} + +BOOST_AUTO_TEST_CASE(inject_some_end) +{ + vector v{"abc", "def", "ghi"}; + function>(string&)> f = [](string& _s) -> boost::optional> { + if (_s == "ghi") + return vector{"x", "y"}; + else + return {}; + }; + iterateReplacing(v, f); + vector expectation{"abc", "def", "x", "y"}; + BOOST_CHECK(v == expectation); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} diff --git a/test/libdevcore/StringUtils.cpp b/test/libdevcore/StringUtils.cpp index 9ee93d02a..76c11b828 100644 --- a/test/libdevcore/StringUtils.cpp +++ b/test/libdevcore/StringUtils.cpp @@ -48,6 +48,7 @@ BOOST_AUTO_TEST_CASE(test_similarity) BOOST_CHECK_EQUAL(stringWithinDistance("abc", "abcdef", 2), false); BOOST_CHECK_EQUAL(stringWithinDistance("abcd", "wxyz", 2), false); BOOST_CHECK_EQUAL(stringWithinDistance("", "", 2), true); + BOOST_CHECK_EQUAL(stringWithinDistance("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY", "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZ", 2, 6400), false); } BOOST_AUTO_TEST_CASE(test_dldistance) @@ -81,6 +82,24 @@ BOOST_AUTO_TEST_CASE(test_alternatives_list) BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\", \"c\" or \"d\""); } +BOOST_AUTO_TEST_CASE(test_human_readable_join) +{ + BOOST_CHECK_EQUAL(joinHumanReadable(vector({})), ""); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a"})), "a"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a", "b"})), "a, b"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a", "b", "c"})), "a, b, c"); + + BOOST_CHECK_EQUAL(joinHumanReadable(vector({}), "; "), ""); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a"}), "; "), "a"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a", "b"}), "; "), "a; b"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a", "b", "c"}), "; "), "a; b; c"); + + BOOST_CHECK_EQUAL(joinHumanReadable(vector({}), "; ", " or "), ""); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a"}), "; ", " or "), "a"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a", "b"}), "; ", " or "), "a or b"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector({"a", "b", "c"}), "; ", " or "), "a; b or c"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libdevcore/UTF8.cpp b/test/libdevcore/UTF8.cpp index 6de4570fe..daf47bb06 100644 --- a/test/libdevcore/UTF8.cpp +++ b/test/libdevcore/UTF8.cpp @@ -148,7 +148,7 @@ hélló Ḕ ḕ Ḗ ḗ Ḙ ḙ Ḛ -ἐ ἑ ἒ ἓ ἔ ἕ +ἐ ἑ ἒ ἓ ἔ ἕ ₠ ₡ ₢ ₣ ₤ ₥ @@ -164,9 +164,9 @@ hélló ␀ ␁ ␂ ␃ ␄ ␅ -⑀ ⑁ ⑂ ⑃ ⑄ +⑀ ⑁ ⑂ ⑃ ⑄ -① ② ③ ④ ⑤ +① ② ③ ④ ⑤ ╘ ╙ ╚ ╛ ╜ ╝ @@ -200,7 +200,7 @@ hélló שּׁ שּׂ אַ אָ אּ -ﮄ ﮅ ﮆ ﮇ ﮈ ﮉ +ﮄ ﮅ ﮆ ﮇ ﮈ ﮉ ﺵ ﺶ ﺷ ﺸ diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp new file mode 100644 index 000000000..1c041596a --- /dev/null +++ b/test/libevmasm/Assembler.cpp @@ -0,0 +1,152 @@ +/* + 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 . +*/ +/** + * @author Alex Beregszaszi + * @date 2018 + * Tests for the assembler. + */ + +#include +#include + +#include + +#include +#include +#include + +using namespace std; +using namespace dev::eth; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +namespace +{ + void checkCompilation(::dev::eth::Assembly const& _assembly) + { + LinkerObject output = _assembly.assemble(); + BOOST_CHECK(output.bytecode.size() > 0); + BOOST_CHECK(output.toHex().length() > 0); + } +} + +BOOST_AUTO_TEST_SUITE(Assembler) + +BOOST_AUTO_TEST_CASE(all_assembly_items) +{ + Assembly _assembly; + _assembly.setSourceLocation(SourceLocation(1, 3, make_shared("root.asm"))); + + Assembly _subAsm; + _subAsm.setSourceLocation(SourceLocation(6, 8, make_shared("sub.asm"))); + _subAsm.append(Instruction::INVALID); + shared_ptr _subAsmPtr = make_shared(_subAsm); + + // Tag + auto tag = _assembly.newTag(); + _assembly.append(tag); + // Operation + _assembly.append(u256(1)); + _assembly.append(u256(2)); + // Push + _assembly.append(Instruction::KECCAK256); + // PushProgramSize + _assembly.appendProgramSize(); + // PushLibraryAddress + _assembly.appendLibraryAddress("someLibrary"); + // PushTag + Operation + _assembly.appendJump(tag); + // PushString + _assembly.append("Unused feature for pushing string"); + // PushData + _assembly.append(bytes{0x1, 0x2, 0x3, 0x4}); + // PushSubSize + auto sub = _assembly.appendSubroutine(_subAsmPtr); + // PushSub + _assembly.pushSubroutineOffset(size_t(sub.data())); + // PushDeployTimeAddress + _assembly.append(PushDeployTimeAddress); + // Operation + _assembly.append(Instruction::STOP); + _assembly.appendAuxiliaryDataToEnd(bytes{0x42, 0x66}); + _assembly.appendAuxiliaryDataToEnd(bytes{0xee, 0xaa}); + + checkCompilation(_assembly); + + BOOST_CHECK_EQUAL( + _assembly.assemble().toHex(), + "5b6001600220606773__$bf005014d9d0f534b8fcb268bd84c491a2$__" + "6000567f556e75736564206665617475726520666f722070757368696e" + "6720737472696e605f6001605e73000000000000000000000000000000000000000000fe" + "fe010203044266eeaa" + ); + BOOST_CHECK_EQUAL( + _assembly.assemblyString(), + " /* \"root.asm\":1:3 */\n" + "tag_1:\n" + " keccak256(0x2, 0x1)\n" + " bytecodeSize\n" + " linkerSymbol(\"bf005014d9d0f534b8fcb268bd84c491a2380f4acd260d1ccfe9cd8201f7e994\")\n" + " jump(tag_1)\n" + " data_027497964124140851e8a9992ba16b5c1aaf9730b78d6036c8d65e3bb5ea4c8f\n" + " data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b\n" + " dataSize(sub_0)\n" + " dataOffset(sub_0)\n" + " deployTimeAddress()\n" + " stop\n" + "stop\n" + "data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b 01020304\n" + "\n" + "sub_0: assembly {\n" + " /* \"sub.asm\":6:8 */\n" + " invalid\n" + "}\n" + "\n" + "auxdata: 0x4266eeaa\n" + ); + BOOST_CHECK_EQUAL( + dev::jsonCompactPrint(_assembly.assemblyJSON()), + "{\".auxdata\":\"4266eeaa\",\".code\":[{\"begin\":1,\"end\":3,\"name\":\"tag\",\"value\":\"1\"}," + "{\"begin\":1,\"end\":3,\"name\":\"JUMPDEST\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"value\":\"1\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"value\":\"2\"}," + "{\"begin\":1,\"end\":3,\"name\":\"KECCAK256\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSHSIZE\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSHLIB\",\"value\":\"someLibrary\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH [tag]\",\"value\":\"1\"}," + "{\"begin\":1,\"end\":3,\"name\":\"JUMP\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH tag\",\"value\":\"Unused feature for pushing string\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH data\",\"value\":\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSHDEPLOYADDRESS\"}," + "{\"begin\":1,\"end\":3,\"name\":\"STOP\"}]," + "\".data\":{\"0\":{\".code\":[{\"begin\":6,\"end\":8,\"name\":\"INVALID\"}]}," + "\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"}}" + ); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 4b399a14a..c01e87580 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -967,6 +966,31 @@ BOOST_AUTO_TEST_CASE(peephole_swap_comparison) } } +BOOST_AUTO_TEST_CASE(peephole_truthy_and) +{ + AssemblyItems items{ + AssemblyItem(Tag, 1), + Instruction::BALANCE, + u256(0), + Instruction::NOT, + Instruction::AND, + AssemblyItem(PushTag, 1), + Instruction::JUMPI + }; + AssemblyItems expectation{ + AssemblyItem(Tag, 1), + Instruction::BALANCE, + AssemblyItem(PushTag, 1), + Instruction::JUMPI + }; + PeepholeOptimiser peepOpt(items); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + BOOST_AUTO_TEST_CASE(jumpdest_removal) { AssemblyItems items{ diff --git a/test/libjulia/CommonSubexpression.cpp b/test/libjulia/CommonSubexpression.cpp deleted file mode 100644 index 8a575c48b..000000000 --- a/test/libjulia/CommonSubexpression.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - 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 . -*/ -/** - * Unit tests for the common subexpression eliminator optimizer stage. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = disambiguate(_original, false);\ - (CommonSubexpressionEliminator{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(IuliaCSE) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(trivial) -{ - CHECK( - "{ let a := mul(1, codesize()) let b := mul(1, codesize()) }", - "{ let a := mul(1, codesize()) let b := a }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_instr) -{ - CHECK( - "{ let a := mload(1) let b := mload(1) }", - "{ let a := mload(1) let b := mload(1) }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_instr2) -{ - CHECK( - "{ let a := gas() let b := gas() }", - "{ let a := gas() let b := gas() }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_if) -{ - CHECK( - "{ let b := 1 if b { b := 1 } let c := 1 }", - "{ let b := 1 if b { b := b } let c := 1 }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_for) -{ - CHECK( - "{ let a := 1 let b := codesize()" - "for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) }" - "{ mstore(1, codesize()) } mstore(1, codesize()) }", - - "{ let a := 1 let b := codesize()" - "for { } lt(1, b) { mstore(1, b) a := add(a, b) }" - "{ mstore(1, b) } mstore(1, b) }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/Disambiguator.cpp b/test/libjulia/Disambiguator.cpp deleted file mode 100644 index a63384493..000000000 --- a/test/libjulia/Disambiguator.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for the iulia name disambiguator. - */ - -#include - -#include - -#include - -using namespace std; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - string result = p(disambiguate(_original));\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ - BOOST_CHECK_EQUAL(result, p(disambiguate(result)));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(IuliaDisambiguator) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(variables) -{ - CHECK( - "{ { let a:u256 } { let a:u256 } }", - "{ { let a:u256 } { let a_1:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(variables_clash) -{ - CHECK( - "{ { let a:u256 let a_1:u256 } { let a:u256 } }", - "{ { let a:u256 let a_1:u256 } { let a_2:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(variables_inside_functions) -{ - CHECK( - "{ { let c:u256 let b:u256 } function f(a:u256, c:u256) -> b:u256 { let x:u256 } { let a:u256 let x:u256 } }", - "{ { let c:u256 let b:u256 } function f(a:u256, c_1:u256) -> b_1:u256 { let x:u256 } { let a_1:u256 let x_1:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(function_call) -{ - CHECK( - "{ { let a:u256, b:u256, c:u256, d:u256, f:u256 } { function f(a:u256) -> c:u256, d:u256 { let b:u256, c_1:u256 := f(a) } } }", - "{ { let a:u256, b:u256, c:u256, d:u256, f:u256 } { function f_1(a_1:u256) -> c_1:u256, d_1:u256 { let b_1:u256, c_1_1:u256 := f_1(a_1) } } }" - ); -} - -BOOST_AUTO_TEST_CASE(for_statement) -{ - CHECK( - "{ { let a:u256, b:u256 } { for { let a:u256 } a { a := a } { let b:u256 := a } } }", - "{ { let a:u256, b:u256 } { for { let a_1:u256 } a_1 { a_1 := a_1 } { let b_1:u256 := a_1 } } }" - ); -} - -BOOST_AUTO_TEST_CASE(switch_statement) -{ - CHECK( - "{ { let a:u256, b:u256, c:u256 } { let a:u256 switch a case 0:u256 { let b:u256 := a } default { let c:u256 := a } } }", - "{ { let a:u256, b:u256, c:u256 } { let a_1:u256 switch a_1 case 0:u256 { let b_1:u256 := a_1 } default { let c_1:u256 := a_1 } } }" - ); -} - -BOOST_AUTO_TEST_CASE(if_statement) -{ - CHECK( - "{ { let a:u256, b:u256, c:u256 } { let a:bool if a { let b:bool := a } } }", - "{ { let a:u256, b:u256, c:u256 } { let a_1:bool if a_1 { let b_1:bool := a_1 } } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/FunctionGrouper.cpp b/test/libjulia/FunctionGrouper.cpp deleted file mode 100644 index 78f382cb1..000000000 --- a/test/libjulia/FunctionGrouper.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for the iulia function grouper. - */ - -#include - -#include - -#include - -#include - -using namespace std; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - Block b = disambiguate(_original);\ - (FunctionGrouper{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(IuliaFunctionGrouper) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ { } }"); -} - -BOOST_AUTO_TEST_CASE(single_fun) -{ - CHECK( - "{ let a:u256 function f() {} }", - "{ { let a:u256 } function f() {} }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun_mixed) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 } let c:u256 function g() { let d:u256 } let e:u256 }", - "{ { let a:u256 let c:u256 let e:u256 } function f() { let b:u256 } function g() { let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(nested_fun) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 function g() { let c:u256} let d:u256 } }", - "{ { let a:u256 } function f() { let b:u256 function g() { let c:u256} let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(empty_block) -{ - CHECK( - "{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }", - "{ { let a:u256 { } } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/FunctionHoister.cpp b/test/libjulia/FunctionHoister.cpp deleted file mode 100644 index 3d6fff858..000000000 --- a/test/libjulia/FunctionHoister.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for the iulia function hoister. - */ - -#include - -#include - -#include - -#include - -using namespace std; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - Block b = disambiguate(_original);\ - (FunctionHoister{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(IuliaFunctionHoister) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(single_fun) -{ - CHECK( - "{ let a:u256 function f() {} }", - "{ let a:u256 function f() {} }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun_mixed) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 } let c:u256 function g() { let d:u256 } let e:u256 }", - "{ let a:u256 let c:u256 let e:u256 function f() { let b:u256 } function g() { let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(nested_fun) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 function g() { let c:u256} let d:u256 } }", - "{ let a:u256 function g() { let c:u256 } function f() { let b:u256 let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(empty_block) -{ - CHECK( - "{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }", - "{ let a:u256 function f() -> x:bool { let b:u256 := 4:u256 for {} f() {} {} } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/Inliner.cpp b/test/libjulia/Inliner.cpp deleted file mode 100644 index 464dcd937..000000000 --- a/test/libjulia/Inliner.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for the iulia function inliner. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - -namespace -{ -string inlinableFunctions(string const& _source) -{ - auto ast = disambiguate(_source); - - InlinableExpressionFunctionFinder funFinder; - funFinder(ast); - - return boost::algorithm::join( - funFinder.inlinableFunctions() | boost::adaptors::map_keys, - "," - ); -} - -string inlineFunctions(string const& _source, bool _julia = true) -{ - auto ast = disambiguate(_source, _julia); - ExpressionInliner(ast).run(); - return assembly::AsmPrinter(_julia)(ast); -} -string fullInline(string const& _source, bool _julia = true) -{ - Block ast = disambiguate(_source, _julia); - (FunctionHoister{})(ast); - (FunctionGrouper{})(ast);\ - FullInliner(ast).run(); - return assembly::AsmPrinter(_julia)(ast); -} -} - - -BOOST_AUTO_TEST_SUITE(IuliaInlinableFunctionFilter) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - BOOST_CHECK_EQUAL(inlinableFunctions("{ }"), ""); -} - -BOOST_AUTO_TEST_CASE(simple) -{ - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 } }"), "f"); - BOOST_CHECK_EQUAL(inlinableFunctions("{" - "function g(a:u256) -> b:u256 { b := a }" - "function f() -> x:u256 { x := g(2:u256) }" - "}"), "f,g"); -} - -BOOST_AUTO_TEST_CASE(simple_inside_structures) -{ - BOOST_CHECK_EQUAL(inlinableFunctions("{" - "switch 2:u256 " - "case 2:u256 {" - "function g(a:u256) -> b:u256 { b := a }" - "function f() -> x:u256 { x := g(2:u256) }" - "}" - "}"), "f,g"); - BOOST_CHECK_EQUAL(inlinableFunctions("{" - "for {" - "function g(a:u256) -> b:u256 { b := a }" - "} 1:u256 {" - "function f() -> x:u256 { x := g(2:u256) }" - "}" - "{" - "function h() -> y:u256 { y := 2:u256 }" - "}" - "}"), "f,g,h"); -} - -BOOST_AUTO_TEST_CASE(negative) -{ - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 {} } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := f() } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := x } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256, y:u256 { x := 2:u256 } }"), ""); -} - - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(IuliaFunctionInliner) - -BOOST_AUTO_TEST_CASE(simple) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f() -> x:u256 { x := 2:u256 } let y:u256 := f() }"), - format("{ function f() -> x:u256 { x := 2:u256 } let y:u256 := 2:u256 }") - ); -} - -BOOST_AUTO_TEST_CASE(with_args) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f(a:u256) -> x:u256 { x := a } let y:u256 := f(7:u256) }"), - format("{ function f(a:u256) -> x:u256 { x := a } let y:u256 := 7:u256 }") - ); -} - -BOOST_AUTO_TEST_CASE(no_inline_with_mload) -{ - // Does not inline because mload could be moved out of sequence - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f(a) -> x { x := a } let y := f(mload(2)) }", false), - format("{ function f(a) -> x { x := a } let y := f(mload(2)) }", false) - ); -} - -BOOST_AUTO_TEST_CASE(no_move_with_side_effects) -{ - // The calls to g and h cannot be moved because g and h are not movable. Therefore, the call - // to f is not inlined. - BOOST_CHECK_EQUAL( - inlineFunctions("{" - "function f(a, b) -> x { x := add(b, a) }" - "function g() -> y { y := mload(0) mstore(0, 4) }" - "function h() -> z { mstore(0, 4) z := mload(0) }" - "let r := f(g(), h())" - "}", false), - format("{" - "function f(a, b) -> x { x := add(b, a) }" - "function g() -> y { y := mload(0) mstore(0, 4) }" - "function h() -> z { mstore(0, 4) z := mload(0) }" - "let r := f(g(), h())" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(complex_with_evm) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f(a) -> x { x := add(a, a) } let y := f(calldatasize()) }", false), - format("{ function f(a) -> x { x := add(a, a) } let y := add(calldatasize(), calldatasize()) }", false) - ); -} - -BOOST_AUTO_TEST_CASE(double_calls) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{" - "function f(a) -> x { x := add(a, a) }" - "function g(b, c) -> y { y := mul(mload(c), f(b)) }" - "let y := g(calldatasize(), 7)" - "}", false), - format("{" - "function f(a) -> x { x := add(a, a) }" - "function g(b, c) -> y { y := mul(mload(c), add(b, b)) }" - "let y_1 := mul(mload(7), add(calldatasize(), calldatasize()))" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(double_recursive_calls) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{" - "function f(a, r) -> x { x := g(a, g(r, r)) }" - "function g(b, s) -> y { y := f(b, f(s, s)) }" - "let y := g(calldatasize(), 7)" - "}", false), - format("{" - "function f(a, r) -> x { x := g(a, f(r, f(r, r))) }" - "function g(b, s) -> y { y := f(b, g(s, f(s, f(s, s))))}" - "let y_1 := f(calldatasize(), g(7, f(7, f(7, 7))))" - "}", false) - ); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(IuliaFullInliner) - -BOOST_AUTO_TEST_CASE(simple) -{ - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a) -> x { let r := mul(a, a) x := add(r, r) }" - "let y := add(f(sload(mload(2))), mload(7))" - "}", false), - format("{" - "{" - "let _1 := mload(7)" - "let f_a := sload(mload(2))" - "let f_x" - "{" - "let f_r := mul(f_a, f_a)" - "f_x := add(f_r, f_r)" - "}" - "let y := add(f_x, _1)" - "}" - "function f(a) -> x" - "{" - "let r := mul(a, a)" - "x := add(r, r)" - "}" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun) -{ - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a) -> x { x := add(a, a) }" - "function g(b, c) -> y { y := mul(mload(c), f(b)) }" - "let y := g(f(3), 7)" - "}", false), - format("{" - "{" - "let g_c := 7 " - "let f_a_1 := 3 " - "let f_x_1 " - "{ f_x_1 := add(f_a_1, f_a_1) } " - "let g_y " - "{" - "let g_f_a := f_x_1 " - "let g_f_x " - "{" - "g_f_x := add(g_f_a, g_f_a)" - "}" - "g_y := mul(mload(g_c), g_f_x)" - "}" - "let y_1 := g_y" - "}" - "function f(a) -> x" - "{" - "x := add(a, a)" - "}" - "function g(b, c) -> y" - "{" - "let f_a := b " - "let f_x " - "{" - "f_x := add(f_a, f_a)" - "}" - "y := mul(mload(c), f_x)" - "}" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(move_up_rightwards_arguments) -{ - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a, b, c) -> x { x := add(a, b) x := mul(x, c) }" - "let y := add(mload(1), add(f(mload(2), mload(3), mload(4)), mload(5)))" - "}", false), - format("{" - "{" - "let _1 := mload(5)" - "let f_c := mload(4)" - "let f_b := mload(3)" - "let f_a := mload(2)" - "let f_x" - "{" - "f_x := add(f_a, f_b)" - "f_x := mul(f_x, f_c)" - "}" - "let y := add(mload(1), add(f_x, _1))" - "}" - "function f(a, b, c) -> x" - "{" - "x := add(a, b)" - "x := mul(x, c)" - "}" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(pop_result) -{ - // This tests that `pop(r)` is removed. - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a) -> x { let r := mul(a, a) x := add(r, r) }" - "pop(add(f(7), 2))" - "}", false), - format("{" - "{" - "let _1 := 2 " - "let f_a := 7 " - "let f_x " - "{" - "let f_r := mul(f_a, f_a) " - "f_x := add(f_r, f_r)" - "}" - "{" - "}" - "}" - "function f(a) -> x" - "{" - "let r := mul(a, a) " - "x := add(r, r)" - "}" - "}", false) - ); -} - - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/MainFunction.cpp b/test/libjulia/MainFunction.cpp deleted file mode 100644 index c26b002dc..000000000 --- a/test/libjulia/MainFunction.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2018 - * Unit tests for the Julia MainFunction transformation. - */ - -#include - -#include -#include - -#include - -#include - -using namespace std; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - Block b = disambiguate(_original);\ - (FunctionGrouper{})(b);\ - (MainFunction{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(JuliaMainFunction) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ function main() { } }"); -} - -BOOST_AUTO_TEST_CASE(single_fun) -{ - CHECK( - "{ let a:u256 function f() {} }", - "{ function main() { let a:u256 } function f() {} }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun_mixed) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 } let c:u256 function g() { let d:u256 } let e:u256 }", - "{ function main() { let a:u256 let c:u256 let e:u256 } function f() { let b:u256 } function g() { let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(nested_fun) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 function g() { let c:u256} let d:u256 } }", - "{ function main() { let a:u256 } function f() { let b:u256 function g() { let c:u256} let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(empty_block) -{ - CHECK( - "{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }", - "{ function main() { let a:u256 { } } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/Rematerialiser.cpp b/test/libjulia/Rematerialiser.cpp deleted file mode 100644 index 8f928f8ef..000000000 --- a/test/libjulia/Rematerialiser.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for the rematerialiser optimizer stage. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = disambiguate(_original, false);\ - (Rematerialiser{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(IuliaRematerialiser) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(trivial) -{ - CHECK( - "{ let a := 1 let b := a mstore(0, b) }", - "{ let a := 1 let b := 1 mstore(0, 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(expression) -{ - CHECK( - "{ let a := add(mul(calldatasize(), 2), number()) let b := add(a, a) }", - "{ let a := add(mul(calldatasize(), 2), number()) let b := add(" - "add(mul(calldatasize(), 2), number())," - "add(mul(calldatasize(), 2), number())" - ") }" - ); -} - -BOOST_AUTO_TEST_CASE(reassign) -{ - CHECK( - "{ let a := extcodesize(0) let b := a let c := b a := 2 let d := add(b, c) pop(a) pop(b) pop(c) pop(d) }", - "{ let a := extcodesize(0) let b := a let c := a a := 2 let d := add(b, c) pop(2) pop(b) pop(c) pop(add(b, c)) }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_instr) -{ - CHECK( - "{ let a := 1 let b := mload(a) let c := a mstore(add(a, b), c) }", - "{ let a := 1 let b := mload(1) let c := 1 mstore(add(1, b), 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_fun) -{ - CHECK( - "{ function f(x) -> y {} let a := 1 let b := f(a) let c := a mstore(add(a, b), c) }", - "{ function f(x) -> y {} let a := 1 let b := f(1) let c := 1 mstore(add(1, b), 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_if) -{ - CHECK( - "{ let a := 1 let b := 2 if b { pop(b) b := a } let c := b }", - "{ let a := 1 let b := 2 if 2 { pop(2) b := 1 } let c := b }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_switch) -{ - CHECK( - "{ let a := 1 let b := 2 switch number() case 1 { b := a } default { let x := a let y := b b := a } pop(add(a, b)) }", - "{ let a := 1 let b := 2 switch number() case 1 { b := 1 } default { let x := 1 let y := b b := 1 } pop(add(1, b)) }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_for) -{ - CHECK( - "{ let a := 1 for { pop(a) } a { pop(a) } { pop(a) } }", - "{ let a := 1 for { pop(1) } 1 { pop(1) } { pop(1) } }" - ); - CHECK( - "{ let a := 1 for { pop(a) } a { pop(a) } { a := 7 let c := a } let x := a }", - "{ let a := 1 for { pop(1) } a { pop(7) } { a := 7 let c := 7 } let x := a }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_for_declared_in_init) -{ - CHECK( - "{ let b := 0 for { let a := 1 pop(a) } a { pop(a) } { b := 1 pop(a) } }", - "{ let b := 0 for { let a := 1 pop(1) } 1 { pop(1) } { b := 1 pop(1) } }" - ); - CHECK( - "{ let b := 0 for { let a := 1 pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { b := 1 pop(a) } }", - "{ let b := 0 for { let a := 1 pop(1) } lt(a, 0) { pop(a) a := add(a, 3) } { b := 1 pop(a) } }" - ); -} - -BOOST_AUTO_TEST_CASE(reassignment) -{ - CHECK( - "{ let a := 1 pop(a) if a { a := 2 } let b := mload(a) pop(b) }", - "{ let a := 1 pop(1) if 1 { a := 2 } let b := mload(a) pop(b) }" - ); -} - -BOOST_AUTO_TEST_CASE(update_assignment_remat) -{ - // We cannot substitute `a` in `let b := a` - CHECK( - "{ let a := extcodesize(0) a := mul(a, 2) let b := a }", - "{ let a := extcodesize(0) a := mul(a, 2) let b := a }" - ); -} - -BOOST_AUTO_TEST_CASE(do_not_move_out_of_scope) -{ - // Cannot replace by `let b := x` by `let b := a` since a is out of scope. - CHECK( - "{ let x { let a := sload(0) x := a } let b := x }", - "{ let x { let a := sload(0) x := a } let b := x }" - ); -} - -BOOST_AUTO_TEST_CASE(do_not_remat_large_amounts_of_code) -{ - CHECK( - "{ let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) let b := x }", - "{ let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) let b := x }" - ); - CHECK( - "{ let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) let b := x }", - "{ let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) let b := add(mul(calldataload(2), calldataload(4)), calldatasize()) }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/Simplifier.cpp b/test/libjulia/Simplifier.cpp deleted file mode 100644 index 4d4e8d53a..000000000 --- a/test/libjulia/Simplifier.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for the expression simplifier optimizer stage. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = *(parse(_original, false).first);\ - (ExpressionSimplifier{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(IuliaSimplifier) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(constants) -{ - CHECK( - "{ let a := add(1, mul(3, 4)) }", - "{ let a := 13 }" - ); -} - -BOOST_AUTO_TEST_CASE(invariant) -{ - CHECK( - "{ let a := mload(sub(7, 7)) let b := sub(a, 0) }", - "{ let a := mload(0) let b := a }" - ); -} - -BOOST_AUTO_TEST_CASE(reversed) -{ - CHECK( - "{ let a := add(0, mload(0)) }", - "{ let a := mload(0) }" - ); -} - -BOOST_AUTO_TEST_CASE(constant_propagation) -{ - CHECK( - "{ let a := add(7, sub(mload(0), 7)) }", - "{ let a := mload(0) }" - ); -} - -BOOST_AUTO_TEST_CASE(identity_rules_simple) -{ - CHECK( - "{ let a := mload(0) let b := sub(a, a) }", - "{ let a := mload(0) let b := 0 }" - ); -} - -BOOST_AUTO_TEST_CASE(identity_rules_complex) -{ - CHECK( - "{ let a := sub(calldataload(0), calldataload(0)) }", - "{ let a := 0 }" - ); -} - -BOOST_AUTO_TEST_CASE(identity_rules_negative) -{ - CHECK( - "{ let a := sub(calldataload(1), calldataload(0)) }", - "{ let a := sub(calldataload(1), calldataload(0)) }" - ); -} - -BOOST_AUTO_TEST_CASE(including_function_calls) -{ - CHECK( - "{ function f() -> a {} let b := add(7, sub(f(), 7)) }", - "{ function f() -> a {} let b := f() }" - ); -} - -BOOST_AUTO_TEST_CASE(inside_for) -{ - CHECK( - "{ for { let a := 10 } iszero(eq(a, 0)) { a := add(a, 1) } {} }", - "{ for { let a := 10 } iszero(iszero(a)) { a := add(a, 1) } {} }" - ); -} - -BOOST_AUTO_TEST_CASE(mod_and) -{ - CHECK( - "{ mstore(0, mod(calldataload(0), exp(2, 8))) }", - "{ mstore(0, and(calldataload(0), 255)) }" - ); - CHECK( - "{ mstore(0, mod(calldataload(0), exp(2, 255))) }", - "{ mstore(0, and(calldataload(0), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/UnusedPruner.cpp b/test/libjulia/UnusedPruner.cpp deleted file mode 100644 index b86a54b3f..000000000 --- a/test/libjulia/UnusedPruner.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for the pruning of unused variables and functions. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = disambiguate(_original, false);\ - UnusedPruner::runUntilStabilised(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(IuliaUnusedPruner) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(trivial) -{ - CHECK( - "{ let a := 1 let b := 1 mstore(0, 1) }", - "{ mstore(0, 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_declarations) -{ - CHECK( - "{ let x, y }", - "{ }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_assignments) -{ - CHECK( - "{ let x, y x := 1 y := 2 }", - "{ let x, y x := 1 y := 2 }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_partial_assignments) -{ - CHECK( - "{ let x, y x := 1 }", - "{ let x, y x := 1 }" - ); -} - -BOOST_AUTO_TEST_CASE(functions) -{ - CHECK( - "{ function f() { let a := 1 } function g() { f() } }", - "{ }" - ); -} - -BOOST_AUTO_TEST_CASE(intermediate_assignment) -{ - CHECK( - "{ let a := 1 a := 4 let b := 1 }", - "{ let a := 1 a := 4 }" - ); -} - -BOOST_AUTO_TEST_CASE(intermediate_multi_assignment){ - CHECK( - "{ let a, b function f() -> x { } a := f() b := 1 }", - "{ let a, b function f() -> x { } a := f() b := 1 }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_declare) -{ - CHECK( - "{ function f() -> x, y { } let a, b := f() }", - "{ function f() -> x, y { } let a, b := f() }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_assign) -{ - CHECK( - "{ let a let b function f() -> x, y { } a, b := f() }", - "{ let a let b function f() -> x, y { } a, b := f() }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp index ebdea1858..27db45a5c 100644 --- a/test/liblll/Compiler.cpp +++ b/test/liblll/Compiler.cpp @@ -46,7 +46,7 @@ namespace bool successCompile(string const& _sourceCode) { vector errors; - bytes bytecode = eth::compileLLL(_sourceCode, dev::test::Options::get().evmVersion(), false, &errors); + bytes bytecode = lll::compileLLL(_sourceCode, dev::test::Options::get().evmVersion(), false, &errors); if (!errors.empty()) return false; if (bytecode.empty()) @@ -130,235 +130,238 @@ BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) BOOST_AUTO_TEST_CASE(disallowed_asm_instructions) { for (unsigned i = 1; i <= 32; i++) - BOOST_CHECK(!successCompile("(asm PUSH" + boost::lexical_cast(i) + ")")); + BOOST_CHECK(!successCompile("(asm PUSH" + to_string(i) + ")")); } BOOST_AUTO_TEST_CASE(disallowed_functional_asm_instructions) { for (unsigned i = 1; i <= 32; i++) - BOOST_CHECK(!successCompile("(PUSH" + boost::lexical_cast(i) + ")")); + BOOST_CHECK(!successCompile("(PUSH" + to_string(i) + ")")); for (unsigned i = 1; i <= 16; i++) - BOOST_CHECK(!successCompile("(DUP" + boost::lexical_cast(i) + ")")); + BOOST_CHECK(!successCompile("(DUP" + to_string(i) + ")")); for (unsigned i = 1; i <= 16; i++) - BOOST_CHECK(!successCompile("(SWAP" + boost::lexical_cast(i) + ")")); + BOOST_CHECK(!successCompile("(SWAP" + to_string(i) + ")")); BOOST_CHECK(!successCompile("(JUMPDEST)")); } BOOST_AUTO_TEST_CASE(valid_opcodes_functional) { vector opcodes_bytecode { - "00", - "6000600001", - "6000600002", - "6000600003", - "6000600004", - "6000600005", - "6000600006", - "6000600007", - "60006000600008", - "60006000600009", - "600060000a", - "600060000b", - "6000600010", - "6000600011", - "6000600012", - "6000600013", - "6000600014", - "600015", - "6000600016", - "6000600017", - "6000600018", - "600019", - "600060001a", - "6000600020", - "30", - "600031", - "32", - "33", - "34", - "600035", - "36", - "60006000600037", - "38", - "60006000600039", - "3a", - "60003b", - "60006000600060003c", - "3d", - "6000600060003e", - "600040", - "41", - "42", - "43", - "44", - "45", - "600050", - "600051", - "6000600052", - "6000600053", - "600054", - "6000600055", - "600056", - "6000600057", - "58", - "59", - "5a", - "60ff", - "61ffff", - "62ffffff", - "63ffffffff", - "64ffffffffff", - "65ffffffffffff", - "66ffffffffffffff", - "67ffffffffffffffff", - "68ffffffffffffffffff", - "69ffffffffffffffffffff", - "6affffffffffffffffffffff", - "6bffffffffffffffffffffffff", - "6cffffffffffffffffffffffffff", - "6dffffffffffffffffffffffffffff", - "6effffffffffffffffffffffffffffff", - "6fffffffffffffffffffffffffffffffff", - "70ffffffffffffffffffffffffffffffffff", - "71ffffffffffffffffffffffffffffffffffff", - "72ffffffffffffffffffffffffffffffffffffff", - "73ffffffffffffffffffffffffffffffffffffffff", - "74ffffffffffffffffffffffffffffffffffffffffff", - "75ffffffffffffffffffffffffffffffffffffffffffff", - "76ffffffffffffffffffffffffffffffffffffffffffffff", - "77ffffffffffffffffffffffffffffffffffffffffffffffff", - "78ffffffffffffffffffffffffffffffffffffffffffffffffff", - "79ffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7affffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "60006000a0", - "600060006000a1", - "6000600060006000a2", - "60006000600060006000a3", - "600060006000600060006000a4", - "600060006000f0", - "6000600060006000600060006000f1", - "6000600060006000600060006000f2", - "60006000f3", - "600060006000600060006000f4", - "600060006000600060006000fa", - "60006000fd", - "fe", - "6000ff" + "0000", + "600060000100", + "600060000200", + "600060000300", + "600060000400", + "600060000500", + "600060000600", + "600060000700", + "6000600060000800", + "6000600060000900", + "600060000a00", + "600060000b00", + "600060001000", + "600060001100", + "600060001200", + "600060001300", + "600060001400", + "60001500", + "600060001600", + "600060001700", + "600060001800", + "60001900", + "600060001a00", + "600060002000", + "3000", + "60003100", + "3200", + "3300", + "3400", + "60003500", + "3600", + "6000600060003700", + "3800", + "6000600060003900", + "3a00", + "60003b00", + "60006000600060003c00", + "3d00", + "6000600060003e00", + "60003f00", + "60004000", + "4100", + "4200", + "4300", + "4400", + "4500", + "60005000", + "60005100", + "600060005200", + "600060005300", + "60005400", + "600060005500", + "60005600", + "600060005700", + "5800", + "5900", + "5a00", + "60ff00", + "61ffff00", + "62ffffff00", + "63ffffffff00", + "64ffffffffff00", + "65ffffffffffff00", + "66ffffffffffffff00", + "67ffffffffffffffff00", + "68ffffffffffffffffff00", + "69ffffffffffffffffffff00", + "6affffffffffffffffffffff00", + "6bffffffffffffffffffffffff00", + "6cffffffffffffffffffffffffff00", + "6dffffffffffffffffffffffffffff00", + "6effffffffffffffffffffffffffffff00", + "6fffffffffffffffffffffffffffffffff00", + "70ffffffffffffffffffffffffffffffffff00", + "71ffffffffffffffffffffffffffffffffffff00", + "72ffffffffffffffffffffffffffffffffffffff00", + "73ffffffffffffffffffffffffffffffffffffffff00", + "74ffffffffffffffffffffffffffffffffffffffffff00", + "75ffffffffffffffffffffffffffffffffffffffffffff00", + "76ffffffffffffffffffffffffffffffffffffffffffffff00", + "77ffffffffffffffffffffffffffffffffffffffffffffffff00", + "78ffffffffffffffffffffffffffffffffffffffffffffffffff00", + "79ffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7affffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "60006000a000", + "600060006000a100", + "6000600060006000a200", + "60006000600060006000a300", + "600060006000600060006000a400", + "600060006000f000", + "6000600060006000600060006000f100", + "6000600060006000600060006000f200", + "60006000f300", + "600060006000600060006000f400", + "600060006000600060006000fa00", + "60006000fd00", + "fe00", + "6000ff00" }; vector opcodes_lll { - "{ (STOP) }", - "{ (ADD 0 0) }", - "{ (MUL 0 0) }", - "{ (SUB 0 0) }", - "{ (DIV 0 0) }", - "{ (SDIV 0 0) }", - "{ (MOD 0 0) }", - "{ (SMOD 0 0) }", - "{ (ADDMOD 0 0 0) }", - "{ (MULMOD 0 0 0) }", - "{ (EXP 0 0) }", - "{ (SIGNEXTEND 0 0) }", - "{ (LT 0 0) }", - "{ (GT 0 0) }", - "{ (SLT 0 0) }", - "{ (SGT 0 0) }", - "{ (EQ 0 0) }", - "{ (ISZERO 0) }", - "{ (AND 0 0) }", - "{ (OR 0 0) }", - "{ (XOR 0 0) }", - "{ (NOT 0) }", - "{ (BYTE 0 0) }", - "{ (KECCAK256 0 0) }", - "{ (ADDRESS) }", - "{ (BALANCE 0) }", - "{ (ORIGIN) }", - "{ (CALLER) }", - "{ (CALLVALUE) }", - "{ (CALLDATALOAD 0) }", - "{ (CALLDATASIZE) }", - "{ (CALLDATACOPY 0 0 0) }", - "{ (CODESIZE) }", - "{ (CODECOPY 0 0 0) }", - "{ (GASPRICE) }", - "{ (EXTCODESIZE 0) }", - "{ (EXTCODECOPY 0 0 0 0) }", - "{ (RETURNDATASIZE) }", - "{ (RETURNDATACOPY 0 0 0) }", - "{ (BLOCKHASH 0) }", - "{ (COINBASE) }", - "{ (TIMESTAMP) }", - "{ (NUMBER) }", - "{ (DIFFICULTY) }", - "{ (GASLIMIT) }", - "{ (POP 0) }", - "{ (MLOAD 0) }", - "{ (MSTORE 0 0) }", - "{ (MSTORE8 0 0) }", - "{ (SLOAD 0) }", - "{ (SSTORE 0 0) }", - "{ (JUMP 0) }", - "{ (JUMPI 0 0) }", - "{ (PC) }", - "{ (MSIZE) }", - "{ (GAS) }", - "{ 0xff }", - "{ 0xffff }", - "{ 0xffffff }", - "{ 0xffffffff }", - "{ 0xffffffffff }", - "{ 0xffffffffffff }", - "{ 0xffffffffffffff }", - "{ 0xffffffffffffffff }", - "{ 0xffffffffffffffffff }", - "{ 0xffffffffffffffffffff }", - "{ 0xffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", - "{ (LOG0 0 0) }", - "{ (LOG1 0 0 0) }", - "{ (LOG2 0 0 0 0) }", - "{ (LOG3 0 0 0 0 0) }", - "{ (LOG4 0 0 0 0 0 0) }", - "{ (CREATE 0 0 0) }", - "{ (CALL 0 0 0 0 0 0 0) }", - "{ (CALLCODE 0 0 0 0 0 0 0) }", - "{ (RETURN 0 0) }", - "{ (DELEGATECALL 0 0 0 0 0 0) }", - "{ (STATICCALL 0 0 0 0 0 0) }", - "{ (REVERT 0 0) }", - "{ (INVALID) }", - "{ (SELFDESTRUCT 0) }" + "(STOP)", + "(ADD 0 0)", + "(MUL 0 0)", + "(SUB 0 0)", + "(DIV 0 0)", + "(SDIV 0 0)", + "(MOD 0 0)", + "(SMOD 0 0)", + "(ADDMOD 0 0 0)", + "(MULMOD 0 0 0)", + "(EXP 0 0)", + "(SIGNEXTEND 0 0)", + "(LT 0 0)", + "(GT 0 0)", + "(SLT 0 0)", + "(SGT 0 0)", + "(EQ 0 0)", + "(ISZERO 0)", + "(AND 0 0)", + "(OR 0 0)", + "(XOR 0 0)", + "(NOT 0)", + "(BYTE 0 0)", + "(KECCAK256 0 0)", + "(ADDRESS)", + "(BALANCE 0)", + "(ORIGIN)", + "(CALLER)", + "(CALLVALUE)", + "(CALLDATALOAD 0)", + "(CALLDATASIZE)", + "(CALLDATACOPY 0 0 0)", + "(CODESIZE)", + "(CODECOPY 0 0 0)", + "(GASPRICE)", + "(EXTCODESIZE 0)", + "(EXTCODECOPY 0 0 0 0)", + "(RETURNDATASIZE)", + "(RETURNDATACOPY 0 0 0)", + "(EXTCODEHASH 0)", + "(BLOCKHASH 0)", + "(COINBASE)", + "(TIMESTAMP)", + "(NUMBER)", + "(DIFFICULTY)", + "(GASLIMIT)", + "(POP 0)", + "(MLOAD 0)", + "(MSTORE 0 0)", + "(MSTORE8 0 0)", + "(SLOAD 0)", + "(SSTORE 0 0)", + "(JUMP 0)", + "(JUMPI 0 0)", + "(PC)", + "(MSIZE)", + "(GAS)", + "0xff", + "0xffff", + "0xffffff", + "0xffffffff", + "0xffffffffff", + "0xffffffffffff", + "0xffffffffffffff", + "0xffffffffffffffff", + "0xffffffffffffffffff", + "0xffffffffffffffffffff", + "0xffffffffffffffffffffff", + "0xffffffffffffffffffffffff", + "0xffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "(LOG0 0 0)", + "(LOG1 0 0 0)", + "(LOG2 0 0 0 0)", + "(LOG3 0 0 0 0 0)", + "(LOG4 0 0 0 0 0 0)", + "(CREATE 0 0 0)", + "(CALL 0 0 0 0 0 0 0)", + "(CALLCODE 0 0 0 0 0 0 0)", + "(RETURN 0 0)", + "(DELEGATECALL 0 0 0 0 0 0)", + "(STATICCALL 0 0 0 0 0 0)", + "(REVERT 0 0)", + "(INVALID)", + "(SELFDESTRUCT 0)" }; - for (size_t i = 0; i < opcodes_bytecode.size(); i++) { + for (size_t i = 0; i < opcodes_bytecode.size(); i++) + { vector errors; - bytes code = eth::compileLLL(opcodes_lll[i], dev::test::Options::get().evmVersion(), false, &errors); + bytes code = lll::compileLLL(opcodes_lll[i], dev::test::Options::get().evmVersion(), false, &errors); BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); @@ -369,284 +372,287 @@ BOOST_AUTO_TEST_CASE(valid_opcodes_functional) BOOST_AUTO_TEST_CASE(valid_opcodes_asm) { vector opcodes_bytecode { - "00", - "01", - "02", - "03", - "04", - "05", - "06", - "07", - "08", - "09", - "0a", - "0b", - "10", - "11", - "12", - "13", - "14", - "15", - "16", - "17", - "18", - "19", - "1a", - "20", - "30", - "31", - "32", - "33", - "34", - "35", - "36", - "37", - "38", - "39", - "3a", - "3b", - "3c", - "3d", - "3e", - "40", - "41", - "42", - "43", - "44", - "45", - "50", - "51", - "52", - "53", - "54", - "55", - "56", - "57", - "58", - "59", - "5a", - "5b", - "60ff", - "61ffff", - "62ffffff", - "63ffffffff", - "64ffffffffff", - "65ffffffffffff", - "66ffffffffffffff", - "67ffffffffffffffff", - "68ffffffffffffffffff", - "69ffffffffffffffffffff", - "6affffffffffffffffffffff", - "6bffffffffffffffffffffffff", - "6cffffffffffffffffffffffffff", - "6dffffffffffffffffffffffffffff", - "6effffffffffffffffffffffffffffff", - "6fffffffffffffffffffffffffffffffff", - "70ffffffffffffffffffffffffffffffffff", - "71ffffffffffffffffffffffffffffffffffff", - "72ffffffffffffffffffffffffffffffffffffff", - "73ffffffffffffffffffffffffffffffffffffffff", - "74ffffffffffffffffffffffffffffffffffffffffff", - "75ffffffffffffffffffffffffffffffffffffffffffff", - "76ffffffffffffffffffffffffffffffffffffffffffffff", - "77ffffffffffffffffffffffffffffffffffffffffffffffff", - "78ffffffffffffffffffffffffffffffffffffffffffffffffff", - "79ffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7affffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "80", - "81", - "82", - "83", - "84", - "85", - "86", - "87", - "88", - "89", - "8a", - "8b", - "8c", - "8d", - "8e", - "8f", - "90", - "91", - "92", - "93", - "94", - "95", - "96", - "97", - "98", - "99", - "9a", - "9b", - "9c", - "9d", - "9e", - "9f", - "a0", - "a1", - "a2", - "a3", - "a4", - "f0", - "f1", - "f2", - "f3", - "f4", - "fa", - "fd", - "fe", - "ff" + "0000", + "600060000100", + "600060000200", + "600060000300", + "600060000400", + "600060000500", + "600060000600", + "600060000700", + "6000600060000800", + "6000600060000900", + "600060000a00", + "600060000b00", + "600060001000", + "600060001100", + "600060001200", + "600060001300", + "600060001400", + "60001500", + "600060001600", + "600060001700", + "600060001800", + "60001900", + "600060001a00", + "600060002000", + "3000", + "60003100", + "3200", + "3300", + "3400", + "60003500", + "3600", + "6000600060003700", + "3800", + "6000600060003900", + "3a00", + "60003b00", + "60006000600060003c00", + "3d00", + "6000600060003e00", + "60003f00", + "4000", + "4100", + "4200", + "4300", + "4400", + "4500", + "60005000", + "60005100", + "600060005200", + "600060005300", + "60005400", + "600060005500", + "60005600", + "600060005700", + "5800", + "5900", + "5a00", + "5b00", + "60ff00", + "61ffff00", + "62ffffff00", + "63ffffffff00", + "64ffffffffff00", + "65ffffffffffff00", + "66ffffffffffffff00", + "67ffffffffffffffff00", + "68ffffffffffffffffff00", + "69ffffffffffffffffffff00", + "6affffffffffffffffffffff00", + "6bffffffffffffffffffffffff00", + "6cffffffffffffffffffffffffff00", + "6dffffffffffffffffffffffffffff00", + "6effffffffffffffffffffffffffffff00", + "6fffffffffffffffffffffffffffffffff00", + "70ffffffffffffffffffffffffffffffffff00", + "71ffffffffffffffffffffffffffffffffffff00", + "72ffffffffffffffffffffffffffffffffffffff00", + "73ffffffffffffffffffffffffffffffffffffffff00", + "74ffffffffffffffffffffffffffffffffffffffffff00", + "75ffffffffffffffffffffffffffffffffffffffffffff00", + "76ffffffffffffffffffffffffffffffffffffffffffffff00", + "77ffffffffffffffffffffffffffffffffffffffffffffffff00", + "78ffffffffffffffffffffffffffffffffffffffffffffffffff00", + "79ffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7affffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "60006000600060006000600060006000600060006000600060006000600060008000", + "60006000600060006000600060006000600060006000600060006000600060008100", + "60006000600060006000600060006000600060006000600060006000600060008200", + "60006000600060006000600060006000600060006000600060006000600060008300", + "60006000600060006000600060006000600060006000600060006000600060008400", + "60006000600060006000600060006000600060006000600060006000600060008500", + "60006000600060006000600060006000600060006000600060006000600060008600", + "60006000600060006000600060006000600060006000600060006000600060008700", + "60006000600060006000600060006000600060006000600060006000600060008800", + "60006000600060006000600060006000600060006000600060006000600060008900", + "60006000600060006000600060006000600060006000600060006000600060008a00", + "60006000600060006000600060006000600060006000600060006000600060008b00", + "60006000600060006000600060006000600060006000600060006000600060008c00", + "60006000600060006000600060006000600060006000600060006000600060008d00", + "60006000600060006000600060006000600060006000600060006000600060008e00", + "60006000600060006000600060006000600060006000600060006000600060008f00", + "60006000600060006000600060006000600060006000600060006000600060009000", + "60006000600060006000600060006000600060006000600060006000600060009100", + "60006000600060006000600060006000600060006000600060006000600060009200", + "60006000600060006000600060006000600060006000600060006000600060009300", + "60006000600060006000600060006000600060006000600060006000600060009400", + "60006000600060006000600060006000600060006000600060006000600060009500", + "60006000600060006000600060006000600060006000600060006000600060009600", + "60006000600060006000600060006000600060006000600060006000600060009700", + "60006000600060006000600060006000600060006000600060006000600060009800", + "60006000600060006000600060006000600060006000600060006000600060009900", + "60006000600060006000600060006000600060006000600060006000600060009a00", + "60006000600060006000600060006000600060006000600060006000600060009b00", + "60006000600060006000600060006000600060006000600060006000600060009c00", + "60006000600060006000600060006000600060006000600060006000600060009d00", + "60006000600060006000600060006000600060006000600060006000600060009e00", + "60006000600060006000600060006000600060006000600060006000600060009f00", + "60006000a000", + "600060006000a100", + "6000600060006000a200", + "60006000600060006000a300", + "600060006000600060006000a400", + "600060006000f000", + "600060006000600060006000f100", + "600060006000600060006000f200", + "60006000f300", + "60006000600060006000f400", + "60006000600060006000fa00", + "60006000fd00", + "fe00", + "6000ff00" }; vector opcodes_lll { - "{ (asm STOP) }", - "{ (asm ADD) }", - "{ (asm MUL) }", - "{ (asm SUB) }", - "{ (asm DIV) }", - "{ (asm SDIV ) }", - "{ (asm MOD) }", - "{ (asm SMOD) }", - "{ (asm ADDMOD) }", - "{ (asm MULMOD) }", - "{ (asm EXP) }", - "{ (asm SIGNEXTEND) }", - "{ (asm LT) }", - "{ (asm GT) }", - "{ (asm SLT) }", - "{ (asm SGT) }", - "{ (asm EQ) }", - "{ (asm ISZERO) }", - "{ (asm AND) }", - "{ (asm OR) }", - "{ (asm XOR) }", - "{ (asm NOT) }", - "{ (asm BYTE) }", - "{ (asm KECCAK256) }", - "{ (asm ADDRESS) }", - "{ (asm BALANCE) }", - "{ (asm ORIGIN) }", - "{ (asm CALLER) }", - "{ (asm CALLVALUE) }", - "{ (asm CALLDATALOAD) }", - "{ (asm CALLDATASIZE) }", - "{ (asm CALLDATACOPY) }", - "{ (asm CODESIZE) }", - "{ (asm CODECOPY) }", - "{ (asm GASPRICE) }", - "{ (asm EXTCODESIZE)}", - "{ (asm EXTCODECOPY) }", - "{ (asm RETURNDATASIZE) }", - "{ (asm RETURNDATACOPY) }", - "{ (asm BLOCKHASH) }", - "{ (asm COINBASE) }", - "{ (asm TIMESTAMP) }", - "{ (asm NUMBER) }", - "{ (asm DIFFICULTY) }", - "{ (asm GASLIMIT) }", - "{ (asm POP) }", - "{ (asm MLOAD) }", - "{ (asm MSTORE) }", - "{ (asm MSTORE8) }", - "{ (asm SLOAD) }", - "{ (asm SSTORE) }", - "{ (asm JUMP ) }", - "{ (asm JUMPI ) }", - "{ (asm PC) }", - "{ (asm MSIZE) }", - "{ (asm GAS) }", - "{ (asm JUMPDEST) }", - "{ (asm 0xff) }", - "{ (asm 0xffff) }", - "{ (asm 0xffffff) }", - "{ (asm 0xffffffff) }", - "{ (asm 0xffffffffff) }", - "{ (asm 0xffffffffffff) }", - "{ (asm 0xffffffffffffff) }", - "{ (asm 0xffffffffffffffff) }", - "{ (asm 0xffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", - "{ (asm DUP1) }", - "{ (asm DUP2) }", - "{ (asm DUP3) }", - "{ (asm DUP4) }", - "{ (asm DUP5) }", - "{ (asm DUP6) }", - "{ (asm DUP7) }", - "{ (asm DUP8) }", - "{ (asm DUP9) }", - "{ (asm DUP10) }", - "{ (asm DUP11) }", - "{ (asm DUP12) }", - "{ (asm DUP13) }", - "{ (asm DUP14) }", - "{ (asm DUP15) }", - "{ (asm DUP16) }", - "{ (asm SWAP1) }", - "{ (asm SWAP2) }", - "{ (asm SWAP3) }", - "{ (asm SWAP4) }", - "{ (asm SWAP5) }", - "{ (asm SWAP6) }", - "{ (asm SWAP7) }", - "{ (asm SWAP8) }", - "{ (asm SWAP9) }", - "{ (asm SWAP10) }", - "{ (asm SWAP11) }", - "{ (asm SWAP12) }", - "{ (asm SWAP13) }", - "{ (asm SWAP14) }", - "{ (asm SWAP15) }", - "{ (asm SWAP16) }", - "{ (asm LOG0) }", - "{ (asm LOG1) }", - "{ (asm LOG2) }", - "{ (asm LOG3) }", - "{ (asm LOG4) }", - "{ (asm CREATE) }", - "{ (asm CALL) }", - "{ (asm CALLCODE) }", - "{ (asm RETURN) }", - "{ (asm DELEGATECALL) }", - "{ (asm STATICCALL) }", - "{ (asm REVERT) }", - "{ (asm INVALID) }", - "{ (asm SELFDESTRUCT) }" + "(asm STOP)", + "(asm 0 0 ADD)", + "(asm 0 0 MUL)", + "(asm 0 0 SUB)", + "(asm 0 0 DIV)", + "(asm 0 0 SDIV)", + "(asm 0 0 MOD)", + "(asm 0 0 SMOD)", + "(asm 0 0 0 ADDMOD)", + "(asm 0 0 0 MULMOD)", + "(asm 0 0 EXP)", + "(asm 0 0 SIGNEXTEND)", + "(asm 0 0 LT)", + "(asm 0 0 GT)", + "(asm 0 0 SLT)", + "(asm 0 0 SGT)", + "(asm 0 0 EQ)", + "(asm 0 ISZERO)", + "(asm 0 0 AND)", + "(asm 0 0 OR)", + "(asm 0 0 XOR)", + "(asm 0 NOT)", + "(asm 0 0 BYTE)", + "(asm 0 0 KECCAK256)", + "(asm ADDRESS)", + "(asm 0 BALANCE)", + "(asm ORIGIN)", + "(asm CALLER)", + "(asm CALLVALUE)", + "(asm 0 CALLDATALOAD)", + "(asm CALLDATASIZE)", + "(asm 0 0 0 CALLDATACOPY)", + "(asm CODESIZE)", + "(asm 0 0 0 CODECOPY)", + "(asm GASPRICE)", + "(asm 0 EXTCODESIZE)", + "(asm 0 0 0 0 EXTCODECOPY)", + "(asm RETURNDATASIZE)", + "(asm 0 0 0 RETURNDATACOPY)", + "(asm 0 EXTCODEHASH)", + "(asm BLOCKHASH)", + "(asm COINBASE)", + "(asm TIMESTAMP)", + "(asm NUMBER)", + "(asm DIFFICULTY)", + "(asm GASLIMIT)", + "(asm 0 POP)", + "(asm 0 MLOAD)", + "(asm 0 0 MSTORE)", + "(asm 0 0 MSTORE8)", + "(asm 0 SLOAD)", + "(asm 0 0 SSTORE)", + "(asm 0 JUMP)", + "(asm 0 0 JUMPI)", + "(asm PC)", + "(asm MSIZE)", + "(asm GAS)", + "(asm JUMPDEST)", + "(asm 0xff)", + "(asm 0xffff)", + "(asm 0xffffff)", + "(asm 0xffffffff)", + "(asm 0xffffffffff)", + "(asm 0xffffffffffff)", + "(asm 0xffffffffffffff)", + "(asm 0xffffffffffffffff)", + "(asm 0xffffffffffffffffff)", + "(asm 0xffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP1)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP2)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP3)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP4)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP5)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP6)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP7)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP8)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP9)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP10)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP11)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP12)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP13)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP14)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP15)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP16)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP1)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP2)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP3)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP4)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP5)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP6)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP7)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP8)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP9)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP10)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP11)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP12)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP13)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP14)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP15)", + "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP16)", + "(asm 0 0 LOG0)", + "(asm 0 0 0 LOG1)", + "(asm 0 0 0 0 LOG2)", + "(asm 0 0 0 0 0 LOG3)", + "(asm 0 0 0 0 0 0 LOG4)", + "(asm 0 0 0 CREATE)", + "(asm 0 0 0 0 0 0 CALL)", + "(asm 0 0 0 0 0 0 CALLCODE)", + "(asm 0 0 RETURN)", + "(asm 0 0 0 0 0 DELEGATECALL)", + "(asm 0 0 0 0 0 STATICCALL)", + "(asm 0 0 REVERT)", + "(asm INVALID)", + "(asm 0 SELFDESTRUCT)" }; - for (size_t i = 0; i < opcodes_bytecode.size(); i++) { + for (size_t i = 0; i < opcodes_bytecode.size(); i++) + { vector errors; - bytes code = eth::compileLLL(opcodes_lll[i], dev::test::Options::get().evmVersion(), false, &errors); + bytes code = lll::compileLLL(opcodes_lll[i], dev::test::Options::get().evmVersion(), false, &errors); BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index fd8099f20..60aef7b00 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -50,6 +50,7 @@ BOOST_AUTO_TEST_CASE(bare_panic) { char const* sourceCode = "(panic)"; compileAndRunWithoutCheck(sourceCode); + BOOST_REQUIRE(!m_transactionSuccessful); BOOST_REQUIRE(m_output.empty()); } @@ -57,6 +58,7 @@ BOOST_AUTO_TEST_CASE(panic) { char const* sourceCode = "{ (panic) }"; compileAndRunWithoutCheck(sourceCode); + BOOST_REQUIRE(!m_transactionSuccessful); BOOST_REQUIRE(m_output.empty()); } @@ -69,6 +71,7 @@ BOOST_AUTO_TEST_CASE(macro_zeroarg) (zeroarg))) )"; compileAndRun(sourceCode); + BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(callFallback() == encodeArgs(u256(0x1234))); } @@ -983,6 +986,20 @@ BOOST_AUTO_TEST_CASE(shift_right) BOOST_CHECK(callFallback() == encodeArgs(u256(256))); } +BOOST_AUTO_TEST_CASE(sub_assemblies) +{ + char const* sourceCode = R"( + (returnlll + (return (create 0 (returnlll (sstore 1 1))))) + )"; + compileAndRun(sourceCode); + bytes ret = callFallback(); + BOOST_REQUIRE(ret.size() == 32); + u256 rVal = u256(toHex(ret, 2, HexPrefix::Add)); + BOOST_CHECK(rVal != 0); + BOOST_CHECK(rVal < u256("0x10000000000000000000000000000000000000000")); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/liblll/ExecutionFramework.h b/test/liblll/ExecutionFramework.h index ae5cd988c..7c1ce6708 100644 --- a/test/liblll/ExecutionFramework.h +++ b/test/liblll/ExecutionFramework.h @@ -56,7 +56,7 @@ public: BOOST_REQUIRE(_libraryAddresses.empty()); std::vector errors; - bytes bytecode = eth::compileLLL(_sourceCode, dev::test::Options::get().evmVersion(), m_optimize, &errors); + bytes bytecode = lll::compileLLL(_sourceCode, dev::test::Options::get().evmVersion(), m_optimize, &errors); if (!errors.empty()) { for (auto const& error: errors) diff --git a/test/liblll/Parser.cpp b/test/liblll/Parser.cpp index fc977b817..d343aab1f 100644 --- a/test/liblll/Parser.cpp +++ b/test/liblll/Parser.cpp @@ -39,13 +39,13 @@ namespace bool successParse(std::string const& _source) { - std::string ret = eth::parseLLL(_source); + std::string ret = lll::parseLLL(_source); return ret.size() != 0; } std::string parse(std::string const& _source) { - return eth::parseLLL(_source); + return lll::parseLLL(_source); } } diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index beb7b5af6..94319985d 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(fixed_arrays) { string sourceCode = R"( contract C { - function f(uint16[3] a, uint16[2][3] b, uint i, uint j, uint k) + function f(uint16[3] memory a, uint16[2][3] memory b, uint i, uint j, uint k) public pure returns (uint, uint) { return (a[i], b[j][k]); } @@ -154,7 +154,7 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays) { string sourceCode = R"( contract C { - function f(uint a, uint16[] b, uint c) + function f(uint a, uint16[] memory b, uint c) public pure returns (uint, uint, uint) { return (b.length, b[a], c); } @@ -178,11 +178,11 @@ BOOST_AUTO_TEST_CASE(dynamic_nested_arrays) { string sourceCode = R"( contract C { - function f(uint a, uint16[][] b, uint[2][][3] c, uint d) + function f(uint a, uint16[][] memory b, uint[2][][3] memory c, uint d) public pure returns (uint, uint, uint, uint, uint, uint, uint) { return (a, b.length, b[1].length, b[1][1], c[1].length, c[1][1][1], d); } - function test() view returns (uint, uint, uint, uint, uint, uint, uint) { + function test() public view returns (uint, uint, uint, uint, uint, uint, uint) { uint16[][] memory b = new uint16[][](3); b[0] = new uint16[](2); b[0][0] = 0x55; @@ -229,12 +229,12 @@ BOOST_AUTO_TEST_CASE(byte_arrays) { string sourceCode = R"( contract C { - function f(uint a, bytes b, uint c) + function f(uint a, bytes memory b, uint c) public pure returns (uint, uint, byte, uint) { return (a, b.length, b[3], c); } - function f_external(uint a, bytes b, uint c) + function f_external(uint a, bytes calldata b, uint c) external pure returns (uint, uint, byte, uint) { return (a, b.length, b[3], c); } @@ -261,12 +261,11 @@ BOOST_AUTO_TEST_CASE(calldata_arrays_too_large) { string sourceCode = R"( contract C { - function f(uint a, uint[] b, uint c) external pure returns (uint) { + function f(uint a, uint[] calldata b, uint c) external pure returns (uint) { return 7; } } )"; - bool newEncoder = false; BOTH_ENCODERS( compileAndRun(sourceCode); bytes args = encodeArgs( @@ -275,9 +274,8 @@ BOOST_AUTO_TEST_CASE(calldata_arrays_too_large) ); ABI_CHECK( callContractFunction("f(uint256,uint256[],uint256)", args), - newEncoder ? encodeArgs() : encodeArgs(7) + encodeArgs() ); - newEncoder = true; ) } @@ -287,7 +285,7 @@ BOOST_AUTO_TEST_CASE(decode_from_memory_simple) contract C { uint public _a; uint[] public _b; - function C(uint a, uint[] b) { + constructor(uint a, uint[] memory b) public { _a = a; _b = b; } @@ -312,24 +310,24 @@ BOOST_AUTO_TEST_CASE(decode_function_type) string sourceCode = R"( contract D { function () external returns (uint) public _a; - function D(function () external returns (uint) a) { + constructor(function () external returns (uint) a) public { _a = a; } } contract C { - function f() returns (uint) { + function f() public returns (uint) { return 3; } - function g(function () external returns (uint) _f) returns (uint) { + function g(function () external returns (uint) _f) public returns (uint) { return _f(); } // uses "decode from memory" - function test1() returns (uint) { + function test1() public returns (uint) { D d = new D(this.f); return d._a()(); } // uses "decode from calldata" - function test2() returns (uint) { + function test2() public returns (uint) { return this.g(this.f); } } @@ -346,13 +344,13 @@ BOOST_AUTO_TEST_CASE(decode_function_type_array) string sourceCode = R"( contract D { function () external returns (uint)[] public _a; - function D(function () external returns (uint)[] a) { + constructor(function () external returns (uint)[] memory a) public { _a = a; } } contract E { function () external returns (uint)[3] public _a; - function E(function () external returns (uint)[3] a) { + constructor(function () external returns (uint)[3] memory a) public { _a = a; } } @@ -366,15 +364,15 @@ BOOST_AUTO_TEST_CASE(decode_function_type_array) function f3() public returns (uint) { return 3; } - function g(function () external returns (uint)[] _f, uint i) public returns (uint) { + function g(function () external returns (uint)[] memory _f, uint i) public returns (uint) { return _f[i](); } - function h(function () external returns (uint)[3] _f, uint i) public returns (uint) { + function h(function () external returns (uint)[3] memory _f, uint i) public returns (uint) { return _f[i](); } // uses "decode from memory" function test1_dynamic() public returns (uint) { - var x = new function() external returns (uint)[](3); + function () external returns (uint)[] memory x = new function() external returns (uint)[](4); x[0] = this.f1; x[1] = this.f2; x[2] = this.f3; @@ -387,7 +385,7 @@ BOOST_AUTO_TEST_CASE(decode_function_type_array) } // uses "decode from calldata" function test2_dynamic() public returns (uint) { - var x = new function() external returns (uint)[](3); + function () external returns (uint)[] memory x = new function() external returns (uint)[](3); x[0] = this.f1; x[1] = this.f2; x[2] = this.f3; @@ -414,7 +412,7 @@ BOOST_AUTO_TEST_CASE(decode_from_memory_complex) uint public _a; uint[] public _b; bytes[2] public _c; - function C(uint a, uint[] b, bytes[2] c) { + constructor(uint a, uint[] memory b, bytes[2] memory c) public { _a = a; _b = b; _c = c; @@ -449,13 +447,11 @@ BOOST_AUTO_TEST_CASE(short_input_value_type) function f(uint a, uint b) public pure returns (uint) { return a; } } )"; - bool newDecoder = false; BOTH_ENCODERS( compileAndRun(sourceCode); ABI_CHECK(callContractFunction("f(uint256,uint256)", 1, 2), encodeArgs(1)); ABI_CHECK(callContractFunctionNoEncoding("f(uint256,uint256)", bytes(64, 0)), encodeArgs(0)); - ABI_CHECK(callContractFunctionNoEncoding("f(uint256,uint256)", bytes(63, 0)), newDecoder ? encodeArgs() : encodeArgs(0)); - newDecoder = true; + ABI_CHECK(callContractFunctionNoEncoding("f(uint256,uint256)", bytes(63, 0)), encodeArgs()); ) } @@ -463,18 +459,16 @@ BOOST_AUTO_TEST_CASE(short_input_array) { string sourceCode = R"( contract C { - function f(uint[] a) public pure returns (uint) { return 7; } + function f(uint[] memory a) public pure returns (uint) { return 7; } } )"; - bool newDecoder = false; BOTH_ENCODERS( compileAndRun(sourceCode); ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 0)), encodeArgs(7)); - ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1)), newDecoder ? encodeArgs() : encodeArgs(7)); - ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1) + bytes(31, 0)), newDecoder ? encodeArgs() : encodeArgs(7)); + ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1)), encodeArgs()); + ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1) + bytes(31, 0)), encodeArgs()); ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1) + bytes(32, 0)), encodeArgs(7)); ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 2, 5, 6)), encodeArgs(7)); - newDecoder = true; ) } @@ -482,7 +476,7 @@ BOOST_AUTO_TEST_CASE(short_dynamic_input_array) { string sourceCode = R"( contract C { - function f(bytes[1] a) public pure returns (uint) { return 7; } + function f(bytes[1] memory a) public pure returns (uint) { return 7; } } )"; NEW_ENCODER( @@ -495,8 +489,8 @@ BOOST_AUTO_TEST_CASE(short_input_bytes) { string sourceCode = R"( contract C { - function e(bytes a) public pure returns (uint) { return 7; } - function f(bytes[] a) public pure returns (uint) { return 7; } + function e(bytes memory a) public pure returns (uint) { return 7; } + function f(bytes[] memory a) public pure returns (uint) { return 7; } } )"; NEW_ENCODER( @@ -517,9 +511,9 @@ BOOST_AUTO_TEST_CASE(cleanup_int_inside_arrays) string sourceCode = R"( contract C { enum E { A, B } - function f(uint16[] a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } } - function g(int16[] a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } } - function h(E[] a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } } + function f(uint16[] memory a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } } + function g(int16[] memory a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } } + function h(E[] memory a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } } } )"; NEW_ENCODER( @@ -558,7 +552,7 @@ BOOST_AUTO_TEST_CASE(storage_ptr) r[2] = 3; s.x = 11; s.y = 12; - var (a, b, c, d) = L.f(r, s); + (uint a, uint b, uint c, uint d) = L.f(r, s); return (r[2], s.x, a, b, c, d); } } @@ -575,11 +569,11 @@ BOOST_AUTO_TEST_CASE(struct_simple) string sourceCode = R"( contract C { struct S { uint a; uint8 b; uint8 c; bytes2 d; } - function f(S s) public pure returns (uint a, uint b, uint c, uint d) { + function f(S memory s) public pure returns (uint a, uint b, uint c, uint d) { a = s.a; b = s.b; c = s.c; - d = uint(s.d); + d = uint16(s.d); } } )"; @@ -594,7 +588,7 @@ BOOST_AUTO_TEST_CASE(struct_cleanup) string sourceCode = R"( contract C { struct S { int16 a; uint8 b; bytes2 c; } - function f(S s) public pure returns (uint a, uint b, uint c) { + function f(S memory s) public pure returns (uint a, uint b, uint c) { assembly { a := mload(s) b := mload(add(s, 0x20)) @@ -617,7 +611,7 @@ BOOST_AUTO_TEST_CASE(struct_short) string sourceCode = R"( contract C { struct S { int a; uint b; bytes16 c; } - function f(S s) public pure returns (S q) { + function f(S memory s) public pure returns (S memory q) { q = s; } } @@ -644,7 +638,7 @@ BOOST_AUTO_TEST_CASE(struct_function) string sourceCode = R"( contract C { struct S { function () external returns (uint) f; uint b; } - function f(S s) public returns (uint, uint) { + function f(S memory s) public returns (uint, uint) { return (s.f(), s.b); } function test() public returns (uint, uint) { @@ -659,32 +653,12 @@ BOOST_AUTO_TEST_CASE(struct_function) ) } -BOOST_AUTO_TEST_CASE(empty_struct) -{ - string sourceCode = R"( - contract C { - struct S { } - function f(uint a, S s, uint b) public pure returns (uint x, uint y) { - assembly { x := a y := b } - } - function g() public returns (uint, uint) { - return this.f(7, S(), 8); - } - } - )"; - NEW_ENCODER( - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f(uint256,(),uint256)", 7, 8), encodeArgs(7, 8)); - ABI_CHECK(callContractFunction("g()"), encodeArgs(7, 8)); - ) -} - BOOST_AUTO_TEST_CASE(mediocre_struct) { string sourceCode = R"( contract C { struct S { C c; } - function f(uint a, S[2] s1, uint b) public returns (uint r1, C r2, uint r3) { + function f(uint a, S[2] memory s1, uint b) public returns (uint r1, C r2, uint r3) { r1 = a; r2 = s1[0].c; r3 = b; @@ -705,7 +679,7 @@ BOOST_AUTO_TEST_CASE(mediocre2_struct) string sourceCode = R"( contract C { struct S { C c; uint[] x; } - function f(uint a, S[2] s1, uint b) public returns (uint r1, C r2, uint r3) { + function f(uint a, S[2] memory s1, uint b) public returns (uint r1, C r2, uint r3) { r1 = a; r2 = s1[0].c; r3 = b; @@ -733,7 +707,7 @@ BOOST_AUTO_TEST_CASE(complex_struct) enum E {A, B, C} struct T { uint x; E e; uint8 y; } struct S { C c; T[] t;} - function f(uint a, S[2] s1, S[] s2, uint b) public returns + function f(uint a, S[2] memory s1, S[] memory s2, uint b) public returns (uint r1, C r2, uint r3, uint r4, C r5, uint r6, E r7, uint8 r8) { r1 = a; r2 = s1[0].c; @@ -793,10 +767,10 @@ BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_simple) string sourceCode = R"( contract C { - function dyn() public returns (bytes) { + function dyn() public returns (bytes memory) { return "1234567890123456789012345678901234567890"; } - function f() public returns (bytes) { + function f() public returns (bytes memory) { return this.dyn(); } } @@ -814,15 +788,15 @@ BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_advanced) string sourceCode = R"( contract C { - function dyn() public returns (bytes a, uint b, bytes20[] c, uint d) { + function dyn() public returns (bytes memory a, uint b, bytes20[] memory c, uint d) { a = "1234567890123456789012345678901234567890"; b = uint(-1); c = new bytes20[](4); - c[0] = bytes20(1234); - c[3] = bytes20(6789); + c[0] = bytes20(uint160(1234)); + c[3] = bytes20(uint160(6789)); d = 0x1234; } - function f() public returns (bytes, uint, bytes20[], uint) { + function f() public returns (bytes memory, uint, bytes20[] memory, uint) { return this.dyn(); } } @@ -841,7 +815,7 @@ BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_out_of_range) { string sourceCode = R"( contract C { - function dyn(uint x) public returns (bytes a) { + function dyn(uint x) public returns (bytes memory a) { assembly { mstore(0, 0x20) mstore(0x20, 0x21) diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 49db9ce1c..d2125cc7d 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(value_types) assembly { b := 7 } C c; assembly { c := sub(0, 5) } - E(10, uint16(uint256(-2)), uint24(0x12121212), int24(int256(-1)), bytes3(x), b, c); + emit E(10, uint16(uint256(-2)), uint24(0x12121212), int24(int256(-1)), bytes3(x), b, c); } } )"; @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(string_literal) contract C { event E(string, bytes20, string); function f() public { - E("abcdef", "abcde", "abcdefabcdefgehabcabcasdfjklabcdefabcedefghabcabcasdfjklabcdefabcdefghabcabcasdfjklabcdeefabcdefghabcabcasdefjklabcdefabcdefghabcabcasdfjkl"); + emit E("abcdef", "abcde", "abcdefabcdefgehabcabcasdfjklabcdefabcedefghabcabcasdfjklabcdefabcdefghabcabcasdfjklabcdeefabcdefghabcabcasdefjklabcdefabcdefghabcabcasdfjkl"); } } )"; @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(conversion) int8 c; int16 d; assembly { a := sub(0, 1) c := 0x0101ff d := 0xff01 } - E(10, x, a, uint8(b), c, int8(d)); + emit E(bytes4(uint32(10)), x, a, uint8(b), c, int8(d)); } } )"; @@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE(memory_array_one_dim) mstore(add(x, mul(add(i, 1), 0x20)), add(0xfffffffe, i)) } } - E(10, x, 11); + emit E(10, x, 11); } } )"; @@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(memory_array_two_dim) x[0][2] = -1; x[1][0] = 4; x[1][1] = 5; - E(10, x, 11); + emit E(10, x, 11); } } )"; @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(memory_byte_array) bytes[] memory x = new bytes[](2); x[0] = "abcabcdefghjklmnopqrsuvwabcdefgijklmnopqrstuwabcdefgijklmnoprstuvw"; x[1] = "abcdefghijklmnopqrtuvwabcfghijklmnopqstuvwabcdeghijklmopqrstuvw"; - E(10, x, 11); + emit E(10, x, 11); } } )"; @@ -234,7 +234,7 @@ BOOST_AUTO_TEST_CASE(storage_byte_array) function f() public { short = "123456789012345678901234567890a"; long = "ffff123456789012345678901234567890afffffffff123456789012345678901234567890a"; - E(short, long); + emit E(short, long); } } )"; @@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(storage_array) sstore(1, sub(0, 2)) sstore(2, sub(0, 3)) } - E(addr); + emit E(addr); } } )"; @@ -279,10 +279,10 @@ BOOST_AUTO_TEST_CASE(storage_array_dyn) address[] addr; event E(address[] a); function f() public { - addr.push(1); - addr.push(2); - addr.push(3); - E(addr); + addr.push(0x0000000000000000000000000000000000000001); + addr.push(0x0000000000000000000000000000000000000002); + addr.push(0x0000000000000000000000000000000000000003); + emit E(addr); } } )"; @@ -308,7 +308,7 @@ BOOST_AUTO_TEST_CASE(storage_array_compact) x.push(6); x.push(-7); x.push(8); - E(x); + emit E(x); } } )"; @@ -329,7 +329,7 @@ BOOST_AUTO_TEST_CASE(external_function) function(uint) external returns (uint) g; function f(uint) public returns (uint) { g = this.f; - E(this.f, g); + emit E(this.f, g); } } )"; @@ -351,7 +351,7 @@ BOOST_AUTO_TEST_CASE(external_function_cleanup) function f(uint) public returns (uint) { function(uint) external returns (uint)[1] memory h; assembly { sstore(0, sub(0, 1)) mstore(h, sub(0, 1)) } - E(h[0], g); + emit E(h[0], g); } } )"; @@ -367,22 +367,19 @@ BOOST_AUTO_TEST_CASE(calldata) string sourceCode = R"( contract C { event E(bytes); - function f(bytes a) external { - E(a); + function f(bytes calldata a) external { + emit E(a); } } )"; string s("abcdef"); string t("abcdefgggggggggggggggggggggggggggggggggggggggghhheeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeggg"); - bool newEncoder = false; BOTH_ENCODERS( compileAndRun(sourceCode); callContractFunction("f(bytes)", 0x20, s.size(), s); - // The old encoder did not pad to multiples of 32 bytes - REQUIRE_LOG_DATA(encodeArgs(0x20, s.size()) + (newEncoder ? encodeArgs(s) : asBytes(s))); + REQUIRE_LOG_DATA(encodeArgs(0x20, s.size(), s)); callContractFunction("f(bytes)", 0x20, t.size(), t); - REQUIRE_LOG_DATA(encodeArgs(0x20, t.size()) + (newEncoder ? encodeArgs(t) : asBytes(t))); - newEncoder = true; + REQUIRE_LOG_DATA(encodeArgs(0x20, t.size(), t)); ) } @@ -420,7 +417,7 @@ BOOST_AUTO_TEST_CASE(structs) struct T { uint64[2] x; } S s; event e(uint16, S); - function f() public returns (uint, S) { + function f() public returns (uint, S memory) { uint16 x = 7; s.a = 8; s.b = 9; @@ -429,7 +426,7 @@ BOOST_AUTO_TEST_CASE(structs) s.sub[0].x[0] = 11; s.sub[1].x[0] = 12; s.sub[2].x[1] = 13; - e(x, s); + emit e(x, s); return (x, s); } } @@ -450,28 +447,6 @@ BOOST_AUTO_TEST_CASE(structs) ) } -BOOST_AUTO_TEST_CASE(empty_struct) -{ - string sourceCode = R"( - contract C { - struct S { } - S s; - event e(uint16, S, uint16); - function f() returns (uint, S, uint) { - e(7, s, 8); - return (7, s, 8); - } - } - )"; - - NEW_ENCODER( - compileAndRun(sourceCode, 0, "C"); - bytes encoded = encodeArgs(7, 8); - BOOST_CHECK(callContractFunction("f()") == encoded); - REQUIRE_LOG_DATA(encoded); - ) -} - BOOST_AUTO_TEST_CASE(structs2) { string sourceCode = R"( @@ -479,7 +454,7 @@ BOOST_AUTO_TEST_CASE(structs2) enum E {A, B, C} struct T { uint x; E e; uint8 y; } struct S { C c; T[] t;} - function f() public returns (uint a, S[2] s1, S[] s2, uint b) { + function f() public returns (uint a, S[2] memory s1, S[] memory s2, uint b) { a = 7; b = 8; s1[0].c = this; diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp deleted file mode 100644 index 5d5b14e8b..000000000 --- a/test/libsolidity/ASTJSON.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2016 - * Tests for the json ast output. - */ - -#include - -#include -#include -#include - -#include - -#include - -using namespace std; - -namespace dev -{ -namespace solidity -{ -namespace test -{ - -BOOST_AUTO_TEST_SUITE(SolidityASTJSON) - -BOOST_AUTO_TEST_CASE(short_type_name) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() { uint[] memory x; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["declarations"][0]; - BOOST_CHECK_EQUAL(varDecl["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeIdentifier"], "t_array$_t_uint256_$dyn_memory_ptr"); - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeString"], "uint256[]"); -} - -BOOST_AUTO_TEST_CASE(short_type_name_ref) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() { uint[][] memory rows; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["declarations"][0]; - BOOST_CHECK_EQUAL(varDecl["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(varDecl["typeName"]["typeDescriptions"]["typeIdentifier"], "t_array$_t_array$_t_uint256_$dyn_storage_$dyn_storage_ptr"); - BOOST_CHECK_EQUAL(varDecl["typeName"]["typeDescriptions"]["typeString"], "uint256[][]"); -} - -BOOST_AUTO_TEST_CASE(long_type_name_binary_operation) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() public { uint a = 2 + 3; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["initialValue"]["commonType"]; - BOOST_CHECK_EQUAL(varDecl["typeIdentifier"], "t_rational_5_by_1"); - BOOST_CHECK_EQUAL(varDecl["typeString"], "int_const 5"); -} - -BOOST_AUTO_TEST_CASE(long_type_name_identifier) -{ - CompilerStack c; - c.addSource("a", "contract c { uint[] a; function f() public { uint[] b = a; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][1]["body"]["statements"][0]["initialValue"]; - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeIdentifier"], "t_array$_t_uint256_$dyn_storage"); - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeString"], "uint256[] storage ref"); -} - -BOOST_AUTO_TEST_CASE(documentation) -{ - CompilerStack c; - c.addSource("a", "/**This contract is empty*/ contract C {}"); - c.addSource("b", - "/**This contract is empty" - " and has a line-breaking comment.*/" - "contract C {}" - ); - c.addSource("c", - "contract C {" - " /** Some comment on Evt.*/ event Evt();" - " /** Some comment on mod.*/ modifier mod() { _; }" - " /** Some comment on fn.*/ function fn() public {}" - "}" - ); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 0; - sourceIndices["b"] = 1; - sourceIndices["c"] = 2; - //same tests for non-legacy mode - Json::Value astJsonA = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value documentationA = astJsonA["nodes"][0]["documentation"]; - BOOST_CHECK_EQUAL(documentationA, "This contract is empty"); - Json::Value astJsonB = ASTJsonConverter(false, sourceIndices).toJson(c.ast("b")); - Json::Value documentationB = astJsonB["nodes"][0]["documentation"]; - BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment."); - Json::Value astJsonC = ASTJsonConverter(false, sourceIndices).toJson(c.ast("c")); - Json::Value documentationC0 = astJsonC["nodes"][0]["nodes"][0]["documentation"]; - Json::Value documentationC1 = astJsonC["nodes"][0]["nodes"][1]["documentation"]; - Json::Value documentationC2 = astJsonC["nodes"][0]["nodes"][2]["documentation"]; - BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt."); - BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod."); - BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn."); -} - - -BOOST_AUTO_TEST_SUITE_END() - -} -} -} // end namespaces diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json new file mode 100644 index 000000000..0f30e8e86 --- /dev/null +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -0,0 +1,560 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 37 + ] + }, + "id" : 38, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 37, + "linearizedBaseContracts" : + [ + 37 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "constant" : false, + "id" : 4, + "name" : "m", + "nodeType" : "VariableDeclaration", + "scope" : 37, + "src" : "17:44:1", + "stateVariable" : true, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", + "typeString" : "mapping(address => address payable)" + }, + "typeName" : + { + "id" : 3, + "keyType" : + { + "id" : 1, + "name" : "address", + "nodeType" : "ElementaryTypeName", + "src" : "25:7:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address", + "typeString" : "address" + } + }, + "nodeType" : "Mapping", + "src" : "17:35:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", + "typeString" : "mapping(address => address payable)" + }, + "valueType" : + { + "id" : 2, + "name" : "address", + "nodeType" : "ElementaryTypeName", + "src" : "36:15:1", + "stateMutability" : "payable", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + } + }, + "value" : null, + "visibility" : "public" + }, + { + "body" : + { + "id" : 35, + "nodeType" : "Block", + "src" : "134:122:1", + "statements" : + [ + { + "assignments" : + [ + 12 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 12, + "name" : "a", + "nodeType" : "VariableDeclaration", + "scope" : 35, + "src" : "144:17:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + }, + "typeName" : + { + "id" : 11, + "name" : "address", + "nodeType" : "ElementaryTypeName", + "src" : "144:15:1", + "stateMutability" : "payable", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 16, + "initialValue" : + { + "argumentTypes" : null, + "baseExpression" : + { + "argumentTypes" : null, + "id" : 13, + "name" : "m", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 4, + "src" : "164:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", + "typeString" : "mapping(address => address payable)" + } + }, + "id" : 15, + "indexExpression" : + { + "argumentTypes" : null, + "id" : 14, + "name" : "arg", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 6, + "src" : "166:3:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "isConstant" : false, + "isLValue" : true, + "isPure" : false, + "lValueRequested" : false, + "nodeType" : "IndexAccess", + "src" : "164:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "144:26:1" + }, + { + "expression" : + { + "argumentTypes" : null, + "id" : 19, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "leftHandSide" : + { + "argumentTypes" : null, + "id" : 17, + "name" : "r", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 9, + "src" : "180:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "nodeType" : "Assignment", + "operator" : "=", + "rightHandSide" : + { + "argumentTypes" : null, + "id" : 18, + "name" : "arg", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 6, + "src" : "184:3:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "src" : "180:7:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "id" : 20, + "nodeType" : "ExpressionStatement", + "src" : "180:7:1" + }, + { + "assignments" : + [ + 22 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 22, + "name" : "c", + "nodeType" : "VariableDeclaration", + "scope" : 35, + "src" : "197:9:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_address", + "typeString" : "address" + }, + "typeName" : + { + "id" : 21, + "name" : "address", + "nodeType" : "ElementaryTypeName", + "src" : "197:7:1", + "stateMutability" : "nonpayable", + "typeDescriptions" : + { + "typeIdentifier" : "t_address", + "typeString" : "address" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 26, + "initialValue" : + { + "argumentTypes" : null, + "arguments" : + [ + { + "argumentTypes" : null, + "id" : 24, + "name" : "this", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 65, + "src" : "217:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_contract$_C_$37", + "typeString" : "contract C" + } + } + ], + "expression" : + { + "argumentTypes" : + [ + { + "typeIdentifier" : "t_contract$_C_$37", + "typeString" : "contract C" + } + ], + "id" : 23, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "nodeType" : "ElementaryTypeNameExpression", + "src" : "209:7:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_type$_t_address_$", + "typeString" : "type(address)" + }, + "typeName" : "address" + }, + "id" : 25, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "kind" : "typeConversion", + "lValueRequested" : false, + "names" : [], + "nodeType" : "FunctionCall", + "src" : "209:13:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address", + "typeString" : "address" + } + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "197:25:1" + }, + { + "expression" : + { + "argumentTypes" : null, + "id" : 33, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "leftHandSide" : + { + "argumentTypes" : null, + "baseExpression" : + { + "argumentTypes" : null, + "id" : 27, + "name" : "m", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 4, + "src" : "232:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", + "typeString" : "mapping(address => address payable)" + } + }, + "id" : 29, + "indexExpression" : + { + "argumentTypes" : null, + "id" : 28, + "name" : "c", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 22, + "src" : "234:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address", + "typeString" : "address" + } + }, + "isConstant" : false, + "isLValue" : true, + "isPure" : false, + "lValueRequested" : true, + "nodeType" : "IndexAccess", + "src" : "232:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "nodeType" : "Assignment", + "operator" : "=", + "rightHandSide" : + { + "argumentTypes" : null, + "arguments" : + [ + { + "argumentTypes" : null, + "hexValue" : "30", + "id" : 31, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "247:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_0_by_1", + "typeString" : "int_const 0" + }, + "value" : "0" + } + ], + "expression" : + { + "argumentTypes" : + [ + { + "typeIdentifier" : "t_rational_0_by_1", + "typeString" : "int_const 0" + } + ], + "id" : 30, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "nodeType" : "ElementaryTypeNameExpression", + "src" : "239:7:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_type$_t_address_$", + "typeString" : "type(address)" + }, + "typeName" : "address" + }, + "id" : 32, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "typeConversion", + "lValueRequested" : false, + "names" : [], + "nodeType" : "FunctionCall", + "src" : "239:10:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "src" : "232:17:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "id" : 34, + "nodeType" : "ExpressionStatement", + "src" : "232:17:1" + } + ] + }, + "documentation" : null, + "id" : 36, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 6, + "name" : "arg", + "nodeType" : "VariableDeclaration", + "scope" : 36, + "src" : "78:19:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + }, + "typeName" : + { + "id" : 5, + "name" : "address", + "nodeType" : "ElementaryTypeName", + "src" : "78:15:1", + "stateMutability" : "payable", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "77:21:1" + }, + "returnParameters" : + { + "id" : 10, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 9, + "name" : "r", + "nodeType" : "VariableDeclaration", + "scope" : 36, + "src" : "115:17:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + }, + "typeName" : + { + "id" : 8, + "name" : "address", + "nodeType" : "ElementaryTypeName", + "src" : "115:15:1", + "stateMutability" : "payable", + "typeDescriptions" : + { + "typeIdentifier" : "t_address_payable", + "typeString" : "address payable" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "114:19:1" + }, + "scope" : 37, + "src" : "67:189:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 38, + "src" : "0:258:1" + } + ], + "src" : "0:259:1" +} diff --git a/test/libsolidity/ASTJSON/address_payable.sol b/test/libsolidity/ASTJSON/address_payable.sol new file mode 100644 index 000000000..f7cc66cb5 --- /dev/null +++ b/test/libsolidity/ASTJSON/address_payable.sol @@ -0,0 +1,11 @@ +contract C { + mapping(address => address payable) public m; + function f(address payable arg) public returns (address payable r) { + address payable a = m[arg]; + r = arg; + address c = address(this); + m[c] = address(0); + } +} + +// ---- diff --git a/test/libsolidity/ASTJSON/address_payable_legacy.json b/test/libsolidity/ASTJSON/address_payable_legacy.json new file mode 100644 index 000000000..dd8a5582c --- /dev/null +++ b/test/libsolidity/ASTJSON/address_payable_legacy.json @@ -0,0 +1,601 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 37 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 37 + ], + "name" : "C", + "scope" : 38 + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "m", + "scope" : 37, + "stateVariable" : true, + "storageLocation" : "default", + "type" : "mapping(address => address payable)", + "value" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "type" : "mapping(address => address payable)" + }, + "children" : + [ + { + "attributes" : + { + "name" : "address", + "type" : "address" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "25:7:1" + }, + { + "attributes" : + { + "name" : "address", + "stateMutability" : "payable", + "type" : "address payable" + }, + "id" : 2, + "name" : "ElementaryTypeName", + "src" : "36:15:1" + } + ], + "id" : 3, + "name" : "Mapping", + "src" : "17:35:1" + } + ], + "id" : 4, + "name" : "VariableDeclaration", + "src" : "17:44:1" + }, + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 37, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "arg", + "scope" : 36, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "address payable", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "address", + "stateMutability" : "payable", + "type" : "address payable" + }, + "id" : 5, + "name" : "ElementaryTypeName", + "src" : "78:15:1" + } + ], + "id" : 6, + "name" : "VariableDeclaration", + "src" : "78:19:1" + } + ], + "id" : 7, + "name" : "ParameterList", + "src" : "77:21:1" + }, + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "r", + "scope" : 36, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "address payable", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "address", + "stateMutability" : "payable", + "type" : "address payable" + }, + "id" : 8, + "name" : "ElementaryTypeName", + "src" : "115:15:1" + } + ], + "id" : 9, + "name" : "VariableDeclaration", + "src" : "115:17:1" + } + ], + "id" : 10, + "name" : "ParameterList", + "src" : "114:19:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 12 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "a", + "scope" : 35, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "address payable", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "address", + "stateMutability" : "payable", + "type" : "address payable" + }, + "id" : 11, + "name" : "ElementaryTypeName", + "src" : "144:15:1" + } + ], + "id" : 12, + "name" : "VariableDeclaration", + "src" : "144:17:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : true, + "isPure" : false, + "lValueRequested" : false, + "type" : "address payable" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 4, + "type" : "mapping(address => address payable)", + "value" : "m" + }, + "id" : 13, + "name" : "Identifier", + "src" : "164:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 6, + "type" : "address payable", + "value" : "arg" + }, + "id" : 14, + "name" : "Identifier", + "src" : "166:3:1" + } + ], + "id" : 15, + "name" : "IndexAccess", + "src" : "164:6:1" + } + ], + "id" : 16, + "name" : "VariableDeclarationStatement", + "src" : "144:26:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "operator" : "=", + "type" : "address payable" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 9, + "type" : "address payable", + "value" : "r" + }, + "id" : 17, + "name" : "Identifier", + "src" : "180:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 6, + "type" : "address payable", + "value" : "arg" + }, + "id" : 18, + "name" : "Identifier", + "src" : "184:3:1" + } + ], + "id" : 19, + "name" : "Assignment", + "src" : "180:7:1" + } + ], + "id" : 20, + "name" : "ExpressionStatement", + "src" : "180:7:1" + }, + { + "attributes" : + { + "assignments" : + [ + 22 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "c", + "scope" : 35, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "address", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "address", + "stateMutability" : "nonpayable", + "type" : "address" + }, + "id" : 21, + "name" : "ElementaryTypeName", + "src" : "197:7:1" + } + ], + "id" : 22, + "name" : "VariableDeclaration", + "src" : "197:9:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "isStructConstructorCall" : false, + "lValueRequested" : false, + "names" : + [ + null + ], + "type" : "address", + "type_conversion" : true + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : + [ + { + "typeIdentifier" : "t_contract$_C_$37", + "typeString" : "contract C" + } + ], + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "type" : "type(address)", + "value" : "address" + }, + "id" : 23, + "name" : "ElementaryTypeNameExpression", + "src" : "209:7:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 65, + "type" : "contract C", + "value" : "this" + }, + "id" : 24, + "name" : "Identifier", + "src" : "217:4:1" + } + ], + "id" : 25, + "name" : "FunctionCall", + "src" : "209:13:1" + } + ], + "id" : 26, + "name" : "VariableDeclarationStatement", + "src" : "197:25:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "operator" : "=", + "type" : "address payable" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : true, + "isPure" : false, + "lValueRequested" : true, + "type" : "address payable" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 4, + "type" : "mapping(address => address payable)", + "value" : "m" + }, + "id" : 27, + "name" : "Identifier", + "src" : "232:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 22, + "type" : "address", + "value" : "c" + }, + "id" : 28, + "name" : "Identifier", + "src" : "234:1:1" + } + ], + "id" : 29, + "name" : "IndexAccess", + "src" : "232:4:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "isStructConstructorCall" : false, + "lValueRequested" : false, + "names" : + [ + null + ], + "type" : "address payable", + "type_conversion" : true + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : + [ + { + "typeIdentifier" : "t_rational_0_by_1", + "typeString" : "int_const 0" + } + ], + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "type" : "type(address)", + "value" : "address" + }, + "id" : 30, + "name" : "ElementaryTypeNameExpression", + "src" : "239:7:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "30", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 0", + "value" : "0" + }, + "id" : 31, + "name" : "Literal", + "src" : "247:1:1" + } + ], + "id" : 32, + "name" : "FunctionCall", + "src" : "239:10:1" + } + ], + "id" : 33, + "name" : "Assignment", + "src" : "232:17:1" + } + ], + "id" : 34, + "name" : "ExpressionStatement", + "src" : "232:17:1" + } + ], + "id" : 35, + "name" : "Block", + "src" : "134:122:1" + } + ], + "id" : 36, + "name" : "FunctionDefinition", + "src" : "67:189:1" + } + ], + "id" : 37, + "name" : "ContractDefinition", + "src" : "0:258:1" + } + ], + "id" : 38, + "name" : "SourceUnit", + "src" : "0:259:1" +} diff --git a/test/libsolidity/ASTJSON/array_type_name.json b/test/libsolidity/ASTJSON/array_type_name.json new file mode 100644 index 000000000..e3a3bea94 --- /dev/null +++ b/test/libsolidity/ASTJSON/array_type_name.json @@ -0,0 +1,76 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + }, + "id" : 5, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 4, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "constant" : false, + "id" : 3, + "name" : "i", + "nodeType" : "VariableDeclaration", + "scope" : 4, + "src" : "13:8:1", + "stateVariable" : true, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "13:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 2, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "13:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "scope" : 5, + "src" : "0:24:1" + } + ], + "src" : "0:25:1" +} diff --git a/test/libsolidity/ASTJSON/array_type_name.sol b/test/libsolidity/ASTJSON/array_type_name.sol new file mode 100644 index 000000000..202ecf02b --- /dev/null +++ b/test/libsolidity/ASTJSON/array_type_name.sol @@ -0,0 +1 @@ +contract C { uint[] i; } diff --git a/test/libsolidity/ASTJSON/array_type_name_legacy.json b/test/libsolidity/ASTJSON/array_type_name_legacy.json new file mode 100644 index 000000000..80feb344b --- /dev/null +++ b/test/libsolidity/ASTJSON/array_type_name_legacy.json @@ -0,0 +1,89 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "scope" : 5 + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "i", + "scope" : 4, + "stateVariable" : true, + "storageLocation" : "default", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "13:4:1" + } + ], + "id" : 2, + "name" : "ArrayTypeName", + "src" : "13:6:1" + } + ], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "13:8:1" + } + ], + "id" : 4, + "name" : "ContractDefinition", + "src" : "0:24:1" + } + ], + "id" : 5, + "name" : "SourceUnit", + "src" : "0:25:1" +} diff --git a/test/libsolidity/ASTJSON/constructor.json b/test/libsolidity/ASTJSON/constructor.json new file mode 100644 index 000000000..b0bc42019 --- /dev/null +++ b/test/libsolidity/ASTJSON/constructor.json @@ -0,0 +1,70 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + }, + "id" : 6, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 5, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 3, + "nodeType" : "Block", + "src" : "35:4:1", + "statements" : [] + }, + "documentation" : null, + "id" : 4, + "implemented" : true, + "kind" : "constructor", + "modifiers" : [], + "name" : "", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "25:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "35:0:1" + }, + "scope" : 5, + "src" : "14:25:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 6, + "src" : "0:41:1" + } + ], + "src" : "0:42:1" +} diff --git a/test/libsolidity/ASTJSON/constructor.sol b/test/libsolidity/ASTJSON/constructor.sol new file mode 100644 index 000000000..79d04eb5a --- /dev/null +++ b/test/libsolidity/ASTJSON/constructor.sol @@ -0,0 +1,4 @@ +contract C { + constructor() public { + } +} diff --git a/test/libsolidity/ASTJSON/constructor_legacy.json b/test/libsolidity/ASTJSON/constructor_legacy.json new file mode 100644 index 000000000..0617073e3 --- /dev/null +++ b/test/libsolidity/ASTJSON/constructor_legacy.json @@ -0,0 +1,110 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "scope" : 6 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : true, + "kind" : "constructor", + "modifiers" : + [ + null + ], + "name" : "", + "scope" : 5, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "25:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "35:0:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 3, + "name" : "Block", + "src" : "35:4:1" + } + ], + "id" : 4, + "name" : "FunctionDefinition", + "src" : "14:25:1" + } + ], + "id" : 5, + "name" : "ContractDefinition", + "src" : "0:41:1" + } + ], + "id" : 6, + "name" : "SourceUnit", + "src" : "0:42:1" +} diff --git a/test/libsolidity/ASTJSON/documentation.json b/test/libsolidity/ASTJSON/documentation.json new file mode 100644 index 000000000..ce1e0b57a --- /dev/null +++ b/test/libsolidity/ASTJSON/documentation.json @@ -0,0 +1,180 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 1 + ] + }, + "id" : 2, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : "This contract is empty", + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 2, + "src" : "28:13:1" + } + ], + "src" : "28:14:1" +}, +{ + "absolutePath" : "b", + "exportedSymbols" : + { + "C" : + [ + 3 + ] + }, + "id" : 4, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : "This contract is empty\nand has a line-breaking comment.", + "fullyImplemented" : true, + "id" : 3, + "linearizedBaseContracts" : + [ + 3 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 4, + "src" : "62:13:2" + } + ], + "src" : "62:14:2" +}, +{ + "absolutePath" : "c", + "exportedSymbols" : + { + "C" : + [ + 15 + ] + }, + "id" : 16, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 15, + "linearizedBaseContracts" : + [ + 15 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "anonymous" : false, + "documentation" : "Some comment on Evt.", + "id" : 6, + "name" : "Evt", + "nodeType" : "EventDefinition", + "parameters" : + { + "id" : 5, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "51:2:3" + }, + "src" : "42:12:3" + }, + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "99:6:3", + "statements" : + [ + { + "id" : 8, + "nodeType" : "PlaceholderStatement", + "src" : "101:1:3" + } + ] + }, + "documentation" : "Some comment on mod.", + "id" : 10, + "name" : "mod", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "96:2:3" + }, + "src" : "84:21:3", + "visibility" : "internal" + }, + { + "body" : + { + "id" : 13, + "nodeType" : "Block", + "src" : "155:2:3", + "statements" : [] + }, + "documentation" : "Some comment on fn.", + "id" : 14, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "fn", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "145:2:3" + }, + "returnParameters" : + { + "id" : 12, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "155:0:3" + }, + "scope" : 15, + "src" : "134:23:3", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 16, + "src" : "0:159:3" + } + ], + "src" : "0:160:3" +} diff --git a/test/libsolidity/ASTJSON/documentation.sol b/test/libsolidity/ASTJSON/documentation.sol new file mode 100644 index 000000000..e65af9b44 --- /dev/null +++ b/test/libsolidity/ASTJSON/documentation.sol @@ -0,0 +1,17 @@ +// ---- SOURCE: a + +/**This contract is empty*/ contract C {} + +// ---- SOURCE: b + +/**This contract is empty + and has a line-breaking comment.*/ +contract C {} + +// ---- SOURCE: c + +contract C { + /** Some comment on Evt.*/ event Evt(); + /** Some comment on mod.*/ modifier mod() { _; } + /** Some comment on fn.*/ function fn() public {} +} diff --git a/test/libsolidity/ASTJSON/documentation_legacy.json b/test/libsolidity/ASTJSON/documentation_legacy.json new file mode 100644 index 000000000..0277902f8 --- /dev/null +++ b/test/libsolidity/ASTJSON/documentation_legacy.json @@ -0,0 +1,177 @@ +{ + "attributes" : + { + "absolutePath" : "c", + "exportedSymbols" : + { + "C" : + [ + 15 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 15 + ], + "name" : "C", + "scope" : 16 + }, + "children" : + [ + { + "attributes" : + { + "anonymous" : false, + "documentation" : "Some comment on Evt.", + "name" : "Evt" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 5, + "name" : "ParameterList", + "src" : "51:2:3" + } + ], + "id" : 6, + "name" : "EventDefinition", + "src" : "42:12:3" + }, + { + "attributes" : + { + "documentation" : "Some comment on mod.", + "name" : "mod", + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 7, + "name" : "ParameterList", + "src" : "96:2:3" + }, + { + "children" : + [ + { + "id" : 8, + "name" : "PlaceholderStatement", + "src" : "101:1:3" + } + ], + "id" : 9, + "name" : "Block", + "src" : "99:6:3" + } + ], + "id" : 10, + "name" : "ModifierDefinition", + "src" : "84:21:3" + }, + { + "attributes" : + { + "documentation" : "Some comment on fn.", + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "fn", + "scope" : 15, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 11, + "name" : "ParameterList", + "src" : "145:2:3" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 12, + "name" : "ParameterList", + "src" : "155:0:3" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 13, + "name" : "Block", + "src" : "155:2:3" + } + ], + "id" : 14, + "name" : "FunctionDefinition", + "src" : "134:23:3" + } + ], + "id" : 15, + "name" : "ContractDefinition", + "src" : "0:159:3" + } + ], + "id" : 16, + "name" : "SourceUnit", + "src" : "0:160:3" +} diff --git a/test/libsolidity/ASTJSON/enum_value.json b/test/libsolidity/ASTJSON/enum_value.json new file mode 100644 index 000000000..21afd9a78 --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value.json @@ -0,0 +1,57 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + }, + "id" : 5, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 4, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "canonicalName" : "C.E", + "id" : 3, + "members" : + [ + { + "id" : 1, + "name" : "A", + "nodeType" : "EnumValue", + "src" : "22:1:1" + }, + { + "id" : 2, + "name" : "B", + "nodeType" : "EnumValue", + "src" : "25:1:1" + } + ], + "name" : "E", + "nodeType" : "EnumDefinition", + "src" : "13:15:1" + } + ], + "scope" : 5, + "src" : "0:30:1" + } + ], + "src" : "0:31:1" +} diff --git a/test/libsolidity/ASTJSON/enum_value.sol b/test/libsolidity/ASTJSON/enum_value.sol new file mode 100644 index 000000000..ef0875fbe --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value.sol @@ -0,0 +1 @@ +contract C { enum E { A, B } } diff --git a/test/libsolidity/ASTJSON/enum_value_legacy.json b/test/libsolidity/ASTJSON/enum_value_legacy.json new file mode 100644 index 000000000..d7782969b --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value_legacy.json @@ -0,0 +1,78 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "scope" : 5 + }, + "children" : + [ + { + "attributes" : + { + "canonicalName" : "C.E", + "name" : "E" + }, + "children" : + [ + { + "attributes" : + { + "name" : "A" + }, + "id" : 1, + "name" : "EnumValue", + "src" : "22:1:1" + }, + { + "attributes" : + { + "name" : "B" + }, + "id" : 2, + "name" : "EnumValue", + "src" : "25:1:1" + } + ], + "id" : 3, + "name" : "EnumDefinition", + "src" : "13:15:1" + } + ], + "id" : 4, + "name" : "ContractDefinition", + "src" : "0:30:1" + } + ], + "id" : 5, + "name" : "SourceUnit", + "src" : "0:31:1" +} diff --git a/test/libsolidity/ASTJSON/event_definition.json b/test/libsolidity/ASTJSON/event_definition.json new file mode 100644 index 000000000..029062c32 --- /dev/null +++ b/test/libsolidity/ASTJSON/event_definition.json @@ -0,0 +1,50 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 3 + ] + }, + "id" : 4, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 3, + "linearizedBaseContracts" : + [ + 3 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "anonymous" : false, + "documentation" : null, + "id" : 2, + "name" : "E", + "nodeType" : "EventDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "20:2:1" + }, + "src" : "13:10:1" + } + ], + "scope" : 4, + "src" : "0:25:1" + } + ], + "src" : "0:26:1" +} diff --git a/test/libsolidity/ASTJSON/event_definition.sol b/test/libsolidity/ASTJSON/event_definition.sol new file mode 100644 index 000000000..81b43c672 --- /dev/null +++ b/test/libsolidity/ASTJSON/event_definition.sol @@ -0,0 +1 @@ +contract C { event E(); } diff --git a/test/libsolidity/ASTJSON/event_definition_legacy.json b/test/libsolidity/ASTJSON/event_definition_legacy.json new file mode 100644 index 000000000..f5967bf4e --- /dev/null +++ b/test/libsolidity/ASTJSON/event_definition_legacy.json @@ -0,0 +1,74 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 3 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 3 + ], + "name" : "C", + "scope" : 4 + }, + "children" : + [ + { + "attributes" : + { + "anonymous" : false, + "documentation" : null, + "name" : "E" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "20:2:1" + } + ], + "id" : 2, + "name" : "EventDefinition", + "src" : "13:10:1" + } + ], + "id" : 3, + "name" : "ContractDefinition", + "src" : "0:25:1" + } + ], + "id" : 4, + "name" : "SourceUnit", + "src" : "0:26:1" +} diff --git a/test/libsolidity/ASTJSON/fallback.json b/test/libsolidity/ASTJSON/fallback.json new file mode 100644 index 000000000..a9c85b2fb --- /dev/null +++ b/test/libsolidity/ASTJSON/fallback.json @@ -0,0 +1,70 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + }, + "id" : 6, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 5, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 3, + "nodeType" : "Block", + "src" : "43:5:1", + "statements" : [] + }, + "documentation" : null, + "id" : 4, + "implemented" : true, + "kind" : "fallback", + "modifiers" : [], + "name" : "", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "43:0:1" + }, + "scope" : 5, + "src" : "15:33:1", + "stateMutability" : "payable", + "superFunction" : null, + "visibility" : "external" + } + ], + "scope" : 6, + "src" : "0:50:1" + } + ], + "src" : "0:51:1" +} diff --git a/test/libsolidity/ASTJSON/fallback.sol b/test/libsolidity/ASTJSON/fallback.sol new file mode 100644 index 000000000..4e318892e --- /dev/null +++ b/test/libsolidity/ASTJSON/fallback.sol @@ -0,0 +1,4 @@ +contract C { + function() external payable { + } +} diff --git a/test/libsolidity/ASTJSON/fallback_legacy.json b/test/libsolidity/ASTJSON/fallback_legacy.json new file mode 100644 index 000000000..0aca3128e --- /dev/null +++ b/test/libsolidity/ASTJSON/fallback_legacy.json @@ -0,0 +1,110 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "scope" : 6 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "fallback", + "modifiers" : + [ + null + ], + "name" : "", + "scope" : 5, + "stateMutability" : "payable", + "superFunction" : null, + "visibility" : "external" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "43:0:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 3, + "name" : "Block", + "src" : "43:5:1" + } + ], + "id" : 4, + "name" : "FunctionDefinition", + "src" : "15:33:1" + } + ], + "id" : 5, + "name" : "ContractDefinition", + "src" : "0:50:1" + } + ], + "id" : 6, + "name" : "SourceUnit", + "src" : "0:51:1" +} diff --git a/test/libsolidity/ASTJSON/fallback_payable.json b/test/libsolidity/ASTJSON/fallback_payable.json new file mode 100644 index 000000000..9d56f74bd --- /dev/null +++ b/test/libsolidity/ASTJSON/fallback_payable.json @@ -0,0 +1,70 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + }, + "id" : 6, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 5, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 3, + "nodeType" : "Block", + "src" : "34:2:1", + "statements" : [] + }, + "documentation" : null, + "id" : 4, + "implemented" : true, + "kind" : "fallback", + "modifiers" : [], + "name" : "", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "22:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "34:0:1" + }, + "scope" : 5, + "src" : "14:22:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "external" + } + ], + "scope" : 6, + "src" : "0:38:1" + } + ], + "src" : "0:39:1" +} diff --git a/test/libsolidity/ASTJSON/fallback_payable.sol b/test/libsolidity/ASTJSON/fallback_payable.sol new file mode 100644 index 000000000..21db99ecd --- /dev/null +++ b/test/libsolidity/ASTJSON/fallback_payable.sol @@ -0,0 +1,3 @@ +contract C { + function() external {} +} diff --git a/test/libsolidity/ASTJSON/fallback_payable_legacy.json b/test/libsolidity/ASTJSON/fallback_payable_legacy.json new file mode 100644 index 000000000..7320f574a --- /dev/null +++ b/test/libsolidity/ASTJSON/fallback_payable_legacy.json @@ -0,0 +1,110 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "scope" : 6 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "fallback", + "modifiers" : + [ + null + ], + "name" : "", + "scope" : 5, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "external" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "22:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "34:0:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 3, + "name" : "Block", + "src" : "34:2:1" + } + ], + "id" : 4, + "name" : "FunctionDefinition", + "src" : "14:22:1" + } + ], + "id" : 5, + "name" : "ContractDefinition", + "src" : "0:38:1" + } + ], + "id" : 6, + "name" : "SourceUnit", + "src" : "0:39:1" +} diff --git a/test/libsolidity/ASTJSON/function_type.json b/test/libsolidity/ASTJSON/function_type.json new file mode 100644 index 000000000..b78d84463 --- /dev/null +++ b/test/libsolidity/ASTJSON/function_type.json @@ -0,0 +1,224 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 17 + ] + }, + "id" : 18, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 17, + "linearizedBaseContracts" : + [ + 17 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 15, + "nodeType" : "Block", + "src" : "120:2:1", + "statements" : [] + }, + "documentation" : null, + "id" : 16, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 6, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 16, + "src" : "24:44:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_payable$__$returns$_t_uint256_$", + "typeString" : "function () payable external returns (uint256)" + }, + "typeName" : + { + "id" : 5, + "nodeType" : "FunctionTypeName", + "parameterTypes" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "32:2:1" + }, + "returnParameterTypes" : + { + "id" : 4, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 3, + "name" : "", + "nodeType" : "VariableDeclaration", + "scope" : 5, + "src" : "61:4:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 2, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "61:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "60:6:1" + }, + "src" : "24:44:1", + "stateMutability" : "payable", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_payable$__$returns$_t_uint256_$", + "typeString" : "function () payable external returns (uint256)" + }, + "visibility" : "external" + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "23:46:1" + }, + "returnParameters" : + { + "id" : 14, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 13, + "name" : "", + "nodeType" : "VariableDeclaration", + "scope" : 16, + "src" : "79:40:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_view$__$returns$_t_uint256_$", + "typeString" : "function () view external returns (uint256)" + }, + "typeName" : + { + "id" : 12, + "nodeType" : "FunctionTypeName", + "parameterTypes" : + { + "id" : 8, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "87:2:1" + }, + "returnParameterTypes" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 10, + "name" : "", + "nodeType" : "VariableDeclaration", + "scope" : 12, + "src" : "113:4:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 9, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "113:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "112:6:1" + }, + "src" : "79:40:1", + "stateMutability" : "view", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_view$__$returns$_t_uint256_$", + "typeString" : "function () view external returns (uint256)" + }, + "visibility" : "external" + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "78:41:1" + }, + "scope" : 17, + "src" : "13:109:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 18, + "src" : "0:124:1" + } + ], + "src" : "0:125:1" +} diff --git a/test/libsolidity/ASTJSON/function_type.sol b/test/libsolidity/ASTJSON/function_type.sol new file mode 100644 index 000000000..bed2742b2 --- /dev/null +++ b/test/libsolidity/ASTJSON/function_type.sol @@ -0,0 +1,3 @@ +contract C { function f(function() external payable returns (uint) x) returns (function() external view returns (uint)) {} } + +// ---- diff --git a/test/libsolidity/ASTJSON/function_type_legacy.json b/test/libsolidity/ASTJSON/function_type_legacy.json new file mode 100644 index 000000000..72ceec81e --- /dev/null +++ b/test/libsolidity/ASTJSON/function_type_legacy.json @@ -0,0 +1,266 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 17 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 17 + ], + "name" : "C", + "scope" : 18 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 17, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 16, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "function () payable external returns (uint256)", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "stateMutability" : "payable", + "type" : "function () payable external returns (uint256)", + "visibility" : "external" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "32:2:1" + }, + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "", + "scope" : 5, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 2, + "name" : "ElementaryTypeName", + "src" : "61:4:1" + } + ], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "61:4:1" + } + ], + "id" : 4, + "name" : "ParameterList", + "src" : "60:6:1" + } + ], + "id" : 5, + "name" : "FunctionTypeName", + "src" : "24:44:1" + } + ], + "id" : 6, + "name" : "VariableDeclaration", + "src" : "24:44:1" + } + ], + "id" : 7, + "name" : "ParameterList", + "src" : "23:46:1" + }, + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "", + "scope" : 16, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "function () view external returns (uint256)", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "stateMutability" : "view", + "type" : "function () view external returns (uint256)", + "visibility" : "external" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 8, + "name" : "ParameterList", + "src" : "87:2:1" + }, + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "", + "scope" : 12, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 9, + "name" : "ElementaryTypeName", + "src" : "113:4:1" + } + ], + "id" : 10, + "name" : "VariableDeclaration", + "src" : "113:4:1" + } + ], + "id" : 11, + "name" : "ParameterList", + "src" : "112:6:1" + } + ], + "id" : 12, + "name" : "FunctionTypeName", + "src" : "79:40:1" + } + ], + "id" : 13, + "name" : "VariableDeclaration", + "src" : "79:40:1" + } + ], + "id" : 14, + "name" : "ParameterList", + "src" : "78:41:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 15, + "name" : "Block", + "src" : "120:2:1" + } + ], + "id" : 16, + "name" : "FunctionDefinition", + "src" : "13:109:1" + } + ], + "id" : 17, + "name" : "ContractDefinition", + "src" : "0:124:1" + } + ], + "id" : 18, + "name" : "SourceUnit", + "src" : "0:125:1" +} diff --git a/test/libsolidity/ASTJSON/inheritance_specifier.json b/test/libsolidity/ASTJSON/inheritance_specifier.json new file mode 100644 index 000000000..edef86779 --- /dev/null +++ b/test/libsolidity/ASTJSON/inheritance_specifier.json @@ -0,0 +1,80 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C1" : + [ + 1 + ], + "C2" : + [ + 4 + ] + }, + "id" : 5, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C1", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 5, + "src" : "0:14:1" + }, + { + "baseContracts" : + [ + { + "arguments" : null, + "baseName" : + { + "contractScope" : null, + "id" : 2, + "name" : "C1", + "nodeType" : "UserDefinedTypeName", + "referencedDeclaration" : 1, + "src" : "30:2:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_contract$_C1_$1", + "typeString" : "contract C1" + } + }, + "id" : 3, + "nodeType" : "InheritanceSpecifier", + "src" : "30:2:1" + } + ], + "contractDependencies" : + [ + 1 + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 4, + "linearizedBaseContracts" : + [ + 4, + 1 + ], + "name" : "C2", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 5, + "src" : "15:20:1" + } + ], + "src" : "0:36:1" +} diff --git a/test/libsolidity/ASTJSON/inheritance_specifier.sol b/test/libsolidity/ASTJSON/inheritance_specifier.sol new file mode 100644 index 000000000..02dbf0c51 --- /dev/null +++ b/test/libsolidity/ASTJSON/inheritance_specifier.sol @@ -0,0 +1 @@ +contract C1 {} contract C2 is C1 {} diff --git a/test/libsolidity/ASTJSON/inheritance_specifier_legacy.json b/test/libsolidity/ASTJSON/inheritance_specifier_legacy.json new file mode 100644 index 000000000..0fcf29394 --- /dev/null +++ b/test/libsolidity/ASTJSON/inheritance_specifier_legacy.json @@ -0,0 +1,105 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C1" : + [ + 1 + ], + "C2" : + [ + 4 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C1", + "nodes" : + [ + null + ], + "scope" : 5 + }, + "id" : 1, + "name" : "ContractDefinition", + "src" : "0:14:1" + }, + { + "attributes" : + { + "contractDependencies" : + [ + 1 + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 4, + 1 + ], + "name" : "C2", + "nodes" : + [ + null + ], + "scope" : 5 + }, + "children" : + [ + { + "attributes" : + { + "arguments" : null + }, + "children" : + [ + { + "attributes" : + { + "contractScope" : null, + "name" : "C1", + "referencedDeclaration" : 1, + "type" : "contract C1" + }, + "id" : 2, + "name" : "UserDefinedTypeName", + "src" : "30:2:1" + } + ], + "id" : 3, + "name" : "InheritanceSpecifier", + "src" : "30:2:1" + } + ], + "id" : 4, + "name" : "ContractDefinition", + "src" : "15:20:1" + } + ], + "id" : 5, + "name" : "SourceUnit", + "src" : "0:36:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json new file mode 100644 index 000000000..c6d40af24 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json @@ -0,0 +1,175 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + }, + "id" : 12, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 11, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "33:19:1", + "statements" : + [ + { + "assignments" : + [ + 4 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 4, + "name" : "a", + "nodeType" : "VariableDeclaration", + "scope" : 9, + "src" : "35:6:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 3, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "35:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 8, + "initialValue" : + { + "argumentTypes" : null, + "commonType" : + { + "typeIdentifier" : "t_rational_5_by_1", + "typeString" : "int_const 5" + }, + "id" : 7, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "leftExpression" : + { + "argumentTypes" : null, + "hexValue" : "32", + "id" : 5, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "44:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_2_by_1", + "typeString" : "int_const 2" + }, + "value" : "2" + }, + "nodeType" : "BinaryOperation", + "operator" : "+", + "rightExpression" : + { + "argumentTypes" : null, + "hexValue" : "33", + "id" : 6, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "48:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_3_by_1", + "typeString" : "int_const 3" + }, + "value" : "3" + }, + "src" : "44:5:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_5_by_1", + "typeString" : "int_const 5" + } + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:14:1" + } + ] + }, + "documentation" : null, + "id" : 10, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 11, + "src" : "13:39:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 12, + "src" : "0:54:1" + } + ], + "src" : "0:55:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation.sol b/test/libsolidity/ASTJSON/long_type_name_binary_operation.sol new file mode 100644 index 000000000..f07029d7a --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation.sol @@ -0,0 +1 @@ +contract c { function f() public { uint a = 2 + 3; } } diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json new file mode 100644 index 000000000..b53332860 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json @@ -0,0 +1,208 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "scope" : 12 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 11, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 4 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "a", + "scope" : 9, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 3, + "name" : "ElementaryTypeName", + "src" : "35:4:1" + } + ], + "id" : 4, + "name" : "VariableDeclaration", + "src" : "35:6:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "commonType" : + { + "typeIdentifier" : "t_rational_5_by_1", + "typeString" : "int_const 5" + }, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "operator" : "+", + "type" : "int_const 5" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "32", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 2", + "value" : "2" + }, + "id" : 5, + "name" : "Literal", + "src" : "44:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "33", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 3", + "value" : "3" + }, + "id" : 6, + "name" : "Literal", + "src" : "48:1:1" + } + ], + "id" : 7, + "name" : "BinaryOperation", + "src" : "44:5:1" + } + ], + "id" : 8, + "name" : "VariableDeclarationStatement", + "src" : "35:14:1" + } + ], + "id" : 9, + "name" : "Block", + "src" : "33:19:1" + } + ], + "id" : 10, + "name" : "FunctionDefinition", + "src" : "13:39:1" + } + ], + "id" : 11, + "name" : "ContractDefinition", + "src" : "0:54:1" + } + ], + "id" : 12, + "name" : "SourceUnit", + "src" : "0:55:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier.json b/test/libsolidity/ASTJSON/long_type_name_identifier.json new file mode 100644 index 000000000..505d260c4 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_identifier.json @@ -0,0 +1,181 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 14 + ] + }, + "id" : 15, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 14, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "constant" : false, + "id" : 3, + "name" : "a", + "nodeType" : "VariableDeclaration", + "scope" : 14, + "src" : "13:8:1", + "stateVariable" : true, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "13:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 2, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "13:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + }, + { + "body" : + { + "id" : 12, + "nodeType" : "Block", + "src" : "43:25:1", + "statements" : + [ + { + "assignments" : + [ + 9 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 9, + "name" : "b", + "nodeType" : "VariableDeclaration", + "scope" : 12, + "src" : "45:16:1", + "stateVariable" : false, + "storageLocation" : "storage", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 7, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "45:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 8, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "45:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 11, + "initialValue" : + { + "argumentTypes" : null, + "id" : 10, + "name" : "a", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 3, + "src" : "64:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage", + "typeString" : "uint256[] storage ref" + } + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "45:20:1" + } + ] + }, + "documentation" : null, + "id" : 13, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 4, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:2:1" + }, + "returnParameters" : + { + "id" : 5, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "43:0:1" + }, + "scope" : 14, + "src" : "23:45:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 15, + "src" : "0:70:1" + } + ], + "src" : "0:71:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier.sol b/test/libsolidity/ASTJSON/long_type_name_identifier.sol new file mode 100644 index 000000000..f03f7a84d --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_identifier.sol @@ -0,0 +1 @@ +contract c { uint[] a; function f() public { uint[] storage b = a; } } diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json new file mode 100644 index 000000000..d3bcda561 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json @@ -0,0 +1,220 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 14 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "c", + "scope" : 15 + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "a", + "scope" : 14, + "stateVariable" : true, + "storageLocation" : "default", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "13:4:1" + } + ], + "id" : 2, + "name" : "ArrayTypeName", + "src" : "13:6:1" + } + ], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "13:8:1" + }, + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 14, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 4, + "name" : "ParameterList", + "src" : "33:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 5, + "name" : "ParameterList", + "src" : "43:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 9 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "b", + "scope" : 12, + "stateVariable" : false, + "storageLocation" : "storage", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 7, + "name" : "ElementaryTypeName", + "src" : "45:4:1" + } + ], + "id" : 8, + "name" : "ArrayTypeName", + "src" : "45:6:1" + } + ], + "id" : 9, + "name" : "VariableDeclaration", + "src" : "45:16:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 3, + "type" : "uint256[] storage ref", + "value" : "a" + }, + "id" : 10, + "name" : "Identifier", + "src" : "64:1:1" + } + ], + "id" : 11, + "name" : "VariableDeclarationStatement", + "src" : "45:20:1" + } + ], + "id" : 12, + "name" : "Block", + "src" : "43:25:1" + } + ], + "id" : 13, + "name" : "FunctionDefinition", + "src" : "23:45:1" + } + ], + "id" : 14, + "name" : "ContractDefinition", + "src" : "0:70:1" + } + ], + "id" : 15, + "name" : "SourceUnit", + "src" : "0:71:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_definition.json b/test/libsolidity/ASTJSON/modifier_definition.json new file mode 100644 index 000000000..66359453c --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_definition.json @@ -0,0 +1,174 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + }, + "id" : 15, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 14, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 5, + "nodeType" : "Block", + "src" : "32:6:1", + "statements" : + [ + { + "id" : 4, + "nodeType" : "PlaceholderStatement", + "src" : "34:1:1" + } + ] + }, + "documentation" : null, + "id" : 6, + "name" : "M", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 3, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 2, + "name" : "i", + "nodeType" : "VariableDeclaration", + "scope" : 6, + "src" : "24:6:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "24:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "23:8:1" + }, + "src" : "13:25:1", + "visibility" : "internal" + }, + { + "body" : + { + "id" : 12, + "nodeType" : "Block", + "src" : "64:2:1", + "statements" : [] + }, + "documentation" : null, + "id" : 13, + "implemented" : true, + "kind" : "function", + "modifiers" : + [ + { + "arguments" : + [ + { + "argumentTypes" : null, + "hexValue" : "31", + "id" : 9, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "54:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_1_by_1", + "typeString" : "int_const 1" + }, + "value" : "1" + } + ], + "id" : 10, + "modifierName" : + { + "argumentTypes" : null, + "id" : 8, + "name" : "M", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 6, + "src" : "52:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_modifier$_t_uint256_$", + "typeString" : "modifier (uint256)" + } + }, + "nodeType" : "ModifierInvocation", + "src" : "52:4:1" + } + ], + "name" : "F", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "49:2:1" + }, + "returnParameters" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "64:0:1" + }, + "scope" : 14, + "src" : "39:27:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 15, + "src" : "0:68:1" + } + ], + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_definition.sol b/test/libsolidity/ASTJSON/modifier_definition.sol new file mode 100644 index 000000000..96474e0f3 --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_definition.sol @@ -0,0 +1 @@ +contract C { modifier M(uint i) { _; } function F() M(1) public {} } diff --git a/test/libsolidity/ASTJSON/modifier_definition_legacy.json b/test/libsolidity/ASTJSON/modifier_definition_legacy.json new file mode 100644 index 000000000..5186912c8 --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_definition_legacy.json @@ -0,0 +1,212 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "scope" : 15 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "name" : "M", + "visibility" : "internal" + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "i", + "scope" : 6, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "24:4:1" + } + ], + "id" : 2, + "name" : "VariableDeclaration", + "src" : "24:6:1" + } + ], + "id" : 3, + "name" : "ParameterList", + "src" : "23:8:1" + }, + { + "children" : + [ + { + "id" : 4, + "name" : "PlaceholderStatement", + "src" : "34:1:1" + } + ], + "id" : 5, + "name" : "Block", + "src" : "32:6:1" + } + ], + "id" : 6, + "name" : "ModifierDefinition", + "src" : "13:25:1" + }, + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "name" : "F", + "scope" : 14, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 7, + "name" : "ParameterList", + "src" : "49:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 11, + "name" : "ParameterList", + "src" : "64:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 6, + "type" : "modifier (uint256)", + "value" : "M" + }, + "id" : 8, + "name" : "Identifier", + "src" : "52:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "31", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 1", + "value" : "1" + }, + "id" : 9, + "name" : "Literal", + "src" : "54:1:1" + } + ], + "id" : 10, + "name" : "ModifierInvocation", + "src" : "52:4:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 12, + "name" : "Block", + "src" : "64:2:1" + } + ], + "id" : 13, + "name" : "FunctionDefinition", + "src" : "39:27:1" + } + ], + "id" : 14, + "name" : "ContractDefinition", + "src" : "0:68:1" + } + ], + "id" : 15, + "name" : "SourceUnit", + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_invocation.json b/test/libsolidity/ASTJSON/modifier_invocation.json new file mode 100644 index 000000000..66359453c --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_invocation.json @@ -0,0 +1,174 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + }, + "id" : 15, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 14, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 5, + "nodeType" : "Block", + "src" : "32:6:1", + "statements" : + [ + { + "id" : 4, + "nodeType" : "PlaceholderStatement", + "src" : "34:1:1" + } + ] + }, + "documentation" : null, + "id" : 6, + "name" : "M", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 3, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 2, + "name" : "i", + "nodeType" : "VariableDeclaration", + "scope" : 6, + "src" : "24:6:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "24:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "23:8:1" + }, + "src" : "13:25:1", + "visibility" : "internal" + }, + { + "body" : + { + "id" : 12, + "nodeType" : "Block", + "src" : "64:2:1", + "statements" : [] + }, + "documentation" : null, + "id" : 13, + "implemented" : true, + "kind" : "function", + "modifiers" : + [ + { + "arguments" : + [ + { + "argumentTypes" : null, + "hexValue" : "31", + "id" : 9, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "54:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_1_by_1", + "typeString" : "int_const 1" + }, + "value" : "1" + } + ], + "id" : 10, + "modifierName" : + { + "argumentTypes" : null, + "id" : 8, + "name" : "M", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 6, + "src" : "52:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_modifier$_t_uint256_$", + "typeString" : "modifier (uint256)" + } + }, + "nodeType" : "ModifierInvocation", + "src" : "52:4:1" + } + ], + "name" : "F", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "49:2:1" + }, + "returnParameters" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "64:0:1" + }, + "scope" : 14, + "src" : "39:27:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 15, + "src" : "0:68:1" + } + ], + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_invocation.sol b/test/libsolidity/ASTJSON/modifier_invocation.sol new file mode 100644 index 000000000..96474e0f3 --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_invocation.sol @@ -0,0 +1 @@ +contract C { modifier M(uint i) { _; } function F() M(1) public {} } diff --git a/test/libsolidity/ASTJSON/modifier_invocation_legacy.json b/test/libsolidity/ASTJSON/modifier_invocation_legacy.json new file mode 100644 index 000000000..5186912c8 --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_invocation_legacy.json @@ -0,0 +1,212 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "scope" : 15 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "name" : "M", + "visibility" : "internal" + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "i", + "scope" : 6, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "24:4:1" + } + ], + "id" : 2, + "name" : "VariableDeclaration", + "src" : "24:6:1" + } + ], + "id" : 3, + "name" : "ParameterList", + "src" : "23:8:1" + }, + { + "children" : + [ + { + "id" : 4, + "name" : "PlaceholderStatement", + "src" : "34:1:1" + } + ], + "id" : 5, + "name" : "Block", + "src" : "32:6:1" + } + ], + "id" : 6, + "name" : "ModifierDefinition", + "src" : "13:25:1" + }, + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "name" : "F", + "scope" : 14, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 7, + "name" : "ParameterList", + "src" : "49:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 11, + "name" : "ParameterList", + "src" : "64:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 6, + "type" : "modifier (uint256)", + "value" : "M" + }, + "id" : 8, + "name" : "Identifier", + "src" : "52:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "31", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 1", + "value" : "1" + }, + "id" : 9, + "name" : "Literal", + "src" : "54:1:1" + } + ], + "id" : 10, + "name" : "ModifierInvocation", + "src" : "52:4:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 12, + "name" : "Block", + "src" : "64:2:1" + } + ], + "id" : 13, + "name" : "FunctionDefinition", + "src" : "39:27:1" + } + ], + "id" : 14, + "name" : "ContractDefinition", + "src" : "0:68:1" + } + ], + "id" : 15, + "name" : "SourceUnit", + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/non_utf8.json b/test/libsolidity/ASTJSON/non_utf8.json new file mode 100644 index 000000000..1852bd38f --- /dev/null +++ b/test/libsolidity/ASTJSON/non_utf8.json @@ -0,0 +1,122 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 8 + ] + }, + "id" : 9, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 8, + "linearizedBaseContracts" : + [ + 8 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 6, + "nodeType" : "Block", + "src" : "33:20:1", + "statements" : + [ + { + "assignments" : + [ + 3 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 3, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 6, + "src" : "35:5:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_string_memory_ptr", + "typeString" : "string" + }, + "typeName" : null, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 5, + "initialValue" : + { + "argumentTypes" : null, + "hexValue" : "ff", + "id" : 4, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "string", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "43:7:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_stringliteral_8b1a944cf13a9a1c08facb2c9e98623ef3254d2ddb48113885c3e8e97fec8db9", + "typeString" : "literal_string (contains invalid UTF-8 sequence at position 0)" + }, + "value" : null + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ] + }, + "documentation" : null, + "id" : 7, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 8, + "src" : "13:40:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 9, + "src" : "0:55:1" + } + ], + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/non_utf8.sol b/test/libsolidity/ASTJSON/non_utf8.sol new file mode 100644 index 000000000..b83f3d706 --- /dev/null +++ b/test/libsolidity/ASTJSON/non_utf8.sol @@ -0,0 +1 @@ +contract C { function f() public { var x = hex"ff"; } } diff --git a/test/libsolidity/ASTJSON/non_utf8_legacy.json b/test/libsolidity/ASTJSON/non_utf8_legacy.json new file mode 100644 index 000000000..df1050966 --- /dev/null +++ b/test/libsolidity/ASTJSON/non_utf8_legacy.json @@ -0,0 +1,156 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 8 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 8 + ], + "name" : "C", + "scope" : 9 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 8, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 3 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 6, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "string", + "typeName" : null, + "value" : null, + "visibility" : "internal" + }, + "children" : [], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "35:5:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "ff", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "string", + "type" : "literal_string (contains invalid UTF-8 sequence at position 0)", + "value" : null + }, + "id" : 4, + "name" : "Literal", + "src" : "43:7:1" + } + ], + "id" : 5, + "name" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ], + "id" : 6, + "name" : "Block", + "src" : "33:20:1" + } + ], + "id" : 7, + "name" : "FunctionDefinition", + "src" : "13:40:1" + } + ], + "id" : 8, + "name" : "ContractDefinition", + "src" : "0:55:1" + } + ], + "id" : 9, + "name" : "SourceUnit", + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/placeholder_statement.json b/test/libsolidity/ASTJSON/placeholder_statement.json new file mode 100644 index 000000000..496e15001 --- /dev/null +++ b/test/libsolidity/ASTJSON/placeholder_statement.json @@ -0,0 +1,64 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + }, + "id" : 6, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 5, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 3, + "nodeType" : "Block", + "src" : "24:6:1", + "statements" : + [ + { + "id" : 2, + "nodeType" : "PlaceholderStatement", + "src" : "26:1:1" + } + ] + }, + "documentation" : null, + "id" : 4, + "name" : "M", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "24:0:1" + }, + "src" : "13:17:1", + "visibility" : "internal" + } + ], + "scope" : 6, + "src" : "0:32:1" + } + ], + "src" : "0:33:1" +} diff --git a/test/libsolidity/ASTJSON/placeholder_statement.sol b/test/libsolidity/ASTJSON/placeholder_statement.sol new file mode 100644 index 000000000..cb2c0990d --- /dev/null +++ b/test/libsolidity/ASTJSON/placeholder_statement.sol @@ -0,0 +1 @@ +contract C { modifier M { _; } } diff --git a/test/libsolidity/ASTJSON/placeholder_statement_legacy.json b/test/libsolidity/ASTJSON/placeholder_statement_legacy.json new file mode 100644 index 000000000..a55829762 --- /dev/null +++ b/test/libsolidity/ASTJSON/placeholder_statement_legacy.json @@ -0,0 +1,87 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "scope" : 6 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "name" : "M", + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "24:0:1" + }, + { + "children" : + [ + { + "id" : 2, + "name" : "PlaceholderStatement", + "src" : "26:1:1" + } + ], + "id" : 3, + "name" : "Block", + "src" : "24:6:1" + } + ], + "id" : 4, + "name" : "ModifierDefinition", + "src" : "13:17:1" + } + ], + "id" : 5, + "name" : "ContractDefinition", + "src" : "0:32:1" + } + ], + "id" : 6, + "name" : "SourceUnit", + "src" : "0:33:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name.json b/test/libsolidity/ASTJSON/short_type_name.json new file mode 100644 index 000000000..acb461571 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name.json @@ -0,0 +1,126 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 10 + ] + }, + "id" : 11, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 10, + "linearizedBaseContracts" : + [ + 10 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 8, + "nodeType" : "Block", + "src" : "33:20:1", + "statements" : + [ + { + "assignments" : + [ + 6 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 6, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 8, + "src" : "35:15:1", + "stateVariable" : false, + "storageLocation" : "memory", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_memory_ptr", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 4, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "35:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 5, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "35:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 7, + "initialValue" : null, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ] + }, + "documentation" : null, + "id" : 9, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 10, + "src" : "13:40:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 11, + "src" : "0:55:1" + } + ], + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name.sol b/test/libsolidity/ASTJSON/short_type_name.sol new file mode 100644 index 000000000..533874ae4 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name.sol @@ -0,0 +1 @@ +contract c { function f() public { uint[] memory x; } } diff --git a/test/libsolidity/ASTJSON/short_type_name_legacy.json b/test/libsolidity/ASTJSON/short_type_name_legacy.json new file mode 100644 index 000000000..1f9b19687 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_legacy.json @@ -0,0 +1,163 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 10 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 10 + ], + "name" : "c", + "scope" : 11 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 10, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 6 + ], + "initialValue" : null + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 8, + "stateVariable" : false, + "storageLocation" : "memory", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 4, + "name" : "ElementaryTypeName", + "src" : "35:4:1" + } + ], + "id" : 5, + "name" : "ArrayTypeName", + "src" : "35:6:1" + } + ], + "id" : 6, + "name" : "VariableDeclaration", + "src" : "35:15:1" + } + ], + "id" : 7, + "name" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ], + "id" : 8, + "name" : "Block", + "src" : "33:20:1" + } + ], + "id" : 9, + "name" : "FunctionDefinition", + "src" : "13:40:1" + } + ], + "id" : 10, + "name" : "ContractDefinition", + "src" : "0:55:1" + } + ], + "id" : 11, + "name" : "SourceUnit", + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name_ref.json b/test/libsolidity/ASTJSON/short_type_name_ref.json new file mode 100644 index 000000000..b6b7bca5d --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_ref.json @@ -0,0 +1,138 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + }, + "id" : 12, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 11, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "33:25:1", + "statements" : + [ + { + "assignments" : + [ + 7 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 7, + "name" : "rows", + "nodeType" : "VariableDeclaration", + "scope" : 9, + "src" : "35:20:1", + "stateVariable" : false, + "storageLocation" : "memory", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_array$_t_uint256_$dyn_memory_$dyn_memory_ptr", + "typeString" : "uint256[][]" + }, + "typeName" : + { + "baseType" : + { + "baseType" : + { + "id" : 4, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "35:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 5, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "35:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "id" : 6, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "35:8:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_array$_t_uint256_$dyn_storage_$dyn_storage_ptr", + "typeString" : "uint256[][]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 8, + "initialValue" : null, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:20:1" + } + ] + }, + "documentation" : null, + "id" : 10, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 11, + "src" : "13:45:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 12, + "src" : "0:60:1" + } + ], + "src" : "0:61:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name_ref.sol b/test/libsolidity/ASTJSON/short_type_name_ref.sol new file mode 100644 index 000000000..a808b982b --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_ref.sol @@ -0,0 +1 @@ +contract c { function f() public { uint[][] memory rows; } } diff --git a/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json new file mode 100644 index 000000000..420b0f609 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json @@ -0,0 +1,176 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "scope" : 12 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 11, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 7 + ], + "initialValue" : null + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "rows", + "scope" : 9, + "stateVariable" : false, + "storageLocation" : "memory", + "type" : "uint256[][]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[][]" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 4, + "name" : "ElementaryTypeName", + "src" : "35:4:1" + } + ], + "id" : 5, + "name" : "ArrayTypeName", + "src" : "35:6:1" + } + ], + "id" : 6, + "name" : "ArrayTypeName", + "src" : "35:8:1" + } + ], + "id" : 7, + "name" : "VariableDeclaration", + "src" : "35:20:1" + } + ], + "id" : 8, + "name" : "VariableDeclarationStatement", + "src" : "35:20:1" + } + ], + "id" : 9, + "name" : "Block", + "src" : "33:25:1" + } + ], + "id" : 10, + "name" : "FunctionDefinition", + "src" : "13:45:1" + } + ], + "id" : 11, + "name" : "ContractDefinition", + "src" : "0:60:1" + } + ], + "id" : 12, + "name" : "SourceUnit", + "src" : "0:61:1" +} diff --git a/test/libsolidity/ASTJSON/smoke.json b/test/libsolidity/ASTJSON/smoke.json new file mode 100644 index 000000000..f5369bfc8 --- /dev/null +++ b/test/libsolidity/ASTJSON/smoke.json @@ -0,0 +1,33 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 1 + ] + }, + "id" : 2, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 2, + "src" : "0:13:1" + } + ], + "src" : "0:14:1" +} diff --git a/test/libsolidity/ASTJSON/smoke.sol b/test/libsolidity/ASTJSON/smoke.sol new file mode 100644 index 000000000..2dde0d209 --- /dev/null +++ b/test/libsolidity/ASTJSON/smoke.sol @@ -0,0 +1 @@ +contract C {} diff --git a/test/libsolidity/ASTJSON/smoke_legacy.json b/test/libsolidity/ASTJSON/smoke_legacy.json new file mode 100644 index 000000000..e01a3c9b2 --- /dev/null +++ b/test/libsolidity/ASTJSON/smoke_legacy.json @@ -0,0 +1,48 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 1 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C", + "nodes" : + [ + null + ], + "scope" : 2 + }, + "id" : 1, + "name" : "ContractDefinition", + "src" : "0:13:1" + } + ], + "id" : 2, + "name" : "SourceUnit", + "src" : "0:14:1" +} diff --git a/test/libsolidity/ASTJSON/source_location.json b/test/libsolidity/ASTJSON/source_location.json new file mode 100644 index 000000000..f0ed216db --- /dev/null +++ b/test/libsolidity/ASTJSON/source_location.json @@ -0,0 +1,160 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 11 + ] + }, + "id" : 12, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 11, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "26:19:1", + "statements" : + [ + { + "assignments" : + [ + 3 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 3, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 9, + "src" : "28:5:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint8", + "typeString" : "uint8" + }, + "typeName" : null, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 5, + "initialValue" : + { + "argumentTypes" : null, + "hexValue" : "32", + "id" : 4, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "36:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_2_by_1", + "typeString" : "int_const 2" + }, + "value" : "2" + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "28:9:1" + }, + { + "expression" : + { + "argumentTypes" : null, + "id" : 7, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "nodeType" : "UnaryOperation", + "operator" : "++", + "prefix" : false, + "src" : "39:3:1", + "subExpression" : + { + "argumentTypes" : null, + "id" : 6, + "name" : "x", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 3, + "src" : "39:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint8", + "typeString" : "uint8" + } + }, + "typeDescriptions" : + { + "typeIdentifier" : "t_uint8", + "typeString" : "uint8" + } + }, + "id" : 8, + "nodeType" : "ExpressionStatement", + "src" : "39:3:1" + } + ] + }, + "documentation" : null, + "id" : 10, + "implemented" : true, + "kind" : "function", + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "26:0:1" + }, + "scope" : 11, + "src" : "13:32:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 12, + "src" : "0:47:1" + } + ], + "src" : "0:48:1" +} diff --git a/test/libsolidity/ASTJSON/source_location.sol b/test/libsolidity/ASTJSON/source_location.sol new file mode 100644 index 000000000..1fcec2e66 --- /dev/null +++ b/test/libsolidity/ASTJSON/source_location.sol @@ -0,0 +1 @@ +contract C { function f() { var x = 2; x++; } } diff --git a/test/libsolidity/ASTJSON/source_location_legacy.json b/test/libsolidity/ASTJSON/source_location_legacy.json new file mode 100644 index 000000000..a65979d66 --- /dev/null +++ b/test/libsolidity/ASTJSON/source_location_legacy.json @@ -0,0 +1,199 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 11 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "C", + "scope" : 12 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "kind" : "function", + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 11, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "26:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 3 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 9, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint8", + "typeName" : null, + "value" : null, + "visibility" : "internal" + }, + "children" : [], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "28:5:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "32", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 2", + "value" : "2" + }, + "id" : 4, + "name" : "Literal", + "src" : "36:1:1" + } + ], + "id" : 5, + "name" : "VariableDeclarationStatement", + "src" : "28:9:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "operator" : "++", + "prefix" : false, + "type" : "uint8" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 3, + "type" : "uint8", + "value" : "x" + }, + "id" : 6, + "name" : "Identifier", + "src" : "39:1:1" + } + ], + "id" : 7, + "name" : "UnaryOperation", + "src" : "39:3:1" + } + ], + "id" : 8, + "name" : "ExpressionStatement", + "src" : "39:3:1" + } + ], + "id" : 9, + "name" : "Block", + "src" : "26:19:1" + } + ], + "id" : 10, + "name" : "FunctionDefinition", + "src" : "13:32:1" + } + ], + "id" : 11, + "name" : "ContractDefinition", + "src" : "0:47:1" + } + ], + "id" : 12, + "name" : "SourceUnit", + "src" : "0:48:1" +} diff --git a/test/libsolidity/ASTJSON/using_for_directive.json b/test/libsolidity/ASTJSON/using_for_directive.json new file mode 100644 index 000000000..33caabb47 --- /dev/null +++ b/test/libsolidity/ASTJSON/using_for_directive.json @@ -0,0 +1,87 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ], + "L" : + [ + 1 + ] + }, + "id" : 6, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "library", + "documentation" : null, + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "L", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 6, + "src" : "0:12:1" + }, + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 5, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "id" : 4, + "libraryName" : + { + "contractScope" : null, + "id" : 2, + "name" : "L", + "nodeType" : "UserDefinedTypeName", + "referencedDeclaration" : 1, + "src" : "32:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_contract$_L_$1", + "typeString" : "library L" + } + }, + "nodeType" : "UsingForDirective", + "src" : "26:17:1", + "typeName" : + { + "id" : 3, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "38:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + } + } + ], + "scope" : 6, + "src" : "13:32:1" + } + ], + "src" : "0:46:1" +} diff --git a/test/libsolidity/ASTJSON/using_for_directive.sol b/test/libsolidity/ASTJSON/using_for_directive.sol new file mode 100644 index 000000000..a882ad887 --- /dev/null +++ b/test/libsolidity/ASTJSON/using_for_directive.sol @@ -0,0 +1 @@ +library L {} contract C { using L for uint; } diff --git a/test/libsolidity/ASTJSON/using_for_directive_legacy.json b/test/libsolidity/ASTJSON/using_for_directive_legacy.json new file mode 100644 index 000000000..0827ef90f --- /dev/null +++ b/test/libsolidity/ASTJSON/using_for_directive_legacy.json @@ -0,0 +1,110 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ], + "L" : + [ + 1 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "library", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "L", + "nodes" : + [ + null + ], + "scope" : 6 + }, + "id" : 1, + "name" : "ContractDefinition", + "src" : "0:12:1" + }, + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "scope" : 6 + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "contractScope" : null, + "name" : "L", + "referencedDeclaration" : 1, + "type" : "library L" + }, + "id" : 2, + "name" : "UserDefinedTypeName", + "src" : "32:1:1" + }, + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 3, + "name" : "ElementaryTypeName", + "src" : "38:4:1" + } + ], + "id" : 4, + "name" : "UsingForDirective", + "src" : "26:17:1" + } + ], + "id" : 5, + "name" : "ContractDefinition", + "src" : "13:32:1" + } + ], + "id" : 6, + "name" : "SourceUnit", + "src" : "0:46:1" +} diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp new file mode 100644 index 000000000..be482d998 --- /dev/null +++ b/test/libsolidity/ASTJSONTest.cpp @@ -0,0 +1,200 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace dev; +using namespace solidity; +using namespace dev::solidity::test; +using namespace dev::solidity::test::formatting; +using namespace std; +namespace fs = boost::filesystem; +using namespace boost::unit_test; + +ASTJSONTest::ASTJSONTest(string const& _filename) +{ + if (!boost::algorithm::ends_with(_filename, ".sol")) + BOOST_THROW_EXCEPTION(runtime_error("Invalid test contract file name: \"" + _filename + "\".")); + + m_astFilename = _filename.substr(0, _filename.size() - 4) + ".json"; + m_legacyAstFilename = _filename.substr(0, _filename.size() - 4) + "_legacy.json"; + + ifstream file(_filename); + if (!file) + BOOST_THROW_EXCEPTION(runtime_error("Cannot open test contract: \"" + _filename + "\".")); + file.exceptions(ios::badbit); + + string sourceName; + string source; + string line; + string const sourceDelimiter("// ---- SOURCE: "); + string const delimiter("// ----"); + while (getline(file, line)) + { + if (boost::algorithm::starts_with(line, sourceDelimiter)) + { + if (!sourceName.empty()) + m_sources.emplace_back(sourceName, source); + + sourceName = line.substr(sourceDelimiter.size(), string::npos); + source = string(); + } + else if (!line.empty() && !boost::algorithm::starts_with(line, delimiter)) + source += line + "\n"; + } + + m_sources.emplace_back(sourceName.empty() ? "a" : sourceName, source); + + file.close(); + file.open(m_astFilename); + if (file) + { + string line; + while (getline(file, line)) + m_expectation += line + "\n"; + } + + file.close(); + file.open(m_legacyAstFilename); + if (file) + { + string line; + while (getline(file, line)) + m_expectationLegacy += line + "\n"; + } +} + +bool ASTJSONTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + CompilerStack c; + + map sourceIndices; + for (size_t i = 0; i < m_sources.size(); i++) + { + c.addSource(m_sources[i].first, m_sources[i].second); + sourceIndices[m_sources[i].first] = i + 1; + } + + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + + for (size_t i = 0; i < m_sources.size(); i++) + { + ostringstream result; + ASTJsonConverter(false, sourceIndices).print(result, c.ast(m_sources[i].first)); + m_result += result.str(); + if (i != m_sources.size() - 1) + m_result += ","; + m_result += "\n"; + } + + bool resultsMatch = true; + + if (m_expectation != m_result) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; + { + istringstream stream(m_expectation); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl; + { + istringstream stream(m_result); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + resultsMatch = false; + } + + for (size_t i = 0; i < m_sources.size(); i++) + { + ostringstream result; + ASTJsonConverter(true, sourceIndices).print(result, c.ast(m_sources[i].first)); + m_resultLegacy = result.str(); + if (i != m_sources.size() - 1) + m_resultLegacy += ","; + m_resultLegacy += "\n"; + } + + if (m_expectationLegacy != m_resultLegacy) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result (legacy):" << endl; + { + istringstream stream(m_expectationLegacy); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result (legacy):" << endl; + { + istringstream stream(m_resultLegacy); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + resultsMatch = false; + } + + return resultsMatch; +} + +void ASTJSONTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const +{ + for (auto const& source: m_sources) + { + if (m_sources.size() > 1 || source.first != "a") + _stream << _linePrefix << "// ---- SOURCE: " << source.first << endl << endl; + stringstream stream(source.second); + string line; + while (getline(stream, line)) + _stream << _linePrefix << line << endl; + _stream << endl; + } +} + +void ASTJSONTest::printUpdatedExpectations(std::ostream&, std::string const&) const +{ + ofstream file(m_astFilename.c_str()); + if (!file) BOOST_THROW_EXCEPTION(runtime_error("Cannot write AST expectation to \"" + m_astFilename + "\".")); + file.exceptions(ios::badbit); + file << m_result; + file.flush(); + file.close(); + file.open(m_legacyAstFilename.c_str()); + if (!file) BOOST_THROW_EXCEPTION(runtime_error("Cannot write legacy AST expectation to \"" + m_legacyAstFilename + "\".")); + file << m_resultLegacy; + file.flush(); + file.close(); +} diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h new file mode 100644 index 000000000..6f24bb60d --- /dev/null +++ b/test/libsolidity/ASTJSONTest.h @@ -0,0 +1,58 @@ +/* + 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 +#include + +#include +#include +#include +#include + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class ASTJSONTest: public TestCase +{ +public: + static std::unique_ptr create(std::string const& _filename) + { return std::unique_ptr(new ASTJSONTest(_filename)); } + ASTJSONTest(std::string const& _filename); + + virtual bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + + virtual void printSource(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) const override; + virtual void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; +private: + std::vector> m_sources; + std::string m_expectation; + std::string m_expectationLegacy; + std::string m_astFilename; + std::string m_legacyAstFilename; + std::string m_result; + std::string m_resultLegacy; +}; + +} +} +} diff --git a/test/libsolidity/ASTLegacyJSON.cpp b/test/libsolidity/ASTLegacyJSON.cpp deleted file mode 100644 index 13148682c..000000000 --- a/test/libsolidity/ASTLegacyJSON.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2016 - * Tests for the json ast output. - */ - -#include - -#include -#include -#include - -#include - -#include - -using namespace std; - -namespace dev -{ -namespace solidity -{ -namespace test -{ - -BOOST_AUTO_TEST_SUITE(SolidityASTLegacyJSON) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CompilerStack c; - c.addSource("a", "contract C {}"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); -} - -BOOST_AUTO_TEST_CASE(source_location) -{ - CompilerStack c; - c.addSource("a", "contract C { function f() { var x = 2; x++; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); - BOOST_CHECK_EQUAL(astJson["children"][0]["name"], "ContractDefinition"); - BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["name"], "FunctionDefinition"); - BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["src"], "13:32:1"); - -} - -BOOST_AUTO_TEST_CASE(inheritance_specifier) -{ - CompilerStack c; - c.addSource("a", "contract C1 {} contract C2 is C1 {}"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["children"][1]["attributes"]["name"], "C2"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["name"], "InheritanceSpecifier"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["src"], "30:2:1"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["name"], "UserDefinedTypeName"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["attributes"]["name"], "C1"); -} - -BOOST_AUTO_TEST_CASE(using_for_directive) -{ - CompilerStack c; - c.addSource("a", "library L {} contract C { using L for uint; }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value usingFor = astJson["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(usingFor["name"], "UsingForDirective"); - BOOST_CHECK_EQUAL(usingFor["src"], "26:17:1"); - BOOST_CHECK_EQUAL(usingFor["children"][0]["name"], "UserDefinedTypeName"); - BOOST_CHECK_EQUAL(usingFor["children"][0]["attributes"]["name"], "L"); - BOOST_CHECK_EQUAL(usingFor["children"][1]["name"], "ElementaryTypeName"); - BOOST_CHECK_EQUAL(usingFor["children"][1]["attributes"]["name"], "uint"); -} - -BOOST_AUTO_TEST_CASE(enum_value) -{ - CompilerStack c; - c.addSource("a", "contract C { enum E { A, B } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value enumDefinition = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["name"], "EnumValue"); - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["attributes"]["name"], "A"); - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["src"], "22:1:1"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["name"], "EnumValue"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["attributes"]["name"], "B"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["src"], "25:1:1"); -} - -BOOST_AUTO_TEST_CASE(modifier_definition) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value modifier = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(modifier["name"], "ModifierDefinition"); - BOOST_CHECK_EQUAL(modifier["attributes"]["name"], "M"); - BOOST_CHECK_EQUAL(modifier["src"], "13:25:1"); -} - -BOOST_AUTO_TEST_CASE(modifier_invocation) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value modifier = astJson["children"][0]["children"][1]["children"][2]; - BOOST_CHECK_EQUAL(modifier["name"], "ModifierInvocation"); - BOOST_CHECK_EQUAL(modifier["src"], "52:4:1"); - BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["type"], "modifier (uint256)"); - BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["value"], "M"); - BOOST_CHECK_EQUAL(modifier["children"][1]["attributes"]["value"], "1"); -} - -BOOST_AUTO_TEST_CASE(event_definition) -{ - CompilerStack c; - c.addSource("a", "contract C { event E(); }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value event = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(event["name"], "EventDefinition"); - BOOST_CHECK_EQUAL(event["attributes"]["name"], "E"); - BOOST_CHECK_EQUAL(event["src"], "13:10:1"); -} - -BOOST_AUTO_TEST_CASE(array_type_name) -{ - CompilerStack c; - c.addSource("a", "contract C { uint[] i; }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value arrayDecl = astJson["children"][0]["children"][0]["attributes"]; - BOOST_CHECK_EQUAL(arrayDecl["storageLocation"], "default"); - BOOST_CHECK_EQUAL(arrayDecl["type"], "uint256[]"); - Json::Value array = astJson["children"][0]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(array["name"], "ArrayTypeName"); - BOOST_CHECK_EQUAL(array["src"], "13:6:1"); -} - -BOOST_AUTO_TEST_CASE(short_type_name) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() { uint[] memory x; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value arrayDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["type"], "uint256[]"); -} - -BOOST_AUTO_TEST_CASE(short_type_name_ref) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() { uint[][] memory rows; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value arrayDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["type"], "uint256[][]"); -} - -BOOST_AUTO_TEST_CASE(placeholder_statement) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M { _; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value placeholder = astJson["children"][0]["children"][0]["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(placeholder["name"], "PlaceholderStatement"); - BOOST_CHECK_EQUAL(placeholder["src"], "26:1:1"); -} - -BOOST_AUTO_TEST_CASE(non_utf8) -{ - CompilerStack c; - c.addSource("a", "contract C { function f() { var x = hex\"ff\"; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(varDecl["attributes"]["type"], "string"); - BOOST_CHECK_EQUAL(varDecl["attributes"]["typeName"], Json::nullValue); - Json::Value literal = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][1]; - BOOST_CHECK_EQUAL(literal["name"], "Literal"); - BOOST_CHECK_EQUAL(literal["attributes"]["hexvalue"], "ff"); - BOOST_CHECK_EQUAL(literal["attributes"]["token"], "string"); - BOOST_CHECK_EQUAL(literal["attributes"]["value"], Json::nullValue); - BOOST_CHECK(literal["attributes"]["type"].asString().find("invalid") != string::npos); -} - -BOOST_AUTO_TEST_CASE(function_type) -{ - CompilerStack c; - c.addSource("a", - "contract C { function f(function() external payable returns (uint) x) " - "returns (function() external constant returns (uint)) {} }" - ); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value fun = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(fun["name"], "FunctionDefinition"); - Json::Value argument = fun["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(argument["name"], "VariableDeclaration"); - BOOST_CHECK_EQUAL(argument["attributes"]["name"], "x"); - BOOST_CHECK_EQUAL(argument["attributes"]["type"], "function () payable external returns (uint256)"); - Json::Value funType = argument["children"][0]; - BOOST_CHECK_EQUAL(funType["attributes"]["constant"], false); - BOOST_CHECK_EQUAL(funType["attributes"]["payable"], true); - BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); - Json::Value retval = fun["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(retval["name"], "VariableDeclaration"); - BOOST_CHECK_EQUAL(retval["attributes"]["name"], ""); - BOOST_CHECK_EQUAL(retval["attributes"]["type"], "function () view external returns (uint256)"); - funType = retval["children"][0]; - BOOST_CHECK_EQUAL(funType["attributes"]["constant"], true); - BOOST_CHECK_EQUAL(funType["attributes"]["payable"], false); - BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); -} - -BOOST_AUTO_TEST_CASE(documentation) -{ - CompilerStack c; - c.addSource("a", "/**This contract is empty*/ contract C {}"); - c.addSource("b", - "/**This contract is empty" - " and has a line-breaking comment.*/" - "contract C {}" - ); - c.addSource("c", - "contract C {" - " /** Some comment on Evt.*/ event Evt();" - " /** Some comment on mod.*/ modifier mod() { _; }" - " /** Some comment on fn.*/ function fn() public {}" - "}" - ); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map sourceIndices; - sourceIndices["a"] = 0; - sourceIndices["b"] = 1; - sourceIndices["c"] = 2; - Json::Value astJsonA = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value documentationA = astJsonA["children"][0]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationA, "This contract is empty"); - Json::Value astJsonB = ASTJsonConverter(true, sourceIndices).toJson(c.ast("b")); - Json::Value documentationB = astJsonB["children"][0]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment."); - Json::Value astJsonC = ASTJsonConverter(true, sourceIndices).toJson(c.ast("c")); - Json::Value documentationC0 = astJsonC["children"][0]["children"][0]["attributes"]["documentation"]; - Json::Value documentationC1 = astJsonC["children"][0]["children"][1]["attributes"]["documentation"]; - Json::Value documentationC2 = astJsonC["children"][0]["children"][2]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt."); - BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod."); - BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn."); -} - - -BOOST_AUTO_TEST_SUITE_END() - -} -} -} // end namespaces diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 72b867673..ec98026cc 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -29,7 +29,7 @@ #include -#include +#include #include diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 7b3df043f..e815d7d59 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(location_test) { char const* sourceCode = R"( contract test { - function f() returns (uint256 a) { + function f() public returns (uint256 a) { return 16; } } @@ -160,19 +160,19 @@ BOOST_AUTO_TEST_CASE(location_test) AssemblyItems items = compileContract(sourceCode); bool hasShifts = dev::test::Options::get().evmVersion().hasBitwiseShifting(); vector locations = - vector(hasShifts ? 23 : 24, SourceLocation(2, 75, make_shared(""))) + - vector(2, SourceLocation(20, 72, make_shared(""))) + + vector(hasShifts ? 23 : 24, SourceLocation(2, 82, make_shared(""))) + + vector(2, SourceLocation(20, 79, make_shared(""))) + vector(1, SourceLocation(8, 17, make_shared("--CODEGEN--"))) + vector(3, SourceLocation(5, 7, make_shared("--CODEGEN--"))) + vector(1, SourceLocation(30, 31, make_shared("--CODEGEN--"))) + vector(1, SourceLocation(27, 28, make_shared("--CODEGEN--"))) + vector(1, SourceLocation(20, 32, make_shared("--CODEGEN--"))) + vector(1, SourceLocation(5, 7, make_shared("--CODEGEN--"))) + - vector(24, SourceLocation(20, 72, make_shared(""))) + - vector(1, SourceLocation(42, 51, make_shared(""))) + - vector(1, SourceLocation(65, 67, make_shared(""))) + - vector(2, SourceLocation(58, 67, make_shared(""))) + - vector(2, SourceLocation(20, 72, make_shared(""))); + vector(24, SourceLocation(20, 79, make_shared(""))) + + vector(1, SourceLocation(49, 58, make_shared(""))) + + vector(1, SourceLocation(72, 74, make_shared(""))) + + vector(2, SourceLocation(65, 74, make_shared(""))) + + vector(2, SourceLocation(20, 79, make_shared(""))); checkAssemblyLocations(items, locations); } diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index f16d9abe1..4887dd5b0 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -87,6 +87,7 @@ public: for (bytes const& arguments: _argumentVariants) { sendMessage(hash.asBytes() + arguments, false, 0); + BOOST_CHECK(m_transactionSuccessful); gasUsed = max(gasUsed, m_gasUsed); gas = max(gas, gasForTransaction(hash.asBytes() + arguments, false)); } @@ -118,10 +119,10 @@ BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs) char const* sourceCode = R"( contract test { bytes x; - function f(uint a) returns (uint b) { + function f(uint a) public returns (uint b) { x.length = a; for (; a < 200; ++a) { - x[a] = 9; + x[a] = 0x09; b = a * a; } return f(a - 1); @@ -151,8 +152,8 @@ BOOST_AUTO_TEST_CASE(simple_contract) char const* sourceCode = R"( contract test { bytes32 public shaValue; - function f(uint a) { - shaValue = keccak256(a); + function f(uint a) public { + shaValue = keccak256(abi.encodePacked(a)); } } )"; @@ -164,8 +165,8 @@ BOOST_AUTO_TEST_CASE(store_keccak256) char const* sourceCode = R"( contract test { bytes32 public shaValue; - function test(uint a) { - shaValue = keccak256(a); + constructor(uint a) public { + shaValue = keccak256(abi.encodePacked(a)); } } )"; @@ -178,7 +179,7 @@ BOOST_AUTO_TEST_CASE(updating_store) contract test { uint data; uint data2; - function test() { + constructor() public { data = 1; data = 2; data2 = 0; @@ -194,7 +195,7 @@ BOOST_AUTO_TEST_CASE(branches) contract test { uint data; uint data2; - function f(uint x) { + function f(uint x) public { if (x > 7) data2 = 1; else @@ -212,7 +213,7 @@ BOOST_AUTO_TEST_CASE(function_calls) contract test { uint data; uint data2; - function f(uint x) { + function f(uint x) public { if (x > 7) data2 = g(x**8) + 1; else @@ -233,13 +234,13 @@ BOOST_AUTO_TEST_CASE(multiple_external_functions) contract test { uint data; uint data2; - function f(uint x) { + function f(uint x) public { if (x > 7) data2 = g(x**8) + 1; else data = 1; } - function g(uint x) returns (uint) { + function g(uint x) public returns (uint) { return data2; } } @@ -253,10 +254,10 @@ BOOST_AUTO_TEST_CASE(exponent_size) { char const* sourceCode = R"( contract A { - function g(uint x) returns (uint) { + function g(uint x) public returns (uint) { return x ** 0x100; } - function h(uint x) returns (uint) { + function h(uint x) public returns (uint) { return x ** 0x10000; } } @@ -270,7 +271,7 @@ BOOST_AUTO_TEST_CASE(balance_gas) { char const* sourceCode = R"( contract A { - function lookup_balance(address a) returns (uint) { + function lookup_balance(address a) public returns (uint) { return a.balance; } } @@ -283,7 +284,7 @@ BOOST_AUTO_TEST_CASE(extcodesize_gas) { char const* sourceCode = R"( contract A { - function f() returns (uint _s) { + function f() public returns (uint _s) { assembly { _s := extcodesize(0x30) } @@ -301,7 +302,7 @@ BOOST_AUTO_TEST_CASE(regular_functions_exclude_fallback) char const* sourceCode = R"( contract A { uint public x; - function() { x = 2; } + function() external { x = 2; } } )"; testCreationTimeGas(sourceCode); @@ -315,7 +316,7 @@ BOOST_AUTO_TEST_CASE(complex_control_flow) // we previously considered. This of course reduces accuracy. char const* sourceCode = R"( contract log { - function ln(int128 x) constant returns (int128 result) { + function ln(int128 x) public pure returns (int128 result) { int128 t = x / 256; int128 y = 5545177; x = t; diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index 1b5dd4a5b..dc33d5779 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(simple_alias) { CompilerStack c; c.addSource("a", "contract A {} pragma solidity >=0.0;"); - c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() { x.A r = x.A(20); } } pragma solidity >=0.0;"); + c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() external { x.A r = x.A(20); } } pragma solidity >=0.0;"); c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(complex_import) CompilerStack c; c.addSource("a", "contract A {} contract B {} contract C { struct S { uint a; } } pragma solidity >=0.0;"); c.addSource("b", "import \"a\" as x; import {B as b, C as c, C} from \"a\"; " - "contract D is b { function f(c.S var1, x.C.S var2, C.S var3) internal {} } pragma solidity >=0.0;"); + "contract D is b { function f(c.S memory var1, x.C.S memory var2, C.S memory var3) internal {} } pragma solidity >=0.0;"); c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); } @@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(name_clash_in_import) BOOST_AUTO_TEST_CASE(remappings) { CompilerStack c; - c.setRemappings(vector{"s=s_1.4.6", "t=Tee"}); + c.setRemappings(vector{{"", "s", "s_1.4.6"},{"", "t", "Tee"}}); c.addSource("a", "import \"s/s.sol\"; contract A is S {} pragma solidity >=0.0;"); c.addSource("b", "import \"t/tee.sol\"; contract A is Tee {} pragma solidity >=0.0;"); c.addSource("s_1.4.6/s.sol", "contract S {} pragma solidity >=0.0;"); @@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(remappings) BOOST_AUTO_TEST_CASE(context_dependent_remappings) { CompilerStack c; - c.setRemappings(vector{"a:s=s_1.4.6", "b:s=s_1.4.7"}); + c.setRemappings(vector{{"a", "s", "s_1.4.6"}, {"b", "s", "s_1.4.7"}}); c.addSource("a/a.sol", "import \"s/s.sol\"; contract A is SSix {} pragma solidity >=0.0;"); c.addSource("b/b.sol", "import \"s/s.sol\"; contract B is SSeven {} pragma solidity >=0.0;"); c.addSource("s_1.4.6/s.sol", "contract SSix {} pragma solidity >=0.0;"); @@ -200,7 +200,11 @@ BOOST_AUTO_TEST_CASE(filename_with_period) BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_preserved) { CompilerStack c; - c.setRemappings(vector{"foo=vendor/foo_2.0.0", "vendor/bar:foo=vendor/foo_1.0.0", "bar=vendor/bar"}); + c.setRemappings(vector{ + {"", "foo", "vendor/foo_2.0.0"}, + {"vendor/bar", "foo", "vendor/foo_1.0.0"}, + {"", "bar", "vendor/bar"} + }); c.addSource("main.sol", "import \"foo/foo.sol\"; import {Bar} from \"bar/bar.sol\"; contract Main is Foo2, Bar {} pragma solidity >=0.0;"); c.addSource("vendor/bar/bar.sol", "import \"foo/foo.sol\"; contract Bar {Foo1 foo;} pragma solidity >=0.0;"); c.addSource("vendor/foo_1.0.0/foo.sol", "contract Foo1 {} pragma solidity >=0.0;"); @@ -212,7 +216,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_pres BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent) { CompilerStack c; - c.setRemappings(vector{"a:x/y/z=d", "a/b:x=e"}); + c.setRemappings(vector{{"a", "x/y/z", "d"}, {"a/b", "x", "e"}}); c.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;"); c.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;"); c.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;"); @@ -220,7 +224,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent) c.setEVMVersion(dev::test::Options::get().evmVersion()); BOOST_CHECK(c.compile()); CompilerStack d; - d.setRemappings(vector{"a/b:x=e", "a:x/y/z=d"}); + d.setRemappings(vector{{"a/b", "x", "e"}, {"a", "x/y/z", "d"}}); d.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;"); d.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;"); d.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;"); diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 181ca959b..a9ce6e499 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -178,9 +178,9 @@ BOOST_AUTO_TEST_CASE(simple_instructions) BOOST_CHECK(successParse("{ dup1 dup1 mul dup1 sub pop }")); } -BOOST_AUTO_TEST_CASE(suicide_selfdestruct) +BOOST_AUTO_TEST_CASE(selfdestruct) { - BOOST_CHECK(successParse("{ 0x01 suicide 0x02 selfdestruct }")); + BOOST_CHECK(successParse("{ 0x02 selfdestruct }")); } BOOST_AUTO_TEST_CASE(keywords) @@ -461,7 +461,7 @@ BOOST_AUTO_TEST_CASE(recursion_depth) BOOST_AUTO_TEST_CASE(multiple_assignment) { CHECK_PARSE_ERROR("{ let x function f() -> a, b {} 123, x := f() }", ParserError, "Label name / variable name must precede \",\" (multiple assignment)."); - CHECK_PARSE_ERROR("{ let x function f() -> a, b {} x, 123 := f() }", ParserError, "Variable name expected in multiple assignemnt."); + CHECK_PARSE_ERROR("{ let x function f() -> a, b {} x, 123 := f() }", ParserError, "Variable name expected in multiple assignment."); /// NOTE: Travis hiccups if not having a variable char const* text = R"( @@ -740,8 +740,6 @@ BOOST_AUTO_TEST_CASE(keccak256) { BOOST_CHECK(successAssemble("{ 0 0 keccak256 pop }")); BOOST_CHECK(successAssemble("{ pop(keccak256(0, 0)) }")); - BOOST_CHECK(successAssemble("{ 0 0 sha3 pop }")); - BOOST_CHECK(successAssemble("{ pop(sha3(0, 0)) }")); } BOOST_AUTO_TEST_CASE(returndatasize) diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp deleted file mode 100644 index 2b3df3a73..000000000 --- a/test/libsolidity/JSONCompiler.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Unit tests for solc/jsonCompiler.cpp. - */ - -#include -#include -#include -#include -#include - -#include -#include - -using namespace std; - -namespace dev -{ -namespace solidity -{ -namespace test -{ - -namespace -{ - -Json::Value compileSingle(string const& _input) -{ - string output(compileJSON(_input.c_str(), dev::test::Options::get().optimize)); - Json::Value ret; - BOOST_REQUIRE(jsonParseStrict(output, ret)); - return ret; -} - -Json::Value compileMulti(string const& _input, bool _callback) -{ - string output( - _callback ? - compileJSONCallback(_input.c_str(), dev::test::Options::get().optimize, NULL) : - compileJSONMulti(_input.c_str(), dev::test::Options::get().optimize) - ); - Json::Value ret; - BOOST_REQUIRE(jsonParseStrict(output, ret)); - return ret; -} - -Json::Value compile(string const& _input) -{ - string output(compileStandard(_input.c_str(), NULL)); - Json::Value ret; - BOOST_REQUIRE(jsonParseStrict(output, ret)); - return ret; -} - -} // end anonymous namespace - -BOOST_AUTO_TEST_SUITE(JSONCompiler) - -BOOST_AUTO_TEST_CASE(read_version) -{ - string output(version()); - BOOST_CHECK(output.find(VersionString) == 0); -} - -BOOST_AUTO_TEST_CASE(read_license) -{ - string output(license()); - BOOST_CHECK(output.find("GNU GENERAL PUBLIC LICENSE") != string::npos); -} - -BOOST_AUTO_TEST_CASE(basic_compilation) -{ - char const* input = R"( - { - "sources": { - "fileA": "contract A { }" - } - } - )"; - Json::Value result = compileMulti(input, false); - BOOST_CHECK(result.isObject()); - - // Compare with compileJSONCallback - BOOST_CHECK_EQUAL( - dev::jsonCompactPrint(result), - dev::jsonCompactPrint(compileMulti(input, true)) - ); - - BOOST_CHECK(result["contracts"].isObject()); - BOOST_CHECK(result["contracts"]["fileA:A"].isObject()); - Json::Value contract = result["contracts"]["fileA:A"]; - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["interface"].isString()); - BOOST_CHECK_EQUAL(contract["interface"].asString(), "[]"); - BOOST_CHECK(contract["bytecode"].isString()); - BOOST_CHECK_EQUAL( - dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" - ); - BOOST_CHECK(contract["runtimeBytecode"].isString()); - BOOST_CHECK_EQUAL( - dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()), - "6080604052600080fd00" - ); - BOOST_CHECK(contract["functionHashes"].isObject()); - BOOST_CHECK(contract["gasEstimates"].isObject()); - BOOST_CHECK_EQUAL( - dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[66,10600],\"external\":{},\"internal\":{}}" - ); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); - BOOST_CHECK(result["sources"].isObject()); - BOOST_CHECK(result["sources"]["fileA"].isObject()); - BOOST_CHECK(result["sources"]["fileA"]["AST"].isObject()); - BOOST_CHECK_EQUAL( - dev::jsonCompactPrint(result["sources"]["fileA"]["AST"]), - "{\"attributes\":{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]}}," - "\"children\":[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null]," - "\"contractKind\":\"contract\",\"documentation\":null,\"fullyImplemented\":true,\"linearizedBaseContracts\":[1]," - "\"name\":\"A\",\"nodes\":[null],\"scope\":2},\"id\":1,\"name\":\"ContractDefinition\"," - "\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}" - ); -} - -BOOST_AUTO_TEST_CASE(single_compilation) -{ - Json::Value result = compileSingle("contract A { }"); - BOOST_CHECK(result.isObject()); - - BOOST_CHECK(result["contracts"].isObject()); - BOOST_CHECK(result["contracts"][":A"].isObject()); - Json::Value contract = result["contracts"][":A"]; - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["interface"].isString()); - BOOST_CHECK_EQUAL(contract["interface"].asString(), "[]"); - BOOST_CHECK(contract["bytecode"].isString()); - BOOST_CHECK_EQUAL( - dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" - ); - BOOST_CHECK(contract["runtimeBytecode"].isString()); - BOOST_CHECK_EQUAL( - dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()), - "6080604052600080fd00" - ); - BOOST_CHECK(contract["functionHashes"].isObject()); - BOOST_CHECK(contract["gasEstimates"].isObject()); - BOOST_CHECK_EQUAL( - dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[66,10600],\"external\":{},\"internal\":{}}" - ); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); - BOOST_CHECK(result["sources"].isObject()); - BOOST_CHECK(result["sources"][""].isObject()); - BOOST_CHECK(result["sources"][""]["AST"].isObject()); - BOOST_CHECK_EQUAL( - dev::jsonCompactPrint(result["sources"][""]["AST"]), - "{\"attributes\":{\"absolutePath\":\"\",\"exportedSymbols\":{\"A\":[1]}}," - "\"children\":[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null]," - "\"contractKind\":\"contract\",\"documentation\":null,\"fullyImplemented\":true,\"linearizedBaseContracts\":[1]," - "\"name\":\"A\",\"nodes\":[null],\"scope\":2},\"id\":1,\"name\":\"ContractDefinition\"," - "\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}" - ); -} - -BOOST_AUTO_TEST_CASE(standard_compilation) -{ - char const* input = R"( - { - "language": "Solidity", - "sources": { - "fileA": { - "content": "contract A { }" - } - } - } - )"; - Json::Value result = compile(input); - BOOST_CHECK(result.isObject()); - - // Only tests some assumptions. The StandardCompiler is tested properly in another suite. - BOOST_CHECK(result.isMember("sources")); - BOOST_CHECK(result.isMember("contracts")); -} - -BOOST_AUTO_TEST_SUITE_END() - -} -} -} // end namespaces diff --git a/test/libsolidity/LibSolc.cpp b/test/libsolidity/LibSolc.cpp new file mode 100644 index 000000000..09c087001 --- /dev/null +++ b/test/libsolidity/LibSolc.cpp @@ -0,0 +1,91 @@ +/* + 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 . +*/ +/** + * @date 2017 + * Unit tests for libsolc/libsolc.cpp. + */ + +#include +#include +#include +#include +#include + +#include +#include + +using namespace std; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +namespace +{ + +Json::Value compile(string const& _input) +{ + string output(solidity_compile(_input.c_str(), nullptr)); + Json::Value ret; + BOOST_REQUIRE(jsonParseStrict(output, ret)); + return ret; +} + +} // end anonymous namespace + +BOOST_AUTO_TEST_SUITE(LibSolc) + +BOOST_AUTO_TEST_CASE(read_version) +{ + string output(solidity_version()); + BOOST_CHECK(output.find(VersionString) == 0); +} + +BOOST_AUTO_TEST_CASE(read_license) +{ + string output(solidity_license()); + BOOST_CHECK(output.find("GNU GENERAL PUBLIC LICENSE") != string::npos); +} + +BOOST_AUTO_TEST_CASE(standard_compilation) +{ + char const* input = R"( + { + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(result.isObject()); + + // Only tests some assumptions. The StandardCompiler is tested properly in another suite. + BOOST_CHECK(result.isMember("sources")); + BOOST_CHECK(result.isMember("contracts")); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 808bd1e15..007ee2b6b 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) pragma solidity >=0.0; pragma experimental __testOnlyAnalysis; contract test { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; CompilerStack compilerStack; @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) pragma solidity >=0.0; pragma experimental __test; contract test { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; CompilerStack compilerStack; @@ -97,14 +97,14 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources) char const* sourceCode = R"( pragma solidity >=0.0; contract A { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; compilerStack.addSource("A", std::string(sourceCode)); sourceCode = R"( pragma solidity >=0.0; contract B { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; compilerStack.addSource("B", std::string(sourceCode)); @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) char const* sourceCode = R"( pragma solidity >=0.0; contract A { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; compilerStack.addSource("A", std::string(sourceCode)); @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) pragma solidity >=0.0; import "./A"; contract B is A { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; compilerStack.addSource("B", std::string(sourceCode)); @@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) pragma solidity >=0.0; import "./B"; contract C is B { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; compilerStack.addSource("C", std::string(sourceCode)); diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index 71fdb906f..195004cb4 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(warn_on_struct) pragma experimental ABIEncoderV2; contract C { struct A { uint a; uint b; } - function f() public pure returns (A) { + function f() public pure returns (A memory) { return A({ a: 1, b: 2 }); } } @@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(simple_assert) function f(uint a) public pure { assert(a == 2); } } )"; - CHECK_WARNING(text, "Assertion violation happens here for"); + CHECK_WARNING(text, "Assertion violation happens here"); } BOOST_AUTO_TEST_CASE(simple_assert_with_require) @@ -133,38 +133,6 @@ BOOST_AUTO_TEST_CASE(assignment_in_declaration) CHECK_SUCCESS_NO_WARNINGS(text); } -BOOST_AUTO_TEST_CASE(use_before_declaration) -{ - string text = R"( - contract C { - function f() public pure { a = 3; uint a = 2; assert(a == 2); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f() public pure { assert(a == 0); uint a = 2; assert(a == 2); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(function_call_does_not_clear_local_vars) -{ - string text = R"( - contract C { - function f() public { - uint a = 3; - this.f(); - assert(a == 3); - f(); - assert(a == 3); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - BOOST_AUTO_TEST_CASE(branches_merge_variables) { // Branch does not touch variable a @@ -359,7 +327,7 @@ BOOST_AUTO_TEST_CASE(bool_simple) text = R"( contract C { function f(bool x) public pure { - if(x) { + if (x) { assert(x); } else { assert(!x); @@ -388,35 +356,6 @@ BOOST_AUTO_TEST_CASE(bool_simple) } )"; CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(bool x) public pure { - bool y; - assert(x <= y); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - text = R"( - contract C { - function f(bool x) public pure { - bool y; - assert(x >= y); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(bool x) public pure { - require(x); - bool y; - assert(x > y); - assert(y < x); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); } BOOST_AUTO_TEST_CASE(bool_int_mixed) @@ -425,7 +364,7 @@ BOOST_AUTO_TEST_CASE(bool_int_mixed) contract C { function f(bool x) public pure { uint a; - if(x) + if (x) a = 1; assert(!x || a > 0); } @@ -478,15 +417,15 @@ BOOST_AUTO_TEST_CASE(storage_value_vars) function f(uint x) public { if (x == 0) { - a = 100; + a = 0x0000000000000000000000000000000000000100; b = true; } else { - a = 200; + a = 0x0000000000000000000000000000000000000200; b = false; } - assert(a > 0 && b); + assert(a > 0x0000000000000000000000000000000000000000 && b); } } )"; @@ -509,19 +448,19 @@ BOOST_AUTO_TEST_CASE(storage_value_vars) function f(uint x) public { if (x == 0) { - a = 100; + a = 0x0000000000000000000000000000000000000100; b = true; } else { - a = 200; + a = 0x0000000000000000000000000000000000000200; b = false; } - assert(b == (a < 200)); + assert(b == (a < 0x0000000000000000000000000000000000000200)); } function g() public view { - require(a < 100); + require(a < 0x0000000000000000000000000000000000000100); assert(c >= 0); } address a; @@ -614,7 +553,10 @@ BOOST_AUTO_TEST_CASE(constant_condition) } } )"; - CHECK_WARNING(text, "Condition is always true"); + CHECK_WARNING_ALLOW_MULTI(text, (vector{ + "Condition is always true", + "Assertion checker does not yet implement this type of function call" + })); text = R"( contract C { function f(uint x) public pure { @@ -622,7 +564,10 @@ BOOST_AUTO_TEST_CASE(constant_condition) } } )"; - CHECK_WARNING(text, "Condition is always false"); + CHECK_WARNING_ALLOW_MULTI(text, (vector{ + "Condition is always false", + "Assertion checker does not yet implement this type of function call" + })); // a plain literal constant is fine text = R"( contract C { @@ -631,7 +576,7 @@ BOOST_AUTO_TEST_CASE(constant_condition) } } )"; - CHECK_SUCCESS_NO_WARNINGS(text); + CHECK_WARNING(text, "Assertion checker does not yet implement this type of function call"); } diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 07f8fba62..43951f73d 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -42,13 +42,13 @@ SemVerMatchExpression parseExpression(string const& _input) { Scanner scanner{CharStream(_input)}; vector literals; - vector tokens; + vector tokens; while (scanner.currentToken() != Token::EOS) { auto token = scanner.currentToken(); string literal = scanner.currentLiteral(); - if (literal.empty() && Token::toString(token)) - literal = Token::toString(token); + if (literal.empty() && TokenTraits::toString(token)) + literal = TokenTraits::toString(token); literals.push_back(literal); tokens.push_back(token); scanner.next(); diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 3475b0188..a8a67bca0 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -40,7 +40,7 @@ class JSONInterfaceChecker public: JSONInterfaceChecker(): m_compilerStack() {} - void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) + void checkInterface(std::string const& _code, std::string const& _contractName, std::string const& _expectedInterfaceString) { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); @@ -48,7 +48,7 @@ public: m_compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); - Json::Value generatedInterface = m_compilerStack.contractABI(m_compilerStack.lastContractName()); + Json::Value generatedInterface = m_compilerStack.contractABI(_contractName); Json::Value expectedInterface; BOOST_REQUIRE(jsonParseStrict(_expectedInterfaceString, expectedInterface)); BOOST_CHECK_MESSAGE( @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(basic_test) { char const* sourceCode = R"( contract test { - function f(uint a) returns(uint d) { return a * 7; } + function f(uint a) public returns (uint d) { return a * 7; } } )"; @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(basic_test) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(empty_contract) @@ -104,15 +104,15 @@ BOOST_AUTO_TEST_CASE(empty_contract) )"; char const* interface = "[]"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(multiple_methods) { char const* sourceCode = R"( contract test { - function f(uint a) returns(uint d) { return a * 7; } - function g(uint b) returns(uint e) { return b * 8; } + function f(uint a) public returns (uint d) { return a * 7; } + function g(uint b) public returns (uint e) { return b * 8; } } )"; @@ -157,14 +157,14 @@ BOOST_AUTO_TEST_CASE(multiple_methods) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(multiple_params) { char const* sourceCode = R"( contract test { - function f(uint a, uint b) returns(uint d) { return a + b; } + function f(uint a, uint b) public returns (uint d) { return a + b; } } )"; @@ -194,16 +194,16 @@ BOOST_AUTO_TEST_CASE(multiple_params) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(multiple_methods_order) { - // methods are expected to be in alpabetical order + // methods are expected to be in alphabetical order char const* sourceCode = R"( contract test { - function f(uint a) returns(uint d) { return a * 7; } - function c(uint b) returns(uint e) { return b * 8; } + function f(uint a) public returns (uint d) { return a * 7; } + function c(uint b) public returns (uint e) { return b * 8; } } )"; @@ -248,15 +248,15 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(view_function) { char const* sourceCode = R"( contract test { - function foo(uint a, uint b) returns(uint d) { return a + b; } - function boo(uint32 a) view returns(uint b) { return a * 4; } + function foo(uint a, uint b) public returns (uint d) { return a + b; } + function boo(uint32 a) public view returns(uint b) { return a * 4; } } )"; @@ -303,71 +303,15 @@ BOOST_AUTO_TEST_CASE(view_function) } ])"; - checkInterface(sourceCode, interface); -} - -// constant is an alias to view above -BOOST_AUTO_TEST_CASE(constant_function) -{ - char const* sourceCode = R"( - contract test { - function foo(uint a, uint b) returns(uint d) { return a + b; } - function boo(uint32 a) constant returns(uint b) { return a * 4; } - } - )"; - - char const* interface = R"([ - { - "name": "foo", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - }, - { - "name": "b", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - }, - { - "name": "boo", - "constant": true, - "payable" : false, - "stateMutability": "view", - "type": "function", - "inputs": [{ - "name": "a", - "type": "uint32" - }], - "outputs": [ - { - "name": "b", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(pure_function) { char const* sourceCode = R"( contract test { - function foo(uint a, uint b) returns(uint d) { return a + b; } - function boo(uint32 a) pure returns(uint b) { return a * 4; } + function foo(uint a, uint b) public returns (uint d) { return a + b; } + function boo(uint32 a) public pure returns (uint b) { return a * 4; } } )"; @@ -414,14 +358,14 @@ BOOST_AUTO_TEST_CASE(pure_function) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(events) { char const* sourceCode = R"( contract test { - function f(uint a) returns(uint d) { return a * 7; } + function f(uint a) public returns (uint d) { return a * 7; } event e1(uint b, address indexed c); event e2(); event e2(uint a); @@ -492,7 +436,7 @@ BOOST_AUTO_TEST_CASE(events) ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(events_anonymous) @@ -512,18 +456,18 @@ BOOST_AUTO_TEST_CASE(events_anonymous) ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(inherited) { char const* sourceCode = R"( contract Base { - function baseFunction(uint p) returns (uint i) { return p; } + function baseFunction(uint p) public returns (uint i) { return p; } event baseEvent(bytes32 indexed evtArgBase); } contract Derived is Base { - function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } + function derivedFunction(bytes32 p) public returns (bytes32 i) { return p; } event derivedEvent(uint indexed evtArgDerived); } )"; @@ -587,13 +531,13 @@ BOOST_AUTO_TEST_CASE(inherited) }])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "Derived", interface); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { char const* sourceCode = R"( contract test { - function f(uint, uint k) returns(uint ret_k, uint ret_g) { + function f(uint, uint k) public returns (uint ret_k, uint ret_g) { uint g = 8; ret_k = k; ret_g = g; @@ -631,14 +575,14 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(empty_name_return_parameter) { char const* sourceCode = R"( contract test { - function f(uint k) returns(uint) { + function f(uint k) public returns (uint) { return k; } } @@ -665,14 +609,14 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) ] } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(constructor_abi) { char const* sourceCode = R"( contract test { - function test(uint param1, test param2, bool param3) {} + constructor(uint param1, test param2, bool param3) public {} } )"; @@ -697,14 +641,14 @@ BOOST_AUTO_TEST_CASE(constructor_abi) "type": "constructor" } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(payable_constructor_abi) { char const* sourceCode = R"( contract test { - function test(uint param1, test param2, bool param3) payable {} + constructor(uint param1, test param2, bool param3) public payable {} } )"; @@ -729,7 +673,7 @@ BOOST_AUTO_TEST_CASE(payable_constructor_abi) "type": "constructor" } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(return_param_in_abi) @@ -738,8 +682,8 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) char const* sourceCode = R"( contract test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test(ActionChoices param) {} - function ret() returns(ActionChoices) { + constructor(ActionChoices param) public {} + function ret() public returns (ActionChoices) { ActionChoices action = ActionChoices.GoLeft; return action; } @@ -775,7 +719,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(strings_and_arrays) @@ -783,7 +727,7 @@ BOOST_AUTO_TEST_CASE(strings_and_arrays) // bug #1801 char const* sourceCode = R"( contract test { - function f(string a, bytes b, uint[] c) external {} + function f(string calldata a, bytes calldata b, uint[] calldata c) external {} } )"; @@ -804,7 +748,7 @@ BOOST_AUTO_TEST_CASE(strings_and_arrays) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(library_function) @@ -812,7 +756,7 @@ BOOST_AUTO_TEST_CASE(library_function) char const* sourceCode = R"( library test { struct StructType { uint a; } - function f(StructType storage b, uint[] storage c, test d) returns (uint[] e, StructType storage f) {} + function f(StructType storage b, uint[] storage c, test d) public returns (uint[] memory e, StructType storage f) { f = f; } } )"; @@ -836,14 +780,14 @@ BOOST_AUTO_TEST_CASE(library_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(include_fallback_function) { char const* sourceCode = R"( contract test { - function() {} + function() external {} } )"; @@ -856,15 +800,15 @@ BOOST_AUTO_TEST_CASE(include_fallback_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(payable_function) { char const* sourceCode = R"( contract test { - function f() {} - function g() payable {} + function f() public {} + function g() public payable {} } )"; @@ -890,14 +834,14 @@ BOOST_AUTO_TEST_CASE(payable_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(payable_fallback_function) { char const* sourceCode = R"( contract test { - function () payable {} + function () external payable {} } )"; @@ -910,14 +854,14 @@ BOOST_AUTO_TEST_CASE(payable_fallback_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(function_type) { char const* sourceCode = R"( contract test { - function g(function(uint) external returns (uint) x) {} + function g(function(uint) external returns (uint) x) public {} } )"; @@ -937,17 +881,17 @@ BOOST_AUTO_TEST_CASE(function_type) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(return_structs) { - char const* text = R"( + char const* sourceCode = R"( pragma experimental ABIEncoderV2; contract C { struct S { uint a; T[] sub; } struct T { uint[2] x; } - function f() returns (uint x, S s) { + function f() public returns (uint x, S memory s) { } } )"; @@ -987,16 +931,16 @@ BOOST_AUTO_TEST_CASE(return_structs) "type" : "function" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "C", interface); } BOOST_AUTO_TEST_CASE(return_structs_with_contracts) { - char const* text = R"( + char const* sourceCode = R"( pragma experimental ABIEncoderV2; contract C { struct S { C[] x; C y; } - function f() returns (S s, C c) { + function f() public returns (S memory s, C c) { } } )"; @@ -1030,12 +974,12 @@ BOOST_AUTO_TEST_CASE(return_structs_with_contracts) "type": "function" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "C", interface); } BOOST_AUTO_TEST_CASE(event_structs) { - char const* text = R"( + char const* sourceCode = R"( pragma experimental ABIEncoderV2; contract C { struct S { uint a; T[] sub; bytes b; } @@ -1088,18 +1032,18 @@ BOOST_AUTO_TEST_CASE(event_structs) "type": "event" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "C", interface); } BOOST_AUTO_TEST_CASE(structs_in_libraries) { - char const* text = R"( + char const* sourceCode = R"( pragma experimental ABIEncoderV2; library L { struct S { uint a; T[] sub; bytes b; } struct T { uint[2] x; } - function f(L.S storage s) {} - function g(L.S s) {} + function f(L.S storage s) public {} + function g(L.S memory s) public {} } )"; char const* interface = R"( @@ -1152,7 +1096,7 @@ BOOST_AUTO_TEST_CASE(structs_in_libraries) "type": "function" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "L", interface); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp index 90540f3ef..0cc80dd82 100644 --- a/test/libsolidity/SolidityCompiler.cpp +++ b/test/libsolidity/SolidityCompiler.cpp @@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions) char const* sourceCode = R"( contract C { uint x; - function C() { f(); } + constructor() public { f(); } function f() internal { for (uint i = 0; i < 10; ++i) x += 3 + i; } } )"; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index f2cc78bfa..876467370 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -49,11 +49,30 @@ namespace test BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityExecutionFramework) +BOOST_AUTO_TEST_CASE(transaction_status) +{ + char const* sourceCode = R"( + contract test { + function f() public { } + function g() public { revert(); } + function h() public { assert(false); } + } + )"; + compileAndRun(sourceCode); + callContractFunction("f()"); + BOOST_CHECK(m_transactionSuccessful); + callContractFunction("g()"); + BOOST_CHECK(!m_transactionSuccessful); + callContractFunction("h()"); + BOOST_CHECK(!m_transactionSuccessful); +} + + BOOST_AUTO_TEST_CASE(smoke_test) { char const* sourceCode = R"( contract test { - function f(uint a) returns(uint d) { return a * 7; } + function f(uint a) public returns(uint d) { return a * 7; } } )"; compileAndRun(sourceCode); @@ -73,7 +92,7 @@ BOOST_AUTO_TEST_CASE(exp_operator) { char const* sourceCode = R"( contract test { - function f(uint a) returns(uint d) { return 2 ** a; } + function f(uint a) public returns(uint d) { return 2 ** a; } } )"; compileAndRun(sourceCode); @@ -84,7 +103,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_const) { char const* sourceCode = R"( contract test { - function f() returns(uint d) { return 2 ** 3; } + function f() public returns(uint d) { return 2 ** 3; } } )"; compileAndRun(sourceCode); @@ -95,7 +114,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) { char const* sourceCode = R"( contract test { - function f() returns(int d) { return (-2) ** 3; } + function f() public returns(int d) { return (-2) ** 3; } } )"; compileAndRun(sourceCode); @@ -106,7 +125,7 @@ BOOST_AUTO_TEST_CASE(exp_zero) { char const* sourceCode = R"( contract test { - function f(uint a) returns(uint d) { return a ** 0; } + function f(uint a) public returns(uint d) { return a ** 0; } } )"; compileAndRun(sourceCode); @@ -117,7 +136,7 @@ BOOST_AUTO_TEST_CASE(exp_zero_literal) { char const* sourceCode = R"( contract test { - function f() returns(uint d) { return 0 ** 0; } + function f() public returns(uint d) { return 0 ** 0; } } )"; compileAndRun(sourceCode); @@ -129,7 +148,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) { char const* sourceCode = R"( contract test { - function f() returns(uint d) { + function f() public returns(uint d) { return true ? 5 : 10; } } @@ -142,7 +161,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) { char const* sourceCode = R"( contract test { - function f() returns(uint d) { + function f() public returns(uint d) { return false ? 5 : 10; } } @@ -155,7 +174,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_multiple) { char const* sourceCode = R"( contract test { - function f(uint x) returns(uint d) { + function f(uint x) public returns(uint d) { return x > 100 ? x > 1000 ? 1000 : 100 : @@ -174,10 +193,11 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) { char const* sourceCode = R"( contract test { - function f(bool cond, uint v) returns (uint a, uint b) { + function f(bool cond, uint v) public returns (uint a, uint b) { cond ? a = v : b = v; } - })"; + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)), encodeArgs(u256(20), u256(0))); ABI_CHECK(callContractFunction("f(bool,uint256)", false, u256(20)), encodeArgs(u256(0), u256(20))); @@ -188,7 +208,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) char const* sourceCode = R"( contract test { bytes2[2] data1; - function f(bool cond) returns (uint) { + function f(bool cond) public returns (uint) { bytes2[2] memory x; x[0] = "aa"; bytes2[2] memory y; @@ -221,7 +241,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) char const* sourceCode = R"( contract test { bytes2[2] data1; - function f(bool cond) returns (uint) { + function f(bool cond) public returns (uint) { data1[0] = "cc"; bytes2[2] memory x; @@ -254,7 +274,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_different_types) { char const* sourceCode = R"( contract test { - function f(bool cond) returns (uint) { + function f(bool cond) public returns (uint) { uint8 x = 0xcd; uint16 y = 0xabab; return cond ? x : y; @@ -271,7 +291,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_string_literal) { char const* sourceCode = R"( contract test { - function f(bool cond) returns (bytes32) { + function f(bool cond) public returns (bytes32) { return cond ? "true" : "false"; } } @@ -286,7 +306,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_tuples) { char const* sourceCode = R"( contract test { - function f(bool cond) returns (uint, uint) { + function f(bool cond) public returns (uint, uint) { return cond ? (1, 2) : (3, 4); } } @@ -300,11 +320,11 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions) { char const* sourceCode = R"( contract test { - function x() returns (uint) { return 1; } - function y() returns (uint) { return 2; } + function x() public returns (uint) { return 1; } + function y() public returns (uint) { return 2; } - function f(bool cond) returns (uint) { - var z = cond ? x : y; + function f(bool cond) public returns (uint) { + function () returns (uint) z = cond ? x : y; return z(); } } @@ -314,10 +334,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions) ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2))); } -BOOST_AUTO_TEST_CASE(C99_scoping_activation) +BOOST_AUTO_TEST_CASE(c99_scoping_activation) { char const* sourceCode = R"( - pragma experimental "v0.5.0"; contract test { function f() pure public returns (uint) { uint x = 7; @@ -366,7 +385,7 @@ BOOST_AUTO_TEST_CASE(recursive_calls) { char const* sourceCode = R"( contract test { - function f(uint n) returns(uint nfac) { + function f(uint n) public returns(uint nfac) { if (n <= 1) return 1; else return n * f(n - 1); } @@ -388,10 +407,10 @@ BOOST_AUTO_TEST_CASE(multiple_functions) { char const* sourceCode = R"( contract test { - function a() returns(uint n) { return 0; } - function b() returns(uint n) { return 1; } - function c() returns(uint n) { return 2; } - function f() returns(uint n) { return 3; } + function a() public returns(uint n) { return 0; } + function b() public returns(uint n) { return 1; } + function c() public returns(uint n) { return 2; } + function f() public returns(uint n) { return 3; } } )"; compileAndRun(sourceCode); @@ -406,8 +425,8 @@ BOOST_AUTO_TEST_CASE(named_args) { char const* sourceCode = R"( contract test { - function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } - function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); } + function a(uint a, uint b, uint c) public returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() public returns (uint r) { r = a({a: 1, b: 2, c: 3}); } } )"; compileAndRun(sourceCode); @@ -418,8 +437,8 @@ BOOST_AUTO_TEST_CASE(disorder_named_args) { char const* sourceCode = R"( contract test { - function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } - function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); } + function a(uint a, uint b, uint c) public returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() public returns (uint r) { r = a({c: 3, a: 1, b: 2}); } } )"; compileAndRun(sourceCode); @@ -430,9 +449,9 @@ BOOST_AUTO_TEST_CASE(while_loop) { char const* sourceCode = R"( contract test { - function f(uint n) returns(uint nfac) { + function f(uint n) public returns(uint nfac) { nfac = 1; - var i = 2; + uint i = 2; while (i <= n) nfac *= i++; } } @@ -457,9 +476,9 @@ BOOST_AUTO_TEST_CASE(do_while_loop) { char const* sourceCode = R"( contract test { - function f(uint n) returns(uint nfac) { + function f(uint n) public returns(uint nfac) { nfac = 1; - var i = 2; + uint i = 2; do { nfac *= i++; } while (i <= n); } } @@ -482,12 +501,123 @@ BOOST_AUTO_TEST_CASE(do_while_loop) testContractAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5); } +BOOST_AUTO_TEST_CASE(do_while_loop_continue) +{ + char const* sourceCode = R"( + contract test { + function f() public pure returns(uint r) { + uint i = 0; + do + { + if (i > 0) return 0; + i++; + continue; + } while (false); + return 42; + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(42)); +} + +BOOST_AUTO_TEST_CASE(array_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint256[] calldata seq) external pure returns (uint256) { + uint i = 0; + uint sum = 0; + while (i < seq.length) + { + uint idx = i; + if (idx >= 10) break; + uint x = seq[idx]; + if (x >= 1000) { + uint n = i + 1; + i = n; + continue; + } + else { + uint y = sum + x; + sum = y; + } + if (sum >= 500) return sum; + i++; + } + return sum; + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f(uint256[])", 32, 3, u256(1000), u256(1), u256(2)), encodeArgs(3)); + ABI_CHECK(callContractFunction("f(uint256[])", 32, 3, u256(100), u256(500), u256(300)), encodeArgs(600)); + ABI_CHECK(callContractFunction( + "f(uint256[])", 32, 11, + u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8), u256(9), u256(10), u256(111) + ), encodeArgs(55)); +} + + +BOOST_AUTO_TEST_CASE(do_while_loop_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint x) public pure returns(uint r) { + uint i = 0; + do + { + uint z = x * 2; + if (z < 4) break; + else { + uint k = z + 1; + if (k < 8) { + x++; + continue; + } + } + if (z > 12) return 0; + x++; + i++; + } while (true); + return 42; + } + } + )"; + compileAndRun(sourceCode); + + auto do_while = [](u256 n) -> u256 + { + u256 i = 0; + do + { + u256 z = n * 2; + if (z < 4) break; + else { + u256 k = z + 1; + if (k < 8) { + n++; + continue; + } + } + if (z > 12) return 0; + n++; + i++; + } while (true); + return 42; + }; + + testContractAgainstCppOnRange("f(uint256)", do_while, 0, 12); +} + BOOST_AUTO_TEST_CASE(nested_loops) { // tests that break and continue statements in nested loops jump to the correct place char const* sourceCode = R"( contract test { - function f(uint x) returns(uint y) { + function f(uint x) public returns(uint y) { while (x > 1) { if (x == 10) break; while (x > 5) { @@ -533,13 +663,186 @@ BOOST_AUTO_TEST_CASE(nested_loops) testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); } +BOOST_AUTO_TEST_CASE(nested_loops_multiple_local_vars) +{ + // tests that break and continue statements in nested loops jump to the correct place + // and free local variables properly + char const* sourceCode = R"( + contract test { + function f(uint x) public returns(uint y) { + while (x > 0) { + uint z = x + 10; + uint k = z + 1; + if (k > 20) { + break; + uint p = 100; + k += p; + } + if (k > 15) { + x--; + continue; + uint t = 1000; + x += t; + } + while (k > 10) { + uint m = k - 1; + if (m == 10) return x; + return k; + uint h = 10000; + z += h; + } + x--; + break; + } + return x; + } + } + )"; + compileAndRun(sourceCode); + + auto nested_loops_cpp = [](u256 n) -> u256 + { + while (n > 0) + { + u256 z = n + 10; + u256 k = z + 1; + if (k > 20) break; + if (k > 15) { + n--; + continue; + } + while (k > 10) + { + u256 m = k - 1; + if (m == 10) return n; + return k; + } + n--; + break; + } + + return n; + }; + + testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); +} + +BOOST_AUTO_TEST_CASE(for_loop_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint x) public pure returns(uint r) { + for (uint i = 0; i < 12; i++) + { + uint z = x + 1; + if (z < 4) break; + else { + uint k = z * 2; + if (i + k < 10) { + x++; + continue; + } + } + if (z > 8) return 0; + x++; + } + return 42; + } + } + )"; + compileAndRun(sourceCode); + + auto for_loop = [](u256 n) -> u256 + { + for (u256 i = 0; i < 12; i++) + { + u256 z = n + 1; + if (z < 4) break; + else { + u256 k = z * 2; + if (i + k < 10) { + n++; + continue; + } + } + if (z > 8) return 0; + n++; + } + return 42; + }; + + testContractAgainstCppOnRange("f(uint256)", for_loop, 0, 12); +} + +BOOST_AUTO_TEST_CASE(nested_for_loop_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint x) public pure returns(uint r) { + for (uint i = 0; i < 5; i++) + { + uint z = x + 1; + if (z < 3) { + break; + uint p = z + 2; + } + for (uint j = 0; j < 5; j++) + { + uint k = z * 2; + if (j + k < 8) { + x++; + continue; + uint t = z * 3; + } + x++; + if (x > 20) { + return 84; + uint h = x + 42; + } + } + if (x > 30) { + return 42; + uint b = 0xcafe; + } + } + return 42; + } + } + )"; + compileAndRun(sourceCode); + + auto for_loop = [](u256 n) -> u256 + { + for (u256 i = 0; i < 5; i++) + { + u256 z = n + 1; + if (z < 3) break; + for (u256 j = 0; j < 5; j++) + { + u256 k = z * 2; + if (j + k < 8) { + n++; + continue; + } + n++; + if (n > 20) return 84; + } + if (n > 30) return 42; + } + return 42; + }; + + testContractAgainstCppOnRange("f(uint256)", for_loop, 0, 12); +} + BOOST_AUTO_TEST_CASE(for_loop) { char const* sourceCode = R"( contract test { - function f(uint n) returns(uint nfac) { + function f(uint n) public returns(uint nfac) { nfac = 1; - for (var i = 2; i <= n; i++) + uint i; + for (i = 2; i <= n; i++) nfac *= i; } } @@ -561,7 +864,7 @@ BOOST_AUTO_TEST_CASE(for_loop_empty) { char const* sourceCode = R"( contract test { - function f() returns(uint ret) { + function f() public returns(uint ret) { ret = 1; for (;;) { ret += 1; @@ -590,7 +893,7 @@ BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr) { char const* sourceCode = R"( contract test { - function f(uint n) returns(uint nfac) { + function f(uint n) public returns(uint nfac) { nfac = 1; uint256 i; for (i = 2; i <= n; i++) @@ -616,7 +919,7 @@ BOOST_AUTO_TEST_CASE(for_loop_break_continue) { char const* sourceCode = R"( contract test { - function f(uint n) returns (uint r) + function f(uint n) public returns (uint r) { uint i = 1; uint k = 0; @@ -662,16 +965,16 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) { char const* sourceCode = R"( contract collatz { - function run(uint x) returns(uint y) { + function run(uint x) public returns(uint y) { while ((y = x) > 1) { if (x % 2 == 0) x = evenStep(x); else x = oddStep(x); } } - function evenStep(uint x) returns(uint y) { + function evenStep(uint x) public returns(uint y) { return x / 2; } - function oddStep(uint x) returns(uint y) { + function oddStep(uint x) public returns(uint y) { return 3 * x + 1; } } @@ -712,8 +1015,8 @@ BOOST_AUTO_TEST_CASE(many_local_variables) { char const* sourceCode = R"( contract test { - function run(uint x1, uint x2, uint x3) returns(uint y) { - var a = 0x1; var b = 0x10; var c = 0x100; + function run(uint x1, uint x2, uint x3) public returns(uint y) { + uint8 a = 0x1; uint8 b = 0x10; uint16 c = 0x100; y = a + b + c + x1 + x2 + x3; y += b + x2; } @@ -735,7 +1038,7 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types) { char const* sourceCode = R"( contract test { - function run(bool a, uint32 b, uint64 c) returns(uint256 y) { + function run(bool a, uint32 b, uint64 c) public returns(uint256 y) { if (a) y = 1; y = y * 0x100000000 | ~b; y = y * 0x10000000000000000 | ~c; @@ -753,7 +1056,7 @@ BOOST_AUTO_TEST_CASE(packing_signed_types) { char const* sourceCode = R"( contract test { - function run() returns(int8 y) { + function run() public returns(int8 y) { uint8 x = 0xfa; return int8(x); } @@ -770,7 +1073,7 @@ BOOST_AUTO_TEST_CASE(multiple_return_values) { char const* sourceCode = R"( contract test { - function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) { + function run(bool x1, uint x2) public returns(uint y1, bool y2, uint y3) { y1 = x2; y2 = x1; } } @@ -783,7 +1086,7 @@ BOOST_AUTO_TEST_CASE(short_circuiting) { char const* sourceCode = R"( contract test { - function run(uint x) returns(uint y) { + function run(uint x) public returns(uint y) { x == 0 || ((x = 8) > 0); return x; } @@ -804,7 +1107,7 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) { char const* sourceCode = R"( contract test { - function run() returns(uint256 y) { + function run() public returns(uint256 y) { uint32 t = uint32(0xffffffff); uint32 x = t + 10; if (x >= 0xffffffff) return 0; @@ -828,7 +1131,7 @@ BOOST_AUTO_TEST_CASE(sign_extension) { char const* sourceCode = R"( contract test { - function run() returns(uint256 y) { + function run() public returns(uint256 y) { int64 x = -int32(0xff); if (x >= 0xff) return 0; return -uint256(x); @@ -850,7 +1153,7 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) { char const* sourceCode = R"( contract test { - function run() returns(uint256 y) { + function run() public returns(uint256 y) { uint32 t = uint32(0xffffff); uint32 x = t * 0xffffff; return x / 0x100; @@ -871,7 +1174,7 @@ BOOST_AUTO_TEST_CASE(small_signed_types) { char const* sourceCode = R"( contract test { - function run() returns(int256 y) { + function run() public returns(int256 y) { return -int32(10) * -int64(20); } } @@ -888,10 +1191,10 @@ BOOST_AUTO_TEST_CASE(strings) { char const* sourceCode = R"( contract test { - function fixedBytes() returns(bytes32 ret) { + function fixedBytes() public returns(bytes32 ret) { return "abc\x00\xff__"; } - function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) { + function pipeThrough(bytes2 small, bool one) public returns(bytes16 large, bool oneRet) { oneRet = one; large = small; } @@ -908,7 +1211,7 @@ BOOST_AUTO_TEST_CASE(inc_dec_operators) contract test { uint8 x; uint v; - function f() returns (uint r) { + function f() public returns (uint r) { uint a = 6; r = a; r += (a++) * 0x10; @@ -927,7 +1230,7 @@ BOOST_AUTO_TEST_CASE(bytes_comparison) { char const* sourceCode = R"( contract test { - function f() returns (bool) { + function f() public returns (bool) { bytes2 a = "a"; bytes2 x = "aa"; bytes2 b = "b"; @@ -945,25 +1248,25 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) contract test { uint256 value1; uint256 value2; - function get(uint8 which) returns (uint256 value) { + function get(uint8 which) public returns (uint256 value) { if (which == 0) return value1; else return value2; } - function set(uint8 which, uint256 value) { + function set(uint8 which, uint256 value) public { if (which == 0) value1 = value; else value2 = value; } } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(0)); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(0)); - ABI_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x1234), encodeArgs()); - ABI_CHECK(callContractFunction("set(uint8,uint256)", byte(0x01), 0x8765), encodeArgs()); - ABI_CHECK(callContractFunction("get(uint8)", byte( 0x00)), encodeArgs(0x1234)); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(0x8765)); - ABI_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x3), encodeArgs()); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(0x3)); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(0)); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(0)); + ABI_CHECK(callContractFunction("set(uint8,uint256)", uint8_t(0x00), 0x1234), encodeArgs()); + ABI_CHECK(callContractFunction("set(uint8,uint256)", uint8_t(0x01), 0x8765), encodeArgs()); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t( 0x00)), encodeArgs(0x1234)); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(0x8765)); + ABI_CHECK(callContractFunction("set(uint8,uint256)", uint8_t(0x00), 0x3), encodeArgs()); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(0x3)); } BOOST_AUTO_TEST_CASE(compound_assign) @@ -972,7 +1275,7 @@ BOOST_AUTO_TEST_CASE(compound_assign) contract test { uint value1; uint value2; - function f(uint x, uint y) returns (uint w) { + function f(uint x, uint y) public returns (uint w) { uint value3 = y; value1 += x; value3 *= x; @@ -1008,31 +1311,31 @@ BOOST_AUTO_TEST_CASE(simple_mapping) char const* sourceCode = R"( contract test { mapping(uint8 => uint8) table; - function get(uint8 k) returns (uint8 v) { + function get(uint8 k) public returns (uint8 v) { return table[k]; } - function set(uint8 k, uint8 v) { + function set(uint8 k, uint8 v) public { table[k] = v; } } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("get(uint8)", byte(0)), encodeArgs(byte(0x00))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0x00))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); - callContractFunction("set(uint8,uint8)", byte(0x01), byte(0xa1)); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(byte(0x00))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0xa1))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); - callContractFunction("set(uint8,uint8)", byte(0x00), byte(0xef)); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(byte(0xef))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0xa1))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); - callContractFunction("set(uint8,uint8)", byte(0x01), byte(0x05)); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x00)), encodeArgs(byte(0xef))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0x01)), encodeArgs(byte(0x05))); - ABI_CHECK(callContractFunction("get(uint8)", byte(0xa7)), encodeArgs(byte(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0)), encodeArgs(uint8_t(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(uint8_t(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0xa7)), encodeArgs(uint8_t(0x00))); + callContractFunction("set(uint8,uint8)", uint8_t(0x01), uint8_t(0xa1)); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(uint8_t(0x00))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(uint8_t(0xa1))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0xa7)), encodeArgs(uint8_t(0x00))); + callContractFunction("set(uint8,uint8)", uint8_t(0x00), uint8_t(0xef)); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(uint8_t(0xef))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(uint8_t(0xa1))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0xa7)), encodeArgs(uint8_t(0x00))); + callContractFunction("set(uint8,uint8)", uint8_t(0x01), uint8_t(0x05)); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(uint8_t(0xef))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(uint8_t(0x05))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0xa7)), encodeArgs(uint8_t(0x00))); } BOOST_AUTO_TEST_CASE(mapping_state) @@ -1042,13 +1345,13 @@ BOOST_AUTO_TEST_CASE(mapping_state) mapping(address => bool) canVote; mapping(address => uint) voteCount; mapping(address => bool) voted; - function getVoteCount(address addr) returns (uint retVoteCount) { + function getVoteCount(address addr) public returns (uint retVoteCount) { return voteCount[addr]; } - function grantVoteRight(address addr) { + function grantVoteRight(address addr) public { canVote[addr] = true; } - function vote(address voter, address vote) returns (bool success) { + function vote(address voter, address vote) public returns (bool success) { if (!canVote[voter] || voted[voter]) return false; voted[voter] = true; voteCount[vote] = voteCount[vote] + 1; @@ -1118,7 +1421,7 @@ BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) contract test { uint value; mapping(uint => uint) table; - function f(uint x) returns (uint y) { + function f(uint x) public returns (uint y) { value = x; if (x > 0) table[++value] = 8; if (x > 1) value--; @@ -1150,7 +1453,7 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) char const* sourceCode = R"( contract test { mapping(uint => mapping(uint => uint)) table; - function f(uint x, uint y, uint z) returns (uint w) { + function f(uint x, uint y, uint z) public returns (uint w) { if (z == 0) return table[x][y]; else return table[x][y] = z; } @@ -1174,6 +1477,159 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); } +BOOST_AUTO_TEST_CASE(mapping_local_assignment) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + m = m2; + m[2] = 21; + + return (m1[1], m1[2], m2[1], m2[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(21))); +} + +BOOST_AUTO_TEST_CASE(mapping_local_tuple_assignment) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + uint8 v; + (m, v) = (m2, 21); + m[2] = v; + + return (m1[1], m1[2], m2[1], m2[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(21))); +} + +BOOST_AUTO_TEST_CASE(mapping_local_compound_assignment) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + (m = m2)[2] = 21; + + return (m1[1], m1[2], m2[1], m2[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(21))); +} + +BOOST_AUTO_TEST_CASE(mapping_internal_argument) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) a; + mapping(uint8 => uint8) b; + function set_internal(mapping(uint8 => uint8) storage m, uint8 key, uint8 value) internal returns (uint8) { + uint8 oldValue = m[key]; + m[key] = value; + return oldValue; + } + function set(uint8 key, uint8 value_a, uint8 value_b) public returns (uint8 old_a, uint8 old_b) { + old_a = set_internal(a, key, value_a); + old_b = set_internal(b, key, value_b); + } + function get(uint8 key) public returns (uint8, uint8) { + return (a[key], b[key]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", uint8_t(1), uint8_t(21), uint8_t(42)), encodeArgs(uint8_t(0), uint8_t(0))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(21), uint8_t(42))); + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", uint8_t(1), uint8_t(10), uint8_t(11)), encodeArgs(uint8_t(21), uint8_t(42))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(10), uint8_t(11))); +} + +BOOST_AUTO_TEST_CASE(mapping_array_internal_argument) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8)[2] a; + mapping(uint8 => uint8)[2] b; + function set_internal(mapping(uint8 => uint8)[2] storage m, uint8 key, uint8 value1, uint8 value2) internal returns (uint8, uint8) { + uint8 oldValue1 = m[0][key]; + uint8 oldValue2 = m[1][key]; + m[0][key] = value1; + m[1][key] = value2; + return (oldValue1, oldValue2); + } + function set(uint8 key, uint8 value_a1, uint8 value_a2, uint8 value_b1, uint8 value_b2) public returns (uint8 old_a1, uint8 old_a2, uint8 old_b1, uint8 old_b2) { + (old_a1, old_a2) = set_internal(a, key, value_a1, value_a2); + (old_b1, old_b2) = set_internal(b, key, value_b1, value_b2); + } + function get(uint8 key) public returns (uint8, uint8, uint8, uint8) { + return (a[0][key], a[1][key], b[0][key], b[1][key]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", uint8_t(1), uint8_t(21), uint8_t(22), uint8_t(42), uint8_t(43)), encodeArgs(uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(21), uint8_t(22), uint8_t(42), uint8_t(43))); + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", uint8_t(1), uint8_t(10), uint8_t(30), uint8_t(11), uint8_t(31)), encodeArgs(uint8_t(21), uint8_t(22), uint8_t(42), uint8_t(43))); + ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(10), uint8_t(30), uint8_t(11), uint8_t(31))); +} + +BOOST_AUTO_TEST_CASE(mapping_internal_return) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) a; + mapping(uint8 => uint8) b; + function f() internal returns (mapping(uint8 => uint8) storage r) { + r = a; + r[1] = 42; + r = b; + r[1] = 84; + } + function g() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { + f()[2] = 21; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + function h() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = f(); + m[2] = 17; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("g()"), encodeArgs(uint8_t(0), uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(84), uint8_t (21))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(uint8_t(0), uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(84), uint8_t (17))); +} + BOOST_AUTO_TEST_CASE(structs) { char const* sourceCode = R"( @@ -1188,7 +1644,7 @@ BOOST_AUTO_TEST_CASE(structs) mapping(uint8 => s2) recursive; } s2 data; - function check() returns (bool ok) { + function check() public returns (bool ok) { return data.z == 1 && data.s1data.x == 2 && data.s1data.y == true && data.recursive[3].recursive[4].z == 5 && @@ -1196,7 +1652,7 @@ BOOST_AUTO_TEST_CASE(structs) data.recursive[0].s1data.y == false && data.recursive[4].z == 9; } - function set() { + function set() public { data.z = 1; data.s1data.x = 2; data.s1data.y = true; @@ -1222,16 +1678,16 @@ BOOST_AUTO_TEST_CASE(struct_reference) mapping(uint8 => s2) recursive; } s2 data; - function check() returns (bool ok) { + function check() public returns (bool ok) { return data.z == 2 && data.recursive[0].z == 3 && data.recursive[0].recursive[1].z == 0 && data.recursive[0].recursive[0].z == 1; } - function set() { + function set() public { data.z = 2; - var map = data.recursive; - s2 inner = map[0]; + mapping(uint8 => s2) storage map = data.recursive; + s2 storage inner = map[0]; inner.z = 3; inner.recursive[0].z = inner.recursive[1].z + 1; } @@ -1249,7 +1705,6 @@ BOOST_AUTO_TEST_CASE(deleteStruct) contract test { struct topStruct { nestedStruct nstr; - emptyStruct empty; uint topValue; mapping (uint => uint) topMapping; } @@ -1259,9 +1714,7 @@ BOOST_AUTO_TEST_CASE(deleteStruct) uint nestedValue; mapping (uint => bool) nestedMapping; } - struct emptyStruct{ - } - function test(){ + constructor() public { toDelete = 5; str.topValue = 1; str.topMapping[0] = 1; @@ -1273,19 +1726,19 @@ BOOST_AUTO_TEST_CASE(deleteStruct) delete str; delete toDelete; } - function getToDelete() returns (uint res){ + function getToDelete() public returns (uint res){ res = toDelete; } - function getTopValue() returns(uint topValue){ + function getTopValue() public returns(uint topValue){ topValue = str.topValue; } - function getNestedValue() returns(uint nestedValue){ + function getNestedValue() public returns(uint nestedValue){ nestedValue = str.nstr.nestedValue; } - function getTopMapping(uint index) returns(uint ret) { + function getTopMapping(uint index) public returns(uint ret) { ret = str.topMapping[index]; } - function getNestedMapping(uint index) returns(bool ret) { + function getNestedMapping(uint index) public returns(bool ret) { return str.nstr.nestedMapping[index]; } } @@ -1305,7 +1758,7 @@ BOOST_AUTO_TEST_CASE(deleteLocal) { char const* sourceCode = R"( contract test { - function delLocal() returns (uint res){ + function delLocal() public returns (uint res){ uint v = 5; delete v; res = v; @@ -1320,7 +1773,7 @@ BOOST_AUTO_TEST_CASE(deleteLocals) { char const* sourceCode = R"( contract test { - function delLocal() returns (uint res1, uint res2){ + function delLocal() public returns (uint res1, uint res2){ uint v = 5; uint w = 6; uint x = 7; @@ -1334,21 +1787,39 @@ BOOST_AUTO_TEST_CASE(deleteLocals) ABI_CHECK(callContractFunction("delLocal()"), encodeArgs(6, 7)); } +BOOST_AUTO_TEST_CASE(deleteLength) +{ + char const* sourceCode = R"( + contract test { + uint[] x; + function f() public returns (uint){ + x.length = 1; + x[0] = 1; + delete x.length; + return x.length; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + BOOST_AUTO_TEST_CASE(constructor) { char const* sourceCode = R"( contract test { mapping(uint => uint) data; - function test() { + constructor() public { data[7] = 8; } - function get(uint key) returns (uint value) { + function get(uint key) public returns (uint value) { return data[key]; } } )"; compileAndRun(sourceCode); - map data; + map data; data[7] = 8; auto get = [&](u256 const& _x) -> u256 { @@ -1363,7 +1834,7 @@ BOOST_AUTO_TEST_CASE(simple_accessor) char const* sourceCode = R"( contract test { uint256 public data; - function test() { + constructor() public { data = 8; } } @@ -1382,7 +1853,7 @@ BOOST_AUTO_TEST_CASE(array_accessor) struct st { uint a; uint[] finalArray; } mapping(uint256 => mapping(uint256 => st[5])) public multiple_map; - function test() { + constructor() public { data[0] = 8; dynamicData.length = 3; dynamicData[2] = 8; @@ -1412,7 +1883,7 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) contract test { mapping(uint => uint[8]) public data; mapping(uint => uint[]) public dynamicData; - function test() { + constructor() public { data[2][2] = 8; dynamicData[2].length = 3; dynamicData[2][2] = 8; @@ -1434,10 +1905,10 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) bytes6 public name; bytes32 public a_hash; address public an_address; - function test() { + constructor() public { data = 8; name = "Celina"; - a_hash = keccak256(123); + a_hash = keccak256("\x7b"); an_address = address(0x1337); super_secret_data = 42; } @@ -1460,7 +1931,7 @@ BOOST_AUTO_TEST_CASE(complex_accessors) mapping(uint256 => bool) public to_bool_map; mapping(uint256 => uint256) public to_uint_map; mapping(uint256 => mapping(uint256 => uint256)) public to_multiple_map; - function test() { + constructor() public { to_string_map[42] = "24"; to_bool_map[42] = false; to_uint_map[42] = 12; @@ -1481,7 +1952,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor) contract test { struct Data { uint a; uint8 b; mapping(uint => uint) c; bool d; } mapping(uint => Data) public data; - function test() { + constructor() public { data[7].a = 1; data[7].b = 2; data[7].c[0] = 3; @@ -1497,8 +1968,8 @@ BOOST_AUTO_TEST_CASE(balance) { char const* sourceCode = R"( contract test { - function test() payable {} - function getBalance() returns (uint256 balance) { + constructor() public payable {} + function getBalance() public returns (uint256 balance) { return address(this).balance; } } @@ -1511,8 +1982,8 @@ BOOST_AUTO_TEST_CASE(blockchain) { char const* sourceCode = R"( contract test { - function test() payable {} - function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) { + constructor() public payable {} + function someInfo() public payable returns (uint256 value, address coinbase, uint256 blockNumber) { value = msg.value; coinbase = block.coinbase; blockNumber = block.number; @@ -1529,7 +2000,7 @@ BOOST_AUTO_TEST_CASE(msg_sig) { char const* sourceCode = R"( contract test { - function foo(uint256 a) returns (bytes4 value) { + function foo(uint256 a) public returns (bytes4 value) { return msg.sig; } } @@ -1542,10 +2013,10 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) { char const* sourceCode = R"( contract test { - function boo() returns (bytes4 value) { + function boo() public returns (bytes4 value) { return msg.sig; } - function foo(uint256 a) returns (bytes4 value) { + function foo(uint256 a) public returns (bytes4 value) { return boo(); } } @@ -1558,7 +2029,7 @@ BOOST_AUTO_TEST_CASE(now) { char const* sourceCode = R"( contract test { - function someInfo() returns (bool equal, uint val) { + function someInfo() public returns (bool equal, uint val) { equal = block.timestamp == now; val = now; } @@ -1581,7 +2052,7 @@ BOOST_AUTO_TEST_CASE(type_conversions_cleanup) // integer should drop the first two bytes char const* sourceCode = R"( contract Test { - function test() returns (uint ret) { return uint(address(Test(address(0x11223344556677889900112233445566778899001122)))); } + function test() public returns (uint ret) { return uint(address(Test(address(0x11223344556677889900112233445566778899001122)))); } } )"; compileAndRun(sourceCode); @@ -1594,7 +2065,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_smaller_size) { char const* sourceCode = R"( contract Test { - function bytesToBytes(bytes4 input) returns (bytes2 ret) { + function bytesToBytes(bytes4 input) public returns (bytes2 ret) { return bytes2(input); } } @@ -1607,7 +2078,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size) { char const* sourceCode = R"( contract Test { - function bytesToBytes(bytes2 input) returns (bytes4 ret) { + function bytesToBytes(bytes2 input) public returns (bytes4 ret) { return bytes4(input); } } @@ -1620,7 +2091,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size) { char const* sourceCode = R"( contract Test { - function bytesToBytes(bytes4 input) returns (bytes4 ret) { + function bytesToBytes(bytes4 input) public returns (bytes4 ret) { return bytes4(input); } } @@ -1634,7 +2105,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_size) { char const* sourceCode = R"( contract Test { - function bytesToUint(bytes32 s) returns (uint256 h) { + function bytesToUint(bytes32 s) public returns (uint256 h) { return uint(s); } } @@ -1650,7 +2121,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size) { char const* sourceCode = R"( contract Test { - function bytesToUint(bytes1 s) returns (uint8 h) { + function bytesToUint(bytes1 s) public returns (uint8 h) { return uint8(s); } } @@ -1666,8 +2137,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) { char const* sourceCode = R"( contract Test { - function bytesToUint(bytes4 s) returns (uint16 h) { - return uint16(s); + function bytesToUint(bytes4 s) public returns (uint16 h) { + return uint16(uint32(s)); } } )"; @@ -1682,8 +2153,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) { char const* sourceCode = R"( contract Test { - function bytesToUint(bytes4 s) returns (uint64 h) { - return uint64(s); + function bytesToUint(bytes4 s) public returns (uint64 h) { + return uint64(uint32(s)); } } )"; @@ -1699,7 +2170,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_size) { char const* sourceCode = R"( contract Test { - function uintToBytes(uint256 h) returns (bytes32 s) { + function uintToBytes(uint256 h) public returns (bytes32 s) { return bytes32(h); } } @@ -1713,7 +2184,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size) { char const* sourceCode = R"( contract Test { - function UintToBytes(uint8 h) returns (bytes1 s) { + function UintToBytes(uint8 h) public returns (bytes1 s) { return bytes1(h); } } @@ -1729,8 +2200,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) { char const* sourceCode = R"( contract Test { - function uintToBytes(uint32 h) returns (bytes2 s) { - return bytes2(h); + function uintToBytes(uint32 h) public returns (bytes2 s) { + return bytes2(uint16(h)); } } )"; @@ -1745,8 +2216,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) { char const* sourceCode = R"( contract Test { - function UintToBytes(uint16 h) returns (bytes8 s) { - return bytes8(h); + function UintToBytes(uint16 h) public returns (bytes8 s) { + return bytes8(uint64(h)); } } )"; @@ -1761,8 +2232,8 @@ BOOST_AUTO_TEST_CASE(send_ether) { char const* sourceCode = R"( contract test { - function test() payable {} - function a(address addr, uint amount) returns (uint ret) { + constructor() payable public {} + function a(address payable addr, uint amount) public returns (uint ret) { addr.send(amount); return address(this).balance; } @@ -1779,12 +2250,12 @@ BOOST_AUTO_TEST_CASE(transfer_ether) { char const* sourceCode = R"( contract A { - function A() payable {} - function a(address addr, uint amount) returns (uint) { + constructor() public payable {} + function a(address payable addr, uint amount) public returns (uint) { addr.transfer(amount); - return this.balance; + return address(this).balance; } - function b(address addr, uint amount) { + function b(address payable addr, uint amount) public { addr.transfer(amount); } } @@ -1793,8 +2264,8 @@ BOOST_AUTO_TEST_CASE(transfer_ether) } contract C { - function () payable { - throw; + function () external payable { + revert(); } } )"; @@ -1817,8 +2288,7 @@ BOOST_AUTO_TEST_CASE(uncalled_blockhash) contract C { function f() public view returns (bytes32) { - var x = block.blockhash; - return x(block.number - 1); + return (blockhash)(block.number - 1); } } )"; @@ -1844,8 +2314,8 @@ BOOST_AUTO_TEST_CASE(log0) { char const* sourceCode = R"( contract test { - function a() { - log0(1); + function a() public { + log0(bytes32(uint256(1))); } } )"; @@ -1861,8 +2331,8 @@ BOOST_AUTO_TEST_CASE(log1) { char const* sourceCode = R"( contract test { - function a() { - log1(1, 2); + function a() public { + log1(bytes32(uint256(1)), bytes32(uint256(2))); } } )"; @@ -1879,8 +2349,8 @@ BOOST_AUTO_TEST_CASE(log2) { char const* sourceCode = R"( contract test { - function a() { - log2(1, 2, 3); + function a() public { + log2(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3))); } } )"; @@ -1898,8 +2368,8 @@ BOOST_AUTO_TEST_CASE(log3) { char const* sourceCode = R"( contract test { - function a() { - log3(1, 2, 3, 4); + function a() public { + log3(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3)), bytes32(uint256(4))); } } )"; @@ -1917,8 +2387,8 @@ BOOST_AUTO_TEST_CASE(log4) { char const* sourceCode = R"( contract test { - function a() { - log4(1, 2, 3, 4, 5); + function a() public { + log4(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3)), bytes32(uint256(4)), bytes32(uint256(5))); } } )"; @@ -1936,8 +2406,8 @@ BOOST_AUTO_TEST_CASE(log_in_constructor) { char const* sourceCode = R"( contract test { - function test() { - log1(1, 2); + constructor() public { + log1(bytes32(uint256(1)), bytes32(uint256(2))); } } )"; @@ -1949,31 +2419,12 @@ BOOST_AUTO_TEST_CASE(log_in_constructor) BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(u256(2))); } -BOOST_AUTO_TEST_CASE(suicide) -{ - char const* sourceCode = R"( - contract test { - function test() payable {} - function a(address receiver) returns (uint ret) { - suicide(receiver); - return 10; - } - } - )"; - u256 amount(130); - compileAndRun(sourceCode, amount); - u160 address(23); - ABI_CHECK(callContractFunction("a(address)", address), bytes()); - BOOST_CHECK(!addressHasCode(m_contractAddress)); - BOOST_CHECK_EQUAL(balanceAt(address), amount); -} - BOOST_AUTO_TEST_CASE(selfdestruct) { char const* sourceCode = R"( contract test { - function test() payable {} - function a(address receiver) returns (uint ret) { + constructor() public payable {} + function a(address payable receiver) public returns (uint ret) { selfdestruct(receiver); return 10; } @@ -1991,8 +2442,8 @@ BOOST_AUTO_TEST_CASE(keccak256) { char const* sourceCode = R"( contract test { - function a(bytes32 input) returns (bytes32 hash) { - return keccak256(input); + function a(bytes32 input) public returns (bytes32 hash) { + return keccak256(abi.encodePacked(input)); } } )"; @@ -2006,29 +2457,12 @@ BOOST_AUTO_TEST_CASE(keccak256) testContractAgainstCpp("a(bytes32)", f, u256(-1)); } -BOOST_AUTO_TEST_CASE(sha3) -{ - char const* sourceCode = R"( - contract test { - // to confuse the optimiser - function b(bytes32 input) returns (bytes32) { - return sha3(input); - } - function a(bytes32 input) returns (bool) { - return keccak256(input) == b(input); - } - } - )"; - compileAndRun(sourceCode); - BOOST_REQUIRE(callContractFunction("a(bytes32)", u256(42)) == encodeArgs(true)); -} - BOOST_AUTO_TEST_CASE(sha256) { char const* sourceCode = R"( contract test { - function a(bytes32 input) returns (bytes32 sha256hash) { - return sha256(input); + function a(bytes32 input) public returns (bytes32 sha256hash) { + return sha256(abi.encodePacked(input)); } } )"; @@ -2052,8 +2486,8 @@ BOOST_AUTO_TEST_CASE(ripemd) { char const* sourceCode = R"( contract test { - function a(bytes32 input) returns (bytes32 sha256hash) { - return ripemd160(input); + function a(bytes32 input) public returns (bytes32 sha256hash) { + return ripemd160(abi.encodePacked(input)); } } )"; @@ -2077,10 +2511,10 @@ BOOST_AUTO_TEST_CASE(packed_keccak256) { char const* sourceCode = R"( contract test { - function a(bytes32 input) returns (bytes32 hash) { - var b = 65536; + function a(bytes32 input) public returns (bytes32 hash) { + uint24 b = 65536; uint c = 256; - return keccak256(8, input, b, input, c); + return keccak256(abi.encodePacked(uint8(8), input, b, input, c)); } } )"; @@ -2105,14 +2539,14 @@ BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types) char const* sourceCode = R"( contract test { uint120[3] x; - function f() returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) { + function f() public returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) { uint120[] memory y = new uint120[](3); x[0] = y[0] = uint120(-2); x[1] = y[1] = uint120(-3); x[2] = y[2] = uint120(-4); - hash1 = keccak256(x); - hash2 = keccak256(y); - hash3 = keccak256(this.f); + hash1 = keccak256(abi.encodePacked(x)); + hash2 = keccak256(abi.encodePacked(y)); + hash3 = keccak256(abi.encodePacked(this.f)); } } )"; @@ -2129,10 +2563,10 @@ BOOST_AUTO_TEST_CASE(packed_sha256) { char const* sourceCode = R"( contract test { - function a(bytes32 input) returns (bytes32 hash) { - var b = 65536; + function a(bytes32 input) public returns (bytes32 hash) { + uint24 b = 65536; uint c = 256; - return sha256(8, input, b, input, c); + return sha256(abi.encodePacked(uint8(8), input, b, input, c)); } } )"; @@ -2156,10 +2590,10 @@ BOOST_AUTO_TEST_CASE(packed_ripemd160) { char const* sourceCode = R"( contract test { - function a(bytes32 input) returns (bytes32 hash) { - var b = 65536; + function a(bytes32 input) public returns (bytes32 hash) { + uint24 b = 65536; uint c = 256; - return ripemd160(8, input, b, input, c); + return ripemd160(abi.encodePacked(uint8(8), input, b, input, c)); } } )"; @@ -2183,14 +2617,14 @@ BOOST_AUTO_TEST_CASE(ecrecover) { char const* sourceCode = R"( contract test { - function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) { + function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) public returns (address addr) { return ecrecover(h, v, r, s); } } )"; compileAndRun(sourceCode); u256 h("0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"); - byte v = 28; + uint8_t v = 28; u256 r("0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"); u256 s("0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"); u160 addr("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); @@ -2201,22 +2635,23 @@ BOOST_AUTO_TEST_CASE(inter_contract_calls) { char const* sourceCode = R"( contract Helper { - function multiply(uint a, uint b) returns (uint c) { + function multiply(uint a, uint b) public returns (uint c) { return a * b; } } contract Main { Helper h; - function callHelper(uint a, uint b) returns (uint c) { + function callHelper(uint a, uint b) public returns (uint c) { return h.multiply(a, b); } - function getHelper() returns (address haddress) { + function getHelper() public returns (address haddress) { return address(h); } - function setHelper(address haddress) { + function setHelper(address haddress) public { h = Helper(haddress); } - })"; + } + )"; compileAndRun(sourceCode, 0, "Helper"); u160 const c_helperAddress = m_contractAddress; compileAndRun(sourceCode, 0, "Main"); @@ -2231,22 +2666,23 @@ BOOST_AUTO_TEST_CASE(inter_contract_calls_with_complex_parameters) { char const* sourceCode = R"( contract Helper { - function sel(uint a, bool select, uint b) returns (uint c) { + function sel(uint a, bool select, uint b) public returns (uint c) { if (select) return a; else return b; } } contract Main { Helper h; - function callHelper(uint a, bool select, uint b) returns (uint c) { + function callHelper(uint a, bool select, uint b) public returns (uint c) { return h.sel(a, select, b) * 3; } - function getHelper() returns (address haddress) { + function getHelper() public returns (address haddress) { return address(h); } - function setHelper(address haddress) { + function setHelper(address haddress) public { h = Helper(haddress); } - })"; + } + )"; compileAndRun(sourceCode, 0, "Helper"); u160 const c_helperAddress = m_contractAddress; compileAndRun(sourceCode, 0, "Main"); @@ -2262,22 +2698,23 @@ BOOST_AUTO_TEST_CASE(inter_contract_calls_accessing_this) { char const* sourceCode = R"( contract Helper { - function getAddress() returns (address addr) { + function getAddress() public returns (address addr) { return address(this); } } contract Main { Helper h; - function callHelper() returns (address addr) { + function callHelper() public returns (address addr) { return h.getAddress(); } - function getHelper() returns (address addr) { + function getHelper() public returns (address addr) { return address(h); } - function setHelper(address addr) { + function setHelper(address addr) public { h = Helper(addr); } - })"; + } + )"; compileAndRun(sourceCode, 0, "Helper"); u160 const c_helperAddress = m_contractAddress; compileAndRun(sourceCode, 0, "Main"); @@ -2290,25 +2727,26 @@ BOOST_AUTO_TEST_CASE(calls_to_this) { char const* sourceCode = R"( contract Helper { - function invoke(uint a, uint b) returns (uint c) { + function invoke(uint a, uint b) public returns (uint c) { return this.multiply(a, b, 10); } - function multiply(uint a, uint b, uint8 c) returns (uint ret) { + function multiply(uint a, uint b, uint8 c) public returns (uint ret) { return a * b + c; } } contract Main { Helper h; - function callHelper(uint a, uint b) returns (uint ret) { + function callHelper(uint a, uint b) public returns (uint ret) { return h.invoke(a, b); } - function getHelper() returns (address addr) { + function getHelper() public returns (address addr) { return address(h); } - function setHelper(address addr) { + function setHelper(address addr) public { h = Helper(addr); } - })"; + } + )"; compileAndRun(sourceCode, 0, "Helper"); u160 const c_helperAddress = m_contractAddress; compileAndRun(sourceCode, 0, "Main"); @@ -2325,25 +2763,25 @@ BOOST_AUTO_TEST_CASE(inter_contract_calls_with_local_vars) // so this tests correct stack slot allocation char const* sourceCode = R"( contract Helper { - function multiply(uint a, uint b) returns (uint c) { + function multiply(uint a, uint b) public returns (uint c) { return a * b; } } contract Main { Helper h; - function callHelper(uint a, uint b) returns (uint c) { - var fu = h.multiply; - var y = 9; - var ret = fu(a, b); + function callHelper(uint a, uint b) public returns (uint c) { + uint8 y = 9; + uint256 ret = h.multiply(a, b); return ret + y; } - function getHelper() returns (address haddress) { + function getHelper() public returns (address haddress) { return address(h); } - function setHelper(address haddress) { + function setHelper(address haddress) public { h = Helper(haddress); } - })"; + } + )"; compileAndRun(sourceCode, 0, "Helper"); u160 const c_helperAddress = m_contractAddress; compileAndRun(sourceCode, 0, "Main"); @@ -2358,22 +2796,23 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_in_calls) { char const* sourceCode = R"( contract Helper { - function invoke(bytes3 x, bool stop) returns (bytes4 ret) { + function invoke(bytes3 x, bool stop) public returns (bytes4 ret) { return x; } } contract Main { Helper h; - function callHelper(bytes2 x, bool stop) returns (bytes5 ret) { + function callHelper(bytes2 x, bool stop) public returns (bytes5 ret) { return h.invoke(x, stop); } - function getHelper() returns (address addr) { + function getHelper() public returns (address addr) { return address(h); } - function setHelper(address addr) { + function setHelper(address addr) public { h = Helper(addr); } - })"; + } + )"; compileAndRun(sourceCode, 0, "Helper"); u160 const c_helperAddress = m_contractAddress; compileAndRun(sourceCode, 0, "Main"); @@ -2389,21 +2828,22 @@ BOOST_AUTO_TEST_CASE(constructor_arguments_internal) bytes3 name; bool flag; - function Helper(bytes3 x, bool f) { + constructor(bytes3 x, bool f) public { name = x; flag = f; } - function getName() returns (bytes3 ret) { return name; } - function getFlag() returns (bool ret) { return flag; } + function getName() public returns (bytes3 ret) { return name; } + function getFlag() public returns (bool ret) { return flag; } } contract Main { Helper h; - function Main() { + constructor() public { h = new Helper("abc", true); } - function getFlag() returns (bool ret) { return h.getFlag(); } - function getName() returns (bytes3 ret) { return h.getName(); } - })"; + function getFlag() public returns (bool ret) { return h.getFlag(); } + function getName() public returns (bytes3 ret) { return h.getName(); } + } + )"; compileAndRun(sourceCode, 0, "Main"); ABI_CHECK(callContractFunction("getFlag()"), encodeArgs(true)); ABI_CHECK(callContractFunction("getName()"), encodeArgs("abc")); @@ -2416,12 +2856,12 @@ BOOST_AUTO_TEST_CASE(constructor_arguments_external) bytes3 name; bool flag; - function Main(bytes3 x, bool f) { + constructor(bytes3 x, bool f) public { name = x; flag = f; } - function getName() returns (bytes3 ret) { return name; } - function getFlag() returns (bool ret) { return flag; } + function getName() public returns (bytes3 ret) { return name; } + function getFlag() public returns (bool ret) { return flag; } } )"; compileAndRun(sourceCode, 0, "Main", encodeArgs("abc", true)); @@ -2436,7 +2876,7 @@ BOOST_AUTO_TEST_CASE(constructor_with_long_arguments) string public a; string public b; - function Main(string _a, string _b) { + constructor(string memory _a, string memory _b) public { a = _a; b = _b; } @@ -2464,7 +2904,7 @@ BOOST_AUTO_TEST_CASE(constructor_static_array_argument) uint public a; uint[3] public b; - function C(uint _a, uint[3] _b) { + constructor(uint _a, uint[3] memory _b) public { a = _a; b = _b; } @@ -2484,7 +2924,7 @@ BOOST_AUTO_TEST_CASE(constant_var_as_array_length) uint constant LEN = 3; uint[LEN] public a; - function C(uint[LEN] _a) { + constructor(uint[LEN] memory _a) public { a = _a; } } @@ -2501,12 +2941,13 @@ BOOST_AUTO_TEST_CASE(functions_called_by_constructor) contract Test { bytes3 name; bool flag; - function Test() { + constructor() public { setName("abc"); } - function getName() returns (bytes3 ret) { return name; } + function getName() public returns (bytes3 ret) { return name; } function setName(bytes3 _name) private { name = _name; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc")); } @@ -2515,14 +2956,14 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses) { char const* sourceCode = R"( contract helper { - function() payable { } // can receive ether + function() external payable { } // can receive ether } contract test { helper h; - function test() payable { h = new helper(); h.send(5); } - function getBalance() returns (uint256 myBalance, uint256 helperBalance) { - myBalance = this.balance; - helperBalance = h.balance; + constructor() public payable { h = new helper(); address(h).send(5); } + function getBalance() public returns (uint256 myBalance, uint256 helperBalance) { + myBalance = address(this).balance; + helperBalance = address(h).balance; } } )"; @@ -2536,25 +2977,25 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic) char const* sourceCode = R"( contract helper { bool flag; - function getBalance() payable returns (uint256 myBalance) { - return this.balance; + function getBalance() payable public returns (uint256 myBalance) { + return address(this).balance; } - function setFlag() { flag = true; } - function getFlag() returns (bool fl) { return flag; } + function setFlag() public { flag = true; } + function getFlag() public returns (bool fl) { return flag; } } contract test { helper h; - function test() payable { h = new helper(); } - function sendAmount(uint amount) payable returns (uint256 bal) { + constructor() public payable { h = new helper(); } + function sendAmount(uint amount) public payable returns (uint256 bal) { return h.getBalance.value(amount)(); } - function outOfGas() returns (bool ret) { + function outOfGas() public returns (bool ret) { h.setFlag.gas(2)(); // should fail due to OOG return true; } - function checkState() returns (bool flagAfter, uint myBal) { + function checkState() public returns (bool flagAfter, uint myBal) { flagAfter = h.getFlag(); - myBal = this.balance; + myBal = address(this).balance; } } )"; @@ -2565,22 +3006,104 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic) BOOST_REQUIRE(callContractFunction("checkState()") == encodeArgs(false, 20 - 5)); } +BOOST_AUTO_TEST_CASE(gasleft_decrease) +{ + char const* sourceCode = R"( + contract C { + uint v; + function f() public returns (bool) { + uint startGas = gasleft(); + v++; + assert(startGas > gasleft()); + return true; + } + function g() public returns (bool) { + uint startGas = gasleft(); + assert(startGas > gasleft()); + return true; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(true)); +} + +BOOST_AUTO_TEST_CASE(gaslimit) +{ + char const* sourceCode = R"( + contract C { + function f() public returns (uint) { + return block.gaslimit; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(gasLimit())); +} + +BOOST_AUTO_TEST_CASE(gasprice) +{ + char const* sourceCode = R"( + contract C { + function f() public returns (uint) { + return tx.gasprice; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(gasPrice())); +} + +BOOST_AUTO_TEST_CASE(blockhash) +{ + // depending on the aleth version, this test only works for pre-constantinople + if (Options::get().evmVersion() < EVMVersion::constantinople()) + { + char const* sourceCode = R"( + contract C { + uint256 counter; + function g() public returns (bool) { counter++; return true; } + function f() public returns (bytes32[] memory r) { + r = new bytes32[](259); + for (uint i = 0; i < 259; i++) + r[i] = blockhash(block.number - 257 + i); + } + } + )"; + compileAndRun(sourceCode); + // generate a sufficient amount of blocks + while (blockNumber() < u256(255)) + ABI_CHECK(callContractFunction("g()"), encodeArgs(true)); + + vector hashes; + // ``blockhash()`` is only valid for the last 256 blocks, otherwise zero + hashes.emplace_back(0); + for (u256 i = blockNumber() - u256(255); i <= blockNumber(); i++) + hashes.emplace_back(blockHash(i)); + // the current block hash is not yet known at execution time and therefore zero + hashes.emplace_back(0); + // future block hashes are zero + hashes.emplace_back(0); + + ABI_CHECK(callContractFunction("f()"), encodeDyn(hashes)); + } +} + BOOST_AUTO_TEST_CASE(value_complex) { char const* sourceCode = R"( contract helper { - function getBalance() payable returns (uint256 myBalance) { - return this.balance; + function getBalance() payable public returns (uint256 myBalance) { + return address(this).balance; } } contract test { helper h; - function test() payable { h = new helper(); } - function sendAmount(uint amount) payable returns (uint256 bal) { - var x1 = h.getBalance.value(amount); + constructor() public payable { h = new helper(); } + function sendAmount(uint amount) public payable returns (uint256 bal) { uint someStackElement = 20; - var x2 = x1.gas(1000); - return x2.value(amount + 3)();// overwrite value + return h.getBalance.value(amount).gas(1000).value(amount + 3)(); } } )"; @@ -2592,18 +3115,15 @@ BOOST_AUTO_TEST_CASE(value_insane) { char const* sourceCode = R"( contract helper { - function getBalance() payable returns (uint256 myBalance) { - return this.balance; + function getBalance() payable public returns (uint256 myBalance) { + return address(this).balance; } } contract test { helper h; - function test() payable { h = new helper(); } - function sendAmount(uint amount) returns (uint256 bal) { - var x1 = h.getBalance.value; - var x2 = x1(amount).gas; - var x3 = x2(1000).value; - return x3(amount + 3)();// overwrite value + constructor() public payable { h = new helper(); } + function sendAmount(uint amount) public returns (uint256 bal) { + return h.getBalance.value(amount).gas(1000).value(amount + 3)();// overwrite value } } )"; @@ -2617,22 +3137,23 @@ BOOST_AUTO_TEST_CASE(value_for_constructor) contract Helper { bytes3 name; bool flag; - function Helper(bytes3 x, bool f) payable { + constructor(bytes3 x, bool f) public payable { name = x; flag = f; } - function getName() returns (bytes3 ret) { return name; } - function getFlag() returns (bool ret) { return flag; } + function getName() public returns (bytes3 ret) { return name; } + function getFlag() public returns (bool ret) { return flag; } } contract Main { Helper h; - function Main() payable { + constructor() public payable { h = (new Helper).value(10)("abc", true); } - function getFlag() returns (bool ret) { return h.getFlag(); } - function getName() returns (bytes3 ret) { return h.getName(); } - function getBalances() returns (uint me, uint them) { me = this.balance; them = h.balance;} - })"; + function getFlag() public returns (bool ret) { return h.getFlag(); } + function getName() public returns (bytes3 ret) { return h.getName(); } + function getBalances() public returns (uint me, uint them) { me = address(this).balance; them = address(h).balance;} + } + )"; compileAndRun(sourceCode, 22, "Main"); BOOST_REQUIRE(callContractFunction("getFlag()") == encodeArgs(true)); BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc")); @@ -2643,11 +3164,11 @@ BOOST_AUTO_TEST_CASE(virtual_function_calls) { char const* sourceCode = R"( contract Base { - function f() returns (uint i) { return g(); } - function g() returns (uint i) { return 1; } + function f() public returns (uint i) { return g(); } + function g() public returns (uint i) { return 1; } } contract Derived is Base { - function g() returns (uint i) { return 2; } + function g() public returns (uint i) { return 2; } } )"; compileAndRun(sourceCode, 0, "Derived"); @@ -2660,16 +3181,16 @@ BOOST_AUTO_TEST_CASE(access_base_storage) char const* sourceCode = R"( contract Base { uint dataBase; - function getViaBase() returns (uint i) { return dataBase; } + function getViaBase() public returns (uint i) { return dataBase; } } contract Derived is Base { uint dataDerived; - function setData(uint base, uint derived) returns (bool r) { + function setData(uint base, uint derived) public returns (bool r) { dataBase = base; dataDerived = derived; return true; } - function getViaDerived() returns (uint base, uint derived) { + function getViaDerived() public returns (uint base, uint derived) { base = dataBase; derived = dataDerived; } @@ -2686,11 +3207,11 @@ BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) char const* sourceCode = R"( contract Base { uint data; - function setData(uint i) { data = i; } - function getViaBase() returns (uint i) { return data; } + function setData(uint i) public { data = i; } + function getViaBase() public returns (uint i) { return data; } } - contract A is Base { function setViaA(uint i) { setData(i); } } - contract B is Base { function getViaB() returns (uint i) { return getViaBase(); } } + contract A is Base { function setViaA(uint i) public { setData(i); } } + contract B is Base { function getViaB() public returns (uint i) { return getViaBase(); } } contract Derived is Base, B, A { } )"; compileAndRun(sourceCode, 0, "Derived"); @@ -2702,11 +3223,11 @@ BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) BOOST_AUTO_TEST_CASE(explicit_base_class) { char const* sourceCode = R"( - contract BaseBase { function g() returns (uint r) { return 1; } } - contract Base is BaseBase { function g() returns (uint r) { return 2; } } + contract BaseBase { function g() public returns (uint r) { return 1; } } + contract Base is BaseBase { function g() public returns (uint r) { return 2; } } contract Derived is Base { - function f() returns (uint r) { return BaseBase.g(); } - function g() returns (uint r) { return 3; } + function f() public returns (uint r) { return BaseBase.g(); } + function g() public returns (uint r) { return 3; } } )"; compileAndRun(sourceCode, 0, "Derived"); @@ -2719,17 +3240,17 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments) char const* sourceCode = R"( contract BaseBase { uint m_a; - function BaseBase(uint a) { + constructor(uint a) public { m_a = a; } } contract Base is BaseBase(7) { - function Base() { + constructor() public { m_a *= m_a; } } contract Derived is Base() { - function getA() returns (uint r) { return m_a; } + function getA() public returns (uint r) { return m_a; } } )"; compileAndRun(sourceCode, 0, "Derived"); @@ -2741,15 +3262,15 @@ BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments) char const* sourceCode = R"( contract BaseBase { uint m_a; - function BaseBase(uint a) { + constructor(uint a) public { m_a = a; } - function g() returns (uint r) { return 2; } + function g() public returns (uint r) { return 2; } } contract Base is BaseBase(BaseBase.g()) { } contract Derived is Base() { - function getA() returns (uint r) { return m_a; } + function getA() public returns (uint r) { return m_a; } } )"; compileAndRun(sourceCode, 0, "Derived"); @@ -2761,46 +3282,28 @@ BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments) char const* sourceCode = R"( contract BaseBase { uint m_a; - function BaseBase(uint a) { + constructor(uint a) public { m_a = a; } - function overridden() returns (uint r) { return 1; } - function g() returns (uint r) { return overridden(); } + function overridden() public returns (uint r) { return 1; } + function g() public returns (uint r) { return overridden(); } } contract Base is BaseBase(BaseBase.g()) { } contract Derived is Base() { - function getA() returns (uint r) { return m_a; } - function overridden() returns (uint r) { return 2; } + function getA() public returns (uint r) { return m_a; } + function overridden() public returns (uint r) { return 2; } } )"; compileAndRun(sourceCode, 0, "Derived"); ABI_CHECK(callContractFunction("getA()"), encodeArgs(2)); } -BOOST_AUTO_TEST_CASE(constructor_argument_overriding) -{ - char const* sourceCode = R"( - contract BaseBase { - uint m_a; - function BaseBase(uint a) { - m_a = a; - } - } - contract Base is BaseBase(2) { } - contract Derived is BaseBase(3), Base { - function getA() returns (uint r) { return m_a; } - } - )"; - compileAndRun(sourceCode, 0, "Derived"); - ABI_CHECK(callContractFunction("getA()"), encodeArgs(3)); -} - BOOST_AUTO_TEST_CASE(internal_constructor) { char const* sourceCode = R"( contract C { - function C() internal {} + constructor() internal {} } )"; BOOST_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "C").empty()); @@ -2810,7 +3313,7 @@ BOOST_AUTO_TEST_CASE(function_modifier) { char const* sourceCode = R"( contract C { - function getOne() payable nonFree returns (uint r) { return 1; } + function getOne() payable nonFree public returns (uint r) { return 1; } modifier nonFree { if (msg.value > 0) _; } } )"; @@ -2823,9 +3326,9 @@ BOOST_AUTO_TEST_CASE(function_modifier_local_variables) { char const* sourceCode = R"( contract C { - modifier mod1 { var a = 1; var b = 2; _; } + modifier mod1 { uint8 a = 1; uint8 b = 2; _; } modifier mod2(bool a) { if (a) return; else _; } - function f(bool a) mod1 mod2(a) returns (uint r) { return 3; } + function f(bool a) mod1 mod2(a) public returns (uint r) { return 3; } } )"; compileAndRun(sourceCode); @@ -2837,8 +3340,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_loop) { char const* sourceCode = R"( contract C { - modifier repeat(uint count) { for (var i = 0; i < count; ++i) _; } - function f() repeat(10) returns (uint r) { r += 1; } + modifier repeat(uint count) { uint i; for (i = 0; i < count; ++i) _; } + function f() repeat(10) public returns (uint r) { r += 1; } } )"; compileAndRun(sourceCode); @@ -2850,7 +3353,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_invocation) char const* sourceCode = R"( contract C { modifier repeat(bool twice) { if (twice) _; _; } - function f(bool twice) repeat(twice) returns (uint r) { r += 1; } + function f(bool twice) repeat(twice) public returns (uint r) { r += 1; } } )"; compileAndRun(sourceCode); @@ -2865,7 +3368,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_with_return) char const* sourceCode = R"( contract C { modifier repeat(bool twice) { if (twice) _; _; } - function f(bool twice) repeat(twice) returns (uint r) { r += 1; return r; } + function f(bool twice) repeat(twice) public returns (uint r) { r += 1; return r; } } )"; compileAndRun(sourceCode); @@ -2877,7 +3380,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_overriding) { char const* sourceCode = R"( contract A { - function f() mod returns (bool r) { return true; } + function f() mod public returns (bool r) { return true; } modifier mod { _; } } contract C is A { @@ -2893,18 +3396,18 @@ BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context) char const* sourceCode = R"( contract A { uint data; - function A() mod1 { f1(); } - function f1() mod2 { data |= 0x1; } - function f2() { data |= 0x20; } - function f3() { } + constructor() mod1 public { f1(); } + function f1() mod2 public { data |= 0x1; } + function f2() public { data |= 0x20; } + function f3() public { } modifier mod1 { f2(); _; } modifier mod2 { f3(); if (false) _; } - function getData() returns (uint r) { return data; } + function getData() public returns (uint r) { return data; } } contract C is A { modifier mod1 { f4(); _; } - function f3() { data |= 0x300; } - function f4() { data |= 0x4000; } + function f3() public { data |= 0x300; } + function f4() public { data |= 0x4000; } } )"; compileAndRun(sourceCode); @@ -2916,9 +3419,9 @@ BOOST_AUTO_TEST_CASE(function_modifier_for_constructor) char const* sourceCode = R"( contract A { uint data; - function A() mod1 { data |= 2; } + constructor() mod1 public { data |= 2; } modifier mod1 { data |= 1; _; } - function getData() returns (uint r) { return data; } + function getData() public returns (uint r) { return data; } } contract C is A { modifier mod1 { data |= 4; _; } @@ -2934,7 +3437,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times) contract C { uint public a; modifier mod(uint x) { a += x; _; } - function f(uint x) mod(2) mod(5) mod(x) returns(uint) { return a; } + function f(uint x) mod(2) mod(5) mod(x) public returns(uint) { return a; } } )"; compileAndRun(sourceCode); @@ -2948,7 +3451,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times_local_vars) contract C { uint public a; modifier mod(uint x) { uint b = x; a += b; _; a -= b; assert(b == x); } - function f(uint x) mod(2) mod(5) mod(x) returns(uint) { return a; } + function f(uint x) mod(2) mod(5) mod(x) public returns(uint) { return a; } } )"; compileAndRun(sourceCode); @@ -3012,11 +3515,10 @@ BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) { char const* sourceCode = R"( contract C { - function f() returns (uint r) { + function f() public returns (uint r) { uint; uint; uint; uint; int x = -7; - var a = uint; - return a(x); + return uint(x); } } )"; @@ -3027,10 +3529,10 @@ BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) BOOST_AUTO_TEST_CASE(super) { char const* sourceCode = R"( - contract A { function f() returns (uint r) { return 1; } } - contract B is A { function f() returns (uint r) { return super.f() | 2; } } - contract C is A { function f() returns (uint r) { return super.f() | 4; } } - contract D is B, C { function f() returns (uint r) { return super.f() | 8; } } + contract A { function f() public returns (uint r) { return 1; } } + contract B is A { function f() public returns (uint r) { return super.f() | 2; } } + contract C is A { function f() public returns (uint r) { return super.f() | 4; } } + contract D is B, C { function f() public returns (uint r) { return super.f() | 8; } } )"; compileAndRun(sourceCode, 0, "D"); ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8)); @@ -3039,10 +3541,10 @@ BOOST_AUTO_TEST_CASE(super) BOOST_AUTO_TEST_CASE(super_in_constructor) { char const* sourceCode = R"( - contract A { function f() returns (uint r) { return 1; } } - contract B is A { function f() returns (uint r) { return super.f() | 2; } } - contract C is A { function f() returns (uint r) { return super.f() | 4; } } - contract D is B, C { uint data; function D() { data = super.f() | 8; } function f() returns (uint r) { return data; } } + contract A { function f() public returns (uint r) { return 1; } } + contract B is A { function f() public returns (uint r) { return super.f() | 2; } } + contract C is A { function f() public returns (uint r) { return super.f() | 4; } } + contract D is B, C { uint data; constructor() public { data = super.f() | 8; } function f() public returns (uint r) { return data; } } )"; compileAndRun(sourceCode, 0, "D"); ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8)); @@ -3051,7 +3553,7 @@ BOOST_AUTO_TEST_CASE(super_in_constructor) BOOST_AUTO_TEST_CASE(super_alone) { char const* sourceCode = R"( - contract A { function f() { super; } } + contract A { function f() public { super; } } )"; compileAndRun(sourceCode, 0, "A"); ABI_CHECK(callContractFunction("f()"), encodeArgs()); @@ -3062,8 +3564,8 @@ BOOST_AUTO_TEST_CASE(fallback_function) char const* sourceCode = R"( contract A { uint data; - function() { data = 1; } - function getData() returns (uint r) { return data; } + function() external { data = 1; } + function getData() public returns (uint r) { return data; } } )"; compileAndRun(sourceCode); @@ -3077,8 +3579,8 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function) char const* sourceCode = R"( contract A { uint data; - function() { data = 1; } - function getData() returns (uint r) { return data; } + function() external { data = 1; } + function getData() public returns (uint r) { return data; } } contract B is A {} )"; @@ -3090,15 +3592,31 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function) BOOST_AUTO_TEST_CASE(default_fallback_throws) { - char const* sourceCode = R"( + char const* sourceCode = R"YY( contract A { - function f() returns (bool) { - return this.call(); + function f() public returns (bool) { + (bool success,) = address(this).call(""); + return success; } } - )"; + )YY"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); + + if (dev::test::Options::get().evmVersion().hasStaticCall()) + { + char const* sourceCode = R"YY( + contract A { + function f() public returns (bool) { + (bool success, bytes memory data) = address(this).staticcall(""); + assert(data.length == 0); + return success; + } + } + )YY"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); + } } BOOST_AUTO_TEST_CASE(short_data_calls_fallback) @@ -3107,16 +3625,18 @@ BOOST_AUTO_TEST_CASE(short_data_calls_fallback) contract A { uint public x; // Signature is d88e0b00 - function fow() { x = 3; } - function () { x = 2; } + function fow() public { x = 3; } + function () external { x = 2; } } )"; compileAndRun(sourceCode); // should call fallback sendMessage(asBytes("\xd8\x8e\x0b"), false, 0); + BOOST_CHECK(m_transactionSuccessful); ABI_CHECK(callContractFunction("x()"), encodeArgs(2)); // should call function sendMessage(asBytes(string("\xd8\x8e\x0b") + string(1, 0)), false, 0); + BOOST_CHECK(m_transactionSuccessful); ABI_CHECK(callContractFunction("x()"), encodeArgs(3)); } @@ -3125,12 +3645,12 @@ BOOST_AUTO_TEST_CASE(event) char const* sourceCode = R"( contract ClientReceipt { event Deposit(address indexed _from, bytes32 indexed _id, uint _value); - function deposit(bytes32 _id, bool _manually) payable { + function deposit(bytes32 _id, bool _manually) public payable { if (_manually) { bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f; - log3(bytes32(msg.value), s, bytes32(msg.sender), _id); + log3(bytes32(msg.value), s, bytes32(uint256(msg.sender)), _id); } else { - Deposit(msg.sender, _id, msg.value); + emit Deposit(msg.sender, _id, msg.value); } } } @@ -3156,7 +3676,7 @@ BOOST_AUTO_TEST_CASE(event_emit) char const* sourceCode = R"( contract ClientReceipt { event Deposit(address indexed _from, bytes32 indexed _id, uint _value); - function deposit(bytes32 _id) payable { + function deposit(bytes32 _id) public payable { emit Deposit(msg.sender, _id, msg.value); } } @@ -3179,8 +3699,8 @@ BOOST_AUTO_TEST_CASE(event_no_arguments) char const* sourceCode = R"( contract ClientReceipt { event Deposit(); - function deposit() { - Deposit(); + function deposit() public { + emit Deposit(); } } )"; @@ -3194,28 +3714,6 @@ BOOST_AUTO_TEST_CASE(event_no_arguments) BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()"))); } -BOOST_AUTO_TEST_CASE(event_access_through_base_name) -{ - char const* sourceCode = R"( - contract A { - event x(); - } - contract B is A { - function f() returns (uint) { - A.x(); - return 1; - } - } - )"; - compileAndRun(sourceCode); - callContractFunction("f()"); - BOOST_REQUIRE_EQUAL(m_logs.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); - BOOST_CHECK(m_logs[0].data.empty()); - BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("x()"))); -} - BOOST_AUTO_TEST_CASE(event_access_through_base_name_emit) { char const* sourceCode = R"( @@ -3223,7 +3721,7 @@ BOOST_AUTO_TEST_CASE(event_access_through_base_name_emit) event x(); } contract B is A { - function f() returns (uint) { + function f() public returns (uint) { emit A.x(); return 1; } @@ -3245,68 +3743,16 @@ BOOST_AUTO_TEST_CASE(events_with_same_name) event Deposit(); event Deposit(address _addr); event Deposit(address _addr, uint _amount); - function deposit() returns (uint) { - Deposit(); + function deposit() public returns (uint) { + emit Deposit(); return 1; } - function deposit(address _addr) returns (uint) { - Deposit(_addr); + function deposit(address _addr) public returns (uint) { + emit Deposit(_addr); return 1; } - function deposit(address _addr, uint _amount) returns (uint) { - Deposit(_addr, _amount); - return 1; - } - } - )"; - u160 const c_loggedAddress = m_contractAddress; - - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("deposit()"), encodeArgs(u256(1))); - BOOST_REQUIRE_EQUAL(m_logs.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); - BOOST_CHECK(m_logs[0].data.empty()); - BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()"))); - - ABI_CHECK(callContractFunction("deposit(address)", c_loggedAddress), encodeArgs(u256(1))); - BOOST_REQUIRE_EQUAL(m_logs.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); - BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress)); - BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address)"))); - - ABI_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)), encodeArgs(u256(1))); - BOOST_REQUIRE_EQUAL(m_logs.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); - BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress, 100)); - BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); - BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,uint256)"))); -} - -BOOST_AUTO_TEST_CASE(events_with_same_name_inherited) -{ - char const* sourceCode = R"( - contract A { - event Deposit(); - } - - contract B { - event Deposit(address _addr); - } - - contract ClientReceipt is A, B { - event Deposit(address _addr, uint _amount); - function deposit() returns (uint) { - Deposit(); - return 1; - } - function deposit(address _addr) returns (uint) { - Deposit(_addr); - return 1; - } - function deposit(address _addr, uint _amount) returns (uint) { - Deposit(_addr, _amount); + function deposit(address _addr, uint _amount) public returns (uint) { + emit Deposit(_addr, _amount); return 1; } } @@ -3349,15 +3795,15 @@ BOOST_AUTO_TEST_CASE(events_with_same_name_inherited_emit) contract ClientReceipt is A, B { event Deposit(address _addr, uint _amount); - function deposit() returns (uint) { + function deposit() public returns (uint) { emit Deposit(); return 1; } - function deposit(address _addr) returns (uint) { + function deposit(address _addr) public returns (uint) { emit Deposit(_addr); return 1; } - function deposit(address _addr, uint _amount) returns (uint) { + function deposit(address _addr, uint _amount) public returns (uint) { emit Deposit(_addr, _amount); return 1; } @@ -3393,8 +3839,8 @@ BOOST_AUTO_TEST_CASE(event_anonymous) char const* sourceCode = R"( contract ClientReceipt { event Deposit() anonymous; - function deposit() { - Deposit(); + function deposit() public { + emit Deposit(); } } )"; @@ -3408,8 +3854,8 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics) char const* sourceCode = R"( contract ClientReceipt { event Deposit(address indexed _from, bytes32 indexed _id, uint indexed _value, uint indexed _value2, bytes32 data) anonymous; - function deposit(bytes32 _id) payable { - Deposit(msg.sender, _id, msg.value, 2, "abc"); + function deposit(bytes32 _id) public payable { + emit Deposit(msg.sender, _id, msg.value, 2, "abc"); } } )"; @@ -3432,8 +3878,8 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data) char const* sourceCode = R"( contract ClientReceipt { event Deposit(address _from, bytes32 _id, uint _value, bool _flag); - function deposit(bytes32 _id) payable { - Deposit(msg.sender, _id, msg.value, true); + function deposit(bytes32 _id) public payable { + emit Deposit(msg.sender, _id, msg.value, true); } } )"; @@ -3453,8 +3899,8 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data) char const* sourceCode = R"( contract ClientReceipt { event Deposit(uint fixeda, bytes dynx, uint fixedb); - function deposit() { - Deposit(10, msg.data, 15); + function deposit() public { + emit Deposit(10, msg.data, 15); } } )"; @@ -3462,7 +3908,7 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data) callContractFunction("deposit()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); - BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 4) + FixedHash<4>(dev::keccak256("deposit()")).asBytes())); + BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 4, asString(FixedHash<4>(dev::keccak256("deposit()")).asBytes())))); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)"))); } @@ -3473,12 +3919,12 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage) contract ClientReceipt { bytes x; event Deposit(uint fixeda, bytes dynx, uint fixedb); - function deposit() { + function deposit() public { x.length = 3; x[0] = "A"; x[1] = "B"; x[2] = "C"; - Deposit(10, x, 15); + emit Deposit(10, x, 15); } } )"; @@ -3497,13 +3943,13 @@ BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage) contract ClientReceipt { bytes x; event Deposit(uint fixeda, bytes dynx, uint fixedb); - function deposit() { + function deposit() public { x.length = 31; x[0] = "A"; x[1] = "B"; x[2] = "C"; x[30] = "Z"; - Deposit(10, x, 15); + emit Deposit(10, x, 15); } } )"; @@ -3726,15 +4172,15 @@ BOOST_AUTO_TEST_CASE(event_indexed_string) string x; uint[4] y; event E(string indexed r, uint[4] indexed t); - function deposit() { + function deposit() public { bytes(x).length = 90; - for (uint i = 0; i < 90; i++) + for (uint8 i = 0; i < 90; i++) bytes(x)[i] = byte(i); y[0] = 4; y[1] = 5; y[2] = 6; y[3] = 7; - E(x, y); + emit E(x, y); } } )"; @@ -3758,7 +4204,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { char const* sourceCode = R"( contract test { - function f(uint, uint k) returns(uint ret_k, uint ret_g){ + function f(uint, uint k) public returns(uint ret_k, uint ret_g){ uint g = 8; ret_k = k; ret_g = g; @@ -3774,7 +4220,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) { char const* sourceCode = R"( contract test { - function f(uint k) returns(uint){ + function f(uint k) public returns(uint){ return k; } } @@ -3787,8 +4233,8 @@ BOOST_AUTO_TEST_CASE(sha256_empty) { char const* sourceCode = R"( contract C { - function f() returns (bytes32) { - return sha256(); + function f() public returns (bytes32) { + return sha256(""); } } )"; @@ -3800,8 +4246,8 @@ BOOST_AUTO_TEST_CASE(ripemd160_empty) { char const* sourceCode = R"( contract C { - function f() returns (bytes20) { - return ripemd160(); + function f() public returns (bytes20) { + return ripemd160(""); } } )"; @@ -3813,8 +4259,8 @@ BOOST_AUTO_TEST_CASE(keccak256_empty) { char const* sourceCode = R"( contract C { - function f() returns (bytes32) { - return keccak256(); + function f() public returns (bytes32) { + return keccak256(""); } } )"; @@ -3826,9 +4272,9 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments) { char const* sourceCode = R"( contract c { - function foo(uint a, uint b, uint c) returns (bytes32 d) + function foo(uint a, uint b, uint c) public returns (bytes32 d) { - d = keccak256(a, b, c); + d = keccak256(abi.encodePacked(a, b, c)); } } )"; @@ -3847,9 +4293,9 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_numeric_literals) { char const* sourceCode = R"( contract c { - function foo(uint a, uint16 b) returns (bytes32 d) + function foo(uint a, uint16 b) public returns (bytes32 d) { - d = keccak256(a, b, 145); + d = keccak256(abi.encodePacked(a, b, uint8(145))); } } )"; @@ -3868,13 +4314,13 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_string_literals) { char const* sourceCode = R"( contract c { - function foo() returns (bytes32 d) + function foo() public returns (bytes32 d) { d = keccak256("foo"); } - function bar(uint a, uint16 b) returns (bytes32 d) + function bar(uint a, uint16 b) public returns (bytes32 d) { - d = keccak256(a, b, 145, "foo"); + d = keccak256(abi.encodePacked(a, b, uint8(145), "foo")); } } )"; @@ -3897,7 +4343,7 @@ BOOST_AUTO_TEST_CASE(keccak256_with_bytes) char const* sourceCode = R"( contract c { bytes data; - function foo() returns (bool) + function foo() public returns (bool) { data.length = 3; data[0] = "f"; @@ -3913,58 +4359,38 @@ BOOST_AUTO_TEST_CASE(keccak256_with_bytes) BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) { - char const* sourceCode = R"( + char const* sourceCode = R"ABC( contract c { bytes data; - function foo() returns (bytes32) + function foo() public returns (bytes32) { data.length = 3; data[0] = "x"; data[1] = "y"; data[2] = "z"; - return keccak256("b", keccak256(data), "a"); + return keccak256(abi.encodePacked("b", keccak256(data), "a")); } } - )"; + )ABC"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("foo()"), encodeArgs( u256(dev::keccak256(bytes{'b'} + dev::keccak256("xyz").asBytes() + bytes{'a'})) )); } -BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) -{ - char const* sourceCode = R"( - contract c { - function foo(uint a, uint b, uint c) returns (bytes32 d) - { - d = sha3(a, b, c); - } - })"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13), encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - toBigEndian(u256(12)) + - toBigEndian(u256(13)) - ) - )); -} - BOOST_AUTO_TEST_CASE(generic_call) { char const* sourceCode = R"**( contract receiver { uint public received; - function receive(uint256 x) payable { received = x; } + function receive(uint256 x) public payable { received = x; } } contract sender { - function sender() payable {} - function doSend(address rec) returns (uint d) + constructor() public payable {} + function doSend(address rec) public returns (uint d) { bytes4 signature = bytes4(bytes32(keccak256("receive(uint256)"))); - rec.call.value(2)(signature, 23); + rec.call.value(2)(abi.encodeWithSelector(signature, 23)); return receiver(rec).received(); } } @@ -3976,38 +4402,6 @@ BOOST_AUTO_TEST_CASE(generic_call) BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 50 - 2); } -BOOST_AUTO_TEST_CASE(generic_callcode) -{ - char const* sourceCode = R"**( - contract Receiver { - uint public received; - function receive(uint256 x) payable { received = x; } - } - contract Sender { - uint public received; - function Sender() payable { } - function doSend(address rec) returns (uint d) - { - bytes4 signature = bytes4(bytes32(keccak256("receive(uint256)"))); - rec.callcode.value(2)(signature, 23); - return Receiver(rec).received(); - } - } - )**"; - compileAndRun(sourceCode, 0, "Receiver"); - u160 const c_receiverAddress = m_contractAddress; - compileAndRun(sourceCode, 50, "Sender"); - u160 const c_senderAddress = m_contractAddress; - ABI_CHECK(callContractFunction("doSend(address)", c_receiverAddress), encodeArgs(0)); - ABI_CHECK(callContractFunction("received()"), encodeArgs(23)); - m_contractAddress = c_receiverAddress; - ABI_CHECK(callContractFunction("received()"), encodeArgs(0)); - BOOST_CHECK(storageEmpty(c_receiverAddress)); - BOOST_CHECK(!storageEmpty(c_senderAddress)); - BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); - BOOST_CHECK_EQUAL(balanceAt(c_senderAddress), 50); -} - BOOST_AUTO_TEST_CASE(generic_delegatecall) { char const* sourceCode = R"**( @@ -4015,18 +4409,19 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall) uint public received; address public sender; uint public value; - function Receiver() payable {} - function receive(uint256 x) payable { received = x; sender = msg.sender; value = msg.value; } + constructor() public payable {} + function receive(uint256 x) public payable { received = x; sender = msg.sender; value = msg.value; } } contract Sender { uint public received; address public sender; uint public value; - function Sender() payable {} - function doSend(address rec) payable + constructor() public payable {} + function doSend(address rec) public payable { bytes4 signature = bytes4(bytes32(keccak256("receive(uint256)"))); - if (rec.delegatecall(signature, 23)) {} + (bool success,) = rec.delegatecall(abi.encodeWithSelector(signature, 23)); + success; } } )**"; @@ -4049,13 +4444,56 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall) BOOST_CHECK_EQUAL(balanceAt(c_senderAddress), 50 + 11); } +BOOST_AUTO_TEST_CASE(generic_staticcall) +{ + if (dev::test::Options::get().evmVersion().hasStaticCall()) + { + char const* sourceCode = R"**( + contract A { + uint public x; + constructor() public { x = 42; } + function pureFunction(uint256 p) public pure returns (uint256) { return p; } + function viewFunction(uint256 p) public view returns (uint256) { return p + x; } + function nonpayableFunction(uint256 p) public returns (uint256) { x = p; return x; } + function assertFunction(uint256 p) public view returns (uint256) { assert(x == p); return x; } + } + contract C { + function f(address a) public view returns (bool, bytes memory) + { + return a.staticcall(abi.encodeWithSignature("pureFunction(uint256)", 23)); + } + function g(address a) public view returns (bool, bytes memory) + { + return a.staticcall(abi.encodeWithSignature("viewFunction(uint256)", 23)); + } + function h(address a) public view returns (bool, bytes memory) + { + return a.staticcall(abi.encodeWithSignature("nonpayableFunction(uint256)", 23)); + } + function i(address a, uint256 v) public view returns (bool, bytes memory) + { + return a.staticcall(abi.encodeWithSignature("assertFunction(uint256)", v)); + } + } + )**"; + compileAndRun(sourceCode, 0, "A"); + u160 const c_addressA = m_contractAddress; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f(address)", c_addressA), encodeArgs(true, 0x40, 0x20, 23)); + ABI_CHECK(callContractFunction("g(address)", c_addressA), encodeArgs(true, 0x40, 0x20, 23 + 42)); + ABI_CHECK(callContractFunction("h(address)", c_addressA), encodeArgs(false, 0x40, 0x00)); + ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 42), encodeArgs(true, 0x40, 0x20, 42)); + ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 23), encodeArgs(false, 0x40, 0x00)); + } +} + BOOST_AUTO_TEST_CASE(library_call_in_homestead) { char const* sourceCode = R"( - library Lib { function m() returns (address) { return msg.sender; } } + library Lib { function m() public returns (address) { return msg.sender; } } contract Test { address public sender; - function f() { + function f() public { sender = Lib.m(); } } @@ -4099,12 +4537,37 @@ BOOST_AUTO_TEST_CASE(library_call_protection) ABI_CHECK(callContractFunction("pu()"), encodeArgs(2)); } + +BOOST_AUTO_TEST_CASE(library_staticcall_delegatecall) +{ + char const* sourceCode = R"( + library Lib { + function x() public view returns (uint) { + return 1; + } + } + contract Test { + uint t; + function f() public returns (uint) { + t = 2; + return this.g(); + } + function g() public view returns (uint) { + return Lib.x(); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1)); +} + BOOST_AUTO_TEST_CASE(store_bytes) { // this test just checks that the copy loop does not mess up the stack char const* sourceCode = R"( contract C { - function save() returns (uint r) { + function save() public returns (uint r) { r = 23; savedData = msg.data; r = 24; @@ -4122,14 +4585,15 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) { char const* sourceCode = R"( contract C { - function f() returns (bytes32) { - return keccak256("abc", msg.data); + function f() public returns (bytes32) { + return keccak256(abi.encodePacked("abc", msg.data)); } } )"; compileAndRun(sourceCode); bytes calldata1 = FixedHash<4>(dev::keccak256("f()")).asBytes() + bytes(61, 0x22) + bytes(12, 0x12); sendMessage(calldata1, false); + BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(m_output == encodeArgs(dev::keccak256(bytes{'a', 'b', 'c'} + calldata1))); } @@ -4138,15 +4602,15 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes) char const* sourceCode = R"( contract receiver { uint public received; - function receive(uint x) { received += x + 1; } - function() { received = 0x80; } + function receive(uint x) public { received += x + 1; } + function() external { received = 0x80; } } contract sender { - function sender() { rec = new receiver(); } - function() { savedData = msg.data; } - function forward() returns (bool) { !rec.call(savedData); return true; } - function clear() returns (bool) { delete savedData; return true; } - function val() returns (uint) { return rec.received(); } + constructor() public { rec = new receiver(); } + function() external { savedData = msg.data; } + function forward() public returns (bool) { address(rec).call(savedData); return true; } + function clear() public returns (bool) { delete savedData; return true; } + function val() public returns (uint) { return rec.received(); } receiver rec; bytes savedData; } @@ -4167,24 +4631,27 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes_length) char const* sourceCode = R"( contract receiver { uint public calledLength; - function() { calledLength = msg.data.length; } + function() external { calledLength = msg.data.length; } } contract sender { receiver rec; - constructor() { rec = new receiver(); } - function viaCalldata() returns (uint) { - require(rec.call(msg.data)); + constructor() public { rec = new receiver(); } + function viaCalldata() public returns (uint) { + (bool success,) = address(rec).call(msg.data); + require(success); return rec.calledLength(); } - function viaMemory() returns (uint) { + function viaMemory() public returns (uint) { bytes memory x = msg.data; - require(rec.call(x)); + (bool success,) = address(rec).call(x); + require(success); return rec.calledLength(); } bytes s; - function viaStorage() returns (uint) { + function viaStorage() public returns (uint) { s = msg.data; - require(rec.call(s)); + (bool success,) = address(rec).call(s); + require(success); return rec.calledLength(); } } @@ -4193,18 +4660,14 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes_length) // No additional data, just function selector ABI_CHECK(callContractFunction("viaCalldata()"), encodeArgs(4)); - ABI_CHECK(callContractFunction("viaMemory()"), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(4)); - ABI_CHECK(callContractFunction("viaStorage()"), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(4)); + ABI_CHECK(callContractFunction("viaMemory()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("viaStorage()"), encodeArgs(4)); // Some additional unpadded data bytes unpadded = asBytes(string("abc")); ABI_CHECK(callContractFunctionNoEncoding("viaCalldata()", unpadded), encodeArgs(7)); - ABI_CHECK(callContractFunctionNoEncoding("viaMemory()", unpadded), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(7)); - ABI_CHECK(callContractFunctionNoEncoding("viaStorage()", unpadded), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(7)); + ABI_CHECK(callContractFunctionNoEncoding("viaMemory()", unpadded), encodeArgs(7)); + ABI_CHECK(callContractFunctionNoEncoding("viaStorage()", unpadded), encodeArgs(7)); } BOOST_AUTO_TEST_CASE(copying_bytes_multiassign) @@ -4212,18 +4675,18 @@ BOOST_AUTO_TEST_CASE(copying_bytes_multiassign) char const* sourceCode = R"( contract receiver { uint public received; - function receive(uint x) { received += x + 1; } - function() { received = 0x80; } + function receive(uint x) public { received += x + 1; } + function() external { received = 0x80; } } contract sender { - function sender() { rec = new receiver(); } - function() { savedData1 = savedData2 = msg.data; } - function forward(bool selector) returns (bool) { - if (selector) { rec.call(savedData1); delete savedData1; } - else { rec.call(savedData2); delete savedData2; } + constructor() public { rec = new receiver(); } + function() external { savedData1 = savedData2 = msg.data; } + function forward(bool selector) public returns (bool) { + if (selector) { address(rec).call(savedData1); delete savedData1; } + else { address(rec).call(savedData2); delete savedData2; } return true; } - function val() returns (uint) { return rec.received(); } + function val() public returns (uint) { return rec.received(); } receiver rec; bytes savedData1; bytes savedData2; @@ -4244,8 +4707,8 @@ BOOST_AUTO_TEST_CASE(delete_removes_bytes_data) { char const* sourceCode = R"( contract c { - function() { data = msg.data; } - function del() returns (bool) { delete data; return true; } + function() external { data = msg.data; } + function del() public returns (bool) { delete data; return true; } bytes data; } )"; @@ -4260,8 +4723,8 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) { char const* sourceCode = R"( contract c { - function set() returns (bool) { data = msg.data; return true; } - function() { data = msg.data; } + function set() public returns (bool) { data = msg.data; return true; } + function() external { data = msg.data; } bytes data; } )"; @@ -4269,7 +4732,8 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); sendMessage(bytes(), false); - BOOST_CHECK(m_output == bytes()); + BOOST_CHECK(m_transactionSuccessful); + BOOST_CHECK(m_output.empty()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4277,8 +4741,8 @@ BOOST_AUTO_TEST_CASE(copy_removes_bytes_data) { char const* sourceCode = R"( contract c { - function set() returns (bool) { data1 = msg.data; return true; } - function reset() returns (bool) { data1 = data2; return true; } + function set() public returns (bool) { data1 = msg.data; return true; } + function reset() public returns (bool) { data1 = data2; return true; } bytes data1; bytes data2; } @@ -4294,8 +4758,8 @@ BOOST_AUTO_TEST_CASE(bytes_inside_mappings) { char const* sourceCode = R"( contract c { - function set(uint key) returns (bool) { data[key] = msg.data; return true; } - function copy(uint from, uint to) returns (bool) { data[to] = data[from]; return true; } + function set(uint key) public returns (bool) { data[key] = msg.data; return true; } + function copy(uint from, uint to) public returns (bool) { data[to] = data[from]; return true; } mapping(uint => bytes) data; } )"; @@ -4318,8 +4782,8 @@ BOOST_AUTO_TEST_CASE(bytes_length_member) { char const* sourceCode = R"( contract c { - function set() returns (bool) { data = msg.data; return true; } - function getLength() returns (uint) { return data.length; } + function set() public returns (bool) { data = msg.data; return true; } + function getLength() public returns (uint) { return data.length; } bytes data; } )"; @@ -4336,18 +4800,18 @@ BOOST_AUTO_TEST_CASE(struct_copy) struct Nested { uint x; uint y; } struct Struct { uint a; mapping(uint => Struct) b; Nested nested; uint c; } mapping(uint => Struct) data; - function set(uint k) returns (bool) { + function set(uint k) public returns (bool) { data[k].a = 1; data[k].nested.x = 3; data[k].nested.y = 4; data[k].c = 2; return true; } - function copy(uint from, uint to) returns (bool) { + function copy(uint from, uint to) public returns (bool) { data[to] = data[from]; return true; } - function retrieve(uint k) returns (uint a, uint x, uint y, uint c) + function retrieve(uint k) public returns (uint a, uint x, uint y, uint c) { a = data[k].a; x = data[k].nested.x; @@ -4376,17 +4840,17 @@ BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) struct Struct { uint a; bytes data; uint b; } Struct data1; Struct data2; - function set(uint _a, bytes _data, uint _b) external returns (bool) { + function set(uint _a, bytes calldata _data, uint _b) external returns (bool) { data1.a = _a; data1.b = _b; data1.data = _data; return true; } - function copy() returns (bool) { + function copy() public returns (bool) { data1 = data2; return true; } - function del() returns (bool) { + function del() public returns (bool) { delete data1; return true; } @@ -4412,10 +4876,10 @@ BOOST_AUTO_TEST_CASE(struct_copy_via_local) struct Struct { uint a; uint b; } Struct data1; Struct data2; - function test() returns (bool) { + function test() public returns (bool) { data1.a = 1; data1.b = 2; - var x = data1; + Struct memory x = data1; data2 = x; return data2.a == data1.a && data2.b == data1.b; } @@ -4430,11 +4894,11 @@ BOOST_AUTO_TEST_CASE(using_enums) char const* sourceCode = R"( contract test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() + constructor() public { choices = ActionChoices.GoStraight; } - function getChoice() returns (uint d) + function getChoice() public returns (uint d) { d = uint256(choices); } @@ -4450,20 +4914,20 @@ BOOST_AUTO_TEST_CASE(enum_explicit_overflow) char const* sourceCode = R"( contract test { enum ActionChoices { GoLeft, GoRight, GoStraight } - function test() + constructor() public { } - function getChoiceExp(uint x) returns (uint d) + function getChoiceExp(uint x) public returns (uint d) { choice = ActionChoices(x); d = uint256(choice); } - function getChoiceFromSigned(int x) returns (uint d) + function getChoiceFromSigned(int x) public returns (uint d) { choice = ActionChoices(x); d = uint256(choice); } - function getChoiceFromNegativeLiteral() returns (uint d) + function getChoiceFromNegativeLiteral() public returns (uint d) { choice = ActionChoices(-1); d = uint256(choice); @@ -4487,7 +4951,7 @@ BOOST_AUTO_TEST_CASE(storing_invalid_boolean) contract C { event Ev(bool); bool public perm; - function set() returns(uint) { + function set() public returns(uint) { bool tmp; assembly { tmp := 5 @@ -4495,19 +4959,19 @@ BOOST_AUTO_TEST_CASE(storing_invalid_boolean) perm = tmp; return 1; } - function ret() returns(bool) { + function ret() public returns(bool) { bool tmp; assembly { tmp := 5 } return tmp; } - function ev() returns(uint) { + function ev() public returns(uint) { bool tmp; assembly { tmp := 5 } - Ev(tmp); + emit Ev(tmp); return 1; } } @@ -4530,7 +4994,7 @@ BOOST_AUTO_TEST_CASE(using_contract_enums_with_explicit_contract_name) char const* sourceCode = R"( contract test { enum Choice { A, B, C } - function answer () returns (test.Choice _ret) + function answer () public returns (test.Choice _ret) { _ret = test.Choice.B; } @@ -4548,7 +5012,7 @@ BOOST_AUTO_TEST_CASE(using_inherited_enum) } contract test is base { - function answer () returns (Choice _ret) + function answer () public returns (Choice _ret) { _ret = Choice.B; } @@ -4566,7 +5030,7 @@ BOOST_AUTO_TEST_CASE(using_inherited_enum_excplicitly) } contract test is base { - function answer () returns (base.Choice _ret) + function answer () public returns (base.Choice _ret) { _ret = base.Choice.B; } @@ -4581,7 +5045,7 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) char const* sourceCode = R"( contract c { enum Truth { False, True } - function test() returns (uint) + function test() public returns (uint) { return uint(Truth(uint8(0x701))); } @@ -4591,23 +5055,130 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } +BOOST_AUTO_TEST_CASE(struct_referencing) +{ + static char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + interface I { + struct S { uint a; } + } + library L { + struct S { uint b; uint a; } + function f() public pure returns (S memory) { + S memory s; + s.a = 3; + return s; + } + function g() public pure returns (I.S memory) { + I.S memory s; + s.a = 4; + return s; + } + // argument-dependant lookup tests + function a(I.S memory) public pure returns (uint) { return 1; } + function a(S memory) public pure returns (uint) { return 2; } + } + contract C is I { + function f() public pure returns (S memory) { + S memory s; + s.a = 1; + return s; + } + function g() public pure returns (I.S memory) { + I.S memory s; + s.a = 2; + return s; + } + function h() public pure returns (L.S memory) { + L.S memory s; + s.a = 5; + return s; + } + function x() public pure returns (L.S memory) { + return L.f(); + } + function y() public pure returns (I.S memory) { + return L.g(); + } + function a1() public pure returns (uint) { S memory s; return L.a(s); } + function a2() public pure returns (uint) { L.S memory s; return L.a(s); } + } + )"; + compileAndRun(sourceCode, 0, "L"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0, 3)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(4)); + compileAndRun(sourceCode, 0, "C", bytes(), map{ {"L", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(0, 5)); + ABI_CHECK(callContractFunction("x()"), encodeArgs(0, 3)); + ABI_CHECK(callContractFunction("y()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("a1()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("a2()"), encodeArgs(2)); +} + +BOOST_AUTO_TEST_CASE(enum_referencing) +{ + char const* sourceCode = R"( + interface I { + enum Direction { A, B, Left, Right } + } + library L { + enum Direction { Left, Right } + function f() public pure returns (Direction) { + return Direction.Right; + } + function g() public pure returns (I.Direction) { + return I.Direction.Right; + } + } + contract C is I { + function f() public pure returns (Direction) { + return Direction.Right; + } + function g() public pure returns (I.Direction) { + return I.Direction.Right; + } + function h() public pure returns (L.Direction) { + return L.Direction.Right; + } + function x() public pure returns (L.Direction) { + return L.f(); + } + function y() public pure returns (I.Direction) { + return L.g(); + } + } + )"; + compileAndRun(sourceCode, 0, "L"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); + compileAndRun(sourceCode, 0, "C", bytes(), map{{"L", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("x()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("y()"), encodeArgs(3)); +} + BOOST_AUTO_TEST_CASE(inline_member_init) { char const* sourceCode = R"( contract test { - function test(){ + constructor() public { m_b = 6; m_c = 8; } uint m_a = 5; uint m_b; uint m_c = 7; - function get() returns (uint a, uint b, uint c){ + function get() public returns (uint a, uint b, uint c){ a = m_a; b = m_b; c = m_c; } - })"; + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("get()"), encodeArgs(5, 6, 8)); } @@ -4616,15 +5187,16 @@ BOOST_AUTO_TEST_CASE(inline_member_init_inheritence) { char const* sourceCode = R"( contract Base { - function Base(){} + constructor() public {} uint m_base = 5; - function getBMember() returns (uint i) { return m_base; } + function getBMember() public returns (uint i) { return m_base; } } contract Derived is Base { - function Derived(){} + constructor() public {} uint m_derived = 6; - function getDMember() returns (uint i) { return m_derived; } - })"; + function getDMember() public returns (uint i) { return m_derived; } + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("getBMember()"), encodeArgs(5)); ABI_CHECK(callContractFunction("getDMember()"), encodeArgs(6)); @@ -4635,12 +5207,13 @@ BOOST_AUTO_TEST_CASE(inline_member_init_inheritence_without_constructor) char const* sourceCode = R"( contract Base { uint m_base = 5; - function getBMember() returns (uint i) { return m_base; } + function getBMember() public returns (uint i) { return m_base; } } contract Derived is Base { uint m_derived = 6; - function getDMember() returns (uint i) { return m_derived; } - })"; + function getDMember() public returns (uint i) { return m_derived; } + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("getBMember()"), encodeArgs(5)); ABI_CHECK(callContractFunction("getDMember()"), encodeArgs(6)); @@ -4650,7 +5223,7 @@ BOOST_AUTO_TEST_CASE(external_function) { char const* sourceCode = R"( contract c { - function f(uint a) returns (uint) { return a; } + function f(uint a) public returns (uint) { return a; } function test(uint a, uint b) external returns (uint r_a, uint r_b) { r_a = f(a + 7); r_b = b; @@ -4666,12 +5239,12 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) char const* sourceCode = R"( contract c { uint result; - function f(uint a, uint b) { result += a + b; } - function g(uint a) { result *= a; } - function test(uint a, bytes data1, bytes data2, uint b) external returns (uint r_a, uint r, uint r_b, uint l) { + function f(uint a, uint b) public { result += a + b; } + function g(uint a) public { result *= a; } + function test(uint a, bytes calldata data1, bytes calldata data2, uint b) external returns (uint r_a, uint r, uint r_b, uint l) { r_a = a; - this.call(data1); - this.call(data2); + address(this).call(data1); + address(this).call(data2); r = result; r_b = b; l = data1.length; @@ -4699,12 +5272,12 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) struct Data { uint x; uint y; } Data[2**10] data; uint[2**10 + 3] ids; - function setIDStatic(uint id) { ids[2] = id; } - function setID(uint index, uint id) { ids[index] = id; } - function setData(uint index, uint x, uint y) { data[index].x = x; data[index].y = y; } - function getID(uint index) returns (uint) { return ids[index]; } - function getData(uint index) returns (uint x, uint y) { x = data[index].x; y = data[index].y; } - function getLengths() returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } + function setIDStatic(uint id) public { ids[2] = id; } + function setID(uint index, uint id) public { ids[index] = id; } + function setData(uint index, uint x, uint y) public { data[index].x = x; data[index].y = y; } + function getID(uint index) public returns (uint) { return ids[index]; } + function getData(uint index) public returns (uint x, uint y) { x = data[index].x; y = data[index].y; } + function getLengths() public returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } } )"; compileAndRun(sourceCode); @@ -4726,13 +5299,13 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) struct Data { uint x; uint y; } Data[] data; uint[] ids; - function setIDStatic(uint id) { ids[2] = id; } - function setID(uint index, uint id) { ids[index] = id; } - function setData(uint index, uint x, uint y) { data[index].x = x; data[index].y = y; } - function getID(uint index) returns (uint) { return ids[index]; } - function getData(uint index) returns (uint x, uint y) { x = data[index].x; y = data[index].y; } - function getLengths() returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } - function setLengths(uint l1, uint l2) { data.length = l1; ids.length = l2; } + function setIDStatic(uint id) public { ids[2] = id; } + function setID(uint index, uint id) public { ids[index] = id; } + function setData(uint index, uint x, uint y) public { data[index].x = x; data[index].y = y; } + function getID(uint index) public returns (uint) { return ids[index]; } + function getData(uint index) public returns (uint x, uint y) { x = data[index].x; y = data[index].y; } + function getLengths() public returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } + function setLengths(uint l1, uint l2) public { data.length = l1; ids.length = l2; } } )"; compileAndRun(sourceCode); @@ -4754,9 +5327,9 @@ BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access) char const* sourceCode = R"( contract c { uint[4] data; - function set(uint index, uint value) returns (bool) { data[index] = value; return true; } - function get(uint index) returns (uint) { return data[index]; } - function length() returns (uint) { return data.length; } + function set(uint index, uint value) public returns (bool) { data[index] = value; return true; } + function get(uint index) public returns (uint) { return data[index]; } + function length() public returns (uint) { return data.length; } } )"; compileAndRun(sourceCode); @@ -4775,10 +5348,10 @@ BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access) char const* sourceCode = R"( contract c { uint[] data; - function enlarge(uint amount) returns (uint) { return data.length += amount; } - function set(uint index, uint value) returns (bool) { data[index] = value; return true; } - function get(uint index) returns (uint) { return data[index]; } - function length() returns (uint) { return data.length; } + function enlarge(uint amount) public returns (uint) { return data.length += amount; } + function set(uint index, uint value) public returns (bool) { data[index] = value; return true; } + function get(uint index) public returns (uint) { return data[index]; } + function length() public returns (uint) { return data.length; } } )"; compileAndRun(sourceCode); @@ -4800,10 +5373,10 @@ BOOST_AUTO_TEST_CASE(fixed_array_cleanup) uint spacer1; uint spacer2; uint[20] data; - function fill() { + function fill() public { for (uint i = 0; i < data.length; ++i) data[i] = i+1; } - function clear() { delete data; } + function clear() public { delete data; } } )"; compileAndRun(sourceCode); @@ -4821,10 +5394,10 @@ BOOST_AUTO_TEST_CASE(short_fixed_array_cleanup) uint spacer1; uint spacer2; uint[3] data; - function fill() { + function fill() public { for (uint i = 0; i < data.length; ++i) data[i] = i+1; } - function clear() { delete data; } + function clear() public { delete data; } } )"; compileAndRun(sourceCode); @@ -4841,12 +5414,12 @@ BOOST_AUTO_TEST_CASE(dynamic_array_cleanup) contract c { uint[20] spacer; uint[] dynamic; - function fill() { + function fill() public { dynamic.length = 21; for (uint i = 0; i < dynamic.length; ++i) dynamic[i] = i+1; } - function halfClear() { dynamic.length = 5; } - function fullClear() { delete dynamic; } + function halfClear() public { dynamic.length = 5; } + function fullClear() public { delete dynamic; } } )"; compileAndRun(sourceCode); @@ -4865,14 +5438,14 @@ BOOST_AUTO_TEST_CASE(dynamic_multi_array_cleanup) contract c { struct s { uint[][] d; } s[] data; - function fill() returns (uint) { + function fill() public returns (uint) { data.length = 3; data[2].d.length = 4; data[2].d[3].length = 5; data[2].d[3][4] = 8; return data[2].d[3][4]; } - function clear() { delete data; } + function clear() public { delete data; } } )"; compileAndRun(sourceCode); @@ -4889,11 +5462,11 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_dyn_dyn) contract c { uint[] data1; uint[] data2; - function setData1(uint length, uint index, uint value) { + function setData1(uint length, uint index, uint value) public { data1.length = length; if (index < length) data1[index] = value; } - function copyStorageStorage() { data2 = data1; } - function getData2(uint index) returns (uint len, uint val) { + function copyStorageStorage() public { data2 = data1; } + function getData2(uint index) public returns (uint len, uint val) { len = data2.length; if (index < len) val = data2[index]; } } @@ -4914,7 +5487,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_static) contract c { uint[40] data1; uint[20] data2; - function test() returns (uint x, uint y){ + function test() public returns (uint x, uint y){ data1[30] = 4; data1[2] = 7; data1[3] = 9; @@ -4935,7 +5508,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_dynamic) contract c { uint[9] data1; uint[] data2; - function test() returns (uint x, uint y){ + function test() public returns (uint x, uint y){ data1[8] = 4; data2 = data1; x = data2.length; @@ -4953,10 +5526,10 @@ BOOST_AUTO_TEST_CASE(array_copy_different_packing) contract c { bytes8[] data1; // 4 per slot bytes10[] data2; // 3 per slot - function test() returns (bytes10 a, bytes10 b, bytes10 c, bytes10 d, bytes10 e) { + function test() public returns (bytes10 a, bytes10 b, bytes10 c, bytes10 d, bytes10 e) { data1.length = 9; for (uint i = 0; i < data1.length; ++i) - data1[i] = bytes8(i); + data1[i] = bytes8(uint64(i)); data2 = data1; a = data2[1]; b = data2[2]; @@ -4982,10 +5555,10 @@ BOOST_AUTO_TEST_CASE(array_copy_target_simple) contract c { bytes8[9] data1; // 4 per slot bytes17[10] data2; // 1 per slot, no offset counter - function test() returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) { + function test() public returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) { for (uint i = 0; i < data1.length; ++i) - data1[i] = bytes8(i); - data2[8] = data2[9] = 2; + data1[i] = bytes8(uint64(i)); + data2[8] = data2[9] = bytes8(uint64(2)); data2 = data1; a = data2[1]; b = data2[2]; @@ -5012,18 +5585,18 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover) contract c { byte[10] data1; bytes2[32] data2; - function test() returns (uint check, uint res1, uint res2) { + function test() public returns (uint check, uint res1, uint res2) { uint i; for (i = 0; i < data2.length; ++i) data2[i] = 0xffff; - check = uint(data2[31]) * 0x10000 | uint(data2[14]); + check = uint(uint16(data2[31])) * 0x10000 | uint(uint16(data2[14])); for (i = 0; i < data1.length; ++i) data1[i] = byte(uint8(1 + i)); data2 = data1; for (i = 0; i < 16; ++i) - res1 |= uint(data2[i]) * 0x10000**i; + res1 |= uint(uint16(data2[i])) * 0x10000**i; for (i = 0; i < 16; ++i) - res2 |= uint(data2[16 + i]) * 0x10000**i; + res2 |= uint(uint16(data2[16 + i])) * 0x10000**i; } } )"; @@ -5043,13 +5616,13 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover2) contract c { bytes8[4] data1; // fits into one slot bytes10[6] data2; // 4 elements need two slots - function test() returns (bytes10 r1, bytes10 r2, bytes10 r3) { - data1[0] = 1; - data1[1] = 2; - data1[2] = 3; - data1[3] = 4; + function test() public returns (bytes10 r1, bytes10 r2, bytes10 r3) { + data1[0] = bytes8(uint64(1)); + data1[1] = bytes8(uint64(2)); + data1[2] = bytes8(uint64(3)); + data1[3] = bytes8(uint64(4)); for (uint i = 0; i < data2.length; ++i) - data2[i] = bytes10(0xffff00 | (1 + i)); + data2[i] = bytes10(uint80(0xffff00 | (1 + i))); data2 = data1; r1 = data2[3]; r2 = data2[4]; @@ -5072,7 +5645,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct) struct Data { uint x; uint y; } Data[] data1; Data[] data2; - function test() returns (uint x, uint y) { + function test() public returns (uint x, uint y) { data1.length = 9; data1[8].x = 4; data1[8].y = 5; @@ -5100,22 +5673,22 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) uint16[] y; uint24[] z; uint24[][] w; - function test1() returns (uint8[]) { + function test1() public returns (uint8[] memory) { for (uint i = 0; i < 101; ++i) x.push(uint8(i)); return x; } - function test2() returns (uint16[]) { + function test2() public returns (uint16[] memory) { for (uint i = 0; i < 101; ++i) y.push(uint16(i)); return y; } - function test3() returns (uint24[]) { + function test3() public returns (uint24[] memory) { for (uint i = 0; i < 101; ++i) z.push(uint24(i)); return z; } - function test4() returns (uint24[][]) { + function test4() public returns (uint24[][] memory) { w.length = 5; for (uint i = 0; i < 5; ++i) for (uint j = 0; j < 101; ++j) @@ -5148,7 +5721,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi_signed) char const* sourceCode = R"( contract c { int16[] x; - function test() returns (int16[]) { + function test() public returns (int16[] memory) { x.push(int16(-1)); x.push(int16(-1)); x.push(int16(8)); @@ -5180,7 +5753,7 @@ BOOST_AUTO_TEST_CASE(array_push) char const* sourceCode = R"( contract c { uint[] data; - function test() returns (uint x, uint y, uint z, uint l) { + function test() public returns (uint x, uint y, uint z, uint l) { data.push(5); x = data[0]; data.push(4); @@ -5200,7 +5773,7 @@ BOOST_AUTO_TEST_CASE(array_push_struct) contract c { struct S { uint16 a; uint16 b; uint16[3] c; uint16[] d; } S[] data; - function test() returns (uint16, uint16, uint16, uint16) { + function test() public returns (uint16, uint16, uint16, uint16) { S memory s; s.a = 2; s.b = 3; @@ -5221,7 +5794,7 @@ BOOST_AUTO_TEST_CASE(array_push_packed_array) char const* sourceCode = R"( contract c { uint80[] x; - function test() returns (uint80, uint80, uint80, uint80) { + function test() public returns (uint80, uint80, uint80, uint80) { x.push(1); x.push(2); x.push(3); @@ -5241,14 +5814,14 @@ BOOST_AUTO_TEST_CASE(byte_array_push) char const* sourceCode = R"( contract c { bytes data; - function test() returns (bool x) { - if (data.push(5) != 1) return true; - if (data[0] != 5) return true; - data.push(4); - if (data[1] != 4) return true; - uint l = data.push(3); - if (data[2] != 3) return true; - if (l != 3) return true; + function test() public returns (bool x) { + if (data.push(0x05) != 1) return true; + if (data[0] != 0x05) return true; + data.push(0x04); + if (data[1] != 0x04) return true; + uint l = data.push(0x03); + if (data[2] != 0x03) return true; + if (l != 0x03) return true; } } )"; @@ -5262,14 +5835,14 @@ BOOST_AUTO_TEST_CASE(byte_array_push_transition) char const* sourceCode = R"( contract c { bytes data; - function test() returns (uint) { - for (uint i = 1; i < 40; i++) + function test() public returns (uint) { + for (uint8 i = 1; i < 40; i++) { data.push(byte(i)); if (data.length != i) return 0x1000 + i; if (data[data.length - 1] != byte(i)) return i; } - for (i = 1; i < 40; i++) + for (uint8 i = 1; i < 40; i++) if (data[i - 1] != byte(i)) return 0x1000000 + i; return 0; } @@ -5279,11 +5852,331 @@ BOOST_AUTO_TEST_CASE(byte_array_push_transition) ABI_CHECK(callContractFunction("test()"), encodeArgs(0)); } +BOOST_AUTO_TEST_CASE(array_pop) +{ + char const* sourceCode = R"( + contract c { + uint[] data; + function test() public returns (uint x, uint l) { + data.push(7); + x = data.push(3); + data.pop(); + x = data.length; + data.pop(); + l = data.length; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1, 0)); +} + +BOOST_AUTO_TEST_CASE(array_pop_uint16_transition) +{ + char const* sourceCode = R"( + contract c { + uint16[] data; + function test() public returns (uint16 x, uint16 y, uint16 z) { + for (uint i = 1; i <= 48; i++) + data.push(uint16(i)); + for (uint j = 1; j <= 10; j++) + data.pop(); + x = data[data.length - 1]; + for (uint k = 1; k <= 10; k++) + data.pop(); + y = data[data.length - 1]; + for (uint l = 1; l <= 10; l++) + data.pop(); + z = data[data.length - 1]; + for (uint m = 1; m <= 18; m++) + data.pop(); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(38, 28, 18)); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + +BOOST_AUTO_TEST_CASE(array_pop_uint24_transition) +{ + char const* sourceCode = R"( + contract c { + uint256 a; + uint256 b; + uint256 c; + uint24[] data; + function test() public returns (uint24 x, uint24 y) { + for (uint i = 1; i <= 30; i++) + data.push(uint24(i)); + for (uint j = 1; j <= 10; j++) + data.pop(); + x = data[data.length - 1]; + for (uint k = 1; k <= 10; k++) + data.pop(); + y = data[data.length - 1]; + for (uint l = 1; l <= 10; l++) + data.pop(); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(20, 10)); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + +BOOST_AUTO_TEST_CASE(array_pop_array_transition) +{ + char const* sourceCode = R"( + contract c { + uint256 a; + uint256 b; + uint256 c; + uint16[] inner = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + uint16[][] data; + function test() public returns (uint x, uint y, uint z) { + for (uint i = 1; i <= 48; i++) + data.push(inner); + for (uint j = 1; j <= 10; j++) + data.pop(); + x = data[data.length - 1][0]; + for (uint k = 1; k <= 10; k++) + data.pop(); + y = data[data.length - 1][1]; + for (uint l = 1; l <= 10; l++) + data.pop(); + z = data[data.length - 1][2]; + for (uint m = 1; m <= 18; m++) + data.pop(); + delete inner; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1, 2, 3)); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + +BOOST_AUTO_TEST_CASE(array_pop_empty_exception) +{ + char const* sourceCode = R"( + contract c { + uint[] data; + function test() public returns (bool) { + data.pop(); + return true; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(array_pop_storage_empty) +{ + char const* sourceCode = R"( + contract c { + uint[] data; + function test() public { + data.push(7); + data.pop(); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop) +{ + char const* sourceCode = R"( + contract c { + bytes data; + function test() public returns (uint x, uint y, uint l) { + data.push(0x07); + x = data.push(0x03); + data.pop(); + data.pop(); + y = data.push(0x02); + l = data.length; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(2, 1, 1)); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_empty_exception) +{ + char const* sourceCode = R"( + contract c { + uint256 a; + uint256 b; + uint256 c; + bytes data; + function test() public returns (bool) { + data.pop(); + return true; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_storage_empty) +{ + char const* sourceCode = R"( + contract c { + bytes data; + function test() public { + data.push(0x07); + data.push(0x05); + data.push(0x03); + data.pop(); + data.pop(); + data.pop(); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty) +{ + char const* sourceCode = R"( + contract c { + uint256 a; + uint256 b; + uint256 c; + bytes data; + function test() public returns (bool) { + for (uint8 i = 0; i <= 40; i++) + data.push(byte(i+1)); + for (int8 j = 40; j >= 0; j--) { + require(data[uint8(j)] == byte(j+1)); + require(data.length == uint8(j+1)); + data.pop(); + } + return true; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty_garbage_ref) +{ + char const* sourceCode = R"( + contract c { + uint256 a; + uint256 b; + bytes data; + function test() public { + for (uint8 i = 0; i <= 40; i++) + data.push(0x03); + for (uint8 j = 0; j <= 40; j++) { + assembly { + mstore(0, "garbage") + } + data.pop(); + } + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); + BOOST_CHECK(storageEmpty(m_contractAddress)); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_masking_long) +{ + char const* sourceCode = R"( + contract c { + bytes data; + function test() public returns (bytes memory) { + for (uint i = 0; i < 34; i++) + data.push(0x03); + data.pop(); + return data; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs( + u256(0x20), + u256(33), + asString(fromHex("0303030303030303030303030303030303030303030303030303030303030303")), + asString(fromHex("03")) + )); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_copy_long) +{ + char const* sourceCode = R"( + contract c { + bytes data; + function test() public returns (bytes memory) { + for (uint i = 0; i < 33; i++) + data.push(0x03); + for (uint j = 0; j < 4; j++) + data.pop(); + return data; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs( + u256(0x20), + u256(29), + asString(fromHex("0303030303030303030303030303030303030303030303030303030303")) + )); +} + +BOOST_AUTO_TEST_CASE(array_pop_isolated) +{ + char const* sourceCode = R"( + // This tests that the compiler knows the correct size of the function on the stack. + contract c { + uint[] data; + function test() public returns (uint x) { + x = 2; + data.pop; + x = 3; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(3)); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_isolated) +{ + char const* sourceCode = R"( + // This tests that the compiler knows the correct size of the function on the stack. + contract c { + bytes data; + function test() public returns (uint x) { + x = 2; + data.pop; + x = 3; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(3)); +} + BOOST_AUTO_TEST_CASE(external_array_args) { char const* sourceCode = R"( contract c { - function test(uint[8] a, uint[] b, uint[5] c, uint a_index, uint b_index, uint c_index) + function test(uint[8] calldata a, uint[] calldata b, uint[5] calldata c, uint a_index, uint b_index, uint c_index) external returns (uint av, uint bv, uint cv) { av = a[a_index]; bv = b[b_index]; @@ -5308,23 +6201,23 @@ BOOST_AUTO_TEST_CASE(bytes_index_access) char const* sourceCode = R"( contract c { bytes data; - function direct(bytes arg, uint index) external returns (uint) { - return uint(arg[index]); + function direct(bytes calldata arg, uint index) external returns (uint) { + return uint(uint8(arg[index])); } - function storageCopyRead(bytes arg, uint index) external returns (uint) { + function storageCopyRead(bytes calldata arg, uint index) external returns (uint) { data = arg; - return uint(data[index]); + return uint(uint8(data[index])); } function storageWrite() external returns (uint) { data.length = 35; data[31] = 0x77; data[32] = 0x14; - data[31] = 1; - data[31] |= 8; - data[30] = 1; - data[32] = 3; - return uint(data[30]) * 0x100 | uint(data[31]) * 0x10 | uint(data[32]); + data[31] = 0x01; + data[31] |= 0x08; + data[30] = 0x01; + data[32] = 0x03; + return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32])); } } )"; @@ -5347,11 +6240,11 @@ BOOST_AUTO_TEST_CASE(bytes_delete_element) function test1() external returns (bool) { data.length = 100; for (uint i = 0; i < data.length; i++) - data[i] = byte(i); + data[i] = byte(uint8(i)); delete data[94]; delete data[96]; delete data[98]; - return data[94] == 0 && data[95] == 95 && data[96] == 0 && data[97] == 97; + return data[94] == 0 && uint8(data[95]) == 95 && data[96] == 0 && uint8(data[97]) == 97; } } )"; @@ -5366,13 +6259,13 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) uint[9] m_data; uint[] m_data_dyn; uint8[][] m_byte_data; - function store(uint[9] a, uint8[3][] b) external returns (uint8) { + function store(uint[9] calldata a, uint8[3][] calldata b) external returns (uint8) { m_data = a; m_data_dyn = a; m_byte_data = b; return b[3][1]; // note that access and declaration are reversed to each other } - function retrieve() returns (uint a, uint b, uint c, uint d, uint e, uint f, uint g) { + function retrieve() public returns (uint a, uint b, uint c, uint d, uint e, uint f, uint g) { a = m_data.length; b = m_data[7]; c = m_data_dyn.length; @@ -5405,7 +6298,7 @@ BOOST_AUTO_TEST_CASE(array_copy_nested_array) uint[4][] a; uint[10][] b; uint[][] c; - function test(uint[2][] d) external returns (uint) { + function test(uint[2][] calldata d) external returns (uint) { a = d; b = a; c = b; @@ -5428,7 +6321,7 @@ BOOST_AUTO_TEST_CASE(array_copy_including_mapping) contract c { mapping(uint=>uint)[90][] large; mapping(uint=>uint)[3][] small; - function test() returns (uint r) { + function test() public returns (uint r) { large.length = small.length = 7; large[3][2][0] = 2; large[1] = large[3]; @@ -5442,7 +6335,7 @@ BOOST_AUTO_TEST_CASE(array_copy_including_mapping) delete small; delete large; } - function clear() returns (uint r) { + function clear() public returns (uint r) { large.length = small.length = 7; small[3][2][0] = 0; large[3][2][0] = 0; @@ -5471,11 +6364,11 @@ BOOST_AUTO_TEST_CASE(swap_in_storage_overwrite) struct S { uint a; uint b; } S public x; S public y; - function set() { + function set() public { x.a = 1; x.b = 2; y.a = 3; y.b = 4; } - function swap() { + function swap() public { (x, y) = (y, x); } } @@ -5495,18 +6388,19 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base) { char const* sourceCode = R"( contract Base { - function Base(uint i) + constructor(uint i) public { m_i = i; } uint public m_i; } contract Derived is Base { - function Derived(uint i) Base(i) + constructor(uint i) Base(i) public {} } contract Final is Derived(4) { - })"; + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } @@ -5515,21 +6409,22 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base) { char const* sourceCode = R"( contract Base { - function Base(uint j) + constructor(uint j) public { m_i = j; } uint public m_i; } contract Base1 is Base { - function Base1(uint k) Base(k*k) {} + constructor(uint k) Base(k) public {} } contract Derived is Base, Base1 { - function Derived(uint i) Base(i) Base1(i) + constructor(uint i) Base1(i) public {} } contract Final is Derived(4) { - })"; + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } @@ -5538,18 +6433,21 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap) { char const* sourceCode = R"( contract Base { - function Base(uint i) + constructor(uint i) public { m_i = i; } uint public m_i; } - contract Base1 is Base(3) {} + contract Base1 is Base { + constructor(uint k) public {} + } contract Derived is Base, Base1 { - function Derived(uint i) Base(i) {} + constructor(uint i) Base(i) Base1(7) public {} } contract Final is Derived(4) { - })"; + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } @@ -5558,9 +6456,10 @@ BOOST_AUTO_TEST_CASE(simple_constant_variables_test) { char const* sourceCode = R"( contract Foo { - function getX() returns (uint r) { return x; } + function getX() public returns (uint r) { return x; } uint constant x = 56; - })"; + } + )"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("getX()"), encodeArgs(56)); } @@ -5573,7 +6472,8 @@ BOOST_AUTO_TEST_CASE(constant_variables) enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } ActionChoices constant choices = ActionChoices.GoLeft; bytes32 constant st = "abc\x00\xff__"; - })"; + } + )"; compileAndRun(sourceCode); } @@ -5582,7 +6482,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_expression) char const* sourceCode = R"( contract C { uint constant x = 0x123 + 0x456; - function f() returns (uint) { return x + 1; } + function f() public returns (uint) { return x + 1; } } )"; compileAndRun(sourceCode); @@ -5594,7 +6494,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) char const* sourceCode = R"( contract C { bytes32 constant x = keccak256("abc"); - function f() returns (bytes32) { return x; } + function f() public returns (bytes32) { return x; } } )"; compileAndRun(sourceCode); @@ -5608,7 +6508,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) // contract C { // uint[3] constant x = [uint(1), 2, 3]; // uint constant y = x[0] + x[1] + x[2]; -// function f() returns (uint) { return y; } +// function f() public returns (uint) { return y; } // } // )"; // compileAndRun(sourceCode); @@ -5622,7 +6522,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) // contract C { // struct S { uint x; uint[] y; } // S constant x = S(5, new uint[](4)); -// function f() returns (uint) { return x.x; } +// function f() public returns (uint) { return x.x; } // } // )"; // compileAndRun(sourceCode); @@ -5635,7 +6535,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_uint) contract C { struct str { uint8 a; uint16 b; uint248 c; } str data; - function test() returns (uint) { + function test() public returns (uint) { data.a = 2; if (data.a != 2) return 2; data.b = 0xabcd; @@ -5667,7 +6567,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_enum) enum larger { A, B, C, D, E} struct str { small a; small b; larger c; larger d; } str data; - function test() returns (uint) { + function test() public returns (uint) { data.a = small.B; if (data.a != small.B) return 2; data.b = small.C; @@ -5700,20 +6600,20 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_bytes) byte x; s2 data; byte y; - function test() returns (bool) { - x = 1; - data.a = 2; - data.inner.a = 3; - data.inner.b = 4; + function test() public returns (bool) { + x = 0x01; + data.a = 0x02; + data.inner.a = 0x03; + data.inner.b = 0x04; data.inner.c = "1234567890"; data.inner.d = "123456789"; data.inner.e = "abcdefghij"; - data.b = 5; - data.c = 6; - y = 7; - return x == 1 && data.a == 2 && data.inner.a == 3 && data.inner.b == 4 && + data.b = 0x05; + data.c = byte(0x06); + y = 0x07; + return x == 0x01 && data.a == 0x02 && data.inner.a == 0x03 && data.inner.b == 0x04 && data.inner.c == "1234567890" && data.inner.d == "123456789" && - data.inner.e == "abcdefghij" && data.b == 5 && data.c == 6 && y == 7; + data.inner.e == "abcdefghij" && data.b == 0x05 && data.c == byte(0x06) && y == 0x07; } } )"; @@ -5729,7 +6629,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_delete) uint8 x; uint16 y; str data; - function test() returns (uint) { + function test() public returns (uint) { x = 1; y = 2; data.a = 2; @@ -5756,9 +6656,9 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_first) { char const* sourceCode = R"( contract test { - function f(uint k) returns(uint d) { return k; } - function f(uint a, uint b) returns(uint d) { return a + b; } - function g() returns(uint d) { return f(3); } + function f(uint k) public returns(uint d) { return k; } + function f(uint a, uint b) public returns(uint d) { return a + b; } + function g() public returns(uint d) { return f(3); } } )"; compileAndRun(sourceCode); @@ -5769,9 +6669,9 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_second) { char const* sourceCode = R"( contract test { - function f(uint a, uint b) returns(uint d) { return a + b; } - function f(uint k) returns(uint d) { return k; } - function g() returns(uint d) { return f(3, 7); } + function f(uint a, uint b) public returns(uint d) { return a + b; } + function f(uint k) public returns(uint d) { return k; } + function g() public returns(uint d) { return f(3, 7); } } )"; compileAndRun(sourceCode); @@ -5782,9 +6682,9 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else) { char const* sourceCode = R"( contract test { - function f(uint a, uint b) returns(uint d) { return a + b; } - function f(uint k) returns(uint d) { return k; } - function g(bool flag) returns(uint d) { + function f(uint a, uint b) public returns(uint d) { return a + b; } + function f(uint k) public returns(uint d) { return k; } + function g(bool flag) public returns(uint d) { if (flag) return f(3); else @@ -5800,10 +6700,10 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else) BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct) { char const* sourceCode = R"( - contract B { function f() returns(uint) { return 10; } } + contract B { function f() public returns(uint) { return 10; } } contract C is B { - function f(uint i) returns(uint) { return 2 * i; } - function g() returns(uint) { return f(1); } + function f(uint i) public returns(uint) { return 2 * i; } + function g() public returns(uint) { return f(1); } } )"; compileAndRun(sourceCode, 0, "C"); @@ -5813,11 +6713,11 @@ BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct) BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect) { char const* sourceCode = R"( - contract A { function f(uint a) returns(uint) { return 2 * a; } } - contract B { function f() returns(uint) { return 10; } } + contract A { function f(uint a) public returns(uint) { return 2 * a; } } + contract B { function f() public returns(uint) { return 10; } } contract C is A, B { - function g() returns(uint) { return f(); } - function h() returns(uint) { return f(1); } + function g() public returns(uint) { return f(); } + function h() public returns(uint) { return f(1); } } )"; compileAndRun(sourceCode, 0, "C"); @@ -5828,11 +6728,11 @@ BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect) BOOST_AUTO_TEST_CASE(super_overload) { char const* sourceCode = R"( - contract A { function f(uint a) returns(uint) { return 2 * a; } } - contract B { function f(bool b) returns(uint) { return 10; } } + contract A { function f(uint a) public returns(uint) { return 2 * a; } } + contract B { function f(bool b) public returns(uint) { return 10; } } contract C is A, B { - function g() returns(uint) { return super.f(true); } - function h() returns(uint) { return super.f(1); } + function g() public returns(uint) { return super.f(true); } + function h() public returns(uint) { return super.f(1); } } )"; compileAndRun(sourceCode, 0, "C"); @@ -5844,8 +6744,8 @@ BOOST_AUTO_TEST_CASE(gasleft_shadow_resolution) { char const* sourceCode = R"( contract C { - function gasleft() returns(uint256) { return 0; } - function f() returns(uint256) { return gasleft(); } + function gasleft() public returns(uint256) { return 0; } + function f() public returns(uint256) { return gasleft(); } } )"; compileAndRun(sourceCode, 0, "C"); @@ -5856,13 +6756,13 @@ BOOST_AUTO_TEST_CASE(bool_conversion) { char const* sourceCode = R"( contract C { - function f(bool _b) returns(uint) { + function f(bool _b) public returns(uint) { if (_b) return 1; else return 0; } - function g(bool _in) returns (bool _out) { + function g(bool _in) public returns (bool _out) { _out = _in; } } @@ -5888,7 +6788,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_signed) uint8 b; int8 c; uint8 d; - function test() returns (uint x1, uint x2, uint x3, uint x4) { + function test() public returns (uint x1, uint x2, uint x3, uint x4) { a = -2; b = -uint8(a) * 2; c = a * int8(120) * int8(121); @@ -5906,15 +6806,15 @@ BOOST_AUTO_TEST_CASE(packed_storage_signed) BOOST_AUTO_TEST_CASE(external_types_in_calls) { char const* sourceCode = R"( - contract C1 { C1 public bla; function C1(C1 x) { bla = x; } } + contract C1 { C1 public bla; constructor(C1 x) public { bla = x; } } contract C { - function test() returns (C1 x, C1 y) { + function test() public returns (C1 x, C1 y) { C1 c = new C1(C1(9)); x = c.bla(); y = this.t1(C1(7)); } - function t1(C1 a) returns (C1) { return a; } - function t2() returns (C1) { return C1(9); } + function t1(C1 a) public returns (C1) { return a; } + function t2() public returns (C1) { return C1(9); } } )"; compileAndRun(sourceCode, 0, "C"); @@ -5928,18 +6828,18 @@ BOOST_AUTO_TEST_CASE(invalid_enum_compared) contract C { enum X { A, B } - function test_eq() returns (bool) { + function test_eq() public returns (bool) { X garbled; assembly { garbled := 5 } return garbled == garbled; } - function test_eq_ok() returns (bool) { + function test_eq_ok() public returns (bool) { X garbled = X.A; return garbled == garbled; } - function test_neq() returns (bool) { + function test_neq() public returns (bool) { X garbled; assembly { garbled := 5 @@ -5962,17 +6862,17 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged) enum X { A, B } event Log(X); - function test_log() returns (uint) { + function test_log() public returns (uint) { X garbled = X.A; assembly { garbled := 5 } - Log(garbled); + emit Log(garbled); return 1; } - function test_log_ok() returns (uint) { + function test_log_ok() public returns (uint) { X x = X.A; - Log(x); + emit Log(x); return 1; } } @@ -5996,7 +6896,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_stored) enum X { A, B } X public x; - function test_store() returns (uint) { + function test_store() public returns (uint) { X garbled = X.A; assembly { garbled := 5 @@ -6004,7 +6904,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_stored) x = garbled; return 1; } - function test_store_ok() returns (uint) { + function test_store_ok() public returns (uint) { x = X.A; return 1; } @@ -6024,19 +6924,19 @@ BOOST_AUTO_TEST_CASE(invalid_enum_as_external_ret) contract C { enum X { A, B } - function test_return() returns (X) { + function test_return() public returns (X) { X garbled; assembly { garbled := 5 } return garbled; } - function test_inline_assignment() returns (X _ret) { + function test_inline_assignment() public returns (X _ret) { assembly { _ret := 5 } } - function test_assignment() returns (X _ret) { + function test_assignment() public returns (X _ret) { X tmp; assembly { tmp := 5 @@ -6058,11 +6958,11 @@ BOOST_AUTO_TEST_CASE(invalid_enum_as_external_arg) contract C { enum X { A, B } - function tested (X x) returns (uint) { + function tested (X x) public returns (uint) { return 1; } - function test() returns (uint) { + function test() public returns (uint) { X garbled; assembly { @@ -6084,19 +6984,19 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) // bug #1798 char const* sourceCode = R"( contract init { - function isOk() returns (bool) { return false; } + function isOk() public returns (bool) { return false; } bool public ok = false; } contract fix { - function isOk() returns (bool) { return true; } + function isOk() public returns (bool) { return true; } bool public ok = true; } contract init_fix is init, fix { - function checkOk() returns (bool) { return ok; } + function checkOk() public returns (bool) { return ok; } } contract fix_init is fix, init { - function checkOk() returns (bool) { return ok; } + function checkOk() public returns (bool) { return ok; } } )"; compileAndRun(sourceCode, 0, "init_fix"); @@ -6119,13 +7019,13 @@ BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) testStruct data1; testStruct data2; testStruct data3; - function test() + constructor() public { data1.m_value = 2; } - function assign() returns (uint ret_local, uint ret_global, uint ret_global3, uint ret_global1) + function assign() public returns (uint ret_local, uint ret_global, uint ret_global3, uint ret_global1) { - testStruct x = data1; //x is a reference data1.m_value == 2 as well as x.m_value = 2 + testStruct storage x = data1; //x is a reference data1.m_value == 2 as well as x.m_value = 2 data2 = data1; // should copy data. data2.m_value == 2 ret_local = x.m_value; // = 2 @@ -6151,13 +7051,13 @@ BOOST_AUTO_TEST_CASE(struct_delete_member) uint m_value; } testStruct data1; - function test() + constructor() public { data1.m_value = 2; } - function deleteMember() returns (uint ret_value) + function deleteMember() public returns (uint ret_value) { - testStruct x = data1; //should not copy the data. data1.m_value == 2 but x.m_value = 0 + testStruct storage x = data1; //should not copy the data. data1.m_value == 2 but x.m_value = 0 x.m_value = 4; delete x.m_value; ret_value = data1.m_value; @@ -6178,11 +7078,11 @@ BOOST_AUTO_TEST_CASE(struct_delete_struct_in_mapping) } mapping (uint => testStruct) campaigns; - function test() + constructor() public { campaigns[0].m_value = 2; } - function deleteIt() returns (uint) + function deleteIt() public returns (uint) { delete campaigns[0]; return campaigns[0].m_value; @@ -6199,11 +7099,11 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_out_of_band_access) contract A { uint[3] arr; bool public test = false; - function getElement(uint i) returns (uint) + function getElement(uint i) public returns (uint) { return arr[i]; } - function testIt() returns (bool) + function testIt() public returns (bool) { uint i = this.getElement(5); test = true; @@ -6221,14 +7121,14 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_call_fail) { char const* sourceCode = R"( contract A { - function A() + constructor() public { - this.call("123"); + address(this).call("123"); } } contract B { uint public test = 1; - function testIt() + function testIt() public { A a = new A(); ++test; @@ -6247,7 +7147,7 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) contract A { uint public test = 1; uint[3] arr; - function A() + constructor() public { uint index = 5; test = arr[index]; @@ -6256,6 +7156,7 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) } )"; ABI_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A"), encodeArgs()); + BOOST_CHECK(!m_transactionSuccessful); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed) @@ -6278,15 +7179,15 @@ BOOST_AUTO_TEST_CASE(failing_send) char const* sourceCode = R"( contract Helper { uint[] data; - function () { + function () external { data[9]; // trigger exception } } contract Main { - function Main() payable {} - function callHelper(address _a) returns (bool r, uint bal) { + constructor() public payable {} + function callHelper(address payable _a) public returns (bool r, uint bal) { r = !_a.send(5); - bal = this.balance; + bal = address(this).balance; } } )"; @@ -6302,14 +7203,14 @@ BOOST_AUTO_TEST_CASE(send_zero_ether) // (it previously did not because the gas stipend was not provided by the EVM) char const* sourceCode = R"( contract Receiver { - function () payable { + function () external payable { } } contract Main { - function Main() payable {} - function s() returns (bool) { - var r = new Receiver(); - return r.send(0); + constructor() public payable {} + function s() public returns (bool) { + Receiver r = new Receiver(); + return address(r).send(0); } } )"; @@ -6323,17 +7224,17 @@ BOOST_AUTO_TEST_CASE(reusing_memory) char const* sourceCode = R"( contract Helper { uint public flag; - function Helper(uint x) { + constructor(uint x) public { flag = x; } } contract Main { mapping(uint => uint) map; - function f(uint x) returns (uint) { + function f(uint x) public returns (uint) { map[x] = x; - return (new Helper(uint(keccak256(this.g(map[x]))))).flag(); + return (new Helper(uint(keccak256(abi.encodePacked(this.g(map[x])))))).flag(); } - function g(uint a) returns (uint) + function g(uint a) public returns (uint) { return map[a]; } @@ -6348,13 +7249,13 @@ BOOST_AUTO_TEST_CASE(return_string) char const* sourceCode = R"( contract Main { string public s; - function set(string _s) external { + function set(string calldata _s) external { s = _s; } - function get1() returns (string r) { + function get1() public returns (string memory r) { return s; } - function get2() returns (string r) { + function get2() public returns (string memory r) { r = s; } } @@ -6374,12 +7275,12 @@ BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) contract Main { string public s1; string public s2; - function set(string _s1, uint x, string _s2) external returns (uint) { + function set(string calldata _s1, uint x, string calldata _s2) external returns (uint) { s1 = _s1; s2 = _s2; return x; } - function get() returns (string r1, string r2) { + function get() public returns (string memory r1, string memory r2) { r1 = s1; r2 = s2; } @@ -6399,9 +7300,9 @@ BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) "ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ" "ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ" ); - vector lengthes{0, 30, 32, 63, 64, 65, 210, 300}; - for (auto l1: lengthes) - for (auto l2: lengthes) + vector lengths{0, 30, 32, 63, 64, 65, 210, 300}; + for (auto l1: lengths) + for (auto l2: lengths) { bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1)); bytes dyn2 = encodeArgs(u256(l2), s2.substr(0, l2)); @@ -6423,7 +7324,7 @@ BOOST_AUTO_TEST_CASE(accessor_involving_strings) contract Main { struct stringData { string a; uint b; string c; } mapping(uint => stringData[]) public data; - function set(uint x, uint y, string a, uint b, string c) external returns (bool) { + function set(uint x, uint y, string calldata a, uint b, string calldata c) external returns (bool) { data[x].length = y + 1; data[x][y].a = a; data[x][y].b = b; @@ -6452,15 +7353,15 @@ BOOST_AUTO_TEST_CASE(bytes_in_function_calls) contract Main { string public s1; string public s2; - function set(string _s1, uint x, string _s2) returns (uint) { + function set(string memory _s1, uint x, string memory _s2) public returns (uint) { s1 = _s1; s2 = _s2; return x; } - function setIndirectFromMemory(string _s1, uint x, string _s2) returns (uint) { + function setIndirectFromMemory(string memory _s1, uint x, string memory _s2) public returns (uint) { return this.set(_s1, x, _s2); } - function setIndirectFromCalldata(string _s1, uint x, string _s2) external returns (uint) { + function setIndirectFromCalldata(string calldata _s1, uint x, string calldata _s2) external returns (uint) { return this.set(_s1, x, _s2); } } @@ -6468,9 +7369,9 @@ BOOST_AUTO_TEST_CASE(bytes_in_function_calls) compileAndRun(sourceCode, 0, "Main"); string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); string s2("ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"); - vector lengthes{0, 31, 64, 65}; - for (auto l1: lengthes) - for (auto l2: lengthes) + vector lengths{0, 31, 64, 65}; + for (auto l1: lengths) + for (auto l2: lengths) { bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1)); bytes dyn2 = encodeArgs(u256(l2), s2.substr(0, l2)); @@ -6497,11 +7398,11 @@ BOOST_AUTO_TEST_CASE(return_bytes_internal) char const* sourceCode = R"( contract Main { bytes s1; - function doSet(bytes _s1) returns (bytes _r1) { + function doSet(bytes memory _s1) public returns (bytes memory _r1) { s1 = _s1; _r1 = s1; } - function set(bytes _s1) external returns (uint _r, bytes _r1) { + function set(bytes calldata _s1) external returns (uint _r, bytes memory _r1) { _r1 = doSet(_s1); _r = _r1.length; } @@ -6509,8 +7410,8 @@ BOOST_AUTO_TEST_CASE(return_bytes_internal) )"; compileAndRun(sourceCode, 0, "Main"); string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); - vector lengthes{0, 31, 64, 65}; - for (auto l1: lengthes) + vector lengths{0, 31, 64, 65}; + for (auto l1: lengths) { bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1)); bytes args1 = encodeArgs(u256(0x20)) + dyn1; @@ -6525,15 +7426,15 @@ BOOST_AUTO_TEST_CASE(bytes_index_access_memory) { char const* sourceCode = R"( contract Main { - function f(bytes _s1, uint i1, uint i2, uint i3) returns (byte c1, byte c2, byte c3) { + function f(bytes memory _s1, uint i1, uint i2, uint i3) public returns (byte c1, byte c2, byte c3) { c1 = _s1[i1]; c2 = intern(_s1, i2); c3 = internIndirect(_s1)[i3]; } - function intern(bytes _s1, uint i) returns (byte c) { + function intern(bytes memory _s1, uint i) public returns (byte c) { return _s1[i]; } - function internIndirect(bytes _s1) returns (bytes) { + function internIndirect(bytes memory _s1) public returns (bytes memory) { return _s1; } } @@ -6554,7 +7455,7 @@ BOOST_AUTO_TEST_CASE(bytes_in_constructors_unpacker) contract Test { uint public m_x; bytes public m_s; - function Test(uint x, bytes s) { + constructor(uint x, bytes memory s) public { m_x = x; m_s = s; } @@ -6575,23 +7476,23 @@ BOOST_AUTO_TEST_CASE(bytes_in_constructors_packer) contract Base { uint public m_x; bytes m_s; - function Base(uint x, bytes s) { + constructor(uint x, bytes memory s) public { m_x = x; m_s = s; } - function part(uint i) returns (byte) { + function part(uint i) public returns (byte) { return m_s[i]; } } contract Main is Base { - function Main(bytes s, uint x) Base(x, f(s)) {} - function f(bytes s) returns (bytes) { + constructor(bytes memory s, uint x) Base(x, f(s)) public {} + function f(bytes memory s) public returns (bytes memory) { return s; } } contract Creator { - function f(uint x, bytes s) returns (uint r, byte ch) { - var c = new Main(s, x); + function f(uint x, bytes memory s) public returns (uint r, byte ch) { + Main c = new Main(s, x); r = c.m_x(); ch = c.part(x); } @@ -6614,23 +7515,23 @@ BOOST_AUTO_TEST_CASE(arrays_in_constructors) contract Base { uint public m_x; address[] m_s; - function Base(uint x, address[] s) { + constructor(uint x, address[] memory s) public { m_x = x; m_s = s; } - function part(uint i) returns (address) { + function part(uint i) public returns (address) { return m_s[i]; } } contract Main is Base { - function Main(address[] s, uint x) Base(x, f(s)) {} - function f(address[] s) returns (address[]) { + constructor(address[] memory s, uint x) Base(x, f(s)) public {} + function f(address[] memory s) public returns (address[] memory) { return s; } } contract Creator { - function f(uint x, address[] s) returns (uint r, address ch) { - var c = new Main(s, x); + function f(uint x, address[] memory s) public returns (uint r, address ch) { + Main c = new Main(s, x); r = c.m_x(); ch = c.part(x); } @@ -6653,7 +7554,7 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_in_constructors) contract Creator { uint public r; address public ch; - function Creator(address[3] s, uint x) { + constructor(address[3] memory s, uint x) public { r = x; ch = s[2]; } @@ -6669,11 +7570,11 @@ BOOST_AUTO_TEST_CASE(arrays_from_and_to_storage) char const* sourceCode = R"( contract Test { uint24[] public data; - function set(uint24[] _data) returns (uint) { + function set(uint24[] memory _data) public returns (uint) { data = _data; return data.length; } - function get() returns (uint24[]) { + function get() public returns (uint24[] memory) { return data; } } @@ -6696,11 +7597,11 @@ BOOST_AUTO_TEST_CASE(arrays_complex_from_and_to_storage) char const* sourceCode = R"( contract Test { uint24[3][] public data; - function set(uint24[3][] _data) returns (uint) { + function set(uint24[3][] memory _data) public returns (uint) { data = _data; return data.length; } - function get() returns (uint24[3][]) { + function get() public returns (uint24[3][] memory) { return data; } } @@ -6722,7 +7623,7 @@ BOOST_AUTO_TEST_CASE(arrays_complex_memory_index_access) { char const* sourceCode = R"( contract Test { - function set(uint24[3][] _data, uint a, uint b) returns (uint l, uint e) { + function set(uint24[3][] memory _data, uint a, uint b) public returns (uint l, uint e) { l = _data.length; e = _data[a][b]; } @@ -6745,7 +7646,7 @@ BOOST_AUTO_TEST_CASE(bytes_memory_index_access) { char const* sourceCode = R"( contract Test { - function set(bytes _data, uint i) returns (uint l, byte c) { + function set(bytes memory _data, uint i) public returns (uint l, byte c) { l = _data.length; c = _data[i]; } @@ -6788,11 +7689,11 @@ BOOST_AUTO_TEST_CASE(storage_array_ref) contract Store is BinarySearch { uint[] data; - function add(uint v) { + function add(uint v) public { data.length++; data[data.length - 1] = v; } - function find(uint v) returns (uint) { + function find(uint v) public returns (uint) { return find(data, v); } } @@ -6821,13 +7722,13 @@ BOOST_AUTO_TEST_CASE(memory_types_initialisation) char const* sourceCode = R"( contract Test { mapping(uint=>uint) data; - function stat() returns (uint[5]) + function stat() public returns (uint[5] memory) { data[2] = 3; // make sure to use some memory } - function dyn() returns (uint[]) { stat(); } - function nested() returns (uint[3][]) { stat(); } - function nestedStat() returns (uint[3][7]) { stat(); } + function dyn() public returns (uint[] memory) { stat(); } + function nested() public returns (uint[3][] memory) { stat(); } + function nestedStat() public returns (uint[3][7] memory) { stat(); } } )"; compileAndRun(sourceCode, 0, "Test"); @@ -6842,7 +7743,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_delete) { char const* sourceCode = R"( contract Test { - function del() returns (uint24[3][4]) { + function del() public returns (uint24[3][4] memory) { uint24[3][4] memory x; for (uint24 i = 0; i < x.length; i ++) for (uint24 j = 0; j < x[i].length; j ++) @@ -6871,11 +7772,11 @@ BOOST_AUTO_TEST_CASE(memory_arrays_index_access_write) { char const* sourceCode = R"( contract Test { - function set(uint24[3][4] x) { + function set(uint24[3][4] memory x) public { x[2][2] = 1; x[3][2] = 7; } - function f() returns (uint24[3][4]){ + function f() public returns (uint24[3][4] memory){ uint24[3][4] memory data; set(data); return data; @@ -6895,12 +7796,12 @@ BOOST_AUTO_TEST_CASE(memory_arrays_dynamic_index_access_write) char const* sourceCode = R"( contract Test { uint24[3][][4] data; - function set(uint24[3][][4] x) internal returns (uint24[3][][4]) { + function set(uint24[3][][4] memory x) internal returns (uint24[3][][4] memory) { x[1][2][2] = 1; x[1][3][2] = 7; return x; } - function f() returns (uint24[3][]) { + function f() public returns (uint24[3][] memory) { data[1].length = 4; return set(data)[1]; } @@ -6920,7 +7821,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_read_write) contract Test { struct S { uint8 x; uint16 y; uint z; uint8[2] a; } S[5] data; - function testInit() returns (uint8 x, uint16 y, uint z, uint8 a, bool flag) { + function testInit() public returns (uint8 x, uint16 y, uint z, uint8 a, bool flag) { S[2] memory d; x = d[0].x; y = d[0].y; @@ -6928,7 +7829,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_read_write) a = d[0].a[1]; flag = true; } - function testCopyRead() returns (uint8 x, uint16 y, uint z, uint8 a) { + function testCopyRead() public returns (uint8 x, uint16 y, uint z, uint8 a) { data[2].x = 1; data[2].y = 2; data[2].z = 3; @@ -6939,7 +7840,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_read_write) z = s.z; a = s.a[1]; } - function testAssign() returns (uint8 x, uint16 y, uint z, uint8 a) { + function testAssign() public returns (uint8 x, uint16 y, uint z, uint8 a) { S memory s; s.x = 1; s.y = 2; @@ -6964,18 +7865,18 @@ BOOST_AUTO_TEST_CASE(memory_structs_as_function_args) char const* sourceCode = R"( contract Test { struct S { uint8 x; uint16 y; uint z; } - function test() returns (uint x, uint y, uint z) { + function test() public returns (uint x, uint y, uint z) { S memory data = combine(1, 2, 3); x = extract(data, 0); y = extract(data, 1); z = extract(data, 2); } - function extract(S s, uint which) internal returns (uint x) { + function extract(S memory s, uint which) internal returns (uint x) { if (which == 0) return s.x; else if (which == 1) return s.y; else return s.z; } - function combine(uint8 x, uint16 y, uint z) internal returns (S s) { + function combine(uint8 x, uint16 y, uint z) internal returns (S memory s) { s.x = x; s.y = y; s.z = z; @@ -6993,20 +7894,20 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested) contract Test { struct S { uint8 x; uint16 y; uint z; } struct X { uint8 x; S s; } - function test() returns (uint a, uint x, uint y, uint z) { + function test() public returns (uint a, uint x, uint y, uint z) { X memory d = combine(1, 2, 3, 4); a = extract(d, 0); x = extract(d, 1); y = extract(d, 2); z = extract(d, 3); } - function extract(X s, uint which) internal returns (uint x) { + function extract(X memory s, uint which) internal returns (uint x) { if (which == 0) return s.x; else if (which == 1) return s.s.x; else if (which == 2) return s.s.y; else return s.s.z; } - function combine(uint8 a, uint8 x, uint16 y, uint z) internal returns (X s) { + function combine(uint8 a, uint8 x, uint16 y, uint z) internal returns (X memory s) { s.x = a; s.s.x = x; s.s.y = y; @@ -7026,7 +7927,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested_load) struct S { uint8 x; uint16 y; uint z; } struct X { uint8 x; S s; uint8[2] a; } X m_x; - function load() returns (uint a, uint x, uint y, uint z, uint a1, uint a2) { + function load() public returns (uint a, uint x, uint y, uint z, uint a1, uint a2) { m_x.x = 1; m_x.s.x = 2; m_x.s.y = 3; @@ -7041,7 +7942,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested_load) a1 = d.a[0]; a2 = d.a[1]; } - function store() returns (uint a, uint x, uint y, uint z, uint a1, uint a2) { + function store() public returns (uint a, uint x, uint y, uint z, uint a1, uint a2) { X memory d; d.x = 1; d.s.x = 2; @@ -7073,12 +7974,12 @@ BOOST_AUTO_TEST_CASE(struct_constructor_nested) struct X { uint x1; uint x2; } struct S { uint s1; uint[3] s2; X s3; } S s; - function C() { + constructor() public { uint[3] memory s2; s2[1] = 9; s = S(1, s2, X(4, 5)); } - function get() returns (uint s1, uint[3] s2, uint x1, uint x2) + function get() public returns (uint s1, uint[3] memory s2, uint x1, uint x2) { s1 = s.s1; s2 = s.s2; @@ -7099,7 +8000,7 @@ BOOST_AUTO_TEST_CASE(struct_named_constructor) contract C { struct S { uint a; bool x; } S public s; - function C() { + constructor() public { s = S({a: 1, x: true}); } } @@ -7117,7 +8018,7 @@ BOOST_AUTO_TEST_CASE(literal_strings) string public medium; string public short; string public empty; - function f() returns (string) { + function f() public returns (string memory) { long = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; medium = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"; short = "123"; @@ -7161,7 +8062,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) contract Test { struct S { uint8 a; mapping(uint => uint) b; uint8 c; } S s; - function f() returns (uint) { + function f() public returns (uint) { S memory x; if (x.a != 0 || x.c != 0) return 1; x.a = 4; x.c = 5; @@ -7184,12 +8085,12 @@ BOOST_AUTO_TEST_CASE(string_bytes_conversion) contract Test { string s; bytes b; - function f(string _s, uint n) returns (byte) { + function f(string memory _s, uint n) public returns (byte) { b = bytes(_s); s = string(b); return bytes(s)[n]; } - function l() returns (uint) { return bytes(s).length; } + function l() public returns (uint) { return bytes(s).length; } } )"; compileAndRun(sourceCode, 0, "Test"); @@ -7208,8 +8109,8 @@ BOOST_AUTO_TEST_CASE(string_as_mapping_key) char const* sourceCode = R"( contract Test { mapping(string => uint) data; - function set(string _s, uint _v) { data[_s] = _v; } - function get(string _s) returns (uint) { return data[_s]; } + function set(string memory _s, uint _v) public { data[_s] = _v; } + function get(string memory _s) public returns (uint) { return data[_s]; } } )"; compileAndRun(sourceCode, 0, "Test"); @@ -7266,7 +8167,7 @@ BOOST_AUTO_TEST_CASE(state_variable_under_contract_name) contract Scope { uint stateVar = 42; - function getStateVar() view returns (uint stateVar) { + function getStateVar() public view returns (uint stateVar) { stateVar = Scope.stateVar; } } @@ -7281,7 +8182,7 @@ BOOST_AUTO_TEST_CASE(state_variable_local_variable_mixture) contract A { uint x = 1; uint y = 2; - function a() returns (uint x) { + function a() public returns (uint x) { x = A.y; } } @@ -7296,7 +8197,7 @@ BOOST_AUTO_TEST_CASE(inherited_function) { contract A { function f() internal returns (uint) { return 1; } } contract B is A { function f() internal returns (uint) { return 2; } - function g() returns (uint) { + function g() public returns (uint) { return A.f(); } } @@ -7311,7 +8212,7 @@ BOOST_AUTO_TEST_CASE(inherited_function_from_a_library) { library A { function f() internal returns (uint) { return 1; } } contract B { function f() internal returns (uint) { return 2; } - function g() returns (uint) { + function g() public returns (uint) { return A.f(); } } @@ -7328,7 +8229,7 @@ BOOST_AUTO_TEST_CASE(inherited_constant_state_var) uint constant x = 7; } contract B is A { - function f() returns (uint) { + function f() public returns (uint) { return A.x; } } @@ -7348,17 +8249,17 @@ BOOST_AUTO_TEST_CASE(multiple_inherited_state_vars) uint x = 9; } contract C is A, B { - function a() returns (uint) { + function a() public returns (uint) { return A.x; } - function b() returns (uint) { + function b() public returns (uint) { return B.x; } - function a_set(uint _x) returns (uint) { + function a_set(uint _x) public returns (uint) { A.x = _x; return 1; } - function b_set(uint _x) returns (uint) { + function b_set(uint _x) public returns (uint) { B.x = _x; return 1; } @@ -7381,14 +8282,14 @@ BOOST_AUTO_TEST_CASE(constant_string_literal) bytes32 constant public b = "abcdefghijklmnopq"; string constant public x = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; - function Test() { - var xx = x; - var bb = b; + constructor() public { + string memory xx = x; + bytes32 bb = b; } - function getB() returns (bytes32) { return b; } - function getX() returns (string) { return x; } - function getX2() returns (string r) { r = x; } - function unused() returns (uint) { + function getB() public returns (bytes32) { return b; } + function getX() public returns (string memory) { return x; } + function getX2() public returns (string memory r) { r = x; } + function unused() public returns (uint) { "unusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunused"; return 2; } @@ -7411,7 +8312,7 @@ BOOST_AUTO_TEST_CASE(storage_string_as_mapping_key_without_variable) char const* sourceCode = R"( contract Test { mapping(string => uint) data; - function f() returns (uint) { + function f() public returns (uint) { data["abc"] = 2; return data["abc"]; } @@ -7424,9 +8325,9 @@ BOOST_AUTO_TEST_CASE(storage_string_as_mapping_key_without_variable) BOOST_AUTO_TEST_CASE(library_call) { char const* sourceCode = R"( - library Lib { function m(uint x, uint y) returns (uint) { return x * y; } } + library Lib { function m(uint x, uint y) public returns (uint) { return x * y; } } contract Test { - function f(uint x) returns (uint) { + function f(uint x) public returns (uint) { return Lib.m(x, 9); } } @@ -7439,9 +8340,9 @@ BOOST_AUTO_TEST_CASE(library_call) BOOST_AUTO_TEST_CASE(library_function_external) { char const* sourceCode = R"( - library Lib { function m(bytes b) external pure returns (byte) { return b[2]; } } + library Lib { function m(bytes calldata b) external pure returns (byte) { return b[2]; } } contract Test { - function f(bytes b) public pure returns (byte) { + function f(bytes memory b) public pure returns (byte) { return Lib.m(b); } } @@ -7454,9 +8355,9 @@ BOOST_AUTO_TEST_CASE(library_function_external) BOOST_AUTO_TEST_CASE(library_stray_values) { char const* sourceCode = R"( - library Lib { function m(uint x, uint y) returns (uint) { return x * y; } } + library Lib { function m(uint x, uint y) public returns (uint) { return x * y; } } contract Test { - function f(uint x) returns (uint) { + function f(uint x) public returns (uint) { Lib; Lib.m; return x + 9; @@ -7473,8 +8374,8 @@ BOOST_AUTO_TEST_CASE(cross_contract_types) char const* sourceCode = R"( contract Lib { struct S {uint a; uint b; } } contract Test { - function f() returns (uint r) { - var x = Lib.S({a: 2, b: 3}); + function f() public returns (uint r) { + Lib.S memory x = Lib.S({a: 2, b: 3}); r = x.b; } } @@ -7487,11 +8388,11 @@ BOOST_AUTO_TEST_CASE(simple_throw) { char const* sourceCode = R"( contract Test { - function f(uint x) returns (uint) { + function f(uint x) public returns (uint) { if (x > 10) return x + 10; else - throw; + revert(); return 2; } } @@ -7514,22 +8415,22 @@ BOOST_AUTO_TEST_CASE(strings_in_struct) string last; } - function buggystruct(){ + constructor() public { bug = Buggy(10, 20, 30, "asdfghjkl"); } - function getFirst() returns (uint) + function getFirst() public returns (uint) { return bug.first; } - function getSecond() returns (uint) + function getSecond() public returns (uint) { return bug.second; } - function getThird() returns (uint) + function getThird() public returns (uint) { return bug.third; } - function getLast() returns (string) + function getLast() public returns (string memory) { return bug.last; } @@ -7547,7 +8448,7 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type) { char const* sourceCode = R"( contract A { - function f(uint16 input) pure returns (uint16[5] arr) + function f(uint16 input) public pure returns (uint16[5] memory arr) { arr[0] = input; arr[1] = ++input; @@ -7557,9 +8458,9 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type) } } contract B { - function f() returns (uint16[5] res, uint16[5] res2) + function f() public returns (uint16[5] memory res, uint16[5] memory res2) { - var a = new A(); + A a = new A(); res = a.f(2); res2 = a.f(1000); } @@ -7576,7 +8477,7 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library) { char const* sourceCode = R"( library Lib { - function find(uint16[] storage _haystack, uint16 _needle) view returns (uint) + function find(uint16[] storage _haystack, uint16 _needle) public view returns (uint) { for (uint i = 0; i < _haystack.length; ++i) if (_haystack[i] == _needle) @@ -7586,7 +8487,7 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library) } contract Test { mapping(string => uint16[]) data; - function f() returns (uint a, uint b) + function f() public returns (uint a, uint b) { data["abc"].length = 20; data["abc"][4] = 9; @@ -7601,12 +8502,168 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library) ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4), u256(17))); } +BOOST_AUTO_TEST_CASE(mapping_arguments_in_library) +{ + char const* sourceCode = R"( + library Lib { + function set(mapping(uint => uint) storage m, uint key, uint value) internal + { + m[key] = value; + } + function get(mapping(uint => uint) storage m, uint key) internal view returns (uint) + { + return m[key]; + } + } + contract Test { + mapping(uint => uint) m; + function set(uint256 key, uint256 value) public returns (uint) + { + uint oldValue = Lib.get(m, key); + Lib.set(m, key, value); + return oldValue; + } + function get(uint256 key) public view returns (uint) { + return Lib.get(m, key); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(42)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(84)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(7)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(21)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(42)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(14)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(14))); +} + +BOOST_AUTO_TEST_CASE(mapping_returns_in_library) +{ + char const* sourceCode = R"( + library Lib { + function choose_mapping(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint=>uint) storage) + { + return c ? a : b; + } + } + contract Test { + mapping(uint => uint) a; + mapping(uint => uint) b; + function set(bool choice, uint256 key, uint256 value) public returns (uint) + { + mapping(uint => uint) storage m = Lib.choose_mapping(a, b, choice); + uint oldValue = m[key]; + m[key] = value; + return oldValue; + } + function get(bool choice, uint256 key) public view returns (uint) { + return Lib.choose_mapping(a, b, choice)[key]; + } + function get_a(uint256 key) public view returns (uint) { + return a[key]; + } + function get_b(uint256 key) public view returns (uint) { + return b[key]; + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(42)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(84)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(7)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(10)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(11)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(12)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(21)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(42)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(14)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(30)), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(31)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(32)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(14))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(14))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(30))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(31))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(32))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(30))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(31))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(32))); +} + +BOOST_AUTO_TEST_CASE(mapping_returns_in_library_named) +{ + char const* sourceCode = R"( + library Lib { + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b) internal returns(mapping(uint=>uint) storage r) + { + r = a; + r[1] = 42; + r = b; + r[1] = 21; + } + } + contract Test { + mapping(uint => uint) a; + mapping(uint => uint) b; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.f(a, b)[2] = 84; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + function g() public returns (uint, uint, uint, uint, uint, uint) + { + mapping(uint => uint) storage m = Lib.f(a, b); + m[2] = 17; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(84))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(17))); +} + BOOST_AUTO_TEST_CASE(using_library_structs) { char const* sourceCode = R"( library Lib { struct Data { uint a; uint[] b; } - function set(Data storage _s) + function set(Data storage _s) public { _s.a = 7; _s.b.length = 20; @@ -7615,7 +8672,7 @@ BOOST_AUTO_TEST_CASE(using_library_structs) } contract Test { mapping(string => Lib.Data) data; - function f() returns (uint a, uint b) + function f() public returns (uint a, uint b) { Lib.set(data["abc"]); a = data["abc"].a; @@ -7639,7 +8696,7 @@ BOOST_AUTO_TEST_CASE(library_struct_as_an_expression) } contract Tsra { - function f() returns(uint) { + function f() public returns(uint) { Arst.Foo; return 1; } @@ -7660,7 +8717,7 @@ BOOST_AUTO_TEST_CASE(library_enum_as_an_expression) } contract Tsra { - function f() returns(uint) { + function f() public returns(uint) { Arst.Foo; return 1; } @@ -7678,7 +8735,7 @@ BOOST_AUTO_TEST_CASE(short_strings) contract A { bytes public data1 = "123"; bytes data2; - function lengthChange() returns (uint) + function lengthChange() public returns (uint) { // store constant in short and long string data1 = "123"; @@ -7701,18 +8758,18 @@ BOOST_AUTO_TEST_CASE(short_strings) if (data1[0] != "1") return 10; if (data1[4] != "4") return 11; for (uint i = 0; i < data1.length; i ++) - data1[i] = byte(i * 3); - if (data1[4] != 4 * 3) return 12; - if (data1[67] != 67 * 3) return 13; + data1[i] = byte(uint8(i * 3)); + if (uint8(data1[4]) != 4 * 3) return 12; + if (uint8(data1[67]) != 67 * 3) return 13; // change length: long -> short data1.length = 22; if (data1.length != 22) return 14; - if (data1[21] != byte(21 * 3)) return 15; - if (data1[2] != 2 * 3) return 16; + if (uint8(data1[21]) != 21 * 3) return 15; + if (uint8(data1[2]) != 2 * 3) return 16; // change length: short -> shorter data1.length = 19; if (data1.length != 19) return 17; - if (data1[7] != byte(7 * 3)) return 18; + if (uint8(data1[7]) != 7 * 3) return 18; // and now again to original size data1.length = 22; if (data1.length != 22) return 19; @@ -7720,7 +8777,7 @@ BOOST_AUTO_TEST_CASE(short_strings) data1.length = 0; data2.length = 0; } - function copy() returns (uint) { + function copy() public returns (uint) { bytes memory x = "123"; bytes memory y = "012345678901234567890123456789012345678901234567890123456789"; bytes memory z = "1234567"; @@ -7753,7 +8810,7 @@ BOOST_AUTO_TEST_CASE(short_strings) data1 = ""; data2 = ""; } - function deleteElements() returns (uint) { + function deleteElements() public returns (uint) { data1 = "01234"; delete data1[2]; if (data1[2] != 0) return 1; @@ -7789,7 +8846,7 @@ BOOST_AUTO_TEST_CASE(calldata_offset) { address[] _arr; string public last = "nd"; - function CB(address[] guardians) + constructor(address[] memory guardians) public { _arr = guardians; } @@ -7802,9 +8859,9 @@ BOOST_AUTO_TEST_CASE(calldata_offset) BOOST_AUTO_TEST_CASE(contract_binary_dependencies) { char const* sourceCode = R"( - contract A { function f() { new B(); } } - contract B { function f() { } } - contract C { function f() { new B(); } } + contract A { function f() public { new B(); } } + contract B { function f() public { } } + contract C { function f() public { new B(); } } )"; compileAndRun(sourceCode); } @@ -7814,11 +8871,11 @@ BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library) char const* sourceCode = R"( library lib {} contract c { - function c() payable {} - function f(address x) returns (bool) { + constructor() public payable {} + function f(address payable x) public returns (bool) { return x.send(1); } - function () payable {} + function () external payable {} } )"; compileAndRun(sourceCode, 0, "lib"); @@ -7838,20 +8895,39 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration) { char const* sourceCode = R"( contract C { - function g() returns (uint a, uint b, uint c) { + function g() public returns (uint a, uint b, uint c) { a = 1; b = 2; c = 3; } - function f() returns (bool) { - var (x, y, z) = g(); + function h() public returns (uint a, uint b, uint c, uint d) { + a = 1; b = 2; c = 3; d = 4; + } + function f1() public returns (bool) { + (uint x, uint y, uint z) = g(); if (x != 1 || y != 2 || z != 3) return false; - var (, a,) = g(); + (, uint a,) = g(); if (a != 2) return false; - var (b,) = g(); + (uint b, , ) = g(); if (b != 1) return false; - var (,c) = g(); + (, , uint c) = g(); if (c != 3) return false; return true; } + function f2() public returns (bool) { + (uint a1, , uint a3, ) = h(); + if (a1 != 1 || a3 != 3) return false; + (uint b1, uint b2, , ) = h(); + if (b1 != 1 || b2 != 2) return false; + (, uint c2, uint c3, ) = h(); + if (c2 != 2 || c3 != 3) return false; + (, , uint d3, uint d4) = h(); + if (d3 != 3 || d4 != 4) return false; + (uint e1, , uint e3, uint e4) = h(); + if (e1 != 1 || e3 != 3 || e4 != 4) return false; + return true; + } + function f() public returns (bool) { + return f1() && f2(); + } } )"; compileAndRun(sourceCode); @@ -7868,7 +8944,7 @@ BOOST_AUTO_TEST_CASE(typed_multi_variable_declaration) s.x = 7; return (1, s, 2); } - function f() returns (bool) { + function f() public returns (bool) { (uint x1, S storage y1, uint z1) = g(); if (x1 != 1 || y1.x != 7 || z1 != 2) return false; (, S storage y2,) = g(); @@ -7890,24 +8966,25 @@ BOOST_AUTO_TEST_CASE(tuples) char const* sourceCode = R"( contract C { uint[] data; + uint[] m_c; function g() internal returns (uint a, uint b, uint[] storage c) { return (1, 2, data); } function h() external returns (uint a, uint b) { return (5, 6); } - function f() returns (uint) { + function f() public returns (uint) { data.length = 1; data[0] = 3; uint a; uint b; (a, b) = this.h(); if (a != 5 || b != 6) return 1; - uint[] storage c; + uint[] storage c = m_c; (a, b, c) = g(); if (a != 1 || b != 2 || c[0] != 3) return 2; (a, b) = (b, a); if (a != 2 || b != 1) return 3; - (a, , b, ) = (8, 9, 10, 11, 12); + (a, , b, , ) = (8, 9, 10, 11, 12); if (a != 8 || b != 10) return 4; } } @@ -7920,14 +8997,14 @@ BOOST_AUTO_TEST_CASE(string_tuples) { char const* sourceCode = R"( contract C { - function f() returns (string, uint) { + function f() public returns (string memory, uint) { return ("abc", 8); } - function g() returns (string, string) { + function g() public returns (string memory, string memory) { return (h(), "def"); } - function h() returns (string) { - return ("abc",); + function h() public returns (string memory) { + return ("abc"); } } )"; @@ -7940,7 +9017,7 @@ BOOST_AUTO_TEST_CASE(decayed_tuple) { char const* sourceCode = R"( contract C { - function f() returns (uint) { + function f() public returns (uint) { uint x = 1; (x) = 2; return x; @@ -7955,7 +9032,7 @@ BOOST_AUTO_TEST_CASE(inline_tuple_with_rational_numbers) { char const* sourceCode = R"( contract c { - function f() returns (int8) { + function f() public returns (int8) { int8[5] memory foo3 = [int8(1), -1, 0, 0, 0]; return foo3[0]; } @@ -7973,13 +9050,13 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment) bytes data; uint[] y; uint[] arrayData; - function returnsArray() returns (uint[]) { + function returnsArray() public returns (uint[] memory) { arrayData.length = 9; arrayData[2] = 5; arrayData[7] = 4; return arrayData; } - function f(bytes s) returns (uint) { + function f(bytes memory s) public returns (uint) { uint loc; uint[] memory memArray; (loc, x, y, data, arrayData[3]) = (8, 4, returnsArray(), s, 2); @@ -7995,7 +9072,7 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment) if (loc != 3) return 9; if (memArray.length != arrayData.length) return 10; bytes memory memBytes; - (x, memBytes, y[2], ) = (456, s, 789, 101112, 131415); + (x, memBytes, y[2], , ) = (456, s, 789, 101112, 131415); if (x != 456 || memBytes.length != s.length || y[2] != 789) return 11; } } @@ -8004,37 +9081,12 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment) ABI_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), string("abcde")), encodeArgs(u256(0))); } -BOOST_AUTO_TEST_CASE(destructuring_assignment_wildcard) -{ - char const* sourceCode = R"( - contract C { - function f() returns (uint) { - uint a; - uint b; - uint c; - (a,) = (1,); - if (a != 1) return 1; - (,b) = (2,3,4); - if (b != 4) return 2; - (, c,) = (5,6,7); - if (c != 6) return 3; - (a, b,) = (11, 12, 13); - if (a != 11 || b != 12) return 4; - (, a, b) = (11, 12, 13); - if (a != 12 || b != 13) return 5; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); -} - BOOST_AUTO_TEST_CASE(lone_struct_array_type) { char const* sourceCode = R"( contract C { struct s { uint a; uint b;} - function f() returns (uint) { + function f() public returns (uint) { s[7][]; // This is only the type, should not have any effect return 3; } @@ -8049,12 +9101,12 @@ BOOST_AUTO_TEST_CASE(create_memory_array) char const* sourceCode = R"( contract C { struct S { uint[2] a; bytes b; } - function f() returns (byte, uint, uint, byte) { - var x = new bytes(200); + function f() public returns (byte, uint, uint, byte) { + bytes memory x = new bytes(200); x[199] = 'A'; - var y = new uint[2][](300); + uint[2][] memory y = new uint[2][](300); y[203][1] = 8; - var z = new S[](180); + S[] memory z = new S[](180); z[170].a[1] = 4; z[170].b = new bytes(102); z[170].b[99] = 'B'; @@ -8072,7 +9124,7 @@ BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size) // multiple of 32 char const* sourceCode = R"( contract C { - function f() pure returns (uint d1, uint d2, uint d3) { + function f() public pure returns (uint d1, uint d2, uint d3, uint memsize) { bytes memory b1 = new bytes(31); bytes memory b2 = new bytes(32); bytes memory b3 = new bytes(256); @@ -8081,12 +9133,13 @@ BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size) d1 := sub(b2, b1) d2 := sub(b3, b2) d3 := sub(b4, b3) + memsize := msize() } } } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256, 0x260)); } BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) @@ -8094,7 +9147,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) // Computes binomial coefficients the chinese way char const* sourceCode = R"( contract C { - function f(uint n, uint k) returns (uint) { + function f(uint n, uint k) public returns (uint) { uint[][] memory rows = new uint[][](n + 1); for (uint i = 1; i <= n; i++) { rows[i] = new uint[](i); @@ -8115,7 +9168,7 @@ BOOST_AUTO_TEST_CASE(create_multiple_dynamic_arrays) { char const* sourceCode = R"( contract C { - function f() returns (uint) { + function f() public returns (uint) { uint[][] memory x = new uint[][](42); assert(x[0].length == 0); x[0] = new uint[](1); @@ -8150,7 +9203,7 @@ BOOST_AUTO_TEST_CASE(memory_overwrite) { char const* sourceCode = R"( contract C { - function f() returns (bytes x) { + function f() public returns (bytes memory x) { x = "12345"; x[3] = 0x61; x[0] = 0x62; @@ -8165,7 +9218,7 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod) { char const* sourceCode = R"( contract C { - function test() returns (uint) { + function test() public returns (uint) { // Note that this only works because computation on literals is done using // unbounded integers. if ((2**255 + 2**255) % 7 != addmod(2**255, 2**255, 7)) @@ -8184,15 +9237,15 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod_zero) { char const* sourceCode = R"( contract C { - function f(uint d) pure returns (uint) { + function f(uint d) public pure returns (uint) { addmod(1, 2, d); return 2; } - function g(uint d) pure returns (uint) { + function g(uint d) public pure returns (uint) { mulmod(1, 2, d); return 2; } - function h() pure returns (uint) { + function h() public pure returns (uint) { mulmod(0, 1, 2); mulmod(1, 0, 2); addmod(0, 1, 2); @@ -8211,10 +9264,10 @@ BOOST_AUTO_TEST_CASE(divisiod_by_zero) { char const* sourceCode = R"( contract C { - function div(uint a, uint b) returns (uint) { + function div(uint a, uint b) public returns (uint) { return a / b; } - function mod(uint a, uint b) returns (uint) { + function mod(uint a, uint b) public returns (uint) { return a % b; } } @@ -8235,7 +9288,7 @@ BOOST_AUTO_TEST_CASE(string_allocation_bug) { struct s { uint16 x; uint16 y; string a; string b;} s[2] public p; - function Sample() { + constructor() public { s memory m; m.x = 0xbbbb; m.y = 0xcccc; @@ -8261,10 +9314,10 @@ BOOST_AUTO_TEST_CASE(string_allocation_bug) BOOST_AUTO_TEST_CASE(using_for_function_on_int) { char const* sourceCode = R"( - library D { function double(uint self) returns (uint) { return 2*self; } } + library D { function double(uint self) public returns (uint) { return 2*self; } } contract C { using D for uint; - function f(uint a) returns (uint) { + function f(uint a) public returns (uint) { return a.double(); } } @@ -8277,11 +9330,11 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_int) BOOST_AUTO_TEST_CASE(using_for_function_on_struct) { char const* sourceCode = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) returns (uint) { return self.a *= x; } } + library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } contract C { using D for D.s; D.s public x; - function f(uint a) returns (uint) { + function f(uint a) public returns (uint) { x.a = 3; return x.mul(a); } @@ -8298,13 +9351,13 @@ BOOST_AUTO_TEST_CASE(using_for_overload) char const* sourceCode = R"( library D { struct s { uint a; } - function mul(s storage self, uint x) returns (uint) { return self.a *= x; } - function mul(s storage self, bytes32 x) returns (bytes32) { } + function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } + function mul(s storage self, bytes32 x) public returns (bytes32) { } } contract C { using D for D.s; D.s public x; - function f(uint a) returns (uint) { + function f(uint a) public returns (uint) { x.a = 6; return x.mul(a); } @@ -8319,11 +9372,11 @@ BOOST_AUTO_TEST_CASE(using_for_overload) BOOST_AUTO_TEST_CASE(using_for_by_name) { char const* sourceCode = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) returns (uint) { return self.a *= x; } } + library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } contract C { using D for D.s; D.s public x; - function f(uint a) returns (uint) { + function f(uint a) public returns (uint) { x.a = 6; return x.mul({x: a}); } @@ -8338,14 +9391,13 @@ BOOST_AUTO_TEST_CASE(using_for_by_name) BOOST_AUTO_TEST_CASE(bound_function_in_var) { char const* sourceCode = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) returns (uint) { return self.a *= x; } } + library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } contract C { using D for D.s; D.s public x; - function f(uint a) returns (uint) { + function f(uint a) public returns (uint) { x.a = 6; - var g = x.mul; - return g({x: a}); + return (x.mul)({x: a}); } } )"; @@ -8358,15 +9410,15 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var) BOOST_AUTO_TEST_CASE(bound_function_to_string) { char const* sourceCode = R"( - library D { function length(string memory self) returns (uint) { return bytes(self).length; } } + library D { function length(string memory self) public returns (uint) { return bytes(self).length; } } contract C { using D for string; string x; - function f() returns (uint) { + function f() public returns (uint) { x = "abc"; return x.length(); } - function g() returns (uint) { + function g() public returns (uint) { string memory s = "abc"; return s.length(); } @@ -8383,7 +9435,7 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) char const* sourceCode = R"( contract C { string s = "doh"; - function f() returns (string, string) { + function f() public returns (string memory, string memory) { string memory t = "ray"; string[3] memory x = [s, t, "mi"]; return (x[1], x[2]); @@ -8398,7 +9450,7 @@ BOOST_AUTO_TEST_CASE(inline_array_strings_from_document) { char const* sourceCode = R"( contract C { - function f(uint i) returns (string) { + function f(uint i) public returns (string memory) { string[4] memory x = ["This", "is", "an", "array"]; return (x[i]); } @@ -8415,7 +9467,7 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) { char const* sourceCode = R"( contract C { - function f() returns (uint x, uint y) { + function f() public returns (uint x, uint y) { x = 3; y = 6; uint[2] memory z = [x, y]; @@ -8431,7 +9483,7 @@ BOOST_AUTO_TEST_CASE(inline_array_index_access_ints) { char const* sourceCode = R"( contract C { - function f() returns (uint) { + function f() public returns (uint) { return ([1, 2, 3, 4][2]); } } @@ -8445,10 +9497,10 @@ BOOST_AUTO_TEST_CASE(inline_array_index_access_strings) char const* sourceCode = R"( contract C { string public tester; - function f() returns (string) { + function f() public returns (string memory) { return (["abc", "def", "g"][0]); } - function test() { + function test() public { tester = f(); } } @@ -8462,15 +9514,15 @@ BOOST_AUTO_TEST_CASE(inline_array_return) { char const* sourceCode = R"( contract C { - uint8[] tester; - function f() returns (uint8[5]) { + uint8[] tester; + function f() public returns (uint8[5] memory) { return ([1,2,3,4,5]); } - function test() returns (uint8, uint8, uint8, uint8, uint8) { - tester = f(); + function test() public returns (uint8, uint8, uint8, uint8, uint8) { + tester = f(); return (tester[0], tester[1], tester[2], tester[3], tester[4]); } - + } )"; compileAndRun(sourceCode, 0, "C"); @@ -8482,7 +9534,7 @@ BOOST_AUTO_TEST_CASE(inline_array_singleton) // This caused a failure since the type was not converted to its mobile type. char const* sourceCode = R"( contract C { - function f() returns (uint) { + function f() public returns (uint) { return [4][0]; } } @@ -8494,13 +9546,13 @@ BOOST_AUTO_TEST_CASE(inline_array_singleton) BOOST_AUTO_TEST_CASE(inline_long_string_return) { char const* sourceCode = R"( - contract C { - function f() returns (string) { + contract C { + function f() public returns (string memory) { return (["somethingShort", "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"][1]); } } )"; - + string strLong = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), encodeDyn(strLong)); @@ -8511,13 +9563,13 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_index_access) char const* sourceCode = R"( contract C { bytes16[] public data; - function f(bytes32 x) returns (byte) { + function f(bytes32 x) public returns (byte) { return x[2]; } - function g(bytes32 x) returns (uint) { + function g(bytes32 x) public returns (uint) { data = [x[0], x[1], x[2]]; data[0] = "12345"; - return uint(data[0][4]); + return uint(uint8(data[0][4])); } } )"; @@ -8532,8 +9584,8 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_length_access) char const* sourceCode = R"( contract C { byte a; - function f(bytes32 x) returns (uint, uint, uint) { - return (x.length, bytes16(2).length, a.length + 7); + function f(bytes32 x) public returns (uint, uint, uint) { + return (x.length, bytes16(uint128(2)).length, a.length + 7); } } )"; @@ -8545,7 +9597,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_write_to_stack) { char const* sourceCode = R"( contract C { - function f() returns (uint r, bytes32 r2) { + function f() public returns (uint r, bytes32 r2) { assembly { r := 7 r2 := "abcdef" } } } @@ -8558,7 +9610,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_read_and_write_stack) { char const* sourceCode = R"( contract C { - function f() returns (uint r) { + function f() public returns (uint r) { for (uint x = 0; x < 10; ++x) assembly { r := add(r, x) } } @@ -8572,10 +9624,10 @@ BOOST_AUTO_TEST_CASE(inline_assembly_memory_access) { char const* sourceCode = R"( contract C { - function test() returns (bytes) { + function test() public returns (bytes memory) { bytes memory x = new bytes(5); for (uint i = 0; i < x.length; ++i) - x[i] = byte(i + 1); + x[i] = byte(uint8(i + 1)); assembly { mstore(add(x, 32), "12345678901234567890123456789012") } return x; } @@ -8592,7 +9644,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access) uint16 x; uint16 public y; uint public z; - function f() returns (bool) { + function f() public returns (bool) { uint off1; uint off2; assembly { @@ -8618,7 +9670,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_inside_function) uint16 x; uint16 public y; uint public z; - function f() returns (bool) { + function f() public returns (bool) { uint off1; uint off2; assembly { @@ -8646,8 +9698,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) uint public separator; Data public a; uint public separator2; - function f() returns (bool) { - Data x = a; + function f() public returns (bool) { + Data storage x = a; uint off; assembly { sstore(x_slot, 7) @@ -8665,57 +9717,11 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) ABI_CHECK(callContractFunction("separator2()"), encodeArgs(u256(0))); } -BOOST_AUTO_TEST_CASE(inline_assembly_jumps) -{ - char const* sourceCode = R"( - contract C { - function f() { - assembly { - let n := calldataload(4) - let a := 1 - let b := a - loop: - jumpi(loopend, eq(n, 0)) - a add swap1 - n := sub(n, 1) - jump(loop) - loopend: - mstore(0, a) - return(0, 0x20) - } - } - } - )"; - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f()", u256(5)), encodeArgs(u256(13))); - ABI_CHECK(callContractFunction("f()", u256(7)), encodeArgs(u256(34))); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_function_access) -{ - char const* sourceCode = R"( - contract C { - uint public x; - function g(uint y) { x = 2 * y; assembly { stop } } - function f(uint _x) { - assembly { - _x - jump(g) - pop - } - } - } - )"; - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f(uint256)", u256(5)), encodeArgs()); - ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(10))); -} - BOOST_AUTO_TEST_CASE(inline_assembly_function_call) { char const* sourceCode = R"( contract C { - function f() { + function f() public { assembly { function asmfun(a, b, c) -> x, y, z { x := a @@ -8739,7 +9745,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call_assignment) { char const* sourceCode = R"( contract C { - function f() { + function f() public { assembly { let a1, b1, c1 function asmfun(a, b, c) -> x, y, z { @@ -8764,7 +9770,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call2) { char const* sourceCode = R"( contract C { - function f() { + function f() public { assembly { let d := 0x10 function asmfun(a, b, c) -> x, y, z { @@ -8790,7 +9796,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_embedded_function_call) { char const* sourceCode = R"( contract C { - function f() { + function f() public { assembly { let d := 0x10 function asmfun(a, b, c) -> x, y, z { @@ -8817,7 +9823,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_if) { char const* sourceCode = R"( contract C { - function f(uint a) returns (uint b) { + function f(uint a) public returns (uint b) { assembly { if gt(a, 1) { b := 2 } } @@ -8835,7 +9841,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_switch) { char const* sourceCode = R"( contract C { - function f(uint a) returns (uint b) { + function f(uint a) public returns (uint b) { assembly { switch a case 1 { b := 8 } @@ -8856,7 +9862,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_recursion) { char const* sourceCode = R"( contract C { - function f(uint a) returns (uint b) { + function f(uint a) public returns (uint b) { assembly { function fac(n) -> nf { switch n @@ -8881,7 +9887,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_for) { char const* sourceCode = R"( contract C { - function f(uint a) returns (uint b) { + function f(uint a) public returns (uint b) { assembly { function fac(n) -> nf { nf := 1 @@ -8907,7 +9913,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_for2) char const* sourceCode = R"( contract C { uint st; - function f(uint a) returns (uint b, uint c, uint d) { + function f(uint a) public returns (uint b, uint c, uint d) { st = 0; assembly { function sideeffect(r) -> x { sstore(0, add(sload(0), r)) x := 1} @@ -8931,7 +9937,7 @@ BOOST_AUTO_TEST_CASE(index_access_with_type_conversion) // Test for a bug where higher order bits cleanup was not done for array index access. char const* sourceCode = R"( contract C { - function f(uint x) returns (uint[256] r){ + function f(uint x) public returns (uint[256] memory r){ r[uint8(x)] = 2; } } @@ -8949,7 +9955,7 @@ BOOST_AUTO_TEST_CASE(delete_on_array_of_structs) contract C { struct S { uint x; uint[] y; } S[] data; - function f() returns (bool) { + function f() public returns (bool) { data.length = 2; data[0].x = 2**200; data[1].x = 2**200; @@ -8971,12 +9977,12 @@ BOOST_AUTO_TEST_CASE(internal_library_function) // and retain the same memory context (i.e. are pulled into the caller's code) char const* sourceCode = R"( library L { - function f(uint[] _data) internal { + function f(uint[] memory _data) internal { _data[3] = 2; } } contract C { - function f() returns (uint) { + function f() public returns (uint) { uint[] memory x = new uint[](7); x[3] = 8; L.f(x); @@ -8996,15 +10002,15 @@ BOOST_AUTO_TEST_CASE(internal_library_function_calling_private) // also has to be pulled into the caller's code) char const* sourceCode = R"( library L { - function g(uint[] _data) private { + function g(uint[] memory _data) private { _data[3] = 2; } - function f(uint[] _data) internal { + function f(uint[] memory _data) internal { g(_data); } } contract C { - function f() returns (uint) { + function f() public returns (uint) { uint[] memory x = new uint[](7); x[3] = 8; L.f(x); @@ -9022,13 +10028,13 @@ BOOST_AUTO_TEST_CASE(internal_library_function_bound) char const* sourceCode = R"( library L { struct S { uint[] data; } - function f(S _s) internal { + function f(S memory _s) internal { _s.data[3] = 2; } } contract C { using L for L.S; - function f() returns (uint) { + function f() public returns (uint) { L.S memory x; x.data = new uint[](7); x.data[3] = 8; @@ -9047,14 +10053,14 @@ BOOST_AUTO_TEST_CASE(internal_library_function_return_var_size) char const* sourceCode = R"( library L { struct S { uint[] data; } - function f(S _s) internal returns (uint[]) { + function f(S memory _s) internal returns (uint[] memory) { _s.data[3] = 2; return _s.data; } } contract C { using L for L.S; - function f() returns (uint) { + function f() public returns (uint) { L.S memory x; x.data = new uint[](7); x.data[3] = 8; @@ -9073,10 +10079,10 @@ BOOST_AUTO_TEST_CASE(iszero_bnot_correct) // "iszero" and "not". char const* sourceCode = R"( contract C { - function f() returns (bool) { - bytes32 x = 1; + function f() public returns (bool) { + bytes32 x = bytes32(uint256(1)); assembly { x := not(x) } - if (x != ~bytes32(1)) return false; + if (x != ~bytes32(uint256(1))) return false; assembly { x := iszero(x) } if (x != bytes32(0)) return false; return true; @@ -9092,10 +10098,10 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types) // Checks that bytesXX types are properly cleaned before they are compared. char const* sourceCode = R"( contract C { - function f(bytes2 a, uint16 x) returns (uint) { + function f(bytes2 a, uint16 x) public returns (uint) { if (a != "ab") return 1; if (x != 0x0102) return 2; - if (bytes3(x) != 0x0102) return 3; + if (bytes3(uint24(x)) != 0x000102) return 3; return 0; } } @@ -9109,7 +10115,7 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types_shortening) { char const* sourceCode = R"( contract C { - function f() pure returns (bytes32 r) { + function f() public pure returns (bytes32 r) { bytes4 x = 0xffffffff; bytes2 y = bytes2(x); assembly { r := y } @@ -9123,17 +10129,65 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types_shortening) ABI_CHECK(callContractFunction("f()"), encodeArgs("\xff\xff\xff\xff")); } +BOOST_AUTO_TEST_CASE(cleanup_address_types) +{ + // Checks that address types are properly cleaned before they are compared. + char const* sourceCode = R"( + contract C { + function f(address a) public returns (uint) { + if (a != 0x1234567890123456789012345678901234567890) return 1; + return 0; + } + function g(address payable a) public returns (uint) { + if (a != 0x1234567890123456789012345678901234567890) return 1; + return 0; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + // We input longer data on purpose. + ABI_CHECK(callContractFunction("f(address)", u256("0xFFFF1234567890123456789012345678901234567890")), encodeArgs(0)); + ABI_CHECK(callContractFunction("g(address)", u256("0xFFFF1234567890123456789012345678901234567890")), encodeArgs(0)); +} + +BOOST_AUTO_TEST_CASE(cleanup_address_types_shortening) +{ + char const* sourceCode = R"( + contract C { + function f() public pure returns (address r) { + bytes21 x = 0x1122334455667788990011223344556677889900ff; + bytes20 y; + assembly { y := x } + address z = address(y); + assembly { r := z } + require(z == 0x1122334455667788990011223344556677889900); + } + function g() public pure returns (address payable r) { + bytes21 x = 0x1122334455667788990011223344556677889900ff; + bytes20 y; + assembly { y := x } + address payable z = address(y); + assembly { r := z } + require(z == 0x1122334455667788990011223344556677889900); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256("0x1122334455667788990011223344556677889900"))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256("0x1122334455667788990011223344556677889900"))); +} + BOOST_AUTO_TEST_CASE(skip_dynamic_types) { // The EVM cannot provide access to dynamically-sized return values, so we have to skip them. char const* sourceCode = R"( contract C { - function f() returns (uint, uint[], uint) { + function f() public returns (uint, uint[] memory, uint) { return (7, new uint[](2), 8); } - function g() returns (uint, uint) { + function g() public returns (uint, uint) { // Previous implementation "moved" b to the second place and did not skip. - var (a, _, b) = this.f(); + (uint a,, uint b) = this.f(); return (a, b); } } @@ -9154,12 +10208,12 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs) uint y; } S public s; - function g() returns (uint, uint) { + function g() public returns (uint, uint) { s.x = 2; s.a = "abc"; s.b = [7, 8, 9]; s.y = 6; - var (x, a, y) = this.s(); + (uint x,, uint y) = this.s(); return (x, y); } } @@ -9171,19 +10225,19 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs) BOOST_AUTO_TEST_CASE(failed_create) { char const* sourceCode = R"( - contract D { function D() payable {} } + contract D { constructor() public payable {} } contract C { uint public x; - function C() payable {} - function f(uint amount) returns (address) { + constructor() public payable {} + function f(uint amount) public returns (D) { x++; return (new D).value(amount)(); } - function stack(uint depth) returns (address) { + function stack(uint depth) public returns (address) { if (depth < 1024) return this.stack(depth - 1); else - return f(0); + return address(f(0)); } } )"; @@ -9200,8 +10254,8 @@ BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length) { char const* sourceCode = R"( contract C { - function f() returns (uint) { - var a = new uint[][](0); + function f() public returns (uint) { + uint[][] memory a = new uint[][](0); return 7; } } @@ -9217,7 +10271,7 @@ BOOST_AUTO_TEST_CASE(correctly_initialize_memory_array_in_constructor) char const* sourceCode = R"( contract C { bool public success; - function C() public { + constructor() public { // Make memory dirty. assembly { for { let i := 0 } lt(i, 64) { i := add(i, 1) } { @@ -9245,7 +10299,7 @@ BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier) _; x = 9; } - function f() setsx returns (uint) { + function f() setsx public returns (uint) { return 2; } } @@ -9267,8 +10321,10 @@ BOOST_AUTO_TEST_CASE(break_in_modifier) break; } } - function f() run { - x++; + function f() run public { + uint k = x; + uint t = k + 1; + x = t; } } )"; @@ -9278,6 +10334,54 @@ BOOST_AUTO_TEST_CASE(break_in_modifier) ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } +BOOST_AUTO_TEST_CASE(continue_in_modifier) +{ + char const* sourceCode = R"( + contract C { + uint public x; + modifier run() { + for (uint i = 0; i < 10; i++) { + if (i % 2 == 1) continue; + _; + } + } + function f() run public { + uint k = x; + uint t = k + 1; + x = t; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(5))); +} + +BOOST_AUTO_TEST_CASE(return_in_modifier) +{ + char const* sourceCode = R"( + contract C { + uint public x; + modifier run() { + for (uint i = 1; i < 10; i++) { + if (i == 5) return; + _; + } + } + function f() run public { + uint k = x; + uint t = k + 1; + x = t; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(4))); +} + BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) { char const* sourceCode = R"( @@ -9289,8 +10393,10 @@ BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) break; } } - function f() run { - x++; + function f() run public { + uint k = x; + uint t = k + 1; + x = t; } } )"; @@ -9306,7 +10412,7 @@ BOOST_AUTO_TEST_CASE(mutex) contract mutexed { bool locked; modifier protected { - if (locked) throw; + if (locked) revert(); locked = true; _; locked = false; @@ -9314,20 +10420,22 @@ BOOST_AUTO_TEST_CASE(mutex) } contract Fund is mutexed { uint shares; - function Fund() payable { shares = msg.value; } - function withdraw(uint amount) protected returns (uint) { + constructor() public payable { shares = msg.value; } + function withdraw(uint amount) public protected returns (uint) { // NOTE: It is very bad practice to write this function this way. // Please refer to the documentation of how to do this properly. - if (amount > shares) throw; - if (!msg.sender.call.value(amount)()) throw; + if (amount > shares) revert(); + (bool success,) = msg.sender.call.value(amount)(""); + require(success); shares -= amount; return shares; } - function withdrawUnprotected(uint amount) returns (uint) { + function withdrawUnprotected(uint amount) public returns (uint) { // NOTE: It is very bad practice to write this function this way. // Please refer to the documentation of how to do this properly. - if (amount > shares) throw; - if (!msg.sender.call.value(amount)()) throw; + if (amount > shares) revert(); + (bool success,) = msg.sender.call.value(amount)(""); + require(success); shares -= amount; return shares; } @@ -9336,9 +10444,9 @@ BOOST_AUTO_TEST_CASE(mutex) Fund public fund; uint callDepth; bool protected; - function setProtected(bool _protected) { protected = _protected; } - function Attacker(Fund _fund) { fund = _fund; } - function attack() returns (uint) { + function setProtected(bool _protected) public { protected = _protected; } + constructor(Fund _fund) public { fund = _fund; } + function attack() public returns (uint) { callDepth = 0; return attackInternal(); } @@ -9348,7 +10456,7 @@ BOOST_AUTO_TEST_CASE(mutex) else return fund.withdrawUnprotected(10); } - function() payable { + function() external payable { callDepth++; if (callDepth < 4) attackInternal(); @@ -9374,8 +10482,8 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input) // Note that the precompile does not return zero but returns nothing. char const* sourceCode = R"( contract C { - function f() returns (address) { - return ecrecover(bytes32(uint(-1)), 1, 2, 3); + function f() public returns (address) { + return ecrecover(bytes32(uint(-1)), 1, bytes32(uint(2)), bytes32(uint(3))); } } )"; @@ -9387,20 +10495,20 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper) { char const* sourceCode = R"( contract C { - function f() returns (address) { + function f() public returns (address) { return recover( 0x77e5189111eb6557e8a637b27ef8fbb15bc61d61c2f00cc48878f3a296e5e0ca, 0, // invalid v value 0x6944c77849b18048f6abe0db8084b0d0d0689cdddb53d2671c36967b58691ad4, 0xef4f06ba4f78319baafd0424365777241af4dfd3da840471b4b4b087b7750d0d, - 0xca35b7d915458ef540ade6068dfe2f44e8fa733c, - 0xca35b7d915458ef540ade6068dfe2f44e8fa733c + 0x000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c, + 0x000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c ); } function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s, uint blockExpired, bytes32 salt) - returns (address) + public returns (address) { - require(hash == keccak256(blockExpired, salt)); + require(hash == keccak256(abi.encodePacked(blockExpired, salt))); return ecrecover(hash, v, r, s); } } @@ -9413,7 +10521,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) { char const* sourceCode = R"( contract C { - function f() returns (address) { + function f() public returns (address) { assembly { mstore(mload(0x40), 0xca35b7d915458ef540ade6068dfe2f44e8fa733c) } @@ -9432,24 +10540,24 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) { - char const* sourceCode = R"( - contract D { function g(); } + char const* sourceCode = R"YY( + contract D { function g() public; } contract C { D d = D(0x1212); - function f() returns (uint) { + function f() public returns (uint) { d.g(); return 7; } - function g() returns (uint) { + function g() public returns (uint) { d.g.gas(200)(); return 7; } - function h() returns (uint) { - d.call(); // this does not throw (low-level) + function h() public returns (uint) { + address(d).call(""); // this does not throw (low-level) return 7; } } - )"; + )YY"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), encodeArgs()); ABI_CHECK(callContractFunction("g()"), encodeArgs()); @@ -9460,7 +10568,7 @@ BOOST_AUTO_TEST_CASE(payable_constructor) { char const* sourceCode = R"( contract C { - function C() payable { } + constructor() public payable { } } )"; compileAndRun(sourceCode, 27, "C"); @@ -9471,10 +10579,10 @@ BOOST_AUTO_TEST_CASE(payable_function) char const* sourceCode = R"( contract C { uint public a; - function f() payable returns (uint) { + function f() payable public returns (uint) { return msg.value; } - function() payable { + function() external payable { a = msg.value + 1; } } @@ -9492,10 +10600,10 @@ BOOST_AUTO_TEST_CASE(payable_function_calls_library) { char const* sourceCode = R"( library L { - function f() returns (uint) { return 7; } + function f() public returns (uint) { return 7; } } contract C { - function f() payable returns (uint) { + function f() public payable returns (uint) { return L.f(); } } @@ -9510,12 +10618,19 @@ BOOST_AUTO_TEST_CASE(non_payable_throw) char const* sourceCode = R"( contract C { uint public a; - function f() returns (uint) { + function f() public returns (uint) { + return msgvalue(); + } + function msgvalue() internal returns (uint) { return msg.value; } - function() { + function() external { + update(); + } + function update() internal { a = msg.value + 1; } + } )"; compileAndRun(sourceCode, 0, "C"); @@ -9537,7 +10652,10 @@ BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier) modifier tryCircumvent { if (false) _; // avoid the function, we should still not accept ether } - function f() tryCircumvent returns (uint) { + function f() tryCircumvent public returns (uint) { + return msgvalue(); + } + function msgvalue() internal returns (uint) { return msg.value; } } @@ -9555,10 +10673,10 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) // Tests that this also survives the optimizer. char const* sourceCode = R"( contract C { - function f() returns (uint[200]) {} + function f() public returns (uint[200] memory) {} } contract D { - function f(C c) returns (uint) { c.f(); return 7; } + function f(C c) public returns (uint) { c.f(); return 7; } } )"; @@ -9572,12 +10690,12 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function) { char const* sourceCode = R"( contract C { - function intern() returns (uint) { + function intern() public returns (uint) { function (uint) internal returns (uint) x; x(2); return 7; } - function extern() returns (uint) { + function extern() public returns (uint) { function (uint) external returns (uint) x; x(2); return 7; @@ -9597,7 +10715,7 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail) contract C { function() internal returns (uint) x; int mutex; - function t() returns (uint) { + function t() public returns (uint) { if (mutex > 0) { assembly { mstore(0, 7) return(0, 0x20) } } mutex = 1; @@ -9617,12 +10735,12 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function_through_array) char const* sourceCode = R"( contract C { int mutex; - function t() returns (uint) { + function t() public returns (uint) { if (mutex > 0) { assembly { mstore(0, 7) return(0, 0x20) } } mutex = 1; // Avoid re-executing this function if we jump somewhere. - function() internal returns (uint)[200] x; + function() internal returns (uint)[200] memory x; x[0](); return 2; } @@ -9637,13 +10755,13 @@ BOOST_AUTO_TEST_CASE(pass_function_types_internally) { char const* sourceCode = R"( contract C { - function f(uint x) returns (uint) { + function f(uint x) public returns (uint) { return eval(g, x); } - function eval(function(uint) returns (uint) x, uint a) internal returns (uint) { + function eval(function(uint) internal returns (uint) x, uint a) internal returns (uint) { return x(a); } - function g(uint x) returns (uint) { return x + 1; } + function g(uint x) public returns (uint) { return x + 1; } } )"; @@ -9655,16 +10773,16 @@ BOOST_AUTO_TEST_CASE(pass_function_types_externally) { char const* sourceCode = R"( contract C { - function f(uint x) returns (uint) { + function f(uint x) public returns (uint) { return this.eval(this.g, x); } - function f2(uint x) returns (uint) { + function f2(uint x) public returns (uint) { return eval(this.g, x); } - function eval(function(uint) external returns (uint) x, uint a) returns (uint) { + function eval(function(uint) external returns (uint) x, uint a) public returns (uint) { return x(a); } - function g(uint x) returns (uint) { return x + 1; } + function g(uint x) public returns (uint) { return x + 1; } } )"; @@ -9677,8 +10795,8 @@ BOOST_AUTO_TEST_CASE(receive_external_function_type) { char const* sourceCode = R"( contract C { - function g() returns (uint) { return 7; } - function f(function() external returns (uint) g) returns (uint) { + function g() public returns (uint) { return 7; } + function f(function() external returns (uint) g) public returns (uint) { return g(); } } @@ -9695,8 +10813,8 @@ BOOST_AUTO_TEST_CASE(return_external_function_type) { char const* sourceCode = R"( contract C { - function g() {} - function f() returns (function() external) { + function g() public {} + function f() public returns (function() external) { return this.g; } } @@ -9713,18 +10831,18 @@ BOOST_AUTO_TEST_CASE(store_function) { char const* sourceCode = R"( contract Other { - function addTwo(uint x) returns (uint) { return x + 2; } + function addTwo(uint x) public returns (uint) { return x + 2; } } contract C { - function (function (uint) external returns (uint)) returns (uint) ev; + function (function (uint) external returns (uint)) internal returns (uint) ev; function (uint) external returns (uint) x; - function store(function(uint) external returns (uint) y) { + function store(function(uint) external returns (uint) y) public { x = y; } - function eval(function(uint) external returns (uint) y) returns (uint) { + function eval(function(uint) external returns (uint) y) public returns (uint) { return y(7); } - function t() returns (uint) { + function t() public returns (uint) { ev = eval; this.store((new Other()).addTwo); return ev(x); @@ -9742,14 +10860,14 @@ BOOST_AUTO_TEST_CASE(store_function_in_constructor) contract C { uint public result_in_constructor; function (uint) internal returns (uint) x; - function C () { + constructor() public { x = double; result_in_constructor = use(2); } - function double(uint _arg) returns (uint _ret) { + function double(uint _arg) public returns (uint _ret) { _ret = _arg * 2; } - function use(uint _arg) returns (uint) { + function use(uint _arg) public returns (uint) { return x(_arg); } } @@ -9767,13 +10885,13 @@ BOOST_AUTO_TEST_CASE(store_internal_unused_function_in_constructor) char const* sourceCode = R"( contract C { function () internal returns (uint) x; - function C () { + constructor() public { x = unused; } function unused() internal returns (uint) { return 7; } - function t() returns (uint) { + function t() public returns (uint) { return x(); } } @@ -9789,10 +10907,10 @@ BOOST_AUTO_TEST_CASE(store_internal_unused_library_function_in_constructor) library L { function x() internal returns (uint) { return 7; } } contract C { function () internal returns (uint) x; - function C () { + constructor() public { x = L.x; } - function t() returns (uint) { + function t() public returns (uint) { return x(); } } @@ -9807,13 +10925,13 @@ BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime) char const* sourceCode = R"( contract C { uint public initial; - function C() { + constructor() public { initial = double(2); } - function double(uint _arg) returns (uint _ret) { + function double(uint _arg) public returns (uint _ret) { _ret = _arg * 2; } - function runtime(uint _arg) returns (uint) { + function runtime(uint _arg) public returns (uint) { return double(_arg); } } @@ -9829,13 +10947,13 @@ BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime_equality_check) char const* sourceCode = R"( contract C { function (uint) internal returns (uint) x; - function C() { + constructor() public { x = double; } - function test() returns (bool) { + function test() public returns (bool) { return x == double; } - function double(uint _arg) returns (uint _ret) { + function double(uint _arg) public returns (uint _ret) { _ret = _arg * 2; } } @@ -9849,7 +10967,7 @@ BOOST_AUTO_TEST_CASE(function_type_library_internal) { char const* sourceCode = R"( library Utils { - function reduce(uint[] memory array, function(uint, uint) returns (uint) f, uint init) internal returns (uint) { + function reduce(uint[] memory array, function(uint, uint) internal returns (uint) f, uint init) internal returns (uint) { for (uint i = 0; i < array.length; i++) { init = f(array[i], init); } @@ -9860,7 +10978,7 @@ BOOST_AUTO_TEST_CASE(function_type_library_internal) } } contract C { - function f(uint[] x) returns (uint) { + function f(uint[] memory x) public returns (uint) { return Utils.reduce(x, Utils.sum, 0); } } @@ -9875,21 +10993,21 @@ BOOST_AUTO_TEST_CASE(call_function_returning_function) { char const* sourceCode = R"( contract test { - function f0() returns (uint) { + function f0() public returns (uint) { return 2; } - function f1() internal returns (function() returns (uint)) { + function f1() internal returns (function() internal returns (uint)) { return f0; } - function f2() internal returns (function() returns (function () returns (uint))) { + function f2() internal returns (function() internal returns (function () internal returns (uint))) { return f1; } - function f3() internal returns (function() returns (function () returns (function () returns (uint)))) + function f3() internal returns (function() internal returns (function () internal returns (function () internal returns (uint)))) { return f2; } - function f() returns (uint) { - function() returns(function() returns(function() returns(function() returns(uint)))) x; + function f() public returns (uint) { + function() internal returns(function() internal returns(function() internal returns(function() internal returns(uint)))) x; x = f3; return x()()()(); } @@ -9920,11 +11038,11 @@ BOOST_AUTO_TEST_CASE(mapping_of_functions) success = true; } - function Flow() { + constructor() public { stages[msg.sender] = stage0; } - function f() returns (uint) { + function f() public returns (uint) { stages[msg.sender](); return 7; } @@ -9945,35 +11063,35 @@ BOOST_AUTO_TEST_CASE(packed_functions) char const* sourceCode = R"( contract C { // these should take the same slot - function() returns (uint) a; + function() internal returns (uint) a; function() external returns (uint) b; function() external returns (uint) c; - function() returns (uint) d; + function() internal returns (uint) d; uint8 public x; - function set() { + function set() public { x = 2; d = g; c = this.h; b = this.h; a = g; } - function t1() returns (uint) { + function t1() public returns (uint) { return a(); } - function t2() returns (uint) { + function t2() public returns (uint) { return b(); } - function t3() returns (uint) { + function t3() public returns (uint) { return a(); } - function t4() returns (uint) { + function t4() public returns (uint) { return b(); } - function g() returns (uint) { + function g() public returns (uint) { return 7; } - function h() returns (uint) { + function h() public returns (uint) { return 8; } } @@ -9992,12 +11110,12 @@ BOOST_AUTO_TEST_CASE(function_memory_array) { char const* sourceCode = R"( contract C { - function a(uint x) returns (uint) { return x + 1; } - function b(uint x) returns (uint) { return x + 2; } - function c(uint x) returns (uint) { return x + 3; } - function d(uint x) returns (uint) { return x + 5; } - function e(uint x) returns (uint) { return x + 8; } - function test(uint x, uint i) returns (uint) { + function a(uint x) public returns (uint) { return x + 1; } + function b(uint x) public returns (uint) { return x + 2; } + function c(uint x) public returns (uint) { return x + 3; } + function d(uint x) public returns (uint) { return x + 5; } + function e(uint x) public returns (uint) { return x + 8; } + function test(uint x, uint i) public returns (uint) { function(uint) internal returns (uint)[] memory arr = new function(uint) internal returns (uint)[](10); arr[0] = a; @@ -10023,17 +11141,17 @@ BOOST_AUTO_TEST_CASE(function_delete_storage) { char const* sourceCode = R"( contract C { - function a() returns (uint) { return 7; } + function a() public returns (uint) { return 7; } function() internal returns (uint) y; - function set() returns (uint) { + function set() public returns (uint) { y = a; return y(); } - function d() returns (uint) { + function d() public returns (uint) { delete y; return 1; } - function ca() returns (uint) { + function ca() public returns (uint) { return y(); } } @@ -10050,9 +11168,9 @@ BOOST_AUTO_TEST_CASE(function_delete_stack) { char const* sourceCode = R"( contract C { - function a() returns (uint) { return 7; } - function test() returns (uint) { - var y = a; + function a() public returns (uint) { return 7; } + function test() public returns (uint) { + function () returns (uint) y = a; delete y; y(); } @@ -10069,13 +11187,13 @@ BOOST_AUTO_TEST_CASE(copy_function_storage_array) contract C { function() internal returns (uint)[] x; function() internal returns (uint)[] y; - function test() returns (uint) { + function test() public returns (uint) { x.length = 10; x[9] = a; y = x; return y[9](); } - function a() returns (uint) { + function a() public returns (uint) { return 7; } } @@ -10089,8 +11207,8 @@ BOOST_AUTO_TEST_CASE(function_array_cross_calls) { char const* sourceCode = R"( contract D { - function f(function() external returns (function() external returns (uint))[] x) - returns (function() external returns (uint)[3] r) + function f(function() external returns (function() external returns (uint))[] memory x) + public returns (function() external returns (uint)[3] memory r) { r[0] = x[0](); r[1] = x[1](); @@ -10098,23 +11216,23 @@ BOOST_AUTO_TEST_CASE(function_array_cross_calls) } } contract C { - function test() returns (uint, uint, uint) { + function test() public returns (uint, uint, uint) { function() external returns (function() external returns (uint))[] memory x = new function() external returns (function() external returns (uint))[](10); for (uint i = 0; i < x.length; i ++) x[i] = this.h; x[0] = this.htwo; - var y = (new D()).f(x); + function() external returns (uint)[3] memory y = (new D()).f(x); return (y[0](), y[1](), y[2]()); } - function e() returns (uint) { return 5; } - function f() returns (uint) { return 6; } - function g() returns (uint) { return 7; } + function e() public returns (uint) { return 5; } + function f() public returns (uint) { return 6; } + function g() public returns (uint) { return 7; } uint counter; - function h() returns (function() external returns (uint)) { + function h() public returns (function() external returns (uint)) { return counter++ == 0 ? this.f : this.g; } - function htwo() returns (function() external returns (uint)) { + function htwo() public returns (function() external returns (uint)) { return this.e; } } @@ -10128,10 +11246,10 @@ BOOST_AUTO_TEST_CASE(external_function_to_address) { char const* sourceCode = R"( contract C { - function f() returns (bool) { + function f() public returns (bool) { return address(this.f) == address(this); } - function g(function() external cb) returns (address) { + function g(function() external cb) public returns (address) { return address(cb); } } @@ -10149,12 +11267,12 @@ BOOST_AUTO_TEST_CASE(copy_internal_function_array_to_storage) contract C { function() internal returns (uint)[20] x; int mutex; - function one() returns (uint) { - function() internal returns (uint)[20] xmem; + function one() public returns (uint) { + function() internal returns (uint)[20] memory xmem; x = xmem; return 3; } - function two() returns (uint) { + function two() public returns (uint) { if (mutex > 0) return 7; mutex = 1; @@ -10218,7 +11336,7 @@ BOOST_AUTO_TEST_CASE(shift_left) { char const* sourceCode = R"( contract C { - function f(uint a, uint b) returns (uint) { + function f(uint a, uint b) public returns (uint) { return a << b; } } @@ -10236,7 +11354,7 @@ BOOST_AUTO_TEST_CASE(shift_left_uint32) { char const* sourceCode = R"( contract C { - function f(uint32 a, uint32 b) returns (uint) { + function f(uint32 a, uint32 b) public returns (uint) { return a << b; } } @@ -10253,7 +11371,7 @@ BOOST_AUTO_TEST_CASE(shift_left_uint8) { char const* sourceCode = R"( contract C { - function f(uint8 a, uint8 b) returns (uint) { + function f(uint8 a, uint8 b) public returns (uint) { return a << b; } } @@ -10268,7 +11386,7 @@ BOOST_AUTO_TEST_CASE(shift_left_larger_type) // This basically tests proper cleanup and conversion. It should not convert x to int8. char const* sourceCode = R"( contract C { - function f() returns (int8) { + function f() public returns (int8) { uint8 x = 254; int8 y = 1; return y << x; @@ -10283,7 +11401,7 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment) { char const* sourceCode = R"( contract C { - function f(uint a, uint b) returns (uint) { + function f(uint a, uint b) public returns (uint) { a <<= b; return a; } @@ -10302,7 +11420,7 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) { char const* sourceCode = R"( contract C { - function f(uint a, uint8 b) returns (uint) { + function f(uint a, uint8 b) public returns (uint) { a <<= b; return a; } @@ -10320,7 +11438,7 @@ BOOST_AUTO_TEST_CASE(shift_right) { char const* sourceCode = R"( contract C { - function f(uint a, uint b) returns (uint) { + function f(uint a, uint b) public returns (uint) { return a >> b; } } @@ -10330,13 +11448,14 @@ BOOST_AUTO_TEST_CASE(shift_right) ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x42))); ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0))); ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(1)<<255, u256(5)), encodeArgs(u256(1)<<250)); } BOOST_AUTO_TEST_CASE(shift_right_garbled) { char const* sourceCode = R"( contract C { - function f(uint8 a, uint8 b) returns (uint) { + function f(uint8 a, uint8 b) public returns (uint) { assembly { a := 0xffffffff } @@ -10350,11 +11469,44 @@ BOOST_AUTO_TEST_CASE(shift_right_garbled) ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(0xf))); } +BOOST_AUTO_TEST_CASE(shift_right_garbled_signed) +{ + char const* sourceCode = R"( + contract C { + function f(int8 a, uint8 b) public returns (int) { + assembly { + a := 0xfffffff0 + } + // Higher bits should be signextended before the shift + return a >> b; + } + function g(int8 a, uint8 b) public returns (int) { + assembly { + a := 0xf0 + } + // Higher bits should be signextended before the shift + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(3)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(4)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(0xFF)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(0x1003)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(3)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(4)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(0xFF)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(0x1003)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(-1))); +} + BOOST_AUTO_TEST_CASE(shift_right_uint32) { char const* sourceCode = R"( contract C { - function f(uint32 a, uint32 b) returns (uint) { + function f(uint32 a, uint32 b) public returns (uint) { return a >> b; } } @@ -10370,7 +11522,7 @@ BOOST_AUTO_TEST_CASE(shift_right_uint8) { char const* sourceCode = R"( contract C { - function f(uint8 a, uint8 b) returns (uint) { + function f(uint8 a, uint8 b) public returns (uint) { return a >> b; } } @@ -10384,7 +11536,7 @@ BOOST_AUTO_TEST_CASE(shift_right_assignment) { char const* sourceCode = R"( contract C { - function f(uint a, uint b) returns (uint) { + function f(uint a, uint b) public returns (uint) { a >>= b; return a; } @@ -10401,7 +11553,7 @@ BOOST_AUTO_TEST_CASE(shift_right_assignment_signed) { char const* sourceCode = R"( contract C { - function f(int a, int b) returns (int) { + function f(int a, int b) public returns (int) { a >>= b; return a; } @@ -10418,7 +11570,7 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) { char const* sourceCode = R"( contract C { - function f(int a, int b) returns (int) { + function f(int a, int b) public returns (int) { return a >> b; } } @@ -10426,23 +11578,80 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(-1))); +} + +BOOST_AUTO_TEST_CASE(shift_right_negative_literal) +{ + char const* sourceCode = R"( + contract C { + function f1() public pure returns (bool) { + return (-4266 >> 0) == -4266; + } + function f2() public pure returns (bool) { + return (-4266 >> 1) == -2133; + } + function f3() public pure returns (bool) { + return (-4266 >> 4) == -267; + } + function f4() public pure returns (bool) { + return (-4266 >> 8) == -17; + } + function f5() public pure returns (bool) { + return (-4266 >> 16) == -1; + } + function f6() public pure returns (bool) { + return (-4266 >> 17) == -1; + } + function g1() public pure returns (bool) { + return (-4267 >> 0) == -4267; + } + function g2() public pure returns (bool) { + return (-4267 >> 1) == -2134; + } + function g3() public pure returns (bool) { + return (-4267 >> 4) == -267; + } + function g4() public pure returns (bool) { + return (-4267 >> 8) == -17; + } + function g5() public pure returns (bool) { + return (-4267 >> 16) == -1; + } + function g6() public pure returns (bool) { + return (-4267 >> 17) == -1; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f1()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f2()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f3()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f5()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f6()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g1()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g2()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g3()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g5()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g6()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int8) { char const* sourceCode = R"( contract C { - function f(int8 a, int8 b) returns (int) { + function f(int8 a, int8 b) public returns (int) { return a >> b; } } @@ -10450,67 +11659,67 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int8) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(0)), encodeArgs(u256(-66))); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(1)), encodeArgs(u256(-33))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(4)), encodeArgs(u256(-4))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(8)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(4)), encodeArgs(u256(-5))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(8)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(0)), encodeArgs(u256(-67))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(1)), encodeArgs(u256(-33))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(4)), encodeArgs(u256(-4))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(8)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(1)), encodeArgs(u256(-34))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(4)), encodeArgs(u256(-5))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(8)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int8) { char const* sourceCode = R"( contract C { - function f(int8 a, int8 b) returns (int8) { + function f(int8 a, int8 b) public returns (int8) { return a >> b; } } )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(8)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int16) { char const* sourceCode = R"( contract C { - function f(int16 a, int16 b) returns (int16) { + function f(int16 a, int16 b) public returns (int16) { return a >> b; } } )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(8)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int32) { char const* sourceCode = R"( contract C { - function f(int32 a, int32 b) returns (int32) { + function f(int32 a, int32 b) public returns (int32) { return a >> b; } } )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(8)), encodeArgs(u256(-1))); } @@ -10518,7 +11727,7 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int16) { char const* sourceCode = R"( contract C { - function f(int16 a, int16 b) returns (int) { + function f(int16 a, int16 b) public returns (int) { return a >> b; } } @@ -10526,23 +11735,23 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int16) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int32) { char const* sourceCode = R"( contract C { - function f(int32 a, int32 b) returns (int) { + function f(int32 a, int32 b) public returns (int) { return a >> b; } } @@ -10550,23 +11759,23 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int32) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) { char const* sourceCode = R"( contract C { - function f(int a, int b) returns (int) { + function f(int a, int b) public returns (int) { a >>= b; return a; } @@ -10575,26 +11784,26 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_negative_rvalue) { char const* sourceCode = R"( contract C { - function f(int a, int b) returns (int) { + function f(int a, int b) public returns (int) { return a << b; } - function g(int a, int b) returns (int) { + function g(int a, int b) public returns (int) { return a >> b; } } @@ -10608,11 +11817,11 @@ BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment) { char const* sourceCode = R"( contract C { - function f(int a, int b) returns (int) { + function f(int a, int b) public returns (int) { a <<= b; return a; } - function g(int a, int b) returns (int) { + function g(int a, int b) public returns (int) { a >>= b; return a; } @@ -10627,7 +11836,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_assignment) { char const* sourceCode = R"( contract C { - function f() returns (uint a) { + function f() public returns (uint a) { a = 0x42; a <<= 8; } @@ -10641,7 +11850,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_assignment) { char const* sourceCode = R"( contract C { - function f() returns (uint a) { + function f() public returns (uint a) { a = 0x4200; a >>= 8; } @@ -10655,7 +11864,7 @@ BOOST_AUTO_TEST_CASE(shift_cleanup) { char const* sourceCode = R"( contract C { - function f() returns (uint16 x) { + function f() public returns (uint16 x) { x = 0xffff; x += 32; x <<= 8; @@ -10671,7 +11880,7 @@ BOOST_AUTO_TEST_CASE(shift_cleanup_garbled) { char const* sourceCode = R"( contract C { - function f() returns (uint8 x) { + function f() public returns (uint8 x) { assembly { x := 0xffff } @@ -10687,10 +11896,10 @@ BOOST_AUTO_TEST_CASE(shift_overflow) { char const* sourceCode = R"( contract C { - function leftU(uint8 x, uint8 y) returns (uint8) { + function leftU(uint8 x, uint8 y) public returns (uint8) { return x << y; } - function leftS(int8 x, int8 y) returns (int8) { + function leftS(int8 x, int8 y) public returns (int8) { return x << y; } } @@ -10709,10 +11918,10 @@ BOOST_AUTO_TEST_CASE(shift_bytes) { char const* sourceCode = R"( contract C { - function left(bytes20 x, uint8 y) returns (bytes20) { + function left(bytes20 x, uint8 y) public returns (bytes20) { return x << y; } - function right(bytes20 x, uint8 y) returns (bytes20) { + function right(bytes20 x, uint8 y) public returns (bytes20) { return x >> y; } } @@ -10726,12 +11935,12 @@ BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) { char const* sourceCode = R"( contract C { - function left(uint8 y) returns (bytes20) { + function left(uint8 y) public returns (bytes20) { bytes20 x; assembly { x := "12345678901234567890abcde" } return x << y; } - function right(uint8 y) returns (bytes20) { + function right(uint8 y) public returns (bytes20) { bytes20 x; assembly { x := "12345678901234567890abcde" } return x >> y; @@ -10787,7 +11996,7 @@ BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) { char const* sourceCode = R"( contract C { - function test() returns (uint, uint) { + function test() public returns (uint, uint) { uint32 a = 0xffffffff; uint16 x = uint16(a); uint16 y = x; @@ -10811,10 +12020,10 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) a := 2 } if (a != 2) - throw; + revert(); _; } - function f() m returns (bool) { + function f() m public returns (bool) { return true; } } @@ -10830,7 +12039,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_overflow) uint16 x = 0x1234; uint16 a = 0xffff; uint16 b; - function f() returns (uint, uint, uint, uint) { + function f() public returns (uint, uint, uint, uint) { a++; uint c = b; delete b; @@ -10862,18 +12071,18 @@ BOOST_AUTO_TEST_CASE(include_creation_bytecode_only_once) contract D { bytes a = hex"1237651237125387136581271652831736512837126583171583712358126123765123712538713658127165283173651283712658317158371235812612376512371253871365812716528317365128371265831715837123581261237651237125387136581271652831736512837126583171583712358126"; bytes b = hex"1237651237125327136581271252831736512837126583171383712358126123765125712538713658127165253173651283712658357158371235812612376512371a5387136581271652a317365128371265a317158371235812612a765123712538a13658127165a83173651283712a58317158371235a126"; - function D(uint) {} + constructor(uint) public {} } contract Double { - function f() { + function f() public { new D(2); } - function g() { + function g() public { new D(3); } } contract Single { - function f() { + function f() public { new D(2); } } @@ -10893,7 +12102,7 @@ BOOST_AUTO_TEST_CASE(recursive_structs) S[] x; } S sstorage; - function f() returns (uint) { + function f() public returns (uint) { S memory s; s.x = new S[](10); delete s; @@ -10911,9 +12120,9 @@ BOOST_AUTO_TEST_CASE(invalid_instruction) { char const* sourceCode = R"( contract C { - function f() { + function f() public { assembly { - invalid + invalid() } } } @@ -10926,14 +12135,14 @@ BOOST_AUTO_TEST_CASE(assert_require) { char const* sourceCode = R"( contract C { - function f() { + function f() public { assert(false); } - function g(bool val) returns (bool) { + function g(bool val) public returns (bool) { assert(val == true); return true; } - function h(bool val) returns (bool) { + function h(bool val) public returns (bool) { require(val); return true; } @@ -10952,11 +12161,11 @@ BOOST_AUTO_TEST_CASE(revert) char const* sourceCode = R"( contract C { uint public a = 42; - function f() { + function f() public { a = 1; revert(); } - function g() { + function g() public { a = 1; assembly { revert(0, 0) @@ -10996,7 +12205,7 @@ BOOST_AUTO_TEST_CASE(revert_with_cause) } contract C { D d = new D(); - function forward(address target, bytes data) internal returns (bool success, bytes retval) { + function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) { uint retsize; assembly { success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) @@ -11007,19 +12216,19 @@ BOOST_AUTO_TEST_CASE(revert_with_cause) returndatacopy(add(retval, 0x20), 0, returndatasize()) } } - function f() public returns (bool, bytes) { + function f() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function g() public returns (bool, bytes) { + function g() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function h() public returns (bool, bytes) { + function h() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function i() public returns (bool, bytes) { + function i() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function j() public returns (bool, bytes) { + function j() public returns (bool, bytes memory) { return forward(address(d), msg.data); } } @@ -11051,7 +12260,7 @@ BOOST_AUTO_TEST_CASE(require_with_message) bool flagCopy = flag; require(flagCopy == false, internalFun()); } - function internalFun() returns (string) { + function internalFun() public returns (string memory) { flag = true; return "only on second run"; } @@ -11068,7 +12277,7 @@ BOOST_AUTO_TEST_CASE(require_with_message) } contract C { D d = new D(); - function forward(address target, bytes data) internal returns (bool success, bytes retval) { + function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) { uint retsize; assembly { success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) @@ -11079,19 +12288,19 @@ BOOST_AUTO_TEST_CASE(require_with_message) returndatacopy(add(retval, 0x20), 0, returndatasize()) } } - function f(uint x) public returns (bool, bytes) { + function f(uint x) public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function g() public returns (bool, bytes) { + function g() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function h() public returns (bool, bytes) { + function h() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function i() public returns (bool, bytes) { + function i() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function j() public returns (bool, bytes) { + function j() public returns (bool, bytes memory) { return forward(address(d), msg.data); } } @@ -11121,7 +12330,7 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages) } contract C { D d = new D(); - function forward(address target, bytes data) internal returns (bool success, bytes retval) { + function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) { uint retsize; assembly { success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) @@ -11132,10 +12341,10 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages) returndatacopy(add(retval, 0x20), 0, returndatasize()) } } - function f() public returns (bool, bytes) { + function f() public returns (bool, bytes memory) { return forward(address(d), msg.data); } - function g() public returns (bool, bytes) { + function g() public returns (bool, bytes memory) { return forward(address(d), msg.data); } } @@ -11151,16 +12360,16 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer) { char const* sourceCode = R"( contract D { - function() public payable { + function() external payable { revert("message"); } function f() public { - this.transfer(0); + address(this).transfer(0); } } contract C { D d = new D(); - function forward(address target, bytes data) internal returns (bool success, bytes retval) { + function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) { uint retsize; assembly { success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) @@ -11171,7 +12380,7 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer) returndatacopy(add(retval, 0x20), 0, returndatasize()) } } - function f() public returns (bool, bytes) { + function f() public returns (bool, bytes memory) { return forward(address(d), msg.data); } } @@ -11186,18 +12395,18 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_create) { char const* sourceCode = R"( contract E { - function E() { + constructor() public { revert("message"); } } contract D { function f() public { - var x = new E(); + E x = new E(); } } contract C { D d = new D(); - function forward(address target, bytes data) internal returns (bool success, bytes retval) { + function forward(address target, bytes memory data) internal returns (bool success, bytes memory retval) { uint retsize; assembly { success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) @@ -11208,7 +12417,7 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_create) returndatacopy(add(retval, 0x20), 0, returndatasize()) } } - function f() public returns (bool, bytes) { + function f() public returns (bool, bytes memory) { return forward(address(d), msg.data); } } @@ -11232,9 +12441,9 @@ BOOST_AUTO_TEST_CASE(negative_stack_height) bool Aboolc; bool exists; } - function nredit(uint startindex) public pure returns(uint[500] CIDs, uint[500] dates, uint[500] RIDs, bool[500] Cboolas, uint[500] amounts){} - function return500InvoicesByDates(uint begindate, uint enddate, uint startindex) public view returns(uint[500] AIDs, bool[500] Aboolas, uint[500] dates, bytes32[3][500] Abytesas, bytes32[3][500] bytesbs, bytes32[2][500] bytescs, uint[500] amounts, bool[500] Aboolbs, bool[500] Aboolcs){} - function return500PaymentsByDates(uint begindate, uint enddate, uint startindex) public view returns(uint[500] BIDs, uint[500] dates, uint[500] RIDs, bool[500] Bboolas, bytes32[3][500] bytesbs,bytes32[2][500] bytescs, uint[500] amounts, bool[500] Bboolbs){} + function nredit(uint startindex) public pure returns(uint[500] memory CIDs, uint[500] memory dates, uint[500] memory RIDs, bool[500] memory Cboolas, uint[500] memory amounts){} + function return500InvoicesByDates(uint begindate, uint enddate, uint startindex) public view returns(uint[500] memory AIDs, bool[500] memory Aboolas, uint[500] memory dates, bytes32[3][500] memory Abytesas, bytes32[3][500] memory bytesbs, bytes32[2][500] memory bytescs, uint[500] memory amounts, bool[500] memory Aboolbs, bool[500] memory Aboolcs){} + function return500PaymentsByDates(uint begindate, uint enddate, uint startindex) public view returns(uint[500] memory BIDs, uint[500] memory dates, uint[500] memory RIDs, bool[500] memory Bboolas, bytes32[3][500] memory bytesbs,bytes32[2][500] memory bytescs, uint[500] memory amounts, bool[500] memory Bboolbs){} } )"; compileAndRun(sourceCode, 0, "C"); @@ -11246,11 +12455,11 @@ BOOST_AUTO_TEST_CASE(literal_empty_string) contract C { bytes32 public x; uint public a; - function f(bytes32 _x, uint _a) { + function f(bytes32 _x, uint _a) public { x = _x; a = _a; } - function g() { + function g() public { this.f("", 2); } } @@ -11267,22 +12476,22 @@ BOOST_AUTO_TEST_CASE(scientific_notation) { char const* sourceCode = R"( contract C { - function f() returns (uint) { + function f() public returns (uint) { return 2e10 wei; } - function g() returns (uint) { + function g() public returns (uint) { return 200e-2 wei; } - function h() returns (uint) { + function h() public returns (uint) { return 2.5e1; } - function i() returns (int) { + function i() public returns (int) { return -2e10; } - function j() returns (int) { + function j() public returns (int) { return -200e-2; } - function k() returns (int) { + function k() public returns (int) { return -2.5e1; } } @@ -11301,25 +12510,25 @@ BOOST_AUTO_TEST_CASE(interface_contract) char const* sourceCode = R"( interface I { event A(); - function f() returns (bool); - function() payable; + function f() external returns (bool); + function() external payable; } contract A is I { - function f() returns (bool) { + function f() public returns (bool) { return g(); } - function g() returns (bool) { + function g() public returns (bool) { return true; } - function() payable { + function() external payable { } } contract C { - function f(address _interfaceAddress) returns (bool) { + function f(address payable _interfaceAddress) public returns (bool) { I i = I(_interfaceAddress); return i.f(); } @@ -11335,39 +12544,15 @@ BOOST_AUTO_TEST_CASE(keccak256_assembly) { char const* sourceCode = R"( contract C { - function f() pure returns (bytes32 ret) { + function f() public pure returns (bytes32 ret) { assembly { ret := keccak256(0, 0) } } - function g() pure returns (bytes32 ret) { - assembly { - 0 - 0 - keccak256 - =: ret - } - } - function h() pure returns (bytes32 ret) { - assembly { - ret := sha3(0, 0) - } - } - function i() pure returns (bytes32 ret) { - assembly { - 0 - 0 - sha3 - =: ret - } - } } )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - ABI_CHECK(callContractFunction("g()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - ABI_CHECK(callContractFunction("h()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - ABI_CHECK(callContractFunction("i()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); } BOOST_AUTO_TEST_CASE(multi_modifiers) @@ -11382,10 +12567,10 @@ BOOST_AUTO_TEST_CASE(multi_modifiers) x++; _; } - function f1() m1() { + function f1() m1() public { x += 7; } - function f2() m1() { + function f2() m1() public { x += 3; } } @@ -11401,7 +12586,7 @@ BOOST_AUTO_TEST_CASE(inlineasm_empty_let) { char const* sourceCode = R"( contract C { - function f() pure returns (uint a, uint b) { + function f() public pure returns (uint a, uint b) { assembly { let x let y, z @@ -11417,60 +12602,238 @@ BOOST_AUTO_TEST_CASE(inlineasm_empty_let) BOOST_AUTO_TEST_CASE(bare_call_invalid_address) { - char const* sourceCode = R"( + char const* sourceCode = R"YY( contract C { /// Calling into non-existant account is successful (creates the account) function f() external returns (bool) { - return address(0x4242).call(); - } - function g() external returns (bool) { - return address(0x4242).callcode(); + (bool success,) = address(0x4242).call(""); + return success; } function h() external returns (bool) { - return address(0x4242).delegatecall(); + (bool success,) = address(0x4242).delegatecall(""); + return success; } } - )"; + )YY"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(1))); + + if (dev::test::Options::get().evmVersion().hasStaticCall()) + { + char const* sourceCode = R"YY( + contract C { + function f() external returns (bool, bytes memory) { + return address(0x4242).staticcall(""); + } + } + )YY"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), 0x40, 0x00)); + } +} + +BOOST_AUTO_TEST_CASE(bare_call_return_data) +{ + if (dev::test::Options::get().evmVersion().supportsReturndata()) + { + vector calltypes = {"call", "delegatecall"}; + if (dev::test::Options::get().evmVersion().hasStaticCall()) + calltypes.emplace_back("staticcall"); + for (string const& calltype: calltypes) + { + string sourceCode = R"DELIMITER( + contract A { + constructor() public { + } + function return_bool() public pure returns(bool) { + return true; + } + function return_int32() public pure returns(int32) { + return -32; + } + function return_uint32() public pure returns(uint32) { + return 0x3232; + } + function return_int256() public pure returns(int256) { + return -256; + } + function return_uint256() public pure returns(uint256) { + return 0x256256; + } + function return_bytes4() public pure returns(bytes4) { + return 0xabcd0012; + } + function return_multi() public pure returns(bool, uint32, bytes4) { + return (false, 0x3232, 0xabcd0012); + } + function return_bytes() public pure returns(bytes memory b) { + b = new bytes(2); + b[0] = 0x42; + b[1] = 0x21; + } + } + contract C { + A addr; + constructor() public { + addr = new A(); + } + function f(string memory signature) public returns (bool, bytes memory) { + return address(addr).)DELIMITER" + calltype + R"DELIMITER((abi.encodeWithSignature(signature)); + } + function check_bool() external returns (bool) { + (bool success, bytes memory data) = f("return_bool()"); + assert(success); + bool a = abi.decode(data, (bool)); + assert(a); + return true; + } + function check_int32() external returns (bool) { + (bool success, bytes memory data) = f("return_int32()"); + assert(success); + int32 a = abi.decode(data, (int32)); + assert(a == -32); + return true; + } + function check_uint32() external returns (bool) { + (bool success, bytes memory data) = f("return_uint32()"); + assert(success); + uint32 a = abi.decode(data, (uint32)); + assert(a == 0x3232); + return true; + } + function check_int256() external returns (bool) { + (bool success, bytes memory data) = f("return_int256()"); + assert(success); + int256 a = abi.decode(data, (int256)); + assert(a == -256); + return true; + } + function check_uint256() external returns (bool) { + (bool success, bytes memory data) = f("return_uint256()"); + assert(success); + uint256 a = abi.decode(data, (uint256)); + assert(a == 0x256256); + return true; + } + function check_bytes4() external returns (bool) { + (bool success, bytes memory data) = f("return_bytes4()"); + assert(success); + bytes4 a = abi.decode(data, (bytes4)); + assert(a == 0xabcd0012); + return true; + } + function check_multi() external returns (bool) { + (bool success, bytes memory data) = f("return_multi()"); + assert(success); + (bool a, uint32 b, bytes4 c) = abi.decode(data, (bool, uint32, bytes4)); + assert(a == false && b == 0x3232 && c == 0xabcd0012); + return true; + } + function check_bytes() external returns (bool) { + (bool success, bytes memory data) = f("return_bytes()"); + assert(success); + (bytes memory d) = abi.decode(data, (bytes)); + assert(d.length == 2 && d[0] == 0x42 && d[1] == 0x21); + return true; + } + } + )DELIMITER"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bool()"))), encodeArgs(true, 0x40, 0x20, true)); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_int32()"))), encodeArgs(true, 0x40, 0x20, u256(-32))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_uint32()"))), encodeArgs(true, 0x40, 0x20, u256(0x3232))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_int256()"))), encodeArgs(true, 0x40, 0x20, u256(-256))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_uint256()"))), encodeArgs(true, 0x40, 0x20, u256(0x256256))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bytes4()"))), encodeArgs(true, 0x40, 0x20, u256(0xabcd0012) << (28*8))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_multi()"))), encodeArgs(true, 0x40, 0x60, false, u256(0x3232), u256(0xabcd0012) << (28*8))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bytes()"))), encodeArgs(true, 0x40, 0x60, 0x20, 0x02, encode(bytes{0x42,0x21}, false))); + ABI_CHECK(callContractFunction("check_bool()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_int32()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_uint32()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_int256()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_uint256()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_bytes4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_multi()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_bytes()"), encodeArgs(true)); + } + } } BOOST_AUTO_TEST_CASE(delegatecall_return_value) { - char const* sourceCode = R"DELIMITER( - contract C { - uint value; - function set(uint _value) external { - value = _value; + if (dev::test::Options::get().evmVersion().supportsReturndata()) + { + char const* sourceCode = R"DELIMITER( + contract C { + uint value; + function set(uint _value) external { + value = _value; + } + function get() external view returns (uint) { + return value; + } + function get_delegated() external returns (bool, bytes memory) { + return address(this).delegatecall(abi.encodeWithSignature("get()")); + } + function assert0() external view { + assert(value == 0); + } + function assert0_delegated() external returns (bool, bytes memory) { + return address(this).delegatecall(abi.encodeWithSignature("assert0()")); + } } - function get() external view returns (uint) { - return value; + )DELIMITER"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(1), 0x40, 0x00)); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1), 0x40, 0x20, 0x00)); + ABI_CHECK(callContractFunction("set(uint256)", u256(1)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0), 0x40, 0x00)); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1), 0x40, 0x20, 1)); + ABI_CHECK(callContractFunction("set(uint256)", u256(42)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0), 0x40, 0x00)); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1), 0x40, 0x20, 42)); + } + else + { + char const* sourceCode = R"DELIMITER( + contract C { + uint value; + function set(uint _value) external { + value = _value; + } + function get() external view returns (uint) { + return value; + } + function get_delegated() external returns (bool) { + (bool success,) = address(this).delegatecall(abi.encodeWithSignature("get()")); + return success; + } + function assert0() external view { + assert(value == 0); + } + function assert0_delegated() external returns (bool) { + (bool success,) = address(this).delegatecall(abi.encodeWithSignature("assert0()")); + return success; + } } - function get_delegated() external returns (bool) { - return this.delegatecall(bytes4(sha3("get()"))); - } - function assert0() external view { - assert(value == 0); - } - function assert0_delegated() external returns (bool) { - return this.delegatecall(bytes4(sha3("assert0()"))); - } - } - )DELIMITER"; - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("set(uint256)", u256(1)), encodeArgs()); - ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("set(uint256)", u256(42)), encodeArgs()); - ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + )DELIMITER"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("set(uint256)", u256(1)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("set(uint256)", u256(42)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + } } BOOST_AUTO_TEST_CASE(function_types_sig) @@ -11478,19 +12841,18 @@ BOOST_AUTO_TEST_CASE(function_types_sig) char const* sourceCode = R"( contract C { uint public x; - function f() pure returns (bytes4) { + function f() public pure returns (bytes4) { return this.f.selector; } - function g() returns (bytes4) { + function g() public returns (bytes4) { function () pure external returns (bytes4) fun = this.f; return fun.selector; } - function h() returns (bytes4) { + function h() public returns (bytes4) { function () pure external returns (bytes4) fun = this.f; - var funvar = fun; - return funvar.selector; + return fun.selector; } - function i() pure returns (bytes4) { + function i() public pure returns (bytes4) { return this.x.selector; } } @@ -11509,13 +12871,13 @@ BOOST_AUTO_TEST_CASE(constant_string) bytes constant a = "\x03\x01\x02"; bytes constant b = hex"030102"; string constant c = "hello"; - function f() returns (bytes) { + function f() public returns (bytes memory) { return a; } - function g() returns (bytes) { + function g() public returns (bytes memory) { return b; } - function h() returns (bytes) { + function h() public returns (bytes memory) { return bytes(c); } } @@ -11530,18 +12892,18 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution) { char const* sourceCode = R"( contract C { - function balance() returns (uint) { + function balance() public returns (uint) { return 1; } - function transfer(uint amount) returns (uint) { + function transfer(uint amount) public returns (uint) { return amount; } } contract D { - function f() returns (uint) { + function f() public returns (uint) { return (new C()).balance(); } - function g() returns (uint) { + function g() public returns (uint) { return (new C()).transfer(5); } } @@ -11566,12 +12928,12 @@ BOOST_AUTO_TEST_CASE(snark) } /// @return the generator of G1 - function P1() internal returns (G1Point) { + function P1() internal returns (G1Point memory) { return G1Point(1, 2); } /// @return the generator of G2 - function P2() internal returns (G2Point) { + function P2() internal returns (G2Point memory) { return G2Point( [11559732032986387107991004021392285783925812861821192530917403151452391805634, 10857046999023057135944570762232829481370756359578518086990519993285655852781], @@ -11581,7 +12943,7 @@ BOOST_AUTO_TEST_CASE(snark) } /// @return the negation of p, i.e. p.add(p.negate()) should be zero. - function negate(G1Point p) internal returns (G1Point) { + function negate(G1Point memory p) internal returns (G1Point memory) { // The prime q in the base field F_q for G1 uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; if (p.X == 0 && p.Y == 0) @@ -11590,7 +12952,7 @@ BOOST_AUTO_TEST_CASE(snark) } /// @return the sum of two points of G1 - function add(G1Point p1, G1Point p2) internal returns (G1Point r) { + function add(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r) { uint[4] memory input; input[0] = p1.X; input[1] = p1.Y; @@ -11607,7 +12969,7 @@ BOOST_AUTO_TEST_CASE(snark) /// @return the product of a point on G1 and a scalar, i.e. /// p == p.mul(1) and p.add(p) == p.mul(2) for all points p. - function mul(G1Point p, uint s) internal returns (G1Point r) { + function mul(G1Point memory p, uint s) internal returns (G1Point memory r) { uint[3] memory input; input[0] = p.X; input[1] = p.Y; @@ -11625,7 +12987,7 @@ BOOST_AUTO_TEST_CASE(snark) /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should /// return true. - function pairing(G1Point[] p1, G2Point[] p2) internal returns (bool) { + function pairing(G1Point[] memory p1, G2Point[] memory p2) internal returns (bool) { require(p1.length == p2.length); uint elements = p1.length; uint inputSize = p1.length * 6; @@ -11649,7 +13011,7 @@ BOOST_AUTO_TEST_CASE(snark) require(success); return out[0] != 0; } - function pairingProd2(G1Point a1, G2Point a2, G1Point b1, G2Point b2) internal returns (bool) { + function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal returns (bool) { G1Point[] memory p1 = new G1Point[](2); G2Point[] memory p2 = new G2Point[](2); p1[0] = a1; @@ -11659,9 +13021,9 @@ BOOST_AUTO_TEST_CASE(snark) return pairing(p1, p2); } function pairingProd3( - G1Point a1, G2Point a2, - G1Point b1, G2Point b2, - G1Point c1, G2Point c2 + G1Point memory a1, G2Point memory a2, + G1Point memory b1, G2Point memory b2, + G1Point memory c1, G2Point memory c2 ) internal returns (bool) { G1Point[] memory p1 = new G1Point[](3); G2Point[] memory p2 = new G2Point[](3); @@ -11674,10 +13036,10 @@ BOOST_AUTO_TEST_CASE(snark) return pairing(p1, p2); } function pairingProd4( - G1Point a1, G2Point a2, - G1Point b1, G2Point b2, - G1Point c1, G2Point c2, - G1Point d1, G2Point d2 + G1Point memory a1, G2Point memory a2, + G1Point memory b1, G2Point memory b2, + G1Point memory c1, G2Point memory c2, + G1Point memory d1, G2Point memory d2 ) internal returns (bool) { G1Point[] memory p1 = new G1Point[](4); G2Point[] memory p2 = new G2Point[](4); @@ -11715,22 +13077,22 @@ BOOST_AUTO_TEST_CASE(snark) Pairing.G1Point K; Pairing.G1Point H; } - function f() returns (bool) { + function f() public returns (bool) { Pairing.G1Point memory p1; Pairing.G1Point memory p2; p1.X = 1; p1.Y = 2; p2.X = 1; p2.Y = 2; - var explict_sum = Pairing.add(p1, p2); - var scalar_prod = Pairing.mul(p1, 2); + Pairing.G1Point memory explict_sum = Pairing.add(p1, p2); + Pairing.G1Point memory scalar_prod = Pairing.mul(p1, 2); return (explict_sum.X == scalar_prod.X && explict_sum.Y == scalar_prod.Y); } - function g() returns (bool) { + function g() public returns (bool) { Pairing.G1Point memory x = Pairing.add(Pairing.P1(), Pairing.negate(Pairing.P1())); // should be zero return (x.X == 0 && x.Y == 0); } - function testMul() returns (bool) { + function testMul() public returns (bool) { Pairing.G1Point memory p; // @TODO The points here are reported to be not well-formed p.X = 14125296762497065001182820090155008161146766663259912659363835465243039841726; @@ -11740,7 +13102,7 @@ BOOST_AUTO_TEST_CASE(snark) p.X == 18256332256630856740336504687838346961237861778318632856900758565550522381207 && p.Y == 6976682127058094634733239494758371323697222088503263230319702770853579280803; } - function pair() returns (bool) { + function pair() public returns (bool) { Pairing.G2Point memory fiveTimesP2 = Pairing.G2Point( [4540444681147253467785307942530223364530218361853237193970751657229138047649, 20954117799226682825035885491234530437475518021362091509513177301640194298072], [11631839690097995216017572651900167465857396346217730511548857041925508482915, 21508930868448350162258892668132814424284302804699005394342512102884055673846] @@ -11766,7 +13128,7 @@ BOOST_AUTO_TEST_CASE(snark) return false; return true; } - function verifyingKey() internal returns (VerifyingKey vk) { + function verifyingKey() internal returns (VerifyingKey memory vk) { vk.A = Pairing.G2Point([0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7, 0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678], [0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d, 0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550]); vk.B = Pairing.G1Point(0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84); vk.C = Pairing.G2Point([0x2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb, 0x01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3], [0x14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713, 0x178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590]); @@ -11786,7 +13148,7 @@ BOOST_AUTO_TEST_CASE(snark) vk.IC[8] = Pairing.G1Point(0x0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a, 0x04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e); vk.IC[9] = Pairing.G1Point(0x111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f, 0x1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30); } - function verify(uint[] input, Proof proof) internal returns (uint) { + function verify(uint[] memory input, Proof memory proof) internal returns (uint) { VerifyingKey memory vk = verifyingKey(); require(input.length + 1 == vk.IC.length); // Compute the linear combination vk_x @@ -11810,7 +13172,7 @@ BOOST_AUTO_TEST_CASE(snark) return 0; } event Verified(string); - function verifyTx() returns (bool) { + function verifyTx() public returns (bool) { uint[] memory input = new uint[](9); Proof memory proof; proof.A = Pairing.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497); @@ -11833,7 +13195,7 @@ BOOST_AUTO_TEST_CASE(snark) input[7] = 9643208548031422463313148630985736896287522941726746581856185889848792022807; input[8] = 18066496933330839731877828156604; if (verify(input, proof) == 0) { - Verified("Transaction successfully verified."); + emit Verified("Transaction successfully verified."); return true; } else { return false; @@ -11856,17 +13218,17 @@ BOOST_AUTO_TEST_CASE(abi_encode) { char const* sourceCode = R"( contract C { - function f0() returns (bytes) { + function f0() public returns (bytes memory) { return abi.encode(); } - function f1() returns (bytes) { + function f1() public returns (bytes memory) { return abi.encode(1, 2); } - function f2() returns (bytes) { + function f2() public returns (bytes memory) { string memory x = "abc"; return abi.encode(1, x, 2); } - function f3() returns (bytes r) { + function f3() public returns (bytes memory r) { // test that memory is properly allocated string memory x = "abc"; r = abi.encode(1, x, 2); @@ -11875,7 +13237,7 @@ BOOST_AUTO_TEST_CASE(abi_encode) y[0] = "e"; require(y[0] == "e"); } - function f4() returns (bytes) { + function f4() public returns (bytes memory) { bytes4 x = "abcd"; return abi.encode(bytes2(x)); } @@ -11895,17 +13257,17 @@ BOOST_AUTO_TEST_CASE(abi_encode_v2) pragma experimental ABIEncoderV2; contract C { struct S { uint a; uint[] b; } - function f0() public pure returns (bytes) { + function f0() public pure returns (bytes memory) { return abi.encode(); } - function f1() public pure returns (bytes) { + function f1() public pure returns (bytes memory) { return abi.encode(1, 2); } - function f2() public pure returns (bytes) { + function f2() public pure returns (bytes memory) { string memory x = "abc"; return abi.encode(1, x, 2); } - function f3() public pure returns (bytes r) { + function f3() public pure returns (bytes memory r) { // test that memory is properly allocated string memory x = "abc"; r = abi.encode(1, x, 2); @@ -11915,7 +13277,7 @@ BOOST_AUTO_TEST_CASE(abi_encode_v2) require(y[0] == "e"); } S s; - function f4() public returns (bytes r) { + function f4() public returns (bytes memory r) { string memory x = "abc"; s.a = 7; s.b.push(2); @@ -11941,17 +13303,17 @@ BOOST_AUTO_TEST_CASE(abi_encodePacked) { char const* sourceCode = R"( contract C { - function f0() public pure returns (bytes) { + function f0() public pure returns (bytes memory) { return abi.encodePacked(); } - function f1() public pure returns (bytes) { + function f1() public pure returns (bytes memory) { return abi.encodePacked(uint8(1), uint8(2)); } - function f2() public pure returns (bytes) { + function f2() public pure returns (bytes memory) { string memory x = "abc"; return abi.encodePacked(uint8(1), x, uint8(2)); } - function f3() public pure returns (bytes r) { + function f3() public pure returns (bytes memory r) { // test that memory is properly allocated string memory x = "abc"; r = abi.encodePacked(uint8(1), x, uint8(2)); @@ -11973,17 +13335,17 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_selector) { char const* sourceCode = R"( contract C { - function f0() public pure returns (bytes) { + function f0() public pure returns (bytes memory) { return abi.encodeWithSelector(0x12345678); } - function f1() public pure returns (bytes) { + function f1() public pure returns (bytes memory) { return abi.encodeWithSelector(0x12345678, "abc"); } - function f2() public pure returns (bytes) { + function f2() public pure returns (bytes memory) { bytes4 x = 0x12345678; return abi.encodeWithSelector(x, "abc"); } - function f3() public pure returns (bytes) { + function f3() public pure returns (bytes memory) { bytes4 x = 0x12345678; return abi.encodeWithSelector(x, uint(-1)); } @@ -12005,22 +13367,22 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_selectorv2) char const* sourceCode = R"( pragma experimental ABIEncoderV2; contract C { - function f0() public pure returns (bytes) { + function f0() public pure returns (bytes memory) { return abi.encodeWithSelector(0x12345678); } - function f1() public pure returns (bytes) { + function f1() public pure returns (bytes memory) { return abi.encodeWithSelector(0x12345678, "abc"); } - function f2() public pure returns (bytes) { + function f2() public pure returns (bytes memory) { bytes4 x = 0x12345678; return abi.encodeWithSelector(x, "abc"); } - function f3() public pure returns (bytes) { + function f3() public pure returns (bytes memory) { bytes4 x = 0x12345678; return abi.encodeWithSelector(x, uint(-1)); } struct S { uint a; string b; uint16 c; } - function f4() public pure returns (bytes) { + function f4() public pure returns (bytes memory) { bytes4 x = 0x12345678; S memory s; s.a = 0x1234567; @@ -12051,19 +13413,19 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signature) { char const* sourceCode = R"T( contract C { - function f0() public pure returns (bytes) { + function f0() public pure returns (bytes memory) { return abi.encodeWithSignature("f(uint256)"); } - function f1() public pure returns (bytes) { + function f1() public pure returns (bytes memory) { string memory x = "f(uint256)"; return abi.encodeWithSignature(x, "abc"); } string xstor; - function f1s() public returns (bytes) { + function f1s() public returns (bytes memory) { xstor = "f(uint256)"; return abi.encodeWithSignature(xstor, "abc"); } - function f2() public pure returns (bytes r, uint[] ar) { + function f2() public pure returns (bytes memory r, uint[] memory ar) { string memory x = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; uint[] memory y = new uint[](4); y[0] = uint(-1); @@ -12095,19 +13457,19 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signaturev2) char const* sourceCode = R"T( pragma experimental ABIEncoderV2; contract C { - function f0() public pure returns (bytes) { + function f0() public pure returns (bytes memory) { return abi.encodeWithSignature("f(uint256)"); } - function f1() public pure returns (bytes) { + function f1() public pure returns (bytes memory) { string memory x = "f(uint256)"; return abi.encodeWithSignature(x, "abc"); } string xstor; - function f1s() public returns (bytes) { + function f1s() public returns (bytes memory) { xstor = "f(uint256)"; return abi.encodeWithSignature(xstor, "abc"); } - function f2() public pure returns (bytes r, uint[] ar) { + function f2() public pure returns (bytes memory r, uint[] memory ar) { string memory x = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; uint[] memory y = new uint[](4); y[0] = uint(-1); @@ -12120,7 +13482,7 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signaturev2) ar = new uint[](2); } struct S { uint a; string b; uint16 c; } - function f4() public pure returns (bytes) { + function f4() public pure returns (bytes memory) { bytes4 x = 0x12345678; S memory s; s.a = 0x1234567; @@ -12149,12 +13511,86 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signaturev2) ABI_CHECK(callContractFunction("f4()"), expectation); } +BOOST_AUTO_TEST_CASE(abi_encode_empty_string) +{ + char const* sourceCode = R"( + // Tests that this will not end up using a "bytes0" type + // (which would assert) + contract C { + function f() public pure returns (bytes memory, bytes memory) { + return (abi.encode(""), abi.encodePacked("")); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x40, 0xc0, + 0x60, 0x20, 0x00, 0x00, + 0x00 + )); +} + +BOOST_AUTO_TEST_CASE(abi_encode_empty_string_v2) +{ + char const* sourceCode = R"( + // Tests that this will not end up using a "bytes0" type + // (which would assert) + pragma experimental ABIEncoderV2; + contract C { + function f() public pure returns (bytes memory, bytes memory) { + return (abi.encode(""), abi.encodePacked("")); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x40, 0xa0, + 0x40, 0x20, 0x00, + 0x00 + )); +} + +BOOST_AUTO_TEST_CASE(abi_encode_rational) +{ + char const* sourceCode = R"( + // Tests that rational numbers (even negative ones) are encoded properly. + contract C { + function f() public pure returns (bytes memory) { + return abi.encode(1, -2); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x20, + 0x40, u256(1), u256(-2) + )); +} + +BOOST_AUTO_TEST_CASE(abi_encode_rational_v2) +{ + char const* sourceCode = R"( + // Tests that rational numbers (even negative ones) are encoded properly. + pragma experimental ABIEncoderV2; + contract C { + function f() public pure returns (bytes memory) { + return abi.encode(1, -2); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x20, + 0x40, u256(1), u256(-2) + )); +} + BOOST_AUTO_TEST_CASE(abi_encode_call) { char const* sourceCode = R"T( contract C { bool x; - function c(uint a, uint[] b) public { + function c(uint a, uint[] memory b) public { require(a == 5); require(b.length == 2); require(b[0] == 6); @@ -12166,7 +13602,8 @@ BOOST_AUTO_TEST_CASE(abi_encode_call) uint[] memory b = new uint[](2); b[0] = 6; b[1] = 7; - require(this.call(abi.encodeWithSignature("c(uint256,uint256[])", a, b))); + (bool success,) = address(this).call(abi.encodeWithSignature("c(uint256,uint256[])", a, b)); + require(success); return x; } } @@ -12178,7 +13615,6 @@ BOOST_AUTO_TEST_CASE(abi_encode_call) BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) { char const* sourceCode = R"( - pragma experimental "v0.5.0"; contract C { uint x; function f() public returns (uint) { @@ -12197,10 +13633,10 @@ BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) return (new C()).f(); } function fview() public returns (uint) { - return (CView(new C())).f(); + return (CView(address(new C()))).f(); } function fpure() public returns (uint) { - return (CPure(new C())).f(); + return (CPure(address(new C()))).f(); } } )"; @@ -12220,78 +13656,25 @@ BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) } } -BOOST_AUTO_TEST_CASE(swap_peephole_optimisation) -{ - char const* sourceCode = R"( - contract C { - function lt(uint a, uint b) returns (bool c) { - assembly { - a - b - swap1 - lt - =: c - } - } - function add(uint a, uint b) returns (uint c) { - assembly { - a - b - swap1 - add - =: c - } - } - function div(uint a, uint b) returns (uint c) { - assembly { - a - b - swap1 - div - =: c - } - } - } - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(100), u256(200)) == encodeArgs(u256(300))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(200), u256(10)) == encodeArgs(u256(20))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(1), u256(0)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(0), u256(1)) == encodeArgs(u256(0))); -} - BOOST_AUTO_TEST_CASE(bitwise_shifting_constantinople) { if (!dev::test::Options::get().evmVersion().hasBitwiseShifting()) return; char const* sourceCode = R"( contract C { - function shl(uint a, uint b) returns (uint c) { + function shl(uint a, uint b) public returns (uint c) { assembly { - a - b - shl - =: c + c := shl(b, a) } } - function shr(uint a, uint b) returns (uint c) { + function shr(uint a, uint b) public returns (uint c) { assembly { - a - b - shr - =: c + c := shr(b, a) } } - function sar(uint a, uint b) returns (uint c) { + function sar(uint a, uint b) public returns (uint c) { assembly { - a - b - sar - =: c + c := sar(b, a) } } } @@ -12316,68 +13699,50 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) return; char const* sourceCode = R"( contract C { - function shl_1() returns (bool) { + function shl_1() public returns (bool) { uint c; assembly { - 1 - 2 - shl - =: c + c := shl(2, 1) } assert(c == 4); return true; } - function shl_2() returns (bool) { + function shl_2() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 1 - shl - =: c + c := shl(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe); return true; } - function shl_3() returns (bool) { + function shl_3() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 256 - shl - =: c + c := shl(256, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0); return true; } - function shr_1() returns (bool) { + function shr_1() public returns (bool) { uint c; assembly { - 3 - 1 - shr - =: c + c := shr(1, 3) } assert(c == 1); return true; } - function shr_2() returns (bool) { + function shr_2() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 1 - shr - =: c + c := shr(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); return true; } - function shr_3() returns (bool) { + function shr_3() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 256 - shr - =: c + c := shr(256, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0); return true; @@ -12403,7 +13768,7 @@ BOOST_AUTO_TEST_CASE(senders_balance) } contract D { C c = new C(); - constructor() payable { } + constructor() public payable { } function f() public view returns (uint) { return c.f(); } @@ -12413,6 +13778,271 @@ BOOST_AUTO_TEST_CASE(senders_balance) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(27))); } +BOOST_AUTO_TEST_CASE(abi_decode_trivial) +{ + char const* sourceCode = R"( + contract C { + function f(bytes memory data) public pure returns (uint) { + return abi.decode(data, (uint)); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f(bytes)", 0x20, 0x20, 33), encodeArgs(u256(33))); +} + +BOOST_AUTO_TEST_CASE(abi_encode_decode_simple) +{ + char const* sourceCode = R"XX( + contract C { + function f() public pure returns (uint, bytes memory) { + bytes memory arg = "abcdefg"; + return abi.decode(abi.encode(uint(33), arg), (uint, bytes)); + } + } + )XX"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f()"), + encodeArgs(33, 0x40, 7, "abcdefg") + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_simple) +{ + char const* sourceCode = R"( + contract C { + function f(bytes memory data) public pure returns (uint, bytes memory) { + return abi.decode(data, (uint, bytes)); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f(bytes)", 0x20, 0x20 * 4, 33, 0x40, 7, "abcdefg"), + encodeArgs(33, 0x40, 7, "abcdefg") + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_v2) +{ + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + contract C { + struct S { uint a; uint[] b; } + function f() public pure returns (S memory) { + S memory s; + s.a = 8; + s.b = new uint[](3); + s.b[0] = 9; + s.b[1] = 10; + s.b[2] = 11; + return abi.decode(abi.encode(s), (S)); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f()"), + encodeArgs(0x20, 8, 0x40, 3, 9, 10, 11) + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_simple_storage) +{ + char const* sourceCode = R"( + contract C { + bytes data; + function f(bytes memory _data) public returns (uint, bytes memory) { + data = _data; + return abi.decode(data, (uint, bytes)); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f(bytes)", 0x20, 0x20 * 4, 33, 0x40, 7, "abcdefg"), + encodeArgs(33, 0x40, 7, "abcdefg") + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_v2_storage) +{ + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + contract C { + bytes data; + struct S { uint a; uint[] b; } + function f() public returns (S memory) { + S memory s; + s.a = 8; + s.b = new uint[](3); + s.b[0] = 9; + s.b[1] = 10; + s.b[2] = 11; + data = abi.encode(s); + return abi.decode(data, (S)); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f()"), + encodeArgs(0x20, 8, 0x40, 3, 9, 10, 11) + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_calldata) +{ + char const* sourceCode = R"( + contract C { + function f(bytes calldata data) external pure returns (uint, bytes memory r) { + return abi.decode(data, (uint, bytes)); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f(bytes)", 0x20, 0x20 * 4, 33, 0x40, 7, "abcdefg"), + encodeArgs(33, 0x40, 7, "abcdefg") + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_v2_calldata) +{ + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + contract C { + struct S { uint a; uint[] b; } + function f(bytes calldata data) external pure returns (S memory) { + return abi.decode(data, (S)); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f(bytes)", 0x20, 0x20 * 7, 0x20, 33, 0x40, 3, 10, 11, 12), + encodeArgs(0x20, 33, 0x40, 3, 10, 11, 12) + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_static_array) +{ + char const* sourceCode = R"( + contract C { + function f(bytes calldata data) external pure returns (uint[2][3] memory) { + return abi.decode(data, (uint[2][3])); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f(bytes)", 0x20, 6 * 0x20, 1, 2, 3, 4, 5, 6), + encodeArgs(1, 2, 3, 4, 5, 6) + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_static_array_v2) +{ + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + contract C { + function f(bytes calldata data) external pure returns (uint[2][3] memory) { + return abi.decode(data, (uint[2][3])); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f(bytes)", 0x20, 6 * 0x20, 1, 2, 3, 4, 5, 6), + encodeArgs(1, 2, 3, 4, 5, 6) + ); +} + +BOOST_AUTO_TEST_CASE(abi_decode_dynamic_array) +{ + char const* sourceCode = R"( + contract C { + function f(bytes calldata data) external pure returns (uint[] memory) { + return abi.decode(data, (uint[])); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK( + callContractFunction("f(bytes)", 0x20, 6 * 0x20, 0x20, 4, 3, 4, 5, 6), + encodeArgs(0x20, 4, 3, 4, 5, 6) + ); +} + +BOOST_AUTO_TEST_CASE(write_storage_external) +{ + char const* sourceCode = R"( + contract C { + uint public x; + function f(uint y) public payable { + x = y; + } + function g(uint y) external { + x = y; + } + function h() public { + this.g(12); + } + } + contract D { + C c = new C(); + function f() public payable returns (uint) { + c.g(3); + return c.x(); + } + function g() public returns (uint) { + c.g(8); + return c.x(); + } + function h() public returns (uint) { + c.h(); + return c.x(); + } + } + )"; + compileAndRun(sourceCode, 0, "D"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(12)); +} + +BOOST_AUTO_TEST_CASE(test_underscore_in_hex) +{ + char const* sourceCode = R"( + contract test { + function f(bool cond) public pure returns (uint) { + uint32 x = 0x1234_ab; + uint y = 0x1234_abcd_1234; + return cond ? x : y; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(0x1234ab))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(0x1234abcd1234))); +} + +BOOST_AUTO_TEST_CASE(flipping_sign_tests) +{ + char const* sourceCode = R"( + contract test { + function f() public returns (bool){ + int x = -2**255; + assert(-x == x); + return true; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 90d8265c6..309cbf0b8 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -77,7 +77,7 @@ Declaration const& resolveDeclaration( ) { ASTNode const* scope = &_sourceUnit; - // bracers are required, cause msvc couldnt handle this macro in for statement + // bracers are required, cause msvc couldn't handle this macro in for statement for (string const& namePart: _namespacedName) { auto declarations = _resolver.resolveName(namePart, scope); @@ -175,12 +175,12 @@ BOOST_AUTO_TEST_CASE(literal_true) { char const* sourceCode = R"( contract test { - function f() { var x = true; } + function f() public { bool x = true; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH1), 0x1}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x1}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -188,12 +188,12 @@ BOOST_AUTO_TEST_CASE(literal_false) { char const* sourceCode = R"( contract test { - function f() { var x = false; } + function f() { bool x = false; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH1), 0x0}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x0}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -201,12 +201,12 @@ BOOST_AUTO_TEST_CASE(int_literal) { char const* sourceCode = R"( contract test { - function f() { var x = 0x12345678901234567890; } + function f() { uint x = 0x12345678901234567890; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, + bytes expectation({uint8_t(Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -215,14 +215,14 @@ BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () { - var x = 1 wei; + constructor() { + uint x = 1 wei; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH1), 0x1}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x1}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -231,13 +231,13 @@ BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination) char const* sourceCode = R"( contract test { function test () { - var x = 1 szabo; + uint x = 1 szabo; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00}); + bytes expectation({uint8_t(Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -245,14 +245,15 @@ BOOST_AUTO_TEST_CASE(int_with_finney_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () + constructor() { - var x = 1 finney; + uint x = 1 finney; } - })"; + } + )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH7), 0x3, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00}); + bytes expectation({uint8_t(Instruction::PUSH7), 0x3, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -260,14 +261,14 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () { - var x = 1 ether; + constructor() { + uint x = 1 ether; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00}); + bytes expectation({uint8_t(Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -275,17 +276,17 @@ BOOST_AUTO_TEST_CASE(comparison) { char const* sourceCode = R"( contract test { - function f() { var x = (0x10aa < 0x11aa) != true; } + function f() { bool x = (0x10aa < 0x11aa) != true; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH1), 0x1, byte(Instruction::ISZERO), byte(Instruction::ISZERO), - byte(Instruction::PUSH2), 0x11, 0xaa, - byte(Instruction::PUSH2), 0x10, 0xaa, - byte(Instruction::LT), byte(Instruction::ISZERO), byte(Instruction::ISZERO), - byte(Instruction::EQ), - byte(Instruction::ISZERO)}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x1, uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), + uint8_t(Instruction::PUSH2), 0x11, 0xaa, + uint8_t(Instruction::PUSH2), 0x10, 0xaa, + uint8_t(Instruction::LT), uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), + uint8_t(Instruction::EQ), + uint8_t(Instruction::ISZERO)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -293,32 +294,32 @@ BOOST_AUTO_TEST_CASE(short_circuiting) { char const* sourceCode = R"( contract test { - function f() { var x = true != (4 <= 8 + 10 || 9 != 2); } + function f() { bool x = true != (4 <= 8 + 10 || 9 != 2); } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(Instruction::PUSH1), 0x12, // 8 + 10 - byte(Instruction::PUSH1), 0x4, - byte(Instruction::GT), - byte(Instruction::ISZERO), // after this we have 4 <= 8 + 10 - byte(Instruction::DUP1), - byte(Instruction::PUSH1), 0x11, - byte(Instruction::JUMPI), // short-circuit if it is true - byte(Instruction::POP), - byte(Instruction::PUSH1), 0x2, - byte(Instruction::PUSH1), 0x9, - byte(Instruction::EQ), - byte(Instruction::ISZERO), // after this we have 9 != 2 - byte(Instruction::JUMPDEST), - byte(Instruction::ISZERO), byte(Instruction::ISZERO), - byte(Instruction::PUSH1), 0x1, byte(Instruction::ISZERO), byte(Instruction::ISZERO), - byte(Instruction::EQ), - byte(Instruction::ISZERO)}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x12, // 8 + 10 + uint8_t(Instruction::PUSH1), 0x4, + uint8_t(Instruction::GT), + uint8_t(Instruction::ISZERO), // after this we have 4 <= 8 + 10 + uint8_t(Instruction::DUP1), + uint8_t(Instruction::PUSH1), 0x11, + uint8_t(Instruction::JUMPI), // short-circuit if it is true + uint8_t(Instruction::POP), + uint8_t(Instruction::PUSH1), 0x2, + uint8_t(Instruction::PUSH1), 0x9, + uint8_t(Instruction::EQ), + uint8_t(Instruction::ISZERO), // after this we have 9 != 2 + uint8_t(Instruction::JUMPDEST), + uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), + uint8_t(Instruction::PUSH1), 0x1, uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), + uint8_t(Instruction::EQ), + uint8_t(Instruction::ISZERO)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } -BOOST_AUTO_TEST_CASE(arithmetics) +BOOST_AUTO_TEST_CASE(arithmetic) { char const* sourceCode = R"( contract test { @@ -326,37 +327,37 @@ BOOST_AUTO_TEST_CASE(arithmetics) } )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}}); - bytes expectation({byte(Instruction::PUSH1), 0x1, - byte(Instruction::PUSH1), 0x2, - byte(Instruction::PUSH1), 0x3, - byte(Instruction::PUSH1), 0x4, - byte(Instruction::PUSH1), 0x5, - byte(Instruction::PUSH1), 0x6, - byte(Instruction::PUSH1), 0x7, - byte(Instruction::PUSH1), 0x8, - byte(Instruction::DUP9), - byte(Instruction::XOR), - byte(Instruction::AND), - byte(Instruction::OR), - byte(Instruction::SUB), - byte(Instruction::ADD), - byte(Instruction::DUP2), - byte(Instruction::ISZERO), - byte(Instruction::ISZERO), - byte(Instruction::PUSH1), 0x1d, - byte(Instruction::JUMPI), - byte(Instruction::INVALID), - byte(Instruction::JUMPDEST), - byte(Instruction::MOD), - byte(Instruction::DUP2), - byte(Instruction::ISZERO), - byte(Instruction::ISZERO), - byte(Instruction::PUSH1), 0x26, - byte(Instruction::JUMPI), - byte(Instruction::INVALID), - byte(Instruction::JUMPDEST), - byte(Instruction::DIV), - byte(Instruction::MUL)}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x1, + uint8_t(Instruction::PUSH1), 0x2, + uint8_t(Instruction::PUSH1), 0x3, + uint8_t(Instruction::PUSH1), 0x4, + uint8_t(Instruction::PUSH1), 0x5, + uint8_t(Instruction::PUSH1), 0x6, + uint8_t(Instruction::PUSH1), 0x7, + uint8_t(Instruction::PUSH1), 0x8, + uint8_t(Instruction::DUP9), + uint8_t(Instruction::XOR), + uint8_t(Instruction::AND), + uint8_t(Instruction::OR), + uint8_t(Instruction::SUB), + uint8_t(Instruction::ADD), + uint8_t(Instruction::DUP2), + uint8_t(Instruction::ISZERO), + uint8_t(Instruction::ISZERO), + uint8_t(Instruction::PUSH1), 0x1d, + uint8_t(Instruction::JUMPI), + uint8_t(Instruction::INVALID), + uint8_t(Instruction::JUMPDEST), + uint8_t(Instruction::MOD), + uint8_t(Instruction::DUP2), + uint8_t(Instruction::ISZERO), + uint8_t(Instruction::ISZERO), + uint8_t(Instruction::PUSH1), 0x26, + uint8_t(Instruction::JUMPI), + uint8_t(Instruction::INVALID), + uint8_t(Instruction::JUMPDEST), + uint8_t(Instruction::DIV), + uint8_t(Instruction::MUL)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -369,13 +370,13 @@ BOOST_AUTO_TEST_CASE(unary_operators) )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}}); - bytes expectation({byte(Instruction::PUSH1), 0x2, - byte(Instruction::DUP2), - byte(Instruction::PUSH1), 0x0, - byte(Instruction::SUB), - byte(Instruction::NOT), - byte(Instruction::EQ), - byte(Instruction::ISZERO)}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x2, + uint8_t(Instruction::DUP2), + uint8_t(Instruction::PUSH1), 0x0, + uint8_t(Instruction::SUB), + uint8_t(Instruction::NOT), + uint8_t(Instruction::EQ), + uint8_t(Instruction::ISZERO)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -383,53 +384,53 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec) { char const* sourceCode = R"( contract test { - function f(uint a) returns (uint x) { x = --a ^ (a-- ^ (++a ^ a++)); } + function f(uint a) public returns (uint x) { x = --a ^ (a-- ^ (++a ^ a++)); } } )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}}); // Stack: a, x - bytes expectation({byte(Instruction::DUP2), - byte(Instruction::DUP1), - byte(Instruction::PUSH1), 0x1, - byte(Instruction::ADD), + bytes expectation({uint8_t(Instruction::DUP2), + uint8_t(Instruction::DUP1), + uint8_t(Instruction::PUSH1), 0x1, + uint8_t(Instruction::ADD), // Stack here: a x a (a+1) - byte(Instruction::SWAP3), - byte(Instruction::POP), // first ++ + uint8_t(Instruction::SWAP3), + uint8_t(Instruction::POP), // first ++ // Stack here: (a+1) x a - byte(Instruction::DUP3), - byte(Instruction::PUSH1), 0x1, - byte(Instruction::ADD), + uint8_t(Instruction::DUP3), + uint8_t(Instruction::PUSH1), 0x1, + uint8_t(Instruction::ADD), // Stack here: (a+1) x a (a+2) - byte(Instruction::SWAP3), - byte(Instruction::POP), + uint8_t(Instruction::SWAP3), + uint8_t(Instruction::POP), // Stack here: (a+2) x a - byte(Instruction::DUP3), // second ++ - byte(Instruction::XOR), + uint8_t(Instruction::DUP3), // second ++ + uint8_t(Instruction::XOR), // Stack here: (a+2) x a^(a+2) - byte(Instruction::DUP3), - byte(Instruction::DUP1), - byte(Instruction::PUSH1), 0x1, - byte(Instruction::SWAP1), - byte(Instruction::SUB), + uint8_t(Instruction::DUP3), + uint8_t(Instruction::DUP1), + uint8_t(Instruction::PUSH1), 0x1, + uint8_t(Instruction::SWAP1), + uint8_t(Instruction::SUB), // Stack here: (a+2) x a^(a+2) (a+2) (a+1) - byte(Instruction::SWAP4), - byte(Instruction::POP), // first -- - byte(Instruction::XOR), + uint8_t(Instruction::SWAP4), + uint8_t(Instruction::POP), // first -- + uint8_t(Instruction::XOR), // Stack here: (a+1) x a^(a+2)^(a+2) - byte(Instruction::DUP3), - byte(Instruction::PUSH1), 0x1, - byte(Instruction::SWAP1), - byte(Instruction::SUB), + uint8_t(Instruction::DUP3), + uint8_t(Instruction::PUSH1), 0x1, + uint8_t(Instruction::SWAP1), + uint8_t(Instruction::SUB), // Stack here: (a+1) x a^(a+2)^(a+2) a - byte(Instruction::SWAP3), - byte(Instruction::POP), // second ++ + uint8_t(Instruction::SWAP3), + uint8_t(Instruction::POP), // second ++ // Stack here: a x a^(a+2)^(a+2) - byte(Instruction::DUP3), // will change - byte(Instruction::XOR), - byte(Instruction::SWAP1), - byte(Instruction::POP), - byte(Instruction::DUP1)}); + uint8_t(Instruction::DUP3), // will change + uint8_t(Instruction::XOR), + uint8_t(Instruction::SWAP1), + uint8_t(Instruction::POP), + uint8_t(Instruction::DUP1)}); // Stack here: a x a^(a+2)^(a+2)^a BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -444,16 +445,16 @@ BOOST_AUTO_TEST_CASE(assignment) bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}}); // Stack: a, b - bytes expectation({byte(Instruction::PUSH1), 0x2, - byte(Instruction::DUP2), - byte(Instruction::DUP4), - byte(Instruction::ADD), + bytes expectation({uint8_t(Instruction::PUSH1), 0x2, + uint8_t(Instruction::DUP2), + uint8_t(Instruction::DUP4), + uint8_t(Instruction::ADD), // Stack here: a b 2 a+b - byte(Instruction::SWAP3), - byte(Instruction::POP), - byte(Instruction::DUP3), + uint8_t(Instruction::SWAP3), + uint8_t(Instruction::POP), + uint8_t(Instruction::DUP3), // Stack here: a+b b 2 a+b - byte(Instruction::MUL)}); + uint8_t(Instruction::MUL)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -466,7 +467,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits) )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80)); + bytes expectation(bytes({uint8_t(Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80)); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -479,7 +480,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_16bits) )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43}); + bytes expectation(bytes({uint8_t(Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -489,12 +490,12 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals) // have been applied char const* sourceCode = R"( contract test { - function f() { var x = (0xffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; } + function f() { uint8 x = (0x00ffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; } } )"; bytes code = compileFirstExpression(sourceCode); - bytes expectation(bytes({byte(Instruction::PUSH1), 0xbf})); + bytes expectation(bytes({uint8_t(Instruction::PUSH1), 0xbf})); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -508,13 +509,13 @@ BOOST_AUTO_TEST_CASE(blockhash) } )"; - auto blockhashFun = make_shared(strings{"uint256"}, strings{"bytes32"}, + auto blockhashFun = make_shared(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View); - + bytes code = compileFirstExpression(sourceCode, {}, {}, {make_shared("blockhash", blockhashFun)}); - bytes expectation({byte(Instruction::PUSH1), 0x03, - byte(Instruction::BLOCKHASH)}); + bytes expectation({uint8_t(Instruction::PUSH1), 0x03, + uint8_t(Instruction::BLOCKHASH)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -522,32 +523,17 @@ BOOST_AUTO_TEST_CASE(gas_left) { char const* sourceCode = R"( contract test { - function f() returns (uint256 val) { - return msg.gas; + function f() public returns (uint256 val) { + return gasleft(); } } )"; bytes code = compileFirstExpression( - sourceCode, {}, {}, - {make_shared("msg", make_shared(MagicType::Kind::Message))} - ); - - bytes expectation({byte(Instruction::GAS)}); - BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); - - sourceCode = R"( - contract test { - function f() returns (uint256 val) { - return gasleft(); - } - } - )"; - code = compileFirstExpression( sourceCode, {}, {}, {make_shared("gasleft", make_shared(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft))} ); - expectation = bytes({byte(Instruction::GAS)}); + bytes expectation = bytes({uint8_t(Instruction::GAS)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 5af676595..5ec010c7f 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -26,7 +26,7 @@ #include -#include +#include #include @@ -43,280 +43,6 @@ namespace test BOOST_FIXTURE_TEST_SUITE(SolidityNameAndTypeResolution, AnalysisFramework) -BOOST_AUTO_TEST_CASE(name_references) -{ - char const* text = R"( - contract test { - uint256 variable; - function f(uint256) public returns (uint out) { f(variable); test; out; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(undeclared_name) -{ - char const* text = R"( - contract test { - uint256 variable; - function f(uint256 arg) public { - f(notfound); - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier."); -} - -BOOST_AUTO_TEST_CASE(undeclared_name_is_not_fatal) -{ - char const* text = R"( - contract test { - uint256 variable; - function f(uint256 arg) public { - f(notfound); - f(notfound); - } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, (vector{"Undeclared identifier", "Undeclared identifier"})); -} - -BOOST_AUTO_TEST_CASE(reference_to_later_declaration) -{ - char const* text = R"( - contract test { - function g() public { f(); } - function f() public {} - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(type_inference_smoke_test) -{ - char const* text = R"( - contract test { - function f(uint256 arg1, uint32 arg2) public returns (bool ret) { - var x = arg1 + arg2 == 8; ret = x; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(type_checking_return) -{ - char const* text = R"( - contract test { - function f() public returns (bool r) { return 1 >= 2; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number) -{ - char const* text = R"( - contract test { - function f() public returns (bool r1, bool r2) { return 1 >= 2; } - } - )"; - CHECK_ERROR(text, TypeError, "Different number of arguments in return statement than in returns declaration."); -} - -BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) -{ - char const* text = R"( - contract test { - function f() public returns (uint256 r) { return 1 >= 2; } - } - )"; - CHECK_ERROR(text, TypeError, "Return argument type bool is not implicitly convertible to expected type (type of first return variable) uint256."); -} - -BOOST_AUTO_TEST_CASE(type_checking_function_call) -{ - char const* text = R"( - contract test { - function f() public returns (bool) { return g(12, true) == 3; } - function g(uint256, bool) public returns (uint256) { } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(type_conversion_for_comparison) -{ - char const* text = R"( - contract test { - function f() public { uint32(2) == int64(2); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid) -{ - char const* text = R"( - contract test { - function f() public { int32(2) == uint64(2); } - } - )"; - CHECK_ERROR(text, TypeError, "Operator == not compatible with types int32 and uint64"); -} - -BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) -{ - char const* text = R"( - contract test { - function f() public returns (int256 r) { var x = int256(uint32(2)); return x; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(large_string_literal) -{ - char const* text = R"( - contract test { - function f() public { var x = "123456789012345678901234567890123"; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(balance) -{ - char const* text = R"( - contract test { - function fun() public { - uint256 x = address(0).balance; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(balance_invalid) -{ - char const* text = R"( - contract test { - function fun() public { - address(0).balance = 7; - } - } - )"; - CHECK_ERROR(text, TypeError, "Expression has to be an lvalue."); -} - -BOOST_AUTO_TEST_CASE(assignment_to_mapping) -{ - char const* text = R"( - contract test { - struct str { - mapping(uint=>uint) map; - } - str data; - function fun() public { - var a = data.map; - data.map = a; - } - } - )"; - CHECK_ERROR(text, TypeError, "Mappings cannot be assigned to."); -} - -BOOST_AUTO_TEST_CASE(assignment_to_struct) -{ - char const* text = R"( - contract test { - struct str { - mapping(uint=>uint) map; - } - str data; - function fun() public { - var a = data; - data = a; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(forward_function_reference) -{ - char const* text = R"( - contract First { - function fun() public returns (bool) { - return Second(1).fun(1, true, 3) > 0; - } - } - contract Second { - function fun(uint, bool, uint) public returns (uint) { - if (First(2).fun() == true) return 1; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) -{ - char const* text = R"( - contract First { - function fun() public returns (bool ret) { - return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(comparison_of_function_types) -{ - char const* text = R"( - contract C { - function f() public returns (bool ret) { - return this.f < this.f; - } - } - )"; - CHECK_ERROR(text, TypeError, "Operator < not compatible"); - text = R"( - contract C { - function f() public returns (bool ret) { - return f < f; - } - } - )"; - CHECK_ERROR(text, TypeError, "Operator < not compatible"); - text = R"( - contract C { - function f() public returns (bool ret) { - return f == f; - } - function g() public returns (bool ret) { - return f != f; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(comparison_of_mapping_types) -{ - char const* text = R"( - contract C { - mapping(uint => uint) x; - function f() public returns (bool ret) { - var y = x; - return x == y; - } - } - )"; - CHECK_ERROR(text, TypeError, "Operator == not compatible"); -} - BOOST_AUTO_TEST_CASE(function_no_implementation) { SourceUnit const* sourceUnit = nullptr; @@ -337,7 +63,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract) { SourceUnit const* sourceUnit = nullptr; char const* text = R"( - contract base { function foo(); } + contract base { function foo() public; } contract derived is base { function foo() public {} } )"; sourceUnit = parseAndAnalyse(text); @@ -356,7 +82,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload) { SourceUnit const* sourceUnit = nullptr; char const* text = R"( - contract base { function foo(bool); } + contract base { function foo(bool) public; } contract derived is base { function foo(uint) public {} } )"; sourceUnit = parseAndAnalyse(text); @@ -369,34 +95,12 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload) BOOST_CHECK(!derived->annotation().unimplementedFunctions.empty()); } -BOOST_AUTO_TEST_CASE(create_abstract_contract) -{ - char const* text = R"( - contract base { function foo(); } - contract derived { - base b; - function foo() public { b = new base(); } - } - )"; - CHECK_ERROR(text, TypeError, "Trying to create an instance of an abstract contract."); -} - -BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract) -{ - char const* text = R"( - contract base { function foo(); } - contract derived is base { function foo() public {} } - contract wrong is derived { function foo(); } - )"; - CHECK_ERROR(text, TypeError, "Redeclaring an already implemented function as abstract"); -} - BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) { SourceUnit const* sourceUnit = nullptr; char const* text = R"( - contract base { function foo(); } - contract foo is base { function foo() public {} } + contract base { function foo() public; } + contract foo is base { constructor() public {} } )"; sourceUnit = parseAndAnalyse(text); std::vector> nodes = sourceUnit->nodes(); @@ -454,7 +158,7 @@ BOOST_AUTO_TEST_CASE(function_external_types) uint a; } contract Test { - function boo(uint, bool, bytes8, bool[2], uint[], C, address[]) external returns (uint ret) { + function boo(uint, bool, bytes8, bool[2] calldata, uint[] calldata, C, address[] calldata) external returns (uint ret) { ret = 5; } } @@ -472,9 +176,9 @@ BOOST_AUTO_TEST_CASE(function_external_types) BOOST_AUTO_TEST_CASE(enum_external_type) { - // bug #1801 SourceUnit const* sourceUnit = nullptr; char const* text = R"( + // test for bug #1801 contract Test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } function boo(ActionChoices enumArg) external returns (uint ret) { @@ -499,13 +203,13 @@ BOOST_AUTO_TEST_CASE(external_structs) pragma experimental ABIEncoderV2; contract Test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - struct Empty {} + struct Simple { uint i; } struct Nested { X[2][] a; uint y; } - struct X { bytes32 x; Test t; Empty[] e; } - function f(ActionChoices, uint, Empty) external {} - function g(Test, Nested) external {} - function h(function(Nested) external returns (uint)[]) external {} - function i(Nested[]) external {} + struct X { bytes32 x; Test t; Simple[] s; } + function f(ActionChoices, uint, Simple calldata) external {} + function g(Test, Nested calldata) external {} + function h(function(Nested memory) external returns (uint)[] calldata) external {} + function i(Nested[] calldata) external {} } )"; SourceUnit const* sourceUnit = parseAndAnalyse(text); @@ -514,10 +218,10 @@ BOOST_AUTO_TEST_CASE(external_structs) { auto functions = contract->definedFunctions(); BOOST_REQUIRE(!functions.empty()); - BOOST_CHECK_EQUAL("f(uint8,uint256,())", functions[0]->externalSignature()); - BOOST_CHECK_EQUAL("g(address,((bytes32,address,()[])[2][],uint256))", functions[1]->externalSignature()); + BOOST_CHECK_EQUAL("f(uint8,uint256,(uint256))", functions[0]->externalSignature()); + BOOST_CHECK_EQUAL("g(address,((bytes32,address,(uint256)[])[2][],uint256))", functions[1]->externalSignature()); BOOST_CHECK_EQUAL("h(function[])", functions[2]->externalSignature()); - BOOST_CHECK_EQUAL("i(((bytes32,address,()[])[2][],uint256)[])", functions[3]->externalSignature()); + BOOST_CHECK_EQUAL("i(((bytes32,address,(uint256)[])[2][],uint256)[])", functions[3]->externalSignature()); } } @@ -527,13 +231,13 @@ BOOST_AUTO_TEST_CASE(external_structs_in_libraries) pragma experimental ABIEncoderV2; library Test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - struct Empty {} + struct Simple { uint i; } struct Nested { X[2][] a; uint y; } - struct X { bytes32 x; Test t; Empty[] e; } - function f(ActionChoices, uint, Empty) external {} - function g(Test, Nested) external {} - function h(function(Nested) external returns (uint)[]) external {} - function i(Nested[]) external {} + struct X { bytes32 x; Test t; Simple[] s; } + function f(ActionChoices, uint, Simple calldata) external {} + function g(Test, Nested calldata) external {} + function h(function(Nested memory) external returns (uint)[] calldata) external {} + function i(Nested[] calldata) external {} } )"; SourceUnit const* sourceUnit = parseAndAnalyse(text); @@ -542,7 +246,7 @@ BOOST_AUTO_TEST_CASE(external_structs_in_libraries) { auto functions = contract->definedFunctions(); BOOST_REQUIRE(!functions.empty()); - BOOST_CHECK_EQUAL("f(Test.ActionChoices,uint256,Test.Empty)", functions[0]->externalSignature()); + BOOST_CHECK_EQUAL("f(Test.ActionChoices,uint256,Test.Simple)", functions[0]->externalSignature()); BOOST_CHECK_EQUAL("g(Test,Test.Nested)", functions[1]->externalSignature()); BOOST_CHECK_EQUAL("h(function[])", functions[2]->externalSignature()); BOOST_CHECK_EQUAL("i(Test.Nested[])", functions[3]->externalSignature()); @@ -568,336 +272,6 @@ BOOST_AUTO_TEST_CASE(struct_with_mapping_in_library) } } -BOOST_AUTO_TEST_CASE(functions_with_identical_structs_in_interface) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - - contract C { - struct S1 { } - struct S2 { } - function f(S1) pure {} - function f(S2) pure {} - } - )"; - CHECK_ERROR(text, TypeError, "Function overload clash during conversion to external types for arguments"); -} - -BOOST_AUTO_TEST_CASE(functions_with_different_structs_in_interface) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - - contract C { - struct S1 { function() external a; } - struct S2 { bytes24 a; } - function f(S1) pure {} - function f(S2) pure {} - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(functions_with_stucts_of_non_external_types_in_interface) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - - contract C { - struct S { function() internal a; } - function f(S) {} - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(functions_with_stucts_of_non_external_types_in_interface_2) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - - contract C { - struct S { mapping(uint => uint) a; } - function f(S) {} - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(functions_with_stucts_of_non_external_types_in_interface_nested) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - - contract C { - struct T { mapping(uint => uint) a; } - struct S { T[][2] b; } - function f(S) {} - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(returning_multi_dimensional_arrays_new_abi) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - - contract C { - function f() public pure returns (string[][]) {} - } - )"; - CHECK_WARNING(text, "Experimental features"); -} - -BOOST_AUTO_TEST_CASE(returning_multi_dimensional_arrays) -{ - char const* text = R"( - contract C { - function f() public pure returns (string[][]) {} - } - )"; - CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder"); -} - -BOOST_AUTO_TEST_CASE(returning_multi_dimensional_static_arrays) -{ - char const* text = R"( - contract C { - function f() public pure returns (uint[][2]) {} - } - )"; - CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder"); -} - -BOOST_AUTO_TEST_CASE(returning_arrays_in_structs_new_abi) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - - contract C { - struct S { string[] s; } - function f() public pure returns (S) {} - } - )"; - CHECK_WARNING(text, "Experimental features"); -} - -BOOST_AUTO_TEST_CASE(returning_arrays_in_structs_arrays) -{ - char const* text = R"( - contract C { - struct S { string[] s; } - function f() public pure returns (S x) {} - } - )"; - CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder"); -} - -BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion) -{ - char const* text = R"( - contract C {} - contract Test { - function externalCall() public { - C arg; - this.g(arg); - } - function g (C c) external {} - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) -{ - char const* text = R"( - contract C {} - contract Test { - function externalCall() public { - address arg; - this.g(arg); - } - function g (C c) external {} - } - )"; - CHECK_ERROR(text, TypeError, "Invalid type for argument in function call. Invalid implicit conversion from address to contract C requested."); -} - -BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) -{ - char const* text = R"( - contract C { - uint a; - } - contract Test { - C a; - function g (C c) public {} - function internalCall() public { - g(a); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) -{ - char const* text = R"( - contract C { - uint a; - } - contract Test { - address a; - function g (C c) public {} - function internalCall() public { - g(a); - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid type for argument in function call. Invalid implicit conversion from address to contract C requested."); -} - -BOOST_AUTO_TEST_CASE(hash_collision_in_interface) -{ - char const* text = R"( - contract test { - function gsf() public { } - function tgeo() public { } - } - )"; - CHECK_ERROR(text, TypeError, "Function signature hash collision for tgeo()"); -} - -BOOST_AUTO_TEST_CASE(inheritance_basic) -{ - char const* text = R"( - contract base { uint baseMember; struct BaseType { uint element; } } - contract derived is base { - BaseType data; - function f() public { baseMember = 7; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inheritance_diamond_basic) -{ - char const* text = R"( - contract root { function rootFunction() public {} } - contract inter1 is root { function f() public {} } - contract inter2 is root { function f() public {} } - contract derived is root, inter2, inter1 { - function g() public { f(); rootFunction(); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(cyclic_inheritance) -{ - char const* text = R"( - contract A is B { } - contract B is A { } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (vector{"Definition of base has to precede definition of derived contract"})); -} - -BOOST_AUTO_TEST_CASE(legal_override_direct) -{ - char const* text = R"( - contract B { function f() public {} } - contract C is B { function f(uint i) public {} } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(legal_override_indirect) -{ - char const* text = R"( - contract A { function f(uint a) public {} } - contract B { function f() public {} } - contract C is A, B { } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(illegal_override_visibility) -{ - char const* text = R"( - contract B { function f() internal {} } - contract C is B { function f() public {} } - )"; - CHECK_ERROR(text, TypeError, "Overriding function visibility differs"); -} - -BOOST_AUTO_TEST_CASE(complex_inheritance) -{ - char const* text = R"( - contract A { function f() public { uint8 x = C(0).g(); } } - contract B { function f() public {} function g() public returns (uint8) {} } - contract C is A, B { } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments) -{ - char const* text = R"( - contract A { function A(uint a) public { } } - contract B is A { } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(base_constructor_arguments_override) -{ - char const* text = R"( - contract A { function A(uint a) public { } } - contract B is A { } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion) -{ - char const* text = R"( - contract A { } - contract B is A { - function f() public { A a = B(1); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion) -{ - char const* text = R"( - contract A { } - contract B is A { - function f() public { B b = A(1); } - } - )"; - CHECK_ERROR(text, TypeError, "Type contract A is not implicitly convertible to expected type contract B."); -} - -BOOST_AUTO_TEST_CASE(super_excludes_current_contract) -{ - char const* text = R"( - contract A { - function b() public {} - } - - contract B is A { - function f() public { - super.f(); - } - } - )"; - - CHECK_ERROR(text, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in contract super B"); -} - BOOST_AUTO_TEST_CASE(state_variable_accessors) { char const* text = R"( @@ -939,20 +313,6 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) BOOST_CHECK(function->stateMutability() == StateMutability::View); } -BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) -{ - char const* text = R"( - contract test { - function fun() public { - uint64(2); - } - uint256 foo; - function foo() public {} - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared."); -} - BOOST_AUTO_TEST_CASE(private_state_variable) { char const* text = R"( @@ -975,3859 +335,40 @@ BOOST_AUTO_TEST_CASE(private_state_variable) BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an internal variable should not exist"); } -BOOST_AUTO_TEST_CASE(base_class_state_variable_accessor) -{ - // test for issue #1126 https://github.com/ethereum/cpp-ethereum/issues/1126 - char const* text = R"( - contract Parent { - uint256 public m_aMember; - } - contract Child is Parent { - function foo() public returns (uint256) { return Parent.m_aMember; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only) -{ - char const* sourceCode = R"( - contract test { - struct Data { uint[15] m_array; } - Data public data; - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Internal or recursive type is not allowed for public state variables."); -} - -BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member) -{ - char const* text = R"( - contract Parent { - uint256 internal m_aMember; - } - contract Child is Parent { - function foo() public returns (uint256) { return Parent.m_aMember; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class1) -{ - char const* text = R"( - contract Parent1 { - uint256 internal m_aMember1; - } - contract Parent2 is Parent1 { - uint256 internal m_aMember2; - } - contract Child is Parent2 { - function foo() public returns (uint256) { return Parent2.m_aMember1; } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"m_aMember1\" not found or not visible after argument-dependent lookup in type(contract Parent2)"); -} - -BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2) -{ - char const* text = R"( - contract Parent1 { - uint256 internal m_aMember1; - } - contract Parent2 is Parent1 { - uint256 internal m_aMember2; - } - contract Child is Parent2 { - function foo() public returns (uint256) { return Child.m_aMember2; } - uint256 public m_aMember3; - } - )"; - CHECK_ERROR(text, TypeError, "Member \"m_aMember2\" not found or not visible after argument-dependent lookup in type(contract Child)"); -} - -BOOST_AUTO_TEST_CASE(fallback_function) -{ - char const* text = R"( - contract C { - uint x; - function() public { x = 2; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(fallback_function_with_arguments) -{ - char const* text = R"( - contract C { - uint x; - function(uint a) public { x = 2; } - } - )"; - CHECK_ERROR(text, TypeError, "Fallback function cannot take parameters."); -} - -BOOST_AUTO_TEST_CASE(fallback_function_in_library) -{ - char const* text = R"( - library C { - function() public {} - } - )"; - CHECK_ERROR(text, TypeError, "Libraries cannot have fallback functions."); -} - -BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) -{ - char const* text = R"( - contract C { - function() public returns (uint) { } - } - )"; - CHECK_ERROR(text, TypeError, "Fallback function cannot return values."); -} - -BOOST_AUTO_TEST_CASE(fallback_function_twice) -{ - char const* text = R"( - contract C { - uint x; - function() public { x = 2; } - function() public { x = 3; } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, (vector{ - "Only one fallback function is" - })); -} - -BOOST_AUTO_TEST_CASE(fallback_function_inheritance) -{ - char const* text = R"( - contract A { - uint x; - function() public { x = 1; } - } - contract C is A { - function() public { x = 2; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(event) -{ - char const* text = R"( - contract c { - event e(uint indexed a, bytes3 indexed s, bool indexed b); - function f() public { e(2, "abc", true); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(event_too_many_indexed) -{ - char const* text = R"( - contract c { - event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d); - } - )"; - CHECK_ERROR(text, TypeError, "More than 3 indexed arguments for event."); -} - -BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed) -{ - char const* text = R"( - contract c { - event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d) anonymous; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed) -{ - char const* text = R"( - contract c { - event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous; - } - )"; - CHECK_ERROR(text, TypeError, "More than 4 indexed arguments for anonymous event."); -} - -BOOST_AUTO_TEST_CASE(events_with_same_name) -{ - char const* text = R"( - contract TestIt { - event A(); - event A(uint i); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(events_with_same_name_unnamed_arguments) -{ - char const* text = R"( - contract test { - event A(uint); - event A(uint, uint); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(events_with_same_name_different_types) -{ - char const* text = R"( - contract test { - event A(uint); - event A(bytes); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(double_event_declaration) -{ - char const* text = R"( - contract test { - event A(uint i); - event A(uint i); - } - )"; - CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); -} - -BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_anonymous) -{ - char const* text = R"( - contract test { - event A(uint i); - event A(uint i) anonymous; - } - )"; - CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); -} - -BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_indexed) -{ - char const* text = R"( - contract test { - event A(uint i); - event A(uint indexed i); - } - )"; - CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); -} - -BOOST_AUTO_TEST_CASE(event_call) -{ - char const* text = R"( - contract c { - event e(uint a, bytes3 indexed s, bool indexed b); - function f() public { e(2, "abc", true); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(event_function_inheritance_clash) -{ - char const* text = R"( - contract A { - function dup() public returns (uint) { - return 1; - } - } - contract B { - event dup(); - } - contract C is A, B { - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared."); -} - -BOOST_AUTO_TEST_CASE(function_event_inheritance_clash) -{ - char const* text = R"( - contract B { - event dup(); - } - contract A { - function dup() public returns (uint) { - return 1; - } - } - contract C is B, A { - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared."); -} - -BOOST_AUTO_TEST_CASE(function_event_in_contract_clash) -{ - char const* text = R"( - contract A { - event dup(); - function dup() public returns (uint) { - return 1; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared."); -} - -BOOST_AUTO_TEST_CASE(event_inheritance) -{ - char const* text = R"( - contract base { - event e(uint a, bytes3 indexed s, bool indexed b); - } - contract c is base { - function f() public { e(2, "abc", true); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(multiple_events_argument_clash) -{ - char const* text = R"( - contract c { - event e1(uint a, uint e1, uint e2); - event e2(uint a, uint e1, uint e2); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(access_to_default_function_visibility) -{ - char const* text = R"( - contract c { - function f() public {} - } - contract d { - function g() public { c(0).f(); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(access_to_internal_function) -{ - char const* text = R"( - contract c { - function f() internal {} - } - contract d { - function g() public { c(0).f(); } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in contract c"); -} - -BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) -{ - char const* text = R"( - contract c { - uint a; - } - contract d { - function g() public { c(0).a(); } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"a\" not found or not visible after argument-dependent lookup in contract c"); -} - -BOOST_AUTO_TEST_CASE(access_to_internal_state_variable) -{ - char const* text = R"( - contract c { - uint public a; - } - contract d { - function g() public { c(0).a(); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(error_count_in_named_args) -{ - char const* sourceCode = R"( - contract test { - function a(uint a, uint b) public returns (uint r) { - r = a + b; - } - function b() public returns (uint r) { - r = a({a: 1}); - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Wrong argument count for function call: 1 arguments given but expected 2."); -} - -BOOST_AUTO_TEST_CASE(empty_in_named_args) -{ - char const* sourceCode = R"( - contract test { - function a(uint a, uint b) public returns (uint r) { - r = a + b; - } - function b() public returns (uint r) { - r = a({}); - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Wrong argument count for function call: 0 arguments given but expected 2."); -} - -BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args) -{ - char const* sourceCode = R"( - contract test { - function a(uint a, uint b) public returns (uint r) { - r = a + b; - } - function b() public returns (uint r) { - r = a({a: 1, a: 2}); - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Duplicate named argument."); -} - -BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) -{ - char const* sourceCode = R"( - contract test { - function a(uint a, uint b) public returns (uint r) { - r = a + b; - } - function b() public returns (uint r) { - r = a({a: 1, c: 2}); - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Named argument does not match function declaration."); -} - -BOOST_AUTO_TEST_CASE(empty_name_input_parameter) -{ - char const* text = R"( - contract test { - function f(uint) public { } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(constant_input_parameter) -{ - char const* text = R"( - contract test { - function f(uint[] constant a) public { } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (vector{ - "Illegal use of \"constant\" specifier", - "Constants of non-value type not yet implemented", - "Uninitialized \"constant\" variable" - })); -} - -BOOST_AUTO_TEST_CASE(empty_name_return_parameter) -{ - char const* text = R"( - contract test { - function f() public returns (bool) { } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) -{ - char const* text = R"( - contract test { - function f(uint, uint k) public returns (uint ret_k) { - return k; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) -{ - char const* text = R"( - contract test { - function f() public returns (uint ret_k, uint) { - return 5; - } - } - )"; - CHECK_ERROR(text, TypeError, "Different number of arguments in return statement than in returns declaration."); -} - -BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) -{ - char const* sourceCode = R"( - contract c { - function f() public { var (x) = f(); } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Not enough components (0) in value to assign all variables (1)."); -} - -BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) -{ - char const* sourceCodeFine = R"( - contract c { - function c () public { - a = 115792089237316195423570985008687907853269984665640564039458; - } - uint256 a; - } - )"; - CHECK_SUCCESS(sourceCodeFine); - char const* sourceCode = R"( - contract c { - function c () public { - a = 115792089237316195423570985008687907853269984665640564039458 ether; - } - uint256 a; - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type int_const 1157...(70 digits omitted)...0000 is not implicitly convertible to expected type uint256."); -} - -BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) -{ - char const* sourceCode = R"( - contract test { - function f() public returns (uint d) { return 2 ** 10000000000; } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Operator ** not compatible with types int_const 2 and int_const 10000000000"); -} - -BOOST_AUTO_TEST_CASE(exp_warn_literal_base) -{ - char const* sourceCode = R"( - contract test { - function f() pure public returns(uint) { - uint8 x = 100; - return 10**x; - } - } - )"; - CHECK_WARNING(sourceCode, "might overflow"); - sourceCode = R"( - contract test { - function f() pure public returns(uint) { - uint8 x = 100; - return uint8(10)**x; - } - } - )"; - CHECK_SUCCESS(sourceCode); - sourceCode = R"( - contract test { - function f() pure public returns(uint) { - return 2**80; - } - } - )"; - CHECK_SUCCESS(sourceCode); -} - -BOOST_AUTO_TEST_CASE(shift_warn_literal_base) -{ - char const* sourceCode = R"( - contract test { - function f() pure public returns(uint) { - uint8 x = 100; - return 10 << x; - } - } - )"; - CHECK_WARNING(sourceCode, "might overflow"); - sourceCode = R"( - contract test { - function f() pure public returns(uint) { - uint8 x = 100; - return uint8(10) << x; - } - } - )"; - CHECK_SUCCESS(sourceCode); - sourceCode = R"( - contract test { - function f() pure public returns(uint) { - return 2 << 80; - } - } - )"; - CHECK_SUCCESS(sourceCode); - sourceCode = R"( - contract test { - function f() pure public returns(uint) { - uint8 x = 100; - return 10 >> x; - } - } - )"; - CHECK_SUCCESS(sourceCode); -} - -BOOST_AUTO_TEST_CASE(warn_var_from_zero) -{ - char const* sourceCode = R"( - contract test { - function f() pure public returns (uint) { - var i = 1; - return i; - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(sourceCode, (std::vector{ - "uint8, which can hold values between 0 and 255", - "Use of the \"var\" keyword is deprecated." - })); - sourceCode = R"( - contract test { - function f() pure public { - var i = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - i; - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(sourceCode, (std::vector{ - "uint256, which can hold values between 0 and 115792089237316195423570985008687907853269984665640564039457584007913129639935", - "Use of the \"var\" keyword is deprecated." - })); - sourceCode = R"( - contract test { - function f() pure public { - var i = -2; - i; - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(sourceCode, (std::vector{ - "int8, which can hold values between -128 and 127", - "Use of the \"var\" keyword is deprecated." - })); - sourceCode = R"( - contract test { - function f() pure public { - for (var i = 0; i < msg.data.length; i++) { } - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(sourceCode, (std::vector{ - "uint8, which can hold", - "Use of the \"var\" keyword is deprecated." - })); -} - -BOOST_AUTO_TEST_CASE(enum_member_access) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - choices = ActionChoices.GoStraight; - } - ActionChoices choices; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(enum_member_access_accross_contracts) -{ - char const* text = R"( - contract Interface { - enum MyEnum { One, Two } - } - contract Impl { - function test() public returns (Interface.MyEnum) { - return Interface.MyEnum.One; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(enum_invalid_member_access) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() public { - choices = ActionChoices.RunAroundWavingYourHands; - } - ActionChoices choices; - } - )"; - CHECK_ERROR(text, TypeError, "Member \"RunAroundWavingYourHands\" not found or not visible after argument-dependent lookup in type(enum test.ActionChoices)"); -} - -BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() public { - choices = Sit; - } - ActionChoices choices; - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier."); -} - -BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() public { - a = uint256(ActionChoices.GoStraight); - b = uint64(ActionChoices.Sit); - } - uint256 a; - uint64 b; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() public { - a = 2; - b = ActionChoices(a); - } - uint256 a; - ActionChoices b; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_256) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() public { - a = ActionChoices.GoStraight; - } - uint256 a; - } - )"; - CHECK_ERROR(text, TypeError, "Type enum test.ActionChoices is not implicitly convertible to expected type uint256."); -} - -BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_64) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() public { - b = ActionChoices.Sit; - } - uint64 b; - } - )"; - CHECK_ERROR(text, TypeError, "Type enum test.ActionChoices is not implicitly convertible to expected type uint64."); -} - -BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) -{ - char const* text = R"( - contract test { - enum Paper { Up, Down, Left, Right } - enum Ground { North, South, West, East } - function test() public { - Ground(Paper.Up); - } - } - )"; - CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed from \"enum test.Paper\" to \"enum test.Ground\"."); -} - -BOOST_AUTO_TEST_CASE(enum_duplicate_values) -{ - char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared."); -} - -BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name) -{ - char const* text = R"( - contract A { - enum Foo { - First, - Second - } - - function a() public { - A.Foo; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(private_visibility) -{ - char const* sourceCode = R"( - contract base { - function f() private {} - } - contract derived is base { - function g() public { f(); } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); -} - -BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) -{ - char const* sourceCode = R"( - contract base { - function f() private {} - } - contract derived is base { - function g() public { base.f(); } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in type(contract base)"); -} - -BOOST_AUTO_TEST_CASE(external_visibility) -{ - char const* sourceCode = R"( - contract c { - function f() external {} - function g() public { f(); } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); -} - -BOOST_AUTO_TEST_CASE(similar_name_suggestions_expected) -{ - char const* sourceCode = R"( - contract c { - function func() {} - function g() public { fun(); } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier. Did you mean \"func\"?"); -} - -BOOST_AUTO_TEST_CASE(no_name_suggestion) -{ - char const* sourceCode = R"( - contract c { - function g() public { fun(); } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); -} - -BOOST_AUTO_TEST_CASE(multiple_similar_suggestions) -{ - char const* sourceCode = R"( - contract c { - function g() public { - uint var1 = 1; - uint var2 = 1; - uint var3 = 1; - uint var4 = 1; - uint var5 = varx; - } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier. Did you mean \"var1\", \"var2\", \"var3\", \"var4\" or \"var5\"?"); -} - -BOOST_AUTO_TEST_CASE(multiple_scopes_suggestions) -{ - char const* sourceCode = R"( - contract c { - uint log9 = 2; - function g() public { - uint log8 = 3; - uint var1 = lgox; - } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier. Did you mean \"log8\", \"log9\", \"log0\", \"log1\", \"log2\", \"log3\" or \"log4\"?"); -} - -BOOST_AUTO_TEST_CASE(inheritence_suggestions) -{ - char const* sourceCode = R"( - contract a { function func() public {} } - contract c is a { - function g() public { - uint var1 = fun(); - } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier. Did you mean \"func\"?"); -} - -BOOST_AUTO_TEST_CASE(no_spurious_suggestions) -{ - char const* sourceCode = R"( - contract c { - function g() public { - uint va = 1; - uint vb = vaxyz; - } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); - - sourceCode = R"( - contract c { - function g() public { - uint va = 1; - uint vb = x; - } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); -} - -BOOST_AUTO_TEST_CASE(external_base_visibility) -{ - char const* sourceCode = R"( - contract base { - function f() external {} - } - contract derived is base { - function g() public { base.f(); } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in type(contract base)"); -} - -BOOST_AUTO_TEST_CASE(external_argument_assign) -{ - char const* sourceCode = R"( - contract c { - function f(uint a) external { a = 1; } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); -} - -BOOST_AUTO_TEST_CASE(external_argument_increment) -{ - char const* sourceCode = R"( - contract c { - function f(uint a) external { a++; } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); -} - -BOOST_AUTO_TEST_CASE(external_argument_delete) -{ - char const* sourceCode = R"( - contract c { - function f(uint a) external { delete a; } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); -} - -BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) -{ - char const* sourceCode = R"( - contract Vehicle { - function f(bytes) external returns (uint256 r) {r = 1;} - } - contract Bike is Vehicle { - function f(bytes) external returns (uint256 r) {r = 42;} - } - )"; - CHECK_SUCCESS(sourceCode); -} - -BOOST_AUTO_TEST_CASE(array_with_nonconstant_length) -{ - char const* text = R"( - contract c { - function f(uint a) public { uint8[a] x; } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(array_with_negative_length) -{ - char const* text = R"( - contract c { - function f(uint a) public { uint8[-1] x; } - } - )"; - CHECK_ERROR(text, TypeError, "Array with negative length specified"); -} - -BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) -{ - char const* text = R"( - contract c { - bytes a; - uint[] b; - function f() public { b = a; } - } - )"; - CHECK_ERROR(text, TypeError, "Type bytes storage ref is not implicitly convertible to expected type uint256[] storage ref."); -} - -BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) -{ - char const* text = R"( - contract c { - uint32[] a; - uint8[] b; - function f() public { b = a; } - } - )"; - CHECK_ERROR(text, TypeError, "Type uint32[] storage ref is not implicitly convertible to expected type uint8[] storage ref."); -} - -BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) -{ - char const* text = R"( - contract c { - uint32[] a; - uint8[] b; - function f() public { a = b; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic) -{ - char const* text = R"( - contract c { - uint32[] a; - uint8[80] b; - function f() public { a = b; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static) -{ - char const* text = R"( - contract c { - uint[] a; - uint[80] b; - function f() public { b = a; } - } - )"; - CHECK_ERROR(text, TypeError, "Type uint256[] storage ref is not implicitly convertible to expected type uint256[80] storage ref."); -} - -BOOST_AUTO_TEST_CASE(array_of_undeclared_type) -{ - char const* text = R"( - contract c { - a[] public foo; - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found or not unique."); -} - -BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) -{ - char const* text = R"( - contract c { - uint8 a = 1000; - } - )"; - CHECK_ERROR(text, TypeError, "Type int_const 1000 is not implicitly convertible to expected type uint8."); -} - -BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) -{ - char const* text = R"( - contract c { - uint a = "abc"; - } - )"; - CHECK_ERROR(text, TypeError, "Type literal_string \"abc\" is not implicitly convertible to expected type uint256."); -} - -BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName) -{ - - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Int, 0, 0)) == *make_shared(256, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 8, 0)) == *make_shared(8, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 16, 0)) == *make_shared(16, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 24, 0)) == *make_shared(24, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 32, 0)) == *make_shared(32, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 40, 0)) == *make_shared(40, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 48, 0)) == *make_shared(48, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 56, 0)) == *make_shared(56, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 64, 0)) == *make_shared(64, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 72, 0)) == *make_shared(72, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 80, 0)) == *make_shared(80, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 88, 0)) == *make_shared(88, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 96, 0)) == *make_shared(96, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 104, 0)) == *make_shared(104, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 112, 0)) == *make_shared(112, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 120, 0)) == *make_shared(120, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 128, 0)) == *make_shared(128, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 136, 0)) == *make_shared(136, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 144, 0)) == *make_shared(144, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 152, 0)) == *make_shared(152, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 160, 0)) == *make_shared(160, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 168, 0)) == *make_shared(168, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 176, 0)) == *make_shared(176, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 184, 0)) == *make_shared(184, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 192, 0)) == *make_shared(192, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 200, 0)) == *make_shared(200, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 208, 0)) == *make_shared(208, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 216, 0)) == *make_shared(216, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 224, 0)) == *make_shared(224, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 232, 0)) == *make_shared(232, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 240, 0)) == *make_shared(240, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 248, 0)) == *make_shared(248, IntegerType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, 256, 0)) == *make_shared(256, IntegerType::Modifier::Signed)); - - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UInt, 0, 0)) == *make_shared(256, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 8, 0)) == *make_shared(8, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 16, 0)) == *make_shared(16, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 24, 0)) == *make_shared(24, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 32, 0)) == *make_shared(32, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 40, 0)) == *make_shared(40, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 48, 0)) == *make_shared(48, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 56, 0)) == *make_shared(56, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 64, 0)) == *make_shared(64, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 72, 0)) == *make_shared(72, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 80, 0)) == *make_shared(80, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 88, 0)) == *make_shared(88, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 96, 0)) == *make_shared(96, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 104, 0)) == *make_shared(104, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 112, 0)) == *make_shared(112, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 120, 0)) == *make_shared(120, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 128, 0)) == *make_shared(128, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 136, 0)) == *make_shared(136, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 144, 0)) == *make_shared(144, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 152, 0)) == *make_shared(152, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 160, 0)) == *make_shared(160, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 168, 0)) == *make_shared(168, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 176, 0)) == *make_shared(176, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 184, 0)) == *make_shared(184, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 192, 0)) == *make_shared(192, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 200, 0)) == *make_shared(200, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 208, 0)) == *make_shared(208, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 216, 0)) == *make_shared(216, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 224, 0)) == *make_shared(224, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 232, 0)) == *make_shared(232, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 240, 0)) == *make_shared(240, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 248, 0)) == *make_shared(248, IntegerType::Modifier::Unsigned)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, 256, 0)) == *make_shared(256, IntegerType::Modifier::Unsigned)); - - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Byte, 0, 0)) == *make_shared(1)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 1, 0)) == *make_shared(1)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 2, 0)) == *make_shared(2)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 3, 0)) == *make_shared(3)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 4, 0)) == *make_shared(4)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 5, 0)) == *make_shared(5)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 6, 0)) == *make_shared(6)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 7, 0)) == *make_shared(7)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 8, 0)) == *make_shared(8)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 9, 0)) == *make_shared(9)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 10, 0)) == *make_shared(10)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 11, 0)) == *make_shared(11)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 12, 0)) == *make_shared(12)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 13, 0)) == *make_shared(13)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 14, 0)) == *make_shared(14)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 15, 0)) == *make_shared(15)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 16, 0)) == *make_shared(16)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 17, 0)) == *make_shared(17)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 18, 0)) == *make_shared(18)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 19, 0)) == *make_shared(19)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 20, 0)) == *make_shared(20)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 21, 0)) == *make_shared(21)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 22, 0)) == *make_shared(22)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 23, 0)) == *make_shared(23)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 24, 0)) == *make_shared(24)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 25, 0)) == *make_shared(25)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 26, 0)) == *make_shared(26)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 27, 0)) == *make_shared(27)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 28, 0)) == *make_shared(28)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 29, 0)) == *make_shared(29)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 30, 0)) == *make_shared(30)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 31, 0)) == *make_shared(31)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 32, 0)) == *make_shared(32)); - - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Fixed, 0, 0)) == *make_shared(128, 18, FixedPointType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UFixed, 0, 0)) == *make_shared(128, 18, FixedPointType::Modifier::Unsigned)); -} - -BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1) -{ - char const* text = R"( - contract c { - bytes arr; - function f() public { byte a = arr[0];} - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(warns_assigning_decimal_to_bytesxx) -{ - char const* text = R"( - contract Foo { - bytes32 a = 7; - } - )"; - CHECK_WARNING(text, "Decimal literal assigned to bytesXX variable will be left-aligned."); -} - -BOOST_AUTO_TEST_CASE(does_not_warn_assigning_hex_number_to_bytesxx) -{ - char const* text = R"( - contract Foo { - bytes32 a = 0x1234; - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(explicit_conversion_from_decimal_to_bytesxx) -{ - char const* text = R"( - contract Foo { - bytes32 a = bytes32(7); - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) -{ - char const* text = R"( - contract Foo { - function changeIt() public { x = 9; } - uint constant x = 56; - } - )"; - CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); -} - -BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable_0_4_x) -{ - char const* text = R"( - contract C { - address constant x = msg.sender; - } - )"; - CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); -} - -BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - - contract C { - address constant x = msg.sender; - } - )"; - CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant."); -} - -BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment) -{ - char const* text = R"( - contract Test { - string constant x = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; - function f() public { - x[0] = "f"; - } - } - )"; - - // Even if this is made possible in the future, we should not allow assignment - // to elements of constant arrays. - CHECK_ERROR(text, TypeError, "Index access for string is not possible."); -} - -BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion) -{ - char const* text = R"( - contract C { - C constant x = C(0x123); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_expression) -{ - char const* text = R"( - contract C { - uint constant x = 0x123 + 0x456; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) -{ - char const* text = R"( - contract C { - bytes32 constant x = keccak256("abc"); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars) -{ - char const* text = R"( - contract C { - uint[3] constant x = [uint(1), 2, 3]; - } - )"; - CHECK_ERROR(text, TypeError, "implemented"); -} - -BOOST_AUTO_TEST_CASE(assignment_to_const_string_bytes) -{ - char const* text = R"( - contract C { - bytes constant a = "\x00\x01\x02"; - bytes constant b = hex"000102"; - string constant c = "hello"; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(constant_struct) -{ - char const* text = R"( - contract C { - struct S { uint x; uint[] y; } - S constant x = S(5, new uint[](4)); - } - )"; - CHECK_ERROR(text, TypeError, "implemented"); -} - -BOOST_AUTO_TEST_CASE(address_is_constant) -{ - char const* text = R"( - contract C { - address constant x = 0x1212121212121212121212121212121212121212; - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(uninitialized_const_variable) -{ - char const* text = R"( - contract Foo { - uint constant y; - } - )"; - CHECK_ERROR(text, TypeError, "Uninitialized \"constant\" variable."); -} - -BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) -{ - char const* sourceCode = R"( - contract test { - function f() public returns (uint) { return 1; } - function f(uint a) public returns (uint) { return a; } - function g() public returns (uint) { return f(3, 5); } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "No matching declaration found after argument-dependent lookup."); -} - -BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) -{ - // literal 1 can be both converted to uint and uint8, so the call is ambiguous. - char const* sourceCode = R"( - contract test { - function f(uint8 a) public returns (uint) { return a; } - function f(uint a) public returns (uint) { return 2*a; } - function g() public returns (uint) { return f(1); } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "No unique declaration found after argument-dependent lookup."); -} - -BOOST_AUTO_TEST_CASE(assignment_of_nonoverloaded_function) -{ - char const* sourceCode = R"( - contract test { - function f(uint a) public returns (uint) { return 2 * a; } - function g() public returns (uint) { var x = f; return x(7); } - } - )"; - CHECK_SUCCESS(sourceCode); -} - -BOOST_AUTO_TEST_CASE(assignment_of_overloaded_function) -{ - char const* sourceCode = R"( - contract test { - function f() public returns (uint) { return 1; } - function f(uint a) public returns (uint) { return 2 * a; } - function g() public returns (uint) { var x = f; return x(7); } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "No matching declaration found after variable lookup."); -} - -BOOST_AUTO_TEST_CASE(external_types_clash) -{ - char const* sourceCode = R"( - contract base { - enum a { X } - function f(a) public { } - } - contract test is base { - function f(uint8 a) public { } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Function overload clash during conversion to external types for arguments."); -} - -BOOST_AUTO_TEST_CASE(override_changes_return_types) -{ - char const* sourceCode = R"( - contract base { - function f(uint a) public returns (uint) { } - } - contract test is base { - function f(uint a) public returns (uint8) { } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Overriding function return types differ"); -} - -BOOST_AUTO_TEST_CASE(equal_overload) -{ - char const* sourceCode = R"( - contract C { - function test(uint a) public returns (uint b) { } - function test(uint a) external {} - } - )"; - CHECK_ALLOW_MULTI(sourceCode, (vector>{ - {Error::Type::DeclarationError, "Function with same name and arguments defined twice."}, - {Error::Type::TypeError, "Overriding function visibility differs"} - })); -} - -BOOST_AUTO_TEST_CASE(uninitialized_var) -{ - char const* sourceCode = R"( - contract C { - function f() public returns (uint) { var x; return 2; } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Assignment necessary for type detection."); -} - BOOST_AUTO_TEST_CASE(string) { char const* sourceCode = R"( contract C { string s; - function f(string x) external { s = x; } + function f(string calldata x) external { s = x; } } )"; BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); } -BOOST_AUTO_TEST_CASE(invalid_utf8_implicit) -{ - char const* sourceCode = R"( - contract C { - string s = "\xa0\x00"; - } - )"; - CHECK_ERROR(sourceCode, TypeError, "invalid UTF-8"); -} - -BOOST_AUTO_TEST_CASE(invalid_utf8_explicit) -{ - char const* sourceCode = R"( - contract C { - string s = string("\xa0\x00"); - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Explicit type conversion not allowed"); -} - -BOOST_AUTO_TEST_CASE(large_utf8_codepoint) -{ - char const* sourceCode = R"( - contract C { - string s = "\xf0\x9f\xa6\x84"; - } - )"; - CHECK_SUCCESS(sourceCode); -} - -BOOST_AUTO_TEST_CASE(string_index) -{ - char const* sourceCode = R"( - contract C { - string s; - function f() public { var a = s[2]; } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Index access for string is not possible."); -} - -BOOST_AUTO_TEST_CASE(string_length) -{ - char const* sourceCode = R"( - contract C { - string s; - function f() public { var a = s.length; } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Member \"length\" not found or not visible after argument-dependent lookup in string storage ref"); -} - -BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) -{ - char const* sourceCode = R"( - contract test { - int8 public i = -129; - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type int_const -129 is not implicitly convertible to expected type int8."); -} - -BOOST_AUTO_TEST_CASE(negative_integers_to_signed_min) -{ - char const* sourceCode = R"( - contract test { - int8 public i = -128; - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound) -{ - char const* sourceCode = R"( - contract test { - int8 public j = 128; - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type int_const 128 is not implicitly convertible to expected type int8."); -} - -BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound_max) -{ - char const* sourceCode = R"( - contract test { - int8 public j = 127; - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(negative_integers_to_unsigned) -{ - char const* sourceCode = R"( - contract test { - uint8 public x = -1; - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type int_const -1 is not implicitly convertible to expected type uint8."); -} - -BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) -{ - char const* sourceCode = R"( - contract test { - uint8 public x = 700; - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type int_const 700 is not implicitly convertible to expected type uint8."); -} - -BOOST_AUTO_TEST_CASE(integer_boolean_operators) -{ - char const* sourceCode1 = R"( - contract test { function() public { uint x = 1; uint y = 2; x || y; } } - )"; - CHECK_ERROR(sourceCode1, TypeError, "Operator || not compatible with types uint256 and uint256"); - char const* sourceCode2 = R"( - contract test { function() public { uint x = 1; uint y = 2; x && y; } } - )"; - CHECK_ERROR(sourceCode2, TypeError, "Operator && not compatible with types uint256 and uint256"); - char const* sourceCode3 = R"( - contract test { function() public { uint x = 1; !x; } } - )"; - CHECK_ERROR(sourceCode3, TypeError, "Unary operator ! cannot be applied to type uint256"); -} - -BOOST_AUTO_TEST_CASE(exp_signed_variable) -{ - char const* sourceCode1 = R"( - contract test { function() public { uint x = 3; int y = -4; x ** y; } } - )"; - CHECK_ERROR(sourceCode1, TypeError, "Operator ** not compatible with types uint256 and int256"); - char const* sourceCode2 = R"( - contract test { function() public { uint x = 3; int y = -4; y ** x; } } - )"; - CHECK_ERROR(sourceCode2, TypeError, "Operator ** not compatible with types int256 and uint256"); - char const* sourceCode3 = R"( - contract test { function() public { int x = -3; int y = -4; x ** y; } } - )"; - CHECK_ERROR(sourceCode3, TypeError, "Operator ** not compatible with types int256 and int256"); -} - -BOOST_AUTO_TEST_CASE(reference_compare_operators) -{ - char const* sourceCode1 = R"( - contract test { bytes a; bytes b; function() public { a == b; } } - )"; - CHECK_ERROR(sourceCode1, TypeError, "Operator == not compatible with types bytes storage ref and bytes storage ref"); - char const* sourceCode2 = R"( - contract test { struct s {uint a;} s x; s y; function() public { x == y; } } - )"; - CHECK_ERROR(sourceCode2, TypeError, "Operator == not compatible with types struct test.s storage ref and struct test.s storage ref"); -} - -BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) -{ - char const* sourceCode = R"( - contract C { - function f(uint[] memory a) external {} - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Location has to be calldata for external functions (remove the \"memory\" or \"storage\" keyword)."); -} - -BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) -{ - char const* sourceCode = R"( - contract C { - function f(uint[] storage a) external {} - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Location has to be calldata for external functions (remove the \"memory\" or \"storage\" keyword)."); -} - -BOOST_AUTO_TEST_CASE(storage_location_local_variables) -{ - char const* sourceCode = R"( - contract C { - function f() public { - uint[] storage x; - uint[] memory y; - uint[] memory z; - x;y;z; - } - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(no_mappings_in_memory_array) -{ - char const* sourceCode = R"( - contract C { - function f() public { - mapping(uint=>uint)[] memory x; - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type mapping(uint256 => uint256)[] memory is only valid in storage."); -} - -BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) -{ - char const* sourceCode = R"( - contract C { - uint[] data; - function f(uint[] x) public { - var dataRef = data; - dataRef = x; - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type uint256[] memory is not implicitly convertible to expected type uint256[] storage pointer."); -} - -BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) -{ - char const* sourceCode = R"( - contract C { - uint[] data; - uint8[] otherData; - function f() public { - uint8[] storage x = otherData; - uint[] storage y = data; - y = x; - // note that data = otherData works - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type uint8[] storage pointer is not implicitly convertible to expected type uint256[] storage pointer."); -} - -BOOST_AUTO_TEST_CASE(uninitialized_mapping_variable) -{ - char const* sourceCode = R"( - contract C { - function f() public { - mapping(uint => uint) x; - x; - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Uninitialized mapping. Mappings cannot be created dynamically, you have to assign them from a state variable"); -} - -BOOST_AUTO_TEST_CASE(uninitialized_mapping_array_variable) -{ - char const* sourceCode = R"( - contract C { - function f() pure public { - mapping(uint => uint)[] storage x; - x; - } - } - )"; - CHECK_WARNING(sourceCode, "Uninitialized storage pointer"); -} - -BOOST_AUTO_TEST_CASE(uninitialized_mapping_array_variable_050) -{ - char const* sourceCode = R"( - pragma experimental "v0.5.0"; - contract C { - function f() pure public { - mapping(uint => uint)[] storage x; - x; - } - } - )"; - CHECK_ERROR(sourceCode, DeclarationError, "Uninitialized storage pointer"); -} - -BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) -{ - char const* sourceCode = R"( - contract C { - uint[] data; - function f() public { - var x = data; - delete x; - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Unary operator delete cannot be applied to type uint256[] storage pointer"); -} - -BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly) -{ - char const* sourceCode = R"( - contract C { - uint[] data; - function f(uint[] x) public { - data = x; - } - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(function_argument_mem_to_storage) -{ - char const* sourceCode = R"( - contract C { - function f(uint[] storage x) private { - } - function g(uint[] x) public { - f(x); - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Invalid type for argument in function call. Invalid implicit conversion from uint256[] memory to uint256[] storage pointer requested."); -} - -BOOST_AUTO_TEST_CASE(function_argument_storage_to_mem) -{ - char const* sourceCode = R"( - contract C { - function f(uint[] storage x) private { - g(x); - } - function g(uint[] x) public { - } - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type) -{ - // Such an assignment is possible in storage, but not in memory - // (because it would incur an otherwise unnecessary copy). - // This requirement might be lifted, though. - char const* sourceCode = R"( - contract C { - function f(uint8[] memory x) private { - uint[] memory y = x; - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Type uint8[] memory is not implicitly convertible to expected type uint256[] memory."); -} - BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) { char const* sourceCode = R"( contract C { - function f(uint) public returns (string); + function f(uint) public returns (string memory); function g() public { - var x = this.f(2); + string memory x = this.f(2); // we can assign to x but it is not usable. bytes(x).length; } } )"; if (dev::test::Options::get().evmVersion() == EVMVersion::homestead()) - CHECK_ERROR(sourceCode, TypeError, "Explicit type conversion not allowed from \"inaccessible dynamic type\" to \"bytes storage pointer\"."); + CHECK_ERROR(sourceCode, TypeError, "Type inaccessible dynamic type is not implicitly convertible to expected type string memory."); else - CHECK_WARNING(sourceCode, "Use of the \"var\" keyword is deprecated"); -} - -BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) -{ - char const* sourceCode = R"( - contract C { - function f() public { - uint[] memory x; - x.length = 2; - } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); -} - -BOOST_AUTO_TEST_CASE(struct_constructor) -{ - char const* sourceCode = R"( - contract C { - struct S { uint a; bool x; } - function f() public { - S memory s = S(1, true); - } - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(struct_constructor_nested) -{ - char const* sourceCode = R"( - contract C { - struct X { uint x1; uint x2; } - struct S { uint s1; uint[3] s2; X s3; } - function f() public { - uint[3] memory s2; - S memory s = S(1, s2, X(4, 5)); - } - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(struct_named_constructor) -{ - char const* sourceCode = R"( - contract C { - struct S { uint a; bool x; } - function f() public { - S memory s = S({a: 1, x: true}); - } - } - )"; - BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(literal_strings) -{ - char const* text = R"( - contract Foo { - function f() public { - string memory long = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; - string memory short = "123"; - long; short; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(string_bytes_conversion) -{ - char const* text = R"( - contract Test { - string s; - bytes b; - function h(string _s) external { bytes(_s).length; } - function i(string _s) internal { bytes(_s).length; } - function j() internal { bytes(s).length; } - function k(bytes _b) external { string(_b); } - function l(bytes _b) internal { string(_b); } - function m() internal { string(b); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inheriting_from_library) -{ - char const* text = R"( - library Lib {} - contract Test is Lib {} - )"; - CHECK_ERROR(text, TypeError, "Libraries cannot be inherited from."); -} - -BOOST_AUTO_TEST_CASE(inheriting_library) -{ - char const* text = R"( - contract Test {} - library Lib is Test {} - )"; - CHECK_ERROR(text, TypeError, "Library is not allowed to inherit."); -} - -BOOST_AUTO_TEST_CASE(library_having_variables) -{ - char const* text = R"( - library Lib { uint x; } - )"; - CHECK_ERROR(text, TypeError, "Library cannot have non-constant state variables"); -} - -BOOST_AUTO_TEST_CASE(valid_library) -{ - char const* text = R"( - library Lib { uint constant x = 9; } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(call_to_library_function) -{ - char const* text = R"( - library Lib { - function min(uint, uint) public returns (uint); - } - contract Test { - function f() public { - uint t = Lib.min(12, 7); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract) -{ - char const* sourceCode = R"( - contract Test { - function f() public { var x = new Test(); } - } - )"; - CHECK_ERROR(sourceCode, TypeError, "Circular reference for contract creation (cannot create instance of derived or same contract)."); -} - -BOOST_AUTO_TEST_CASE(array_out_of_bound_access) -{ - char const* text = R"( - contract c { - uint[2] dataArray; - function set5th() public returns (bool) { - dataArray[5] = 2; - return true; - } - } - )"; - CHECK_ERROR(text, TypeError, "Out of bounds array access."); -} - -BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) -{ - char const* text = R"( - contract C { - function f() public { string x = "abc"; } - } - )"; - CHECK_ERROR(text, TypeError, "Type literal_string \"abc\" is not implicitly convertible to expected type string storage pointer."); -} - -BOOST_AUTO_TEST_CASE(non_initialized_references) -{ - char const* text = R"( - contract c - { - struct s { - uint a; - } - function f() public { - s storage x; - x.a = 2; - } - } - )"; - - CHECK_WARNING(text, "Uninitialized storage pointer"); -} - -BOOST_AUTO_TEST_CASE(non_initialized_references_050) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract c - { - struct s { - uint a; - } - function f() public { - s storage x; - } - } - )"; - - CHECK_ERROR(text, DeclarationError, "Uninitialized storage pointer"); -} - -BOOST_AUTO_TEST_CASE(keccak256_with_large_integer_constant) -{ - char const* text = R"( - contract c - { - function f() public { keccak256(2**500); } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid rational number (too large or division by zero)."); -} - -BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) -{ - char const* text = R"( - contract A { function f() public { new B(); } } - contract B { function f() public { new C(); } } - contract C { function f() public { new A(); } } - )"; - CHECK_ERROR(text, TypeError, "Circular reference for contract creation (cannot create instance of derived or same contract)."); -} - -BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance) -{ - char const* text = R"( - contract A is B { } - contract B { function f() public { new C(); } } - contract C { function f() public { new A(); } } - )"; - CHECK_ERROR(text, TypeError, "Definition of base has to precede definition of derived contract"); -} - -BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail) -{ - char const* text = R"( - contract C { function f() public { var (x,y); x = 1; y = 1;} } - )"; - CHECK_ERROR(text, TypeError, "Assignment necessary for type detection."); -} - -BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine) -{ - char const* text = R"( - contract C { - function three() public returns (uint, uint, uint); - function two() public returns (uint, uint); - function none(); - function f() public { - var (a,) = three(); - var (b,c,) = two(); - var (,d) = three(); - var (,e,g) = two(); - var (,,) = three(); - var () = none(); - a;b;c;d;e;g; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1) -{ - char const* text = R"( - contract C { - function one() public returns (uint); - function f() public { var (a, b, ) = one(); } - } - )"; - CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); -} -BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) -{ - char const* text = R"( - contract C { - function one() public returns (uint); - function f() public { var (a, , ) = one(); } - } - )"; - CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); -} - -BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) -{ - char const* text = R"( - contract C { - function one() public returns (uint); - function f() public { var (, , a) = one(); } - } - )"; - CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); -} - -BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) -{ - char const* text = R"( - contract C { - function one() public returns (uint); - function f() public { var (, a, b) = one(); } - } - )"; - CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); -} - -BOOST_AUTO_TEST_CASE(tuples) -{ - char const* text = R"( - contract C { - function f() public { - uint a = (1); - var (b,) = (uint8(1),); - var (c,d) = (uint32(1), 2 + a); - var (e,) = (uint64(1), 2, b); - a;b;c;d;e; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(tuples_empty_components) -{ - char const* text = R"( - contract C { - function f() public { - (1,,2); - } - } - )"; - CHECK_ERROR(text, TypeError, "Tuple component cannot be empty."); -} - -BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) -{ - char const* text = R"( - contract C { - function one() public returns (uint); - function f() public { var (,) = one(); } - } - )"; - CHECK_ERROR(text, TypeError, "Wildcard both at beginning and end of variable declaration list is only allowed if the number of components is equal."); -} - -BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) -{ - char const* text = R"( - contract C { - function two() public returns (uint, uint); - function f() public { var (a, b, c) = two(); } - } - )"; - CHECK_ERROR(text, TypeError, "Not enough components (2) in value to assign all variables (3)"); -} - -BOOST_AUTO_TEST_CASE(tuple_assignment_from_void_function) -{ - char const* text = R"( - contract C { - function f() public { } - function g() public { - var (x,) = (f(), f()); - } - } - )"; - CHECK_ERROR(text, TypeError, "Cannot declare variable with void (empty tuple) type."); -} - -BOOST_AUTO_TEST_CASE(tuple_compound_assignment) -{ - char const* text = R"( - contract C { - function f() public returns (uint a, uint b) { - (a, b) += (1, 1); - } - } - )"; - CHECK_ERROR(text, TypeError, "Compound assignment is not allowed for tuple types."); -} - -BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) -{ - char const* text = R"( - contract C { - struct R { uint[10][10] y; } - struct S { uint a; uint b; uint[20][20][20] c; R d; } - S data; - function f() public { - C.S x = data; - C.S memory y; - C.S[10] memory z; - C.S[10]; - y.a = 2; - x.c[1][2][3] = 9; - x.d.y[2][2] = 3; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_library) -{ - char const* text = R"( - library D { } - contract C { - using D for uint; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_not_library) -{ - char const* text = R"( - contract D { } - contract C { - using D for uint; - } - )"; - CHECK_ERROR(text, TypeError, "Library name expected."); -} - -BOOST_AUTO_TEST_CASE(using_for_function_exists) -{ - char const* text = R"( - library D { function double(uint self) public returns (uint) { return 2*self; } } - contract C { - using D for uint; - function f(uint a) public { - a.double; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_function_on_int) -{ - char const* text = R"( - library D { function double(uint self) public returns (uint) { return 2*self; } } - contract C { - using D for uint; - function f(uint a) public returns (uint) { - return a.double(); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_function_on_struct) -{ - char const* text = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } - contract C { - using D for D.s; - D.s x; - function f(uint a) public returns (uint) { - return x.mul(a); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_overload) -{ - char const* text = R"( - library D { - struct s { uint a; } - function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } - function mul(s storage, bytes32) public returns (bytes32) { } - } - contract C { - using D for D.s; - D.s x; - function f(uint a) public returns (uint) { - return x.mul(a); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_by_name) -{ - char const* text = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } - contract C { - using D for D.s; - D.s x; - function f(uint a) public returns (uint) { - return x.mul({x: a}); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_mismatch) -{ - char const* text = R"( - library D { function double(bytes32 self) public returns (uint) { return 2; } } - contract C { - using D for uint; - function f(uint a) public returns (uint) { - return a.double(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"double\" not found or not visible after argument-dependent lookup in uint256"); -} - -BOOST_AUTO_TEST_CASE(using_for_not_used) -{ - // This is an error because the function is only bound to uint. - // Had it been bound to *, it would have worked. - char const* text = R"( - library D { function double(uint self) public returns (uint) { return 2; } } - contract C { - using D for uint; - function f(uint16 a) public returns (uint) { - return a.double(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"double\" not found or not visible after argument-dependent lookup in uint16"); -} - -BOOST_AUTO_TEST_CASE(library_memory_struct) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - library c { - struct S { uint x; } - function f() public returns (S ) {} - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) -{ - // Bound to a, but self type does not match. - char const* text = R"( - library D { function double(bytes32 self) public returns (uint) { return 2; } } - contract C { - using D for *; - function f(uint a) public returns (uint) { - return a.double(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"double\" not found or not visible after argument-dependent lookup in uint256"); -} - -BOOST_AUTO_TEST_CASE(bound_function_in_var) -{ - char const* text = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } - contract C { - using D for D.s; - D.s x; - function f(uint a) public returns (uint) { - var g = x.mul; - return g({x: a}); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(create_memory_arrays) -{ - char const* text = R"( - library L { - struct R { uint[10][10] y; } - struct S { uint a; uint b; uint[20][20][20] c; R d; } - } - contract C { - function f(uint size) public { - L.S[][] memory x = new L.S[][](10); - var y = new uint[](20); - var z = new bytes(size); - x;y;z; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(mapping_in_memory_array) -{ - char const* text = R"( - contract C { - function f(uint size) public { - var x = new mapping(uint => uint)[](4); - } - } - )"; - CHECK_ERROR(text, TypeError, "Type cannot live outside storage."); -} - -BOOST_AUTO_TEST_CASE(new_for_non_array) -{ - char const* text = R"( - contract C { - function f(uint size) public { - var x = new uint(7); - } - } - )"; - CHECK_ERROR(text, TypeError, "Contract or array type expected."); -} - -BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) -{ - char const* text = R"( - contract C { - function f(uint size) public { - var x = new uint[](); - } - } - )"; - CHECK_ERROR(text, TypeError, "Wrong argument count for function call: 0 arguments given but expected 1."); -} - -BOOST_AUTO_TEST_CASE(invalid_args_creating_struct) -{ - char const* text = R"( - contract C { - struct S { uint a; uint b; } - - function f() public { - var s = S({a: 1}); - } - } - )"; - CHECK_ERROR(text, TypeError, "Wrong argument count for struct constructor: 1 arguments given but expected 2."); -} - -BOOST_AUTO_TEST_CASE(function_overload_array_type) -{ - char const* text = R"( - contract M { - function f(uint[]); - function f(int[]); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion) -{ - char const* text = R"( - contract C { - function f() public returns (uint) { - uint8 x = 7; - uint16 y = 8; - uint32 z = 9; - uint32[3] memory ending = [x, y, z]; - return (ending[1]); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion_strings) -{ - char const* text = R"( - contract C { - function f() public returns (string) { - string memory x = "Hello"; - string memory y = "World"; - string[2] memory z = [x, y]; - return (z[0]); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_declaration_const_int_conversion) -{ - char const* text = R"( - contract C { - function f() public returns (uint) { - uint8[4] memory z = [1,2,3,5]; - return (z[0]); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_declaration_const_string_conversion) -{ - char const* text = R"( - contract C { - function f() public returns (string) { - string[2] memory z = ["Hello", "World"]; - return (z[0]); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type) -{ - char const* text = R"( - contract C { - function f() public returns (uint) { - return ([4,5,6][1]); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type_strings) -{ - char const* text = R"( - contract C { - function f() public returns (string) { - return (["foo", "man", "choo"][1]); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_struct_declaration_arrays) -{ - char const* text = R"( - contract C { - struct S { - uint a; - string b; - } - function f() { - S[2] memory x = [S({a: 1, b: "fish"}), S({a: 2, b: "fish"})]; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) -{ - char const* text = R"( - contract C { - function f() public { - uint[3] x = [45, 'foo', true]; - } - } - )"; - CHECK_ERROR(text, TypeError, "Unable to deduce common type for array elements."); -} - -BOOST_AUTO_TEST_CASE(dynamic_inline_array) -{ - char const* text = R"( - contract C { - function f() public { - uint8[4][4] memory dyn = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) -{ - char const* text = R"( - contract C { - function f() public { - [1, 2, 3]++; - [1, 2, 3] = [4, 5, 6]; - } - } - )"; - CHECK_ERROR(text, TypeError, "Inline array type cannot be declared as LValue."); -} - -BOOST_AUTO_TEST_CASE(break_not_in_loop) -{ - char const* text = R"( - contract C { - function f() public { - if (true) - break; - } - } - )"; - CHECK_ERROR(text, SyntaxError, "\"break\" has to be in a \"for\" or \"while\" loop."); -} - -BOOST_AUTO_TEST_CASE(continue_not_in_loop) -{ - char const* text = R"( - contract C { - function f() public { - if (true) - continue; - } - } - )"; - CHECK_ERROR(text, SyntaxError, "\"continue\" has to be in a \"for\" or \"while\" loop."); -} - -BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) -{ - char const* text = R"( - contract C { - function f() public { - while (true) - { - } - continue; - } - } - )"; - CHECK_ERROR(text, SyntaxError, "\"continue\" has to be in a \"for\" or \"while\" loop."); -} - -BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) -{ - char const* text = R"( - contract C { - function f() public { - true ? true : 2; - } - } - )"; - CHECK_ERROR(text, TypeError, "True expression's type bool doesn't match false expression's type uint8."); -} - -BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) -{ - char const* text = R"( - contract C { - function f() public { - uint x; - uint y; - (true ? x : y) = 1; - } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector{ - "Conditional expression as left value is not supported yet.", - "Expression has to be an lvalue" - })); -} - -BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) -{ - char const* text = R"( - contract C { - struct s1 { - uint x; - } - struct s2 { - uint x; - } - function f() public { - s1 memory x; - s2 memory y; - true ? x : y; - } - } - )"; - CHECK_ERROR(text, TypeError, "True expression's type struct C.s1 memory doesn't match false expression's type struct C.s2 memory."); -} - -BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) -{ - char const* text = R"( - contract C { - function x(bool) public {} - function y() public {} - - function f() public { - true ? x : y; - } - } - )"; - CHECK_ERROR(text, TypeError, "True expression's type function (bool) doesn't match false expression's type function ()."); -} - -BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) -{ - char const* text = R"( - contract C { - enum small { A, B, C, D } - enum big { A, B, C, D } - - function f() public { - small x; - big y; - - true ? x : y; - } - } - )"; - CHECK_ERROR(text, TypeError, "True expression's type enum C.small doesn't match false expression's type enum C.big."); -} - -BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) -{ - char const* text = R"( - contract C { - mapping(uint8 => uint8) table1; - mapping(uint32 => uint8) table2; - - function f() public { - true ? table1 : table2; - } - } - )"; - CHECK_ERROR(text, TypeError, "True expression's type mapping(uint8 => uint8) doesn't match false expression's type mapping(uint32 => uint8)."); -} - -BOOST_AUTO_TEST_CASE(conditional_with_all_types) -{ - char const* text = R"( - contract C { - struct s1 { - uint x; - } - s1 struct_x; - s1 struct_y; - - function fun_x() public {} - function fun_y() public {} - - enum small { A, B, C, D } - - mapping(uint8 => uint8) table1; - mapping(uint8 => uint8) table2; - - function f() public { - // integers - uint x; - uint y; - uint g = true ? x : y; - g += 1; // Avoid unused var warning - - // integer constants - uint h = true ? 1 : 3; - h += 1; // Avoid unused var warning - - // string literal - var i = true ? "hello" : "world"; - i = "used"; //Avoid unused var warning - } - function f2() public { - // bool - bool j = true ? true : false; - j = j && true; // Avoid unused var warning - - // real is not there yet. - - // array - byte[2] memory a; - byte[2] memory b; - var k = true ? a : b; - k[0] = byte(0); //Avoid unused var warning - - bytes memory e; - bytes memory f; - var l = true ? e : f; - l[0] = byte(0); // Avoid unused var warning - - // fixed bytes - bytes2 c; - bytes2 d; - var m = true ? c : d; - m &= m; - - } - function f3() public { - // contract doesn't fit in here - - // struct - struct_x = true ? struct_x : struct_y; - - // function - var r = true ? fun_x : fun_y; - r(); // Avoid unused var warning - // enum - small enum_x; - small enum_y; - enum_x = true ? enum_x : enum_y; - - // tuple - var (n, o) = true ? (1, 2) : (3, 4); - (n, o) = (o, n); // Avoid unused var warning - // mapping - var p = true ? table1 : table2; - p[0] = 0; // Avoid unused var warning - // typetype - var q = true ? uint32(1) : uint32(2); - q += 1; // Avoid unused var warning - // modifier doesn't fit in here - - // magic doesn't fit in here - - // module doesn't fit in here - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(index_access_for_bytes) -{ - char const* text = R"( - contract C { - bytes20 x; - function f(bytes16 b) public { - b[uint(x[2])]; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier) -{ - char const* text = R"( - contract test { - string uintM = "Hello 4 you"; - function f() public { - uint8 uint7 = 3; - uint7 = 5; - string memory intM; - uint bytesM = 21; - intM; bytesM; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(varM_disqualified_as_keyword) -{ - char const* text = R"( - contract test { - function f() public { - uintM something = 3; - intM should = 4; - bytesM fail = "now"; - } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, (std::vector{ - "Identifier not found or not unique.", - "Identifier not found or not unique.", - "Identifier not found or not unique." - })); -} - -BOOST_AUTO_TEST_CASE(modifier_is_not_a_valid_typename) -{ - char const* text = R"( - contract test { - modifier mod() { _; } - - function f() public { - mod g; - } - } - )"; - CHECK_ERROR(text, TypeError, "Name has to refer to a struct, enum or contract."); -} - -BOOST_AUTO_TEST_CASE(modifier_is_not_a_valid_typename_is_not_fatal) -{ - char const* text = R"( - contract test { - modifier mod() { _; } - - function f() public { - mod g; - g = f; - } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector{"Name has to refer to a struct, enum or contract."})); -} - -BOOST_AUTO_TEST_CASE(function_is_not_a_valid_typename) -{ - char const* text = R"( - contract test { - function foo() public { - } - - function f() public { - foo g; - } - } - )"; - CHECK_ERROR(text, TypeError, "Name has to refer to a struct, enum or contract."); -} - -BOOST_AUTO_TEST_CASE(long_uint_variable_fails) -{ - char const* text = R"( - contract test { - function f() public { - uint99999999999999999999999999 something = 3; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found or not unique."); -} - -BOOST_AUTO_TEST_CASE(bytes10abc_is_identifier) -{ - char const* text = R"( - contract test { - function f() public { - bytes32 bytes10abc = "abc"; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(int10abc_is_identifier) -{ - char const* text = R"( - contract test { - function f() public { - uint uint10abc = 3; - int int10abc = 4; - uint10abc; int10abc; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(library_functions_do_not_have_value) -{ - char const* text = R"( - library L { function l() public {} } - contract test { - function f() public { - L.l.value; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function ()"); -} - -BOOST_AUTO_TEST_CASE(invalid_fixed_types_0x7_mxn) -{ - char const* text = R"( - contract test { - fixed0x7 a = .3; - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found"); -} - -BOOST_AUTO_TEST_CASE(invalid_fixed_types_long_invalid_identifier) -{ - char const* text = R"( - contract test { - fixed99999999999999999999999999999999999999x7 b = 9.5; - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found"); -} - -BOOST_AUTO_TEST_CASE(invalid_fixed_types_7x8_mxn) -{ - char const* text = R"( - contract test { - fixed7x8 c = 3.12345678; - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found"); -} - -BOOST_AUTO_TEST_CASE(library_instances_cannot_be_used) -{ - char const* text = R"( - library L { function l() public {} } - contract test { - function f() public { - L x; - x.l(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"l\" not found or not visible after argument-dependent lookup in library L"); -} - -BOOST_AUTO_TEST_CASE(invalid_fixed_type_long) -{ - char const* text = R"( - contract test { - function f() public { - fixed8x888888888888888888888888888888888888888888888888888 b; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found"); -} - -BOOST_AUTO_TEST_CASE(fixed_type_int_conversion) -{ - char const* text = R"( - contract test { - function f() public { - uint64 a = 3; - int64 b = 4; - fixed c = b; - ufixed d = a; - c; d; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(fixed_type_rational_int_conversion) -{ - char const* text = R"( - contract test { - function f() public { - fixed c = 3; - ufixed d = 4; - c; d; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(fixed_type_rational_fraction_conversion) -{ - char const* text = R"( - contract test { - function f() public { - fixed a = 4.5; - ufixed d = 2.5; - a; d; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(invalid_int_implicit_conversion_from_fixed) -{ - char const* text = R"( - contract test { - function f() public { - fixed a = 4.5; - int b = a; - a; b; - } - } - )"; - CHECK_ERROR(text, TypeError, "Type fixed128x18 is not implicitly convertible to expected type int256"); -} - -BOOST_AUTO_TEST_CASE(rational_unary_operation) -{ - char const* text = R"( - contract test { - function f() pure public { - ufixed16x2 a = 3.25; - fixed16x2 b = -3.25; - a; b; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - - // Test deprecation warning under < 0.5.0 - text = R"( - contract test { - function f() pure public { - ufixed16x2 a = +3.25; - fixed16x2 b = -3.25; - a; b; - } - } - )"; - CHECK_WARNING(text, "Use of unary + is deprecated"); - text = R"( - contract test { - function f(uint x) pure public { - uint y = +x; - y; - } - } - )"; - CHECK_WARNING(text,"Use of unary + is deprecated"); - - // Test syntax error under 0.5.0 - text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - ufixed16x2 a = +3.25; - fixed16x2 b = -3.25; - a; b; - } - } - )"; - CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated"); - text = R"( - pragma experimental "v0.5.0"; - contract test { - function f(uint x) pure public { - uint y = +x; - y; - } - } - )"; - CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated"); -} - -BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert) -{ - char const* text = R"( - contract A { - function f() pure public { - ufixed16x2 a = 0.5; - ufixed256x52 b = 0.0000000000000006661338147750939242541790008544921875; - fixed16x2 c = -0.5; - fixed256x52 d = -0.0000000000000006661338147750939242541790008544921875; - a; b; c; d; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types) -{ - char const* text = R"( - contract test { - function f() public { - ufixed256x1 a = 123456781234567979695948382928485849359686494864095409282048094275023098123.5; - ufixed256x77 b = 0.920890746623327805482905058466021565416131529487595827354393978494366605267637; - ufixed224x78 c = 0.000000000001519884736399797998492268541131529487595827354393978494366605267646; - fixed256x1 d = -123456781234567979695948382928485849359686494864095409282048094275023098123.5; - fixed256x76 e = -0.93322335481643744342575580035176794825198893968114429702091846411734101080123; - fixed256x79 g = -0.0001178860664374434257558003517679482519889396811442970209184641173410108012309; - a; b; c; d; e; g; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(zero_handling) -{ - char const* text = R"( - contract test { - function f() public { - fixed16x2 a = 0; a; - ufixed32x1 b = 0; b; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_size) -{ - char const* text = R"( - contract test { - function f() public { - ufixed a = 11/4; - ufixed248x8 b = a; b; - } - } - )"; - CHECK_ERROR(text, TypeError, "Type ufixed128x18 is not implicitly convertible to expected type ufixed248x8"); -} - -BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_lost_data) -{ - char const* text = R"( - contract test { - function f() public { - ufixed256x1 a = 1/3; a; - } - } - )"; - CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type ufixed256x1"); -} - -BOOST_AUTO_TEST_CASE(fixed_type_valid_explicit_conversions) -{ - char const* text = R"( - contract test { - function f() public { - ufixed256x80 a = ufixed256x80(1/3); a; - ufixed248x80 b = ufixed248x80(1/3); b; - ufixed8x1 c = ufixed8x1(1/3); c; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational) -{ - char const* text = R"( - contract test { - function f() public { - uint[3.5] a; a; - } - } - )"; - CHECK_ERROR(text, TypeError, "Array with fractional length specified."); -} - -BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type) -{ - char const* text = R"( - contract test { - function f() public { - uint[fixed(3.5)] a; a; - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type) -{ - char const* text = R"( - contract test { - function f() public { - uint[ufixed(3.5)] a; a; - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion) -{ - char const* text = R"( - contract test { - function f() public { - bytes32 c = 3.2; c; - } - } - )"; - CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type bytes32"); -} - -BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion) -{ - char const* text = R"( - contract test { - function f() public { - fixed a = 3.25; - bytes32 c = a; c; - } - } - )"; - CHECK_ERROR(text, TypeError, "fixed128x18 is not implicitly convertible to expected type bytes32"); -} - -BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal) -{ - char const* text = R"( - contract test { - mapping(ufixed8x1 => string) fixedString; - function f() public { - fixedString[0.5] = "Half"; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(fixed_points_inside_structs) -{ - char const* text = R"( - contract test { - struct myStruct { - ufixed a; - int b; - } - myStruct a = myStruct(3.125, 3); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_fixed_types) -{ - char const* text = R"( - contract test { - function f() public { - fixed[3] memory a = [fixed(3.5), fixed(-4.25), fixed(967.125)]; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_array_rationals) -{ - char const* text = R"( - contract test { - function f() public { - ufixed128x3[4] memory a = [ufixed128x3(3.5), 4.125, 2.5, 4.0]; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(rational_index_access) -{ - char const* text = R"( - contract test { - function f() public { - uint[] memory a; - a[.5]; - } - } - )"; - CHECK_ERROR(text, TypeError, "rational_const 1 / 2 is not implicitly convertible to expected type uint256"); -} - -BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression) -{ - char const* text = R"( - contract test { - function f() public { - ufixed64x8 a = 3.5 * 3; - ufixed64x8 b = 4 - 2.5; - ufixed64x8 c = 11 / 4; - ufixed240x5 d = 599 + 0.21875; - ufixed256x80 e = ufixed256x80(35.245 % 12.9); - ufixed256x80 f = ufixed256x80(1.2 % 2); - fixed g = 2 ** -2; - a; b; c; d; e; f; g; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(rational_as_exponent_value_signed) -{ - char const* text = R"( - contract test { - function f() public { - fixed g = 2 ** -2.2; - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(rational_as_exponent_value_unsigned) -{ - char const* text = R"( - contract test { - function f() public { - ufixed b = 3 ** 2.5; - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(rational_as_exponent_half) -{ - char const* text = R"( - contract test { - function f() public { - 2 ** (1/2); - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_quarter) -{ - char const* text = R"( - contract test { - function f() public { - 42 ** (-1/4); - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_15) -{ - char const* text = R"( - contract test { - function f() public { - var a = 3 ** ufixed(1.5); - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg) -{ - char const* text = R"( - contract test { - function f() public { - var c = 42 ** fixed(-1/4); - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals) -{ - char const* text = R"( - contract test { - function f() public { - var a = 0.12345678; - var b = 12345678.352; - var c = 0.00000009; - a; b; c; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(var_and_rational_with_tuple) -{ - char const* text = R"( - contract test { - function f() public { - var (a, b) = (.5, 1/3); - a; b; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(var_handle_divided_integers) -{ - char const* text = R"( - contract test { - function f() public { - var x = 1/3; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation) -{ - char const* text = R"( - contract test { - function f() public { - ~fixed(3.5); - } - } - )"; - CHECK_ERROR(text, TypeError, "cannot be applied"); -} - -BOOST_AUTO_TEST_CASE(rational_bitor_binary_operation) -{ - char const* text = R"( - contract test { - function f() public { - fixed(1.5) | 3; - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(rational_bitxor_binary_operation) -{ - char const* text = R"( - contract test { - function f() public { - fixed(1.75) ^ 3; - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation) -{ - char const* text = R"( - contract test { - function f() public { - fixed(1.75) & 3; - } - } - )"; - CHECK_ERROR(text, TypeError, "not compatible with types"); -} - -BOOST_AUTO_TEST_CASE(missing_bool_conversion) -{ - char const* text = R"( - contract test { - function b(uint a) public { - bool(a == 1); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction) -{ - char const* text = R"( - contract test { - function f() public { - ufixed a = uint64(1) + ufixed(2); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(one_divided_by_three_integer_conversion) -{ - char const* text = R"( - contract test { - function f() public { - uint a = 1/3; - } - } - )"; - CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type uint256. Try converting to type ufixed256x77"); -} - -BOOST_AUTO_TEST_CASE(unused_return_value) -{ - char const* text = R"( - contract test { - function g() public returns (uint) {} - function f() public { - g(); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(unused_return_value_send) -{ - char const* text = R"( - contract test { - function f() public { - address(0x12).send(1); - } - } - )"; - CHECK_WARNING(text, "Failure condition of 'send' ignored. Consider using 'transfer' instead."); -} - -BOOST_AUTO_TEST_CASE(unused_return_value_call) -{ - char const* text = R"( - contract test { - function f() public { - address(0x12).call("abc"); - } - } - )"; - CHECK_WARNING(text, "Return value of low-level calls not used"); -} - -BOOST_AUTO_TEST_CASE(unused_return_value_call_value) -{ - char const* text = R"( - contract test { - function f() public { - address(0x12).call.value(2)("abc"); - } - } - )"; - CHECK_WARNING(text, "Return value of low-level calls not used"); -} - -BOOST_AUTO_TEST_CASE(unused_return_value_callcode) -{ - char const* text = R"( - contract test { - function f() public { - address(0x12).callcode("abc"); - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (std::vector{ - "Return value of low-level calls not used", - "\"callcode\" has been deprecated" - })); -} - -BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall) -{ - char const* text = R"( - contract test { - function f() public { - address(0x12).delegatecall("abc"); - } - } - )"; - CHECK_WARNING(text, "Return value of low-level calls not used"); -} - -BOOST_AUTO_TEST_CASE(warn_about_callcode) -{ - char const* text = R"( - contract test { - function f() pure public { - address(0x12).callcode; - } - } - )"; - CHECK_WARNING(text, "\"callcode\" has been deprecated in favour of \"delegatecall\""); - text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - address(0x12).callcode; - } - } - )"; - CHECK_ERROR(text, TypeError, "\"callcode\" has been deprecated in favour of \"delegatecall\""); -} - -BOOST_AUTO_TEST_CASE(no_warn_about_callcode_as_function) -{ - char const* text = R"( - contract test { - function callcode() pure public { - test.callcode(); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(payable_in_library) -{ - char const* text = R"( - library test { - function f() payable public {} - } - )"; - CHECK_ERROR(text, TypeError, "Library functions cannot be payable."); -} - -BOOST_AUTO_TEST_CASE(payable_external) -{ - char const* text = R"( - contract test { - function f() payable external {} - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(payable_internal) -{ - char const* text = R"( - contract test { - function f() payable internal {} - } - )"; - CHECK_ERROR(text, TypeError, "Internal functions cannot be payable."); -} - -BOOST_AUTO_TEST_CASE(payable_private) -{ - char const* text = R"( - contract test { - function f() payable private {} - } - )"; - CHECK_ERROR(text, TypeError, "Internal functions cannot be payable."); -} - -BOOST_AUTO_TEST_CASE(illegal_override_payable) -{ - char const* text = R"( - contract B { function f() payable public {} } - contract C is B { function f() public {} } - )"; - CHECK_ERROR(text, TypeError, "Overriding function changes state mutability from \"payable\" to \"nonpayable\"."); -} - -BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) -{ - char const* text = R"( - contract B { function f() public {} } - contract C is B { function f() payable public {} } - )"; - CHECK_ERROR(text, TypeError, "Overriding function changes state mutability from \"nonpayable\" to \"payable\"."); -} - -BOOST_AUTO_TEST_CASE(function_variable_mixin) -{ - // bug #1798 (cpp-ethereum), related to #1286 (solidity) - char const* text = R"( - contract attribute { - bool ok = false; - } - contract func { - function ok() public returns (bool) { return true; } - } - - contract attr_func is attribute, func { - function checkOk() public returns (bool) { return ok(); } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared."); -} - -BOOST_AUTO_TEST_CASE(calling_payable) -{ - char const* text = R"( - contract receiver { function pay() payable public {} } - contract test { - function f() public { (new receiver()).pay.value(10)(); } - receiver r = new receiver(); - function g() public { r.pay.value(10)(); } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(calling_nonpayable) -{ - char const* text = R"( - contract receiver { function nopay() public {} } - contract test { - function f() public { (new receiver()).nopay.value(10)(); } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function () external - did you forget the \"payable\" modifier?"); -} - -BOOST_AUTO_TEST_CASE(non_payable_constructor) -{ - char const* text = R"( - contract C { - function C() { } - } - contract D { - function f() public returns (uint) { - (new C).value(2)(); - return 2; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function () returns (contract C) - did you forget the \"payable\" modifier?"); + CHECK_SUCCESS_NO_WARNINGS(sourceCode); } BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) { - char const* text = "contract C {}"; + char const* text = R"( + contract C {} + )"; auto sourceAndError = parseAnalyseAndReturnError(text, true, false); BOOST_REQUIRE(!sourceAndError.second.empty()); BOOST_REQUIRE(!!sourceAndError.first); @@ -4846,2272 +387,47 @@ BOOST_AUTO_TEST_CASE(unsatisfied_version) BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file requires different compiler version")); } -BOOST_AUTO_TEST_CASE(invalid_array_as_statement) -{ - char const* text = R"( - contract test { - struct S { uint x; } - function test(uint k) public { S[k]; } - } - )"; - CHECK_ERROR(text, TypeError, "Integer constant expected."); -} - -BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) -{ - char const* text = R"( - library B { - function b() public {} - } - - contract A { - using B for bytes; - - function a() public { - bytes memory x; - x.b(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"b\" not found or not visible after argument-dependent lookup in bytes memory"); -} - -BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) -{ - char const* text = R"( - contract C { - uint public a = 0x42 << -8; - } - )"; - CHECK_ERROR(text, TypeError, "Operator << not compatible with types int_const 66 and int_const -8"); -} - -BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) -{ - char const* text = R"( - contract C { - uint public a = 0x42 >> -8; - } - )"; - CHECK_ERROR(text, TypeError, "Operator >> not compatible with types int_const 66 and int_const -8"); -} - -BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) -{ - char const* text = R"( - contract C { - uint public a = 0x42 << 0x100000000; - } - )"; - CHECK_ERROR(text, TypeError, "Operator << not compatible with types int_const 66 and int_const 4294967296"); -} - -BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) -{ - char const* text = R"( - contract C { - uint public a = 0x42 >> 0x100000000; - } - )"; - CHECK_ERROR(text, TypeError, "Operator >> not compatible with types int_const 66 and int_const 4294967296"); -} - -BOOST_AUTO_TEST_CASE(shift_constant_right_fractional) -{ - char const* text = R"( - contract C { - uint public a = 0x42 >> (1 / 2); - } - )"; - CHECK_ERROR(text, TypeError, "Operator >> not compatible with types int_const 66 and rational_const 1 / 2"); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) -{ - char const* text = R"( - contract test { - function f() public { - assembly { - 1 - } - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Unbalanced stack at the end of a block: 1 surplus item(s)."); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack) -{ - char const* text = R"( - contract test { - function f() public { - assembly { - pop - } - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Unbalanced stack at the end of a block: 1 missing item(s)."); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_two_stack_load) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract c { - uint8 x; - function f() public { - assembly { pop(x) } - } - } - )"; - CHECK_ERROR(text, TypeError, "Only local variables are supported. To access storage variables,"); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - modifier m { - uint a = 1; - assembly { - a := 2 - } - _; - } - function f() public m { - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_storage) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - uint x = 1; - function f() public { - assembly { - x := 2 - } - } - } - )"; - CHECK_ERROR(text, TypeError, "Only local variables are supported. To access storage variables,"); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - uint x = 1; - modifier m { - assembly { - x := 2 - } - _; - } - function f() public m { - } - } - )"; - CHECK_ERROR(text, TypeError, "Only local variables are supported. To access storage variables,"); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_constant_assign) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - uint constant x = 1; - function f() public { - assembly { - x := 2 - } - } - } - )"; - CHECK_ERROR(text, TypeError, "Constant variables not supported by inline assembly"); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_constant_access) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - uint constant x = 1; - function f() public { - assembly { - let y := x - } - } - } - )"; - CHECK_ERROR(text, TypeError, "Constant variables not supported by inline assembly"); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_local_variable_access_out_of_functions) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() public { - uint a; - assembly { - function g() -> x { x := a } - } - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Cannot access local Solidity variables from inside an inline assembly function."); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_local_variable_access_out_of_functions_storage_ptr) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - uint[] r; - function f() public { - uint[] storage a = r; - assembly { - function g() -> x { x := a_offset } - } - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Cannot access local Solidity variables from inside an inline assembly function."); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_storage_variable_access_out_of_functions) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - uint a; - function f() pure public { - assembly { - function g() -> x { x := a_slot } - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_constant_variable_via_offset) -{ - char const* text = R"( - contract test { - uint constant x = 2; - function f() pure public { - assembly { - let r := x_offset - } - } - } - )"; - CHECK_ERROR(text, TypeError, "Constant variables not supported by inline assembly."); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_calldata_variables) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function f(bytes bytesAsCalldata) external { - assembly { - let x := bytesAsCalldata - } - } - } - )"; - CHECK_ERROR(text, TypeError, "Call data elements cannot be accessed directly."); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_050_literals_on_stack) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() pure public { - assembly { - 1 - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::SyntaxError, "are not supposed to return"}, - {Error::Type::DeclarationError, "Unbalanced stack"}, - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_literals_on_stack) -{ - char const* text = R"( - contract C { - function f() pure public { - assembly { - 1 - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "are not supposed to return"}, - {Error::Type::DeclarationError, "Unbalanced stack"}, - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_050_bare_instructions) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() view public { - assembly { - address - pop - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::SyntaxError, "The use of non-functional"}, - {Error::Type::SyntaxError, "The use of non-functional"} - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_bare_instructions) -{ - char const* text = R"( - contract C { - function f() view public { - assembly { - address - pop - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "The use of non-functional"}, - {Error::Type::Warning, "The use of non-functional"} - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_050_labels) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() pure public { - assembly { - label: - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::SyntaxError, "Jump instructions and labels are low-level"}, - {Error::Type::SyntaxError, "The use of labels is deprecated"} - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_labels) -{ - char const* text = R"( - contract C { - function f() pure public { - assembly { - label: - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "Jump instructions and labels are low-level"}, - {Error::Type::Warning, "The use of labels is deprecated"} - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_050_jump) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() pure public { - assembly { - jump(2) - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::SyntaxError, "Jump instructions and labels are low-level"} - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_jump) -{ - char const* text = R"( - contract C { - function f() pure public { - assembly { - jump(2) - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::TypeError, "Function declared as pure"}, - {Error::Type::Warning, "Jump instructions and labels are low-level"} - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_050_leave_items_on_stack) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() pure public { - assembly { - mload(0) - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::SyntaxError, "are not supposed to return"}, - {Error::Type::DeclarationError, "Unbalanced stack"}, - })); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_leave_items_on_stack) -{ - char const* text = R"( - contract C { - function f() pure public { - assembly { - mload(0) - } - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "are not supposed to return"}, - {Error::Type::DeclarationError, "Unbalanced stack"}, - })); -} - -BOOST_AUTO_TEST_CASE(invalid_mobile_type) -{ - char const* text = R"( - contract C { - function f() public { - // Invalid number - [1, 78901234567890123456789012345678901234567890123456789345678901234567890012345678012345678901234567]; - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid rational number."); -} - -BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function) -{ - char const* text = R"( - contract C { - function f() view public { - msg.value; - } - } - )"; - CHECK_WARNING(text, "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?"); -} - -BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_payable_function) -{ - char const* text = R"( - contract C { - function f() payable public { - msg.value; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_internal_function) -{ - char const* text = R"( - contract C { - function f() view internal { - msg.value; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_library) -{ - char const* text = R"( - library C { - function f() view public { - msg.value; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_modifier_following_non_payable_public_function) -{ - char const* text = R"( - contract c { - function f() pure public { } - modifier m() { msg.value; _; } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(assignment_to_constant) -{ - char const* text = R"( - contract c { - uint constant a = 1; - function f() public { a = 2; } - } - )"; - CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); -} - -BOOST_AUTO_TEST_CASE(return_structs) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - contract C { - struct S { uint a; T[] sub; } - struct T { uint[] x; } - function f() returns (uint, S) { - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(read_returned_struct) -{ - char const* text = R"( - pragma experimental ABIEncoderV2; - contract A { - struct T { - int x; - int y; - } - function g() public returns (T) { - return this.g(); - } - } - )"; - CHECK_WARNING(text, "Experimental features"); -} -BOOST_AUTO_TEST_CASE(address_checksum_type_deduction) -{ - char const* text = R"( - contract C { - function f() public { - var x = 0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E; - x.send(2); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(invalid_address_checksum) -{ - char const* text = R"( - contract C { - function f() pure public { - address x = 0xFA0bFc97E48458494Ccd857e1A85DC91F7F0046E; - x; - } - } - )"; - CHECK_WARNING(text, "This looks like an address but has an invalid checksum."); -} - -BOOST_AUTO_TEST_CASE(invalid_address_no_checksum) -{ - char const* text = R"( - contract C { - function f() pure public { - address x = 0xfa0bfc97e48458494ccd857e1a85dc91f7f0046e; - x; - } - } - )"; - CHECK_WARNING(text, "This looks like an address but has an invalid checksum."); -} - -BOOST_AUTO_TEST_CASE(invalid_address_length_short) -{ - char const* text = R"( - contract C { - function f() pure public { - address x = 0xA0bFc97E48458494Ccd857e1A85DC91F7F0046E; - x; - } - } - )"; - CHECK_WARNING(text, "This looks like an address but has an invalid checksum."); -} - -BOOST_AUTO_TEST_CASE(invalid_address_length_long) -{ - char const* text = R"( - contract C { - function f() pure public { - address x = 0xFA0bFc97E48458494Ccd857e1A85DC91F7F0046E0; - x; - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "This looks like an address but has an invalid checksum."}, - {Error::Type::TypeError, "not implicitly convertible"} - })); -} - -BOOST_AUTO_TEST_CASE(address_test_for_bug_in_implementation) -{ - // A previous implementation claimed the string would be an address - char const* text = R"( - contract AddrString { - address public test = "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c"; - } - )"; - CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type address"); - text = R"( - contract AddrString { - function f() public returns (address) { - return "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c"; - } - } - )"; - CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type"); -} - -BOOST_AUTO_TEST_CASE(early_exit_on_fatal_errors) -{ - // This tests a crash that occured because we did not stop for fatal errors. - char const* text = R"( - contract C { - struct S { - ftring a; - } - S public s; - function s() s { - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found or not unique"); -} - -BOOST_AUTO_TEST_CASE(address_methods) -{ - char const* text = R"( - contract C { - function f() public { - address addr; - uint balance = addr.balance; - bool callRet = addr.call(); - bool callcodeRet = addr.callcode(); - bool delegatecallRet = addr.delegatecall(); - bool sendRet = addr.send(1); - addr.transfer(1); - callRet; callcodeRet; delegatecallRet; sendRet; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(interface) -{ - char const* text = R"( - interface I { - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(interface_functions) -{ - char const* text = R"( - interface I { - function(); - function f(); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(interface_function_bodies) -{ - char const* text = R"( - interface I { - function f() public { - } - } - )"; - CHECK_ERROR(text, TypeError, "Functions in interfaces cannot have an implementation"); -} - -BOOST_AUTO_TEST_CASE(interface_events) -{ - char const* text = R"( - interface I { - event E(); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(interface_inheritance) -{ - char const* text = R"( - interface A { - } - interface I is A { - } - )"; - CHECK_ERROR(text, TypeError, "Interfaces cannot inherit"); -} - - -BOOST_AUTO_TEST_CASE(interface_structs) -{ - char const* text = R"( - interface I { - struct A { - } - } - )"; - CHECK_ERROR(text, TypeError, "Structs cannot be defined in interfaces"); -} - -BOOST_AUTO_TEST_CASE(interface_variables) -{ - char const* text = R"( - interface I { - uint a; - } - )"; - CHECK_ERROR(text, TypeError, "Variables cannot be declared in interfaces"); -} - -BOOST_AUTO_TEST_CASE(interface_function_parameters) -{ - char const* text = R"( - interface I { - function f(uint a) public returns (bool); - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(interface_enums) -{ - char const* text = R"( - interface I { - enum A { B, C } - } - )"; - CHECK_ERROR(text, TypeError, "Enumerable cannot be declared in interfaces"); -} - -BOOST_AUTO_TEST_CASE(using_interface) -{ - char const* text = R"( - interface I { - function f(); - } - contract C is I { - function f() public { - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(using_interface_complex) -{ - char const* text = R"( - interface I { - event A(); - function f(); - function g(); - function(); - } - contract C is I { - function f() public { - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(interface_implement_public_contract) -{ - char const* text = R"( - interface I { - function f() external; - } - contract C is I { - function f() public { - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(warn_about_throw) -{ - char const* text = R"( - contract C { - function f() pure public { - throw; - } - } - )"; - CHECK_WARNING(text, "\"throw\" is deprecated in favour of \"revert()\", \"require()\" and \"assert()\""); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() pure public { - throw; - } - } - )"; - CHECK_ERROR(text, SyntaxError, "\"throw\" is deprecated in favour of \"revert()\", \"require()\" and \"assert()\""); -} - -BOOST_AUTO_TEST_CASE(bare_revert) -{ - char const* text = R"( - contract C { - function f(uint x) pure public { - if (x > 7) - revert; - } - } - )"; - CHECK_ERROR(text, TypeError, "No matching declaration found"); -} - -BOOST_AUTO_TEST_CASE(revert_with_reason) -{ - char const* text = R"( - contract C { - function f(uint x) pure public { - if (x > 7) - revert("abc"); - else - revert(); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(bare_others) -{ - CHECK_WARNING("contract C { function f() pure public { selfdestruct; } }", "Statement has no effect."); - CHECK_WARNING("contract C { function f() pure public { assert; } }", "Statement has no effect."); - // This is different because it does have overloads. - CHECK_ERROR("contract C { function f() pure public { require; } }", TypeError, "No matching declaration found after variable lookup."); - CHECK_WARNING("contract C { function f() pure public { selfdestruct; } }", "Statement has no effect."); -} - -BOOST_AUTO_TEST_CASE(pure_statement_in_for_loop) -{ - char const* text = R"( - contract C { - function f() pure public { - for (uint x = 0; x < 10; true) - x++; - } - } - )"; - CHECK_WARNING(text, "Statement has no effect."); -} - -BOOST_AUTO_TEST_CASE(pure_statement_check_for_regular_for_loop) -{ - char const* text = R"( - contract C { - function f() pure public { - for (uint x = 0; true; x++) - {} - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(warn_unused_local) -{ - char const* text = R"( - contract C { - function f() pure public { - uint a; - } - } - )"; - CHECK_WARNING(text, "Unused local variable."); -} - -BOOST_AUTO_TEST_CASE(warn_unused_local_assigned) -{ - char const* text = R"( - contract C { - function f() pure public { - uint a = 1; - } - } - )"; - CHECK_WARNING(text, "Unused local variable."); -} - -BOOST_AUTO_TEST_CASE(warn_unused_function_parameter) -{ - char const* text = R"( - contract C { - function f(uint a) pure public { - } - } - )"; - CHECK_WARNING(text, "Unused function parameter. Remove or comment out the variable name to silence this warning."); - text = R"( - contract C { - function f(uint a) pure public { - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(warn_unused_return_parameter) -{ - char const* text = R"( - contract C { - function f() pure public returns (uint a) { - } - } - )"; - CHECK_WARNING(text, "Unused function parameter. Remove or comment out the variable name to silence this warning."); - text = R"( - contract C { - function f() pure public returns (uint a) { - return; - } - } - )"; - CHECK_WARNING(text, "Unused function parameter. Remove or comment out the variable name to silence this warning."); - text = R"( - contract C { - function f() pure public returns (uint) { - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f() pure public returns (uint a) { - a = 1; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f() pure public returns (uint a) { - return 1; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(no_unused_warning_interface_arguments) -{ - char const* text = R"( - interface I { - function f(uint a) pure external returns (uint b); - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(no_unused_warning_abstract_arguments) -{ - char const* text = R"( - contract C { - function f(uint a) pure public returns (uint b); - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(no_unused_warnings) -{ - char const* text = R"( - contract C { - function f(uint a) pure public returns (uint b) { - uint c = 1; - b = a + c; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(no_unused_dec_after_use) -{ - char const* text = R"( - contract C { - function f() pure public { - a = 7; - uint a; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(no_unused_inline_asm) -{ - char const* text = R"( - contract C { - function f() pure public { - uint a; - assembly { - a := 1 - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_with_functions) -{ - char const* text = R"( - contract C { - function keccak256() pure public {} - } - )"; - CHECK_WARNING(text, "shadows a builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_with_variables) -{ - char const* text = R"( - contract C { - function f() pure public { - uint msg; - msg; - } - } - )"; - CHECK_WARNING(text, "shadows a builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_with_storage_variables) -{ - char const* text = R"( - contract C { - uint msg; - } - )"; - CHECK_WARNING(text, "shadows a builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtin_at_global_scope) -{ - char const* text = R"( - contract msg { - } - )"; - CHECK_WARNING(text, "shadows a builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_with_parameters) -{ - char const* text = R"( - contract C { - function f(uint require) pure public { - require = 2; - } - } - )"; - CHECK_WARNING(text, "shadows a builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_with_return_parameters) -{ - char const* text = R"( - contract C { - function f() pure public returns (uint require) { - require = 2; - } - } - )"; - CHECK_WARNING(text, "shadows a builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_with_events) -{ - char const* text = R"( - contract C { - event keccak256(); - } - )"; - CHECK_WARNING(text, "shadows a builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_ignores_struct) -{ - char const* text = R"( - contract C { - struct a { - uint msg; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(shadowing_builtins_ignores_constructor) -{ - char const* text = R"( - contract C { - constructor() public {} - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(function_overload_is_not_shadowing) -{ - char const* text = R"( - contract C { - function f() pure public {} - function f(uint) pure public {} - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(function_override_is_not_shadowing) -{ - char const* text = R"( - contract D { function f() pure public {} } - contract C is D { - function f(uint) pure public {} - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(event_parameter_cannot_shadow_state_variable) -{ - char const* text = R"( - contract C { - address a; - event E(address a); - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(callable_crash) -{ - char const* text = R"( - contract C { - struct S { uint a; bool x; } - S public s; - function C() public { - 3({a: 1, x: true}); - } - } - )"; - CHECK_ERROR(text, TypeError, "Type is not callable"); -} - -BOOST_AUTO_TEST_CASE(error_transfer_non_payable_fallback) -{ - // This used to be a test for a.transfer to generate a warning - // because A's fallback function is not payable. - char const* text = R"( - contract A { - function() public {} - } - - contract B { - A a; - - function() public { - a.transfer(100); - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, - {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} - })); -} - -BOOST_AUTO_TEST_CASE(error_transfer_no_fallback) -{ - // This used to be a test for a.transfer to generate a warning - // because A does not have a payable fallback function. - std::string text = R"( - contract A {} - - contract B { - A a; - - function() public { - a.transfer(100); - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, - {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} - })); -} - -BOOST_AUTO_TEST_CASE(error_send_non_payable_fallback) -{ - // This used to be a test for a.send to generate a warning - // because A does not have a payable fallback function. - std::string text = R"( - contract A { - function() public {} - } - - contract B { - A a; - - function() public { - require(a.send(100)); - } - } - )"; - CHECK_ALLOW_MULTI(text, (std::vector>{ - {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"}, - {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} - })); -} - -BOOST_AUTO_TEST_CASE(does_not_error_transfer_payable_fallback) -{ - // This used to be a test for a.transfer to generate a warning - // because A does not have a payable fallback function. - char const* text = R"( - contract A { - function() payable public {} - } - - contract B { - A a; - - function() public { - a.transfer(100); - } - } - )"; - CHECK_WARNING(text, "Using contract member \"transfer\" inherited from the address type is deprecated."); -} - -BOOST_AUTO_TEST_CASE(does_not_error_transfer_regular_function) -{ - char const* text = R"( - contract A { - function transfer() pure public {} - } - - contract B { - A a; - - function() public { - a.transfer(); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - BOOST_AUTO_TEST_CASE(returndatasize_as_variable) { char const* text = R"( - contract c { function f() public { uint returndatasize; assembly { returndatasize }}} + contract C { function f() public pure { uint returndatasize; returndatasize; assembly { pop(returndatasize()) }}} )"; vector> expectations(vector>{ - {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"}, - {Error::Type::Warning, "The use of non-functional instructions is deprecated."}, - {Error::Type::DeclarationError, "Unbalanced stack"} + {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"} }); if (!dev::test::Options::get().evmVersion().supportsReturndata()) - expectations.emplace_back(make_pair(Error::Type::Warning, std::string("\"returndatasize\" instruction is only available for Byzantium-compatible"))); + expectations.emplace_back(make_pair(Error::Type::Warning, std::string("\"returndatasize\" instruction is only available for Byzantium-compatible VMs."))); CHECK_ALLOW_MULTI(text, expectations); } BOOST_AUTO_TEST_CASE(create2_as_variable) { char const* text = R"( - contract c { function f() public { uint create2; assembly { create2(0, 0, 0, 0) } }} + contract c { function f() public { uint create2; create2; assembly { pop(create2(0, 0, 0, 0)) } }} )"; + // This needs special treatment, because the message mentions the EVM version, + // so cannot be run via isoltest. + vector> expectations(vector>{ + {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"} + }); + if (!dev::test::Options::get().evmVersion().hasCreate2()) + expectations.emplace_back(make_pair(Error::Type::Warning, std::string("\"create2\" instruction is only available for Constantinople-compatible VMs."))); + CHECK_ALLOW_MULTI(text, expectations); +} + +BOOST_AUTO_TEST_CASE(extcodehash_as_variable) +{ + char const* text = R"( + contract c { function f() public view { uint extcodehash; extcodehash; assembly { pop(extcodehash(0)) } }} + )"; + // This needs special treatment, because the message mentions the EVM version, + // so cannot be run via isoltest. CHECK_ALLOW_MULTI(text, (std::vector>{ {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"}, - {Error::Type::Warning, "The \"create2\" instruction is not supported by the VM version"}, - {Error::Type::DeclarationError, "Unbalanced stack"}, - {Error::Type::Warning, "not supposed to return values"} + {Error::Type::Warning, "The \"extcodehash\" instruction is not supported by the VM version"}, })); } -BOOST_AUTO_TEST_CASE(warn_unspecified_storage) -{ - char const* text = R"( - contract C { - struct S { uint a; string b; } - S x; - function f() view public { - S storage y = x; - y; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - struct S { uint a; } - S x; - function f() view public { - S y = x; - y; - } - } - )"; - CHECK_WARNING(text, "Variable is declared as a storage pointer. Use an explicit \"storage\" keyword to silence this warning"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - struct S { uint a; } - S x; - function f() view public { - S y = x; - y; - } - } - )"; - CHECK_ERROR(text, TypeError, "Storage location must be specified as either \"memory\" or \"storage\"."); -} - -BOOST_AUTO_TEST_CASE(storage_location_non_array_or_struct_disallowed) -{ - char const* text = R"( - contract C { - function f(uint storage a) public { } - } - )"; - CHECK_ERROR(text, TypeError, "Storage location can only be given for array or struct types."); -} - -BOOST_AUTO_TEST_CASE(storage_location_non_array_or_struct_disallowed_is_not_fatal) -{ - char const* text = R"( - contract C { - function f(uint storage a) public { - a = f; - } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector{"Storage location can only be given for array or struct types."})); -} - -BOOST_AUTO_TEST_CASE(implicit_conversion_disallowed) -{ - char const* text = R"( - contract C { - function f() public returns (bytes4) { - uint32 tmp = 1; - return tmp; - } - } - )"; - CHECK_ERROR(text, TypeError, "Return argument type uint32 is not implicitly convertible to expected type (type of first return variable) bytes4."); -} - -BOOST_AUTO_TEST_CASE(too_large_arrays_for_calldata) -{ - char const* text = R"( - contract C { - function f(uint[85678901234] a) pure external { - } - } - )"; - CHECK_ERROR(text, TypeError, "Array is too large to be encoded."); - text = R"( - contract C { - function f(uint[85678901234] a) pure internal { - } - } - )"; - CHECK_ERROR(text, TypeError, "Array is too large to be encoded."); - text = R"( - contract C { - function f(uint[85678901234] a) pure public { - } - } - )"; - CHECK_ERROR(text, TypeError, "Array is too large to be encoded."); -} - -BOOST_AUTO_TEST_CASE(explicit_literal_to_storage_string) -{ - char const* text = R"( - contract C { - function f() pure public { - string memory x = "abc"; - x; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f() pure public { - string storage x = "abc"; - } - } - )"; - CHECK_ERROR(text, TypeError, "Type literal_string \"abc\" is not implicitly convertible to expected type string storage pointer."); - text = R"( - contract C { - function f() pure public { - string x = "abc"; - } - } - )"; - CHECK_ERROR(text, TypeError, "Type literal_string \"abc\" is not implicitly convertible to expected type string storage pointer."); - text = R"( - contract C { - function f() pure public { - string("abc"); - } - } - )"; - CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed from \"literal_string \"abc\"\" to \"string storage pointer\""); -} - -BOOST_AUTO_TEST_CASE(modifiers_access_storage_pointer) -{ - char const* text = R"( - contract C { - struct S { uint a; } - modifier m(S storage x) { - x; - _; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(function_types_sig) -{ - char const* text = R"( - contract C { - function f() view returns (bytes4) { - return f.selector; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"selector\" not found"); - text = R"( - contract C { - function g() pure internal { - } - function f() view returns (bytes4) { - return g.selector; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"selector\" not found"); - text = R"( - contract C { - function f() view returns (bytes4) { - function () g; - return g.selector; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"selector\" not found"); - text = R"( - contract C { - function f() pure external returns (bytes4) { - return this.f.selector; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function h() pure external { - } - function f() view external returns (bytes4) { - var g = this.h; - return g.selector; - } - } - )"; - CHECK_WARNING(text, "Use of the \"var\" keyword is deprecated."); - text = R"( - contract C { - function h() pure external { - } - function f() view external returns (bytes4) { - function () pure external g = this.h; - return g.selector; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function h() pure external { - } - function f() view external returns (bytes4) { - function () pure external g = this.h; - var i = g; - return i.selector; - } - } - )"; - CHECK_WARNING(text, "Use of the \"var\" keyword is deprecated."); -} - -BOOST_AUTO_TEST_CASE(using_this_in_constructor) -{ - char const* text = R"( - contract C { - constructor() public { - this.f(); - } - function f() pure public { - } - } - )"; - CHECK_WARNING(text, "\"this\" used in constructor"); -} - -BOOST_AUTO_TEST_CASE(do_not_crash_on_not_lvalue) -{ - // This checks for a bug that caused a crash because of continued analysis. - char const* text = R"( - contract C { - mapping (uint => uint) m; - function f() public { - m(1) = 2; - } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector{ - "is not callable", - "Expression has to be an lvalue", - "Type int_const 2 is not implicitly" - })); -} - -BOOST_AUTO_TEST_CASE(builtin_reject_gas) -{ - char const* text = R"( - contract C { - function f() public { - keccak256.gas(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); - text = R"( - contract C { - function f() public { - sha256.gas(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); - text = R"( - contract C { - function f() public { - ripemd160.gas(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); - text = R"( - contract C { - function f() public { - ecrecover.gas(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); -} - -BOOST_AUTO_TEST_CASE(gasleft) -{ - char const* text = R"( - contract C { - function f() public view returns (uint256 val) { return msg.gas; } - } - )"; - CHECK_WARNING(text, "\"msg.gas\" has been deprecated in favor of \"gasleft()\""); - - text = R"( - contract C { - function f() public view returns (uint256 val) { return gasleft(); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() public returns (uint256 val) { return msg.gas; } - } - )"; - CHECK_ERROR(text, TypeError, "\"msg.gas\" has been deprecated in favor of \"gasleft()\""); -} - -BOOST_AUTO_TEST_CASE(gasleft_shadowing) -{ - char const* text = R"( - contract C { - function gasleft() public pure returns (bytes32 val) { return "abc"; } - function f() public pure returns (bytes32 val) { return gasleft(); } - } - )"; - CHECK_WARNING(text, "This declaration shadows a builtin symbol."); - - text = R"( - contract C { - uint gasleft; - function f() public { gasleft = 42; } - } - )"; - CHECK_WARNING(text, "This declaration shadows a builtin symbol."); -} - -BOOST_AUTO_TEST_CASE(builtin_reject_value) -{ - char const* text = R"( - contract C { - function f() public { - keccak256.value(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); - text = R"( - contract C { - function f() public { - sha256.value(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); - text = R"( - contract C { - function f() public { - ripemd160.value(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); - text = R"( - contract C { - function f() public { - ecrecover.value(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); -} - -BOOST_AUTO_TEST_CASE(large_storage_array_fine) -{ - char const* text = R"( - contract C { - uint[2**64 - 1] x; - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(large_storage_array_simple) -{ - char const* text = R"( - contract C { - uint[2**64] x; - } - )"; - CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); -} - -BOOST_AUTO_TEST_CASE(large_storage_arrays_combined) -{ - char const* text = R"( - contract C { - uint[200][200][2**30][][2**30] x; - } - )"; - CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); -} - -BOOST_AUTO_TEST_CASE(large_storage_arrays_struct) -{ - char const* text = R"( - contract C { - struct S { uint[2**30] x; uint[2**50] y; } - S[2**20] x; - } - )"; - CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); -} - -BOOST_AUTO_TEST_CASE(large_storage_array_mapping) -{ - char const* text = R"( - contract C { - mapping(uint => uint[2**100]) x; - } - )"; - CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); -} - -BOOST_AUTO_TEST_CASE(library_function_without_implementation) -{ - char const* text = R"( - library L { - function f() public; - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - library L { - function f() internal; - } - )"; - CHECK_ERROR(text, TypeError, "Internal library function must be implemented if declared."); - text = R"( - library L { - function f() private; - } - )"; - CHECK_ERROR(text, TypeError, "Internal library function must be implemented if declared."); -} - -BOOST_AUTO_TEST_CASE(using_for_with_non_library) -{ - // This tests a crash that was resolved by making the first error fatal. - char const* text = R"( - library L { - struct S { uint d; } - using S for S; - function f(S _s) internal { - _s.d = 1; - } - } - )"; - CHECK_ERROR(text, TypeError, "Library name expected."); -} - -BOOST_AUTO_TEST_CASE(experimental_pragma) -{ - char const* text = R"( - pragma experimental; - )"; - CHECK_ERROR(text, SyntaxError, "Experimental feature name is missing."); - text = R"( - pragma experimental 123; - )"; - CHECK_ERROR(text, SyntaxError, "Unsupported experimental feature name."); - text = R"( - pragma experimental unsupportedName; - )"; - CHECK_ERROR(text, SyntaxError, "Unsupported experimental feature name."); - text = R"( - pragma experimental "unsupportedName"; - )"; - CHECK_ERROR(text, SyntaxError, "Unsupported experimental feature name."); - text = R"( - pragma experimental ""; - )"; - CHECK_ERROR(text, SyntaxError, "Empty experimental feature name is invalid."); - text = R"( - pragma experimental unsupportedName unsupportedName; - )"; - CHECK_ERROR(text, SyntaxError, "Stray arguments."); - text = R"( - pragma experimental __test; - )"; - CHECK_WARNING(text, "Experimental features are turned on. Do not use experimental features on live deployments."); - text = R"( - pragma experimental __test; - pragma experimental __test; - )"; - CHECK_ERROR_ALLOW_MULTI(text, SyntaxError, (std::vector{"Duplicate experimental feature name."})); -} - -BOOST_AUTO_TEST_CASE(reject_interface_creation) -{ - char const* text = R"( - interface I {} - contract C { - function f() public { - new I(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Cannot instantiate an interface."); -} - -BOOST_AUTO_TEST_CASE(accept_library_creation) -{ - char const* text = R"( - library L {} - contract C { - function f() public { - new L(); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(reject_interface_constructors) -{ - char const* text = R"( - interface I {} - contract C is I(2) {} - )"; - CHECK_ERROR(text, TypeError, "Wrong argument count for constructor call: 1 arguments given but expected 0."); -} - -BOOST_AUTO_TEST_CASE(non_external_fallback) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function () external { } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function () internal { } - } - )"; - CHECK_ERROR(text, TypeError, "Fallback function must be defined as \"external\"."); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function () private { } - } - )"; - CHECK_ERROR(text, TypeError, "Fallback function must be defined as \"external\"."); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function () public { } - } - )"; - CHECK_ERROR(text, TypeError, "Fallback function must be defined as \"external\"."); -} - -BOOST_AUTO_TEST_CASE(invalid_literal_in_tuple) -{ - char const* text = R"( - contract C { - function f() pure public { - uint x; - (x, ) = (1E111); - } - } - )"; - CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type"); - text = R"( - contract C { - function f() pure public { - uint x; - (x, ) = (1, 1E111); - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid rational number."); - text = R"( - contract C { - function f() pure public { - uint x; - (x, ) = (1E111, 1); - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid rational number."); - text = R"( - contract C { - function f() pure public { - (2**270, 1); - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid rational number."); - text = R"( - contract C { - function f() pure public { - ((2**270) / 2**100, 1); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(address_overload_resolution) -{ - char const* text = R"( - contract C { - function balance() returns (uint) { - this.balance; // to avoid pureness warning - return 1; - } - function transfer(uint amount) { - address(this).transfer(amount); // to avoid pureness warning - } - } - contract D { - function f() { - var x = (new C()).balance(); - x; - (new C()).transfer(5); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(array_length_invalid_expression) -{ - char const* text = R"( - contract C { - uint[-true] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); - text = R"( - contract C { - uint[true/1] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); - text = R"( - contract C { - uint[1/true] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); - text = R"( - contract C { - uint[1.111111E1111111111111] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); - text = R"( - contract C { - uint[3/0] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Operator / not compatible with types int_const 3 and int_const 0"); -} - -BOOST_AUTO_TEST_CASE(warn_about_address_members_on_contract) -{ - std::string text = R"( - contract C { - function f() view public { - this.balance; - } - } - )"; - CHECK_WARNING(text, "Using contract member \"balance\" inherited from the address type is deprecated."); - text = R"( - contract C { - function f() view public { - this.transfer; - } - } - )"; - CHECK_ALLOW_MULTI(text, (vector>{ - {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, - {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} - })); - text = R"( - contract C { - function f() view public { - this.send; - } - } - )"; - CHECK_ALLOW_MULTI(text, (vector>{ - {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"}, - {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} - })); - text = R"( - contract C { - function f() view public { - this.call; - } - } - )"; - CHECK_WARNING(text, "Using contract member \"call\" inherited from the address type is deprecated."); - text = R"( - contract C { - function f() view public { - this.callcode; - } - } - )"; - CHECK_ALLOW_MULTI(text, (vector>{ - {Error::Type::Warning, "Using contract member \"callcode\" inherited from the address type is deprecated"}, - {Error::Type::Warning, "\"callcode\" has been deprecated in favour of \"delegatecall\""} - })); - text = R"( - contract C { - function f() view public { - this.delegatecall; - } - } - )"; - CHECK_WARNING(text, "Using contract member \"delegatecall\" inherited from the address type is deprecated."); -} - -BOOST_AUTO_TEST_CASE(warn_about_address_members_on_non_this_contract) -{ - std::string text = R"( - contract C { - function f() view public { - C c; - c.balance; - } - } - )"; - CHECK_WARNING(text, "Using contract member \"balance\" inherited from the address type is deprecated"); - text = R"( - contract C { - function f() view public { - C c; - c.transfer; - } - } - )"; - CHECK_ALLOW_MULTI(text, (vector>{ - {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, - {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} - })); - text = R"( - contract C { - function f() view public { - C c; - c.send; - } - } - )"; - CHECK_ALLOW_MULTI(text, (vector>{ - {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"}, - {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} - })); - text = R"( - contract C { - function f() pure public { - C c; - c.call; - } - } - )"; - CHECK_WARNING(text, "Using contract member \"call\" inherited from the address type is deprecated"); - text = R"( - contract C { - function f() pure public { - C c; - c.callcode; - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (std::vector{ - "Using contract member \"callcode\" inherited from the address type is deprecated", - "\"callcode\" has been deprecated in favour of \"delegatecall\"" - })); - text = R"( - contract C { - function f() pure public { - C c; - c.delegatecall; - } - } - )"; - CHECK_WARNING(text, "Using contract member \"delegatecall\" inherited from the address type is deprecated"); -} - -BOOST_AUTO_TEST_CASE(no_address_members_on_contract) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() public { - this.balance; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"balance\" not found or not visible after argument-dependent lookup in contract"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() public { - this.transfer; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"transfer\" not found or not visible after argument-dependent lookup in contract"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() public { - this.send; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"send\" not found or not visible after argument-dependent lookup in contract"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() public { - this.call; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"call\" not found or not visible after argument-dependent lookup in contract"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() public { - this.callcode; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"callcode\" not found or not visible after argument-dependent lookup in contract"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() public { - this.delegatecall; - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"delegatecall\" not found or not visible after argument-dependent lookup in contract"); -} - -BOOST_AUTO_TEST_CASE(no_warning_for_using_members_that_look_like_address_members) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract C { - function transfer(uint) public; - function f() public { - this.transfer(10); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(emit_events) -{ - char const* text = R"( - contract C { - event e(); - function f() public { - emit e(); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - event e(uint a, string b); - function f() public { - emit e(2, "abc"); - emit e({b: "abc", a: 8}); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract A { event e(uint a, string b); } - contract C is A { - function f() public { - emit A.e(2, "abc"); - emit A.e({b: "abc", a: 8}); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(old_style_events_050) -{ - char const* text = R"( - contract C { - event e(); - function f() public { - e(); - } - } - )"; - CHECK_WARNING(text, "without \"emit\" prefix"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - event e(); - function f() public { - e(); - } - } - )"; - CHECK_ERROR(text, TypeError, "have to be prefixed"); -} - BOOST_AUTO_TEST_CASE(getter_is_memory_type) { char const* text = R"( @@ -7132,48 +448,88 @@ BOOST_AUTO_TEST_CASE(getter_is_memory_type) } } -BOOST_AUTO_TEST_CASE(require_visibility_specifiers) +BOOST_AUTO_TEST_CASE(address_staticcall) { - char const* text = R"( + char const* sourceCode = R"( contract C { - function f() pure { } - } - )"; - CHECK_WARNING(text, "No visibility specified. Defaulting to"); - text = R"( - pragma experimental "v0.5.0"; - contract C { - function f() pure { } - } - )"; - CHECK_ERROR(text, SyntaxError, "No visibility specified."); -} - -BOOST_AUTO_TEST_CASE(blockhash) -{ - char const* code = R"( - contract C { - function f() public view returns (bytes32) { - return block.blockhash(3); + function f() public view returns(bool) { + (bool success,) = address(0x4242).staticcall(""); + return success; } } )"; - CHECK_WARNING(code, "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""); - code = R"( + if (dev::test::Options::get().evmVersion().hasStaticCall()) + CHECK_SUCCESS_NO_WARNINGS(sourceCode); + else + CHECK_ERROR(sourceCode, TypeError, "\"staticcall\" is not supported by the VM version."); +} + +BOOST_AUTO_TEST_CASE(address_staticcall_value) +{ + if (dev::test::Options::get().evmVersion().hasStaticCall()) + { + char const* sourceCode = R"( + contract C { + function f() public view { + address(0x4242).staticcall.value; + } + } + )"; + CHECK_ERROR(sourceCode, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); + } +} + +BOOST_AUTO_TEST_CASE(address_call_full_return_type) +{ + char const* sourceCode = R"( contract C { - function f() public view returns (bytes32) { return blockhash(3); } + function f() public { + (bool success, bytes memory m) = address(0x4242).call(""); + success; m; + } } )"; - CHECK_SUCCESS_NO_WARNINGS(code); - code = R"( - pragma experimental "v0.5.0"; + if (dev::test::Options::get().evmVersion().supportsReturndata()) + CHECK_SUCCESS_NO_WARNINGS(sourceCode); + else + CHECK_ERROR(sourceCode, TypeError, "Type inaccessible dynamic type is not implicitly convertible to expected type bytes memory."); +} + +BOOST_AUTO_TEST_CASE(address_delegatecall_full_return_type) +{ + char const* sourceCode = R"( contract C { - function f() public returns (bytes32) { return block.blockhash(3); } + function f() public { + (bool success, bytes memory m) = address(0x4242).delegatecall(""); + success; m; + } } )"; - CHECK_ERROR(code, TypeError, "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""); + + if (dev::test::Options::get().evmVersion().supportsReturndata()) + CHECK_SUCCESS_NO_WARNINGS(sourceCode); + else + CHECK_ERROR(sourceCode, TypeError, "Type inaccessible dynamic type is not implicitly convertible to expected type bytes memory."); +} + + +BOOST_AUTO_TEST_CASE(address_staticcall_full_return_type) +{ + if (dev::test::Options::get().evmVersion().hasStaticCall()) + { + char const* sourceCode = R"( + contract C { + function f() public view { + (bool success, bytes memory m) = address(0x4242).staticcall(""); + success; m; + } + } + )"; + + CHECK_SUCCESS_NO_WARNINGS(sourceCode); + } } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index eeebeb745..d77050cbd 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -41,6 +41,7 @@ public: void checkNatspec( std::string const& _code, + std::string const& _contractName, std::string const& _expectedDocumentationString, bool _userDocumentation ) @@ -52,9 +53,9 @@ public: Json::Value generatedDocumentation; if (_userDocumentation) - generatedDocumentation = m_compilerStack.natspecUser(m_compilerStack.lastContractName()); + generatedDocumentation = m_compilerStack.natspecUser(_contractName); else - generatedDocumentation = m_compilerStack.natspecDev(m_compilerStack.lastContractName()); + generatedDocumentation = m_compilerStack.natspecDev(_contractName); Json::Value expectedDocumentation; jsonParseStrict(_expectedDocumentationString, expectedDocumentation); BOOST_CHECK_MESSAGE( @@ -84,7 +85,7 @@ BOOST_AUTO_TEST_CASE(user_basic_test) char const* sourceCode = R"( contract test { /// @notice Multiplies `a` by 7 - function mul(uint a) returns(uint d) { return a * 7; } + function mul(uint a) public returns(uint d) { return a * 7; } } )"; @@ -93,7 +94,7 @@ BOOST_AUTO_TEST_CASE(user_basic_test) " \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}" "}}"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) @@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) contract test { /// @notice Multiplies `a` by 7 /// @dev Multiplies a number by 7 - function mul(uint a) returns(uint d) { return a * 7; } + function mul(uint a) public returns (uint d) { return a * 7; } } )"; @@ -119,8 +120,8 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) " \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}" "}}"; - checkNatspec(sourceCode, devNatspec, false); - checkNatspec(sourceCode, userNatspec, true); + checkNatspec(sourceCode, "test", devNatspec, false); + checkNatspec(sourceCode, "test", userNatspec, true); } BOOST_AUTO_TEST_CASE(user_multiline_comment) @@ -129,7 +130,7 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment) contract test { /// @notice Multiplies `a` by 7 /// and then adds `b` - function mul_and_add(uint a, uint256 b) returns(uint256 d) { + function mul_and_add(uint a, uint256 b) public returns (uint256 d) { return (a * 7) + b; } } @@ -140,7 +141,7 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment) " \"mul_and_add(uint256,uint256)\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"}" "}}"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(user_multiple_functions) @@ -148,17 +149,17 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions) char const* sourceCode = R"( contract test { /// @notice Multiplies `a` by 7 and then adds `b` - function mul_and_add(uint a, uint256 b) returns(uint256 d) { + function mul_and_add(uint a, uint256 b) public returns (uint256 d) { return (a * 7) + b; } /// @notice Divides `input` by `div` - function divide(uint input, uint div) returns(uint d) { + function divide(uint input, uint div) public returns (uint d) { return input / div; } /// @notice Subtracts 3 from `input` - function sub(int input) returns(int d) { + function sub(int input) public returns (int d) { return input - 3; } } @@ -171,7 +172,7 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions) " \"sub(int256)\":{ \"notice\": \"Subtracts 3 from `input`\"}" "}}"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(user_empty_contract) @@ -182,17 +183,17 @@ BOOST_AUTO_TEST_CASE(user_empty_contract) char const* natspec = "{\"methods\":{} }"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) { char const* sourceCode = R"( contract test { - function mul(uint a) returns(uint d) { + function mul(uint a) public returns (uint d) { return a * 7; } - function sub(int input) returns(int d) { + function sub(int input) public returns (int d) { return input - 3; } } @@ -201,8 +202,8 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) char const* devNatspec = "{\"methods\":{}}"; char const* userNatspec = "{\"methods\":{}}"; - checkNatspec(sourceCode, devNatspec, false); - checkNatspec(sourceCode, userNatspec, true); + checkNatspec(sourceCode, "test", devNatspec, false); + checkNatspec(sourceCode, "test", userNatspec, true); } BOOST_AUTO_TEST_CASE(dev_desc_after_nl) @@ -213,7 +214,7 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl) /// Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter /// @param second Documentation for the second parameter - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -228,7 +229,7 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiple_params) @@ -238,7 +239,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params) /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter /// @param second Documentation for the second parameter - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -253,7 +254,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace) @@ -262,7 +263,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace) " /// @dev Multiplies a number by 7 and adds second parameter\n" " /// @param a Documentation for the first parameter\n" " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + " function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; }\n" "}\n"; char const* natspec = "{" @@ -276,7 +277,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) @@ -287,7 +288,7 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) /// @param a Documentation for the first parameter starts here. /// Since it's a really complicated parameter we need 2 lines /// @param second Documentation for the second parameter - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -302,7 +303,7 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiple_functions) @@ -312,18 +313,18 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions) /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter /// @param second Documentation for the second parameter - function mul(uint a, uint second) returns(uint d) { + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } /// @dev Divides 2 numbers /// @param input Documentation for the input parameter /// @param div Documentation for the div parameter - function divide(uint input, uint div) returns(uint d) { + function divide(uint input, uint div) public returns (uint d) { return input / div; } /// @dev Subtracts 3 from `input` /// @param input Documentation for the input parameter - function sub(int input) returns(int d) { + function sub(int input) public returns (int d) { return input - 3; } } @@ -353,7 +354,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_return) @@ -365,7 +366,7 @@ BOOST_AUTO_TEST_CASE(dev_return) /// Since it's a really complicated parameter we need 2 lines /// @param second Documentation for the second parameter /// @return The result of the multiplication - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -381,7 +382,7 @@ BOOST_AUTO_TEST_CASE(dev_return) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) { @@ -393,7 +394,7 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) /// @param second Documentation for the second parameter /// @return /// The result of the multiplication - function mul(uint a, uint second) returns(uint d) { + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } @@ -411,7 +412,7 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } @@ -425,7 +426,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return) /// @param second Documentation for the second parameter /// @return The result of the multiplication /// and cookies with nutella - function mul(uint a, uint second) returns(uint d) { + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } @@ -443,7 +444,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiline_comment) @@ -458,7 +459,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment) * @return The result of the multiplication * and cookies with nutella */ - function mul(uint a, uint second) returns(uint d) { + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } @@ -476,7 +477,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_contract_no_doc) @@ -484,7 +485,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc) char const* sourceCode = R"( contract test { /// @dev Mul function - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -496,7 +497,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc) " }\n" "}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_contract_doc) @@ -506,7 +507,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc) /// @title Just a test contract contract test { /// @dev Mul function - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -520,7 +521,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc) " }\n" "}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_author_at_function) @@ -531,7 +532,7 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function) contract test { /// @dev Mul function /// @author John Doe - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -546,7 +547,7 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function) " }\n" "}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) @@ -554,7 +555,7 @@ BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) char const* sourceCode = R"( contract test { /// I do something awesome - function mul(uint a) returns(uint d) { return a * 7; } + function mul(uint a) public returns (uint d) { return a * 7; } } )"; @@ -569,7 +570,7 @@ BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) } )ABCDEF"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag) @@ -578,7 +579,7 @@ BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag) contract test { /// I do something awesome /// which requires two lines to explain - function mul(uint a) returns(uint d) { return a * 7; } + function mul(uint a) public returns (uint d) { return a * 7; } } )"; @@ -592,7 +593,7 @@ BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag) } )ABCDEF"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(empty_comment) @@ -608,7 +609,7 @@ BOOST_AUTO_TEST_CASE(empty_comment) } )ABCDEF"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(dev_title_at_function_error) @@ -619,7 +620,7 @@ BOOST_AUTO_TEST_CASE(dev_title_at_function_error) contract test { /// @dev Mul function /// @title I really should not be here - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -633,7 +634,7 @@ BOOST_AUTO_TEST_CASE(dev_documenting_nonexistent_param) /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter /// @param not_existing Documentation for the second parameter - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -646,8 +647,8 @@ BOOST_AUTO_TEST_CASE(dev_documenting_no_paramname) contract test { /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter - /// @param - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + /// @param + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -661,7 +662,7 @@ BOOST_AUTO_TEST_CASE(dev_documenting_no_paramname_end) /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter /// @param se - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -674,14 +675,139 @@ BOOST_AUTO_TEST_CASE(dev_documenting_no_param_description) contract test { /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter - /// @param second - function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + /// @param second + function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; expectNatspecError(sourceCode); } +BOOST_AUTO_TEST_CASE(user_constructor) +{ + char const *sourceCode = R"( + contract test { + /// @notice this is a really nice constructor + constructor(uint a, uint second) public { } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods" : { + "constructor" : "this is a really nice constructor" + } + })ABCDEF"; + + checkNatspec(sourceCode, "test", natspec, true); +} + +BOOST_AUTO_TEST_CASE(user_constructor_and_function) +{ + char const *sourceCode = R"( + contract test { + /// @notice this is a really nice constructor + constructor(uint a, uint second) public { } + /// another multiplier + function mul(uint a, uint second) public returns(uint d) { return a * 7 + second; } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods" : { + "mul(uint256,uint256)" : { + "notice" : "another multiplier" + }, + "constructor" : "this is a really nice constructor" + } + })ABCDEF"; + + checkNatspec(sourceCode, "test", natspec, true); +} + +BOOST_AUTO_TEST_CASE(dev_constructor) +{ + char const *sourceCode = R"( + contract test { + /// @author Alex + /// @param a the parameter a is really nice and very useful + /// @param second the second parameter is not very useful, it just provides additional confusion + constructor(uint a, uint second) public { } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods" : { + "constructor" : { + "author" : "Alex", + "params" : { + "a" : "the parameter a is really nice and very useful", + "second" : "the second parameter is not very useful, it just provides additional confusion" + } + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "test", natspec, false); +} + +BOOST_AUTO_TEST_CASE(dev_constructor_return) +{ + char const* sourceCode = R"( + contract test { + /// @author Alex + /// @param a the parameter a is really nice and very useful + /// @param second the second parameter is not very useful, it just provides additional confusion + /// @return return should not work within constructors + constructor(uint a, uint second) public { } + } + )"; + + expectNatspecError(sourceCode); +} + +BOOST_AUTO_TEST_CASE(dev_constructor_and_function) +{ + char const *sourceCode = R"( + contract test { + /// @author Alex + /// @param a the parameter a is really nice and very useful + /// @param second the second parameter is not very useful, it just provides additional confusion + constructor(uint a, uint second) public { } + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + /// @return The result of the multiplication + /// and cookies with nutella + function mul(uint a, uint second) public returns(uint d) { + return a * 7 + second; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods" : { + "mul(uint256,uint256)" : { + "details" : "Multiplies a number by 7 and adds second parameter", + "params" : { + "a" : "Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines", + "second" : "Documentation for the second parameter" + }, + "return" : "The result of the multiplication and cookies with nutella" + }, + "constructor" : { + "author" : "Alex", + "params" : { + "a" : "the parameter a is really nice and very useful", + "second" : "the second parameter is not very useful, it just provides additional confusion" + } + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "test", natspec, false); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 5326feaf0..f925d36ef 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -74,16 +73,16 @@ public: unsigned const _optimizeRuns = 200 ) { - m_nonOptimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, false, _optimizeRuns); + m_nonOptimizedBytecode = compileAndRunWithOptimizer("pragma solidity >=0.0;\n" + _sourceCode, _value, _contractName, false, _optimizeRuns); m_nonOptimizedContract = m_contractAddress; - m_optimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, true, _optimizeRuns); + m_optimizedBytecode = compileAndRunWithOptimizer("pragma solidity >=0.0;\n" + _sourceCode, _value, _contractName, true, _optimizeRuns); size_t nonOptimizedSize = numInstructions(m_nonOptimizedBytecode); size_t optimizedSize = numInstructions(m_optimizedBytecode); BOOST_CHECK_MESSAGE( _optimizeRuns < 50 || optimizedSize < nonOptimizedSize, string("Optimizer did not reduce bytecode size. Non-optimized size: ") + - std::to_string(nonOptimizedSize) + " - optimized size: " + - std::to_string(optimizedSize) + to_string(nonOptimizedSize) + " - optimized size: " + + to_string(optimizedSize) ); m_optimizedContract = m_contractAddress; } @@ -104,7 +103,7 @@ public: "\nOptimized: " + toHex(optimizedOutput)); } - /// @returns the number of intructions in the given bytecode, not taking the metadata hash + /// @returns the number of instructions in the given bytecode, not taking the metadata hash /// into account. size_t numInstructions(bytes const& _bytecode, boost::optional _which = boost::optional{}) { @@ -136,10 +135,11 @@ BOOST_AUTO_TEST_CASE(smoke_test) { char const* sourceCode = R"( contract test { - function f(uint a) returns (uint b) { + function f(uint a) public returns (uint b) { return a; } - })"; + } + )"; compileBothVersions(sourceCode); compareVersions("f(uint256)", u256(7)); } @@ -148,10 +148,11 @@ BOOST_AUTO_TEST_CASE(identities) { char const* sourceCode = R"( contract test { - function f(int a) returns (int b) { + function f(int a) public returns (int b) { return int(0) | (int(1) * (int(0) ^ (0 + a))); } - })"; + } + )"; compileBothVersions(sourceCode); compareVersions("f(int256)", u256(0x12334664)); } @@ -161,11 +162,12 @@ BOOST_AUTO_TEST_CASE(unused_expressions) char const* sourceCode = R"( contract test { uint data; - function f() returns (uint a, uint b) { + function f() public returns (uint a, uint b) { 10 + 20; data; } - })"; + } + )"; compileBothVersions(sourceCode); compareVersions("f()"); } @@ -177,10 +179,11 @@ BOOST_AUTO_TEST_CASE(constant_folding_both_sides) // literals as late as possible char const* sourceCode = R"( contract test { - function f(uint x) returns (uint y) { + function f(uint x) public returns (uint y) { return 98 ^ (7 * ((1 | (x | 1000)) * 40) ^ 102); } - })"; + } + )"; compileBothVersions(sourceCode); compareVersions("f(uint256)", 7); } @@ -190,7 +193,7 @@ BOOST_AUTO_TEST_CASE(storage_access) char const* sourceCode = R"( contract test { uint8[40] data; - function f(uint x) returns (uint y) { + function f(uint x) public returns (uint y) { data[2] = data[7] = uint8(x); data[4] = data[2] * 10 + data[3]; } @@ -206,13 +209,13 @@ BOOST_AUTO_TEST_CASE(array_copy) contract test { bytes2[] data1; bytes5[] data2; - function f(uint x) returns (uint l, uint y) { + function f(uint x) public returns (uint l, uint y) { data1.length = msg.data.length; for (uint i = 0; i < msg.data.length; ++i) data1[i] = msg.data[i]; data2 = data1; l = data2.length; - y = uint(data2[x]); + y = uint(uint40(data2[x])); } } )"; @@ -226,8 +229,8 @@ BOOST_AUTO_TEST_CASE(function_calls) { char const* sourceCode = R"( contract test { - function f1(uint x) returns (uint) { return x*x; } - function f(uint x) returns (uint) { return f1(7+x) - this.f1(x**9); } + function f1(uint x) public returns (uint) { return x*x; } + function f(uint x) public returns (uint) { return f1(7+x) - this.f1(x**9); } } )"; compileBothVersions(sourceCode); @@ -241,8 +244,8 @@ BOOST_AUTO_TEST_CASE(storage_write_in_loops) char const* sourceCode = R"( contract test { uint d; - function f(uint a) returns (uint r) { - var x = d; + function f(uint a) public returns (uint r) { + uint x = d; for (uint i = 1; i < a * a; i++) { r = d; d = i; @@ -261,18 +264,18 @@ BOOST_AUTO_TEST_CASE(storage_write_in_loops) // Information in joining branches is not retained anymore. BOOST_AUTO_TEST_CASE(retain_information_in_branches) { - // This tests that the optimizer knows that we already have "z == keccak256(y)" inside both branches. + // This tests that the optimizer knows that we already have "z == keccak256(abi.encodePacked(y))" inside both branches. char const* sourceCode = R"( contract c { bytes32 d; uint a; - function f(uint x, bytes32 y) returns (uint r_a, bytes32 r_d) { - bytes32 z = keccak256(y); + function f(uint x, bytes32 y) public returns (uint r_a, bytes32 r_d) { + bytes32 z = keccak256(abi.encodePacked(y)); if (x > 8) { - z = keccak256(y); + z = keccak256(abi.encodePacked(y)); a = x; } else { - z = keccak256(y); + z = keccak256(abi.encodePacked(y)); a = x; } r_a = a; @@ -309,19 +312,19 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions) contract test { bytes32 data; function f(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) { - r_d = keccak256(y); + r_d = keccak256(abi.encodePacked(y)); shared(y); - r_d = keccak256(y); + r_d = keccak256(abi.encodePacked(y)); r_a = 5; } function g(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) { - r_d = keccak256(y); + r_d = keccak256(abi.encodePacked(y)); shared(y); - r_d = bytes32(uint(keccak256(y)) + 2); + r_d = bytes32(uint(keccak256(abi.encodePacked(y))) + 2); r_a = 7; } function shared(bytes32 y) internal { - data = keccak256(y); + data = keccak256(abi.encodePacked(y)); } } )"; @@ -347,9 +350,9 @@ BOOST_AUTO_TEST_CASE(incorrect_storage_access_bug) contract C { mapping(uint => uint) data; - function f() returns (uint) + function f() public returns (uint) { - if(data[now] == 0) + if (data[now] == 0) data[uint(-7)] = 5; return data[now]; } @@ -366,7 +369,7 @@ BOOST_AUTO_TEST_CASE(sequence_number_for_calls) // to storage), so the sequence number should be incremented. char const* sourceCode = R"( contract test { - function f(string a, string b) returns (bool) { return sha256(a) == sha256(b); } + function f(string memory a, string memory b) public returns (bool) { return sha256(bytes(a)) == sha256(bytes(b)); } } )"; compileBothVersions(sourceCode); @@ -381,24 +384,24 @@ BOOST_AUTO_TEST_CASE(computing_constants) uint m_b; uint m_c; uint m_d; - function C() { + constructor() public { set(); } - function set() returns (uint) { + function set() public returns (uint) { m_a = 0x77abc0000000000000000000000000000000000000000000000000000000001; m_b = 0x817416927846239487123469187231298734162934871263941234127518276; g(); return 1; } - function g() { + function g() public { m_b = 0x817416927846239487123469187231298734162934871263941234127518276; m_c = 0x817416927846239487123469187231298734162934871263941234127518276; h(); } - function h() { + function h() public { m_d = 0xff05694900000000000000000000000000000000000000000000000000000000; } - function get() returns (uint ra, uint rb, uint rc, uint rd) { + function get() public returns (uint ra, uint rb, uint rc, uint rd) { ra = m_a; rb = m_b; rc = m_c; @@ -437,10 +440,8 @@ BOOST_AUTO_TEST_CASE(constant_optimization_early_exit) // This tests that the constant optimizer does not try to find the best representation // indefinitely but instead stops after some number of iterations. char const* sourceCode = R"( - pragma solidity ^0.4.0; - contract HexEncoding { - function hexEncodeTest(address addr) returns (bytes32 ret) { + function hexEncodeTest(address addr) public returns (bytes32 ret) { uint x = uint(addr) / 2**32; // Nibble interleave @@ -514,8 +515,8 @@ BOOST_AUTO_TEST_CASE(inconsistency) // Called with params: containerIndex=0, valueIndex=0 function levelIII(uint containerIndex, uint valueIndex) private { - Container container = containers[containerIndex]; - Value value = container.values[valueIndex]; + Container storage container = containers[containerIndex]; + Value storage value = container.values[valueIndex]; debug = container.valueIndices[value.number]; } function levelII() private { @@ -526,7 +527,7 @@ BOOST_AUTO_TEST_CASE(inconsistency) function trigger() public returns (uint) { containers.length++; - Container container = containers[0]; + Container storage container = containers[0]; container.values.push(Value({ badnum: 9000, @@ -557,11 +558,11 @@ BOOST_AUTO_TEST_CASE(dead_code_elimination_across_assemblies) char const* sourceCode = R"( contract DCE { function () internal returns (uint) stored; - function DCE() { + constructor() public { stored = f; } function f() internal returns (uint) { return 7; } - function test() returns (uint) { return stored(); } + function test() public returns (uint) { return stored(); } } )"; compileBothVersions(sourceCode); @@ -573,12 +574,12 @@ BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join) char const* sourceCode = R"( contract Test { uint256 public totalSupply = 100; - function f() returns (uint r) { + function f() public returns (uint r) { if (false) r = totalSupply; totalSupply -= 10; } - function test() returns (uint) { + function test() public returns (uint) { f(); return this.totalSupply(); } @@ -596,7 +597,7 @@ BOOST_AUTO_TEST_CASE(init_empty_dynamic_arrays) // not use any memory. char const* sourceCode = R"( contract Test { - function f() pure returns (uint r) { + function f() public pure returns (uint r) { uint[][] memory x = new uint[][](20000); return x.length; } @@ -615,7 +616,7 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores) struct S { uint16 a; uint16 b; uint16[3] c; uint[] dyn; } uint padding; S[] s; - function f() public returns (uint16, uint16, uint16[3], uint) { + function f() public returns (uint16, uint16, uint16[3] memory, uint) { uint16[3] memory c; c[0] = 7; c[1] = 8; diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 0c801cf62..5432e9b51 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -112,59 +112,13 @@ while(0) BOOST_AUTO_TEST_SUITE(SolidityParser) -BOOST_AUTO_TEST_CASE(multiple_return_param_trailing_comma) -{ - char const* text = R"( - contract test { - function() returns (uint a, uint b,) {} - } - )"; - CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); -} - -BOOST_AUTO_TEST_CASE(multiple_modifier_arg_trailing_comma) -{ - char const* text = R"( - contract test { - modifier modTest(uint a, uint b,) { _; } - function(uint a) {} - } - )"; - CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); -} - -BOOST_AUTO_TEST_CASE(multiple_event_arg_trailing_comma) -{ - char const* text = R"( - contract test { - event Test(uint a, uint b,); - function(uint a) {} - } - )"; - CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); -} - -BOOST_AUTO_TEST_CASE(two_exact_functions) -{ - char const* text = R"( - contract test { - function fun(uint a) returns(uint r) { return a; } - function fun(uint a) returns(uint r) { return a; } - } - )"; - // with support of overloaded functions, during parsing, - // we can't determine whether they match exactly, however - // it will throw DeclarationError in following stage. - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_CASE(function_natspec_documentation) { char const* text = R"( contract test { uint256 stateVar; /// This is a test function - function functionName(bytes32 input) returns (bytes32 out) {} + function functionName(bytes32 input) public returns (bytes32 out) {} } )"; BOOST_CHECK(successParse(text)); @@ -184,7 +138,7 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) contract test { uint256 stateVar; // We won't see this comment - function functionName(bytes32 input) returns (bytes32 out) {} + function functionName(bytes32 input) public returns (bytes32 out) {} } )"; BOOST_CHECK(successParse(text)); @@ -203,13 +157,13 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) contract test { uint256 stateVar; /// This is test function 1 - function functionName1(bytes32 input) returns (bytes32 out) {} + function functionName1(bytes32 input) public returns (bytes32 out) {} /// This is test function 2 - function functionName2(bytes32 input) returns (bytes32 out) {} + function functionName2(bytes32 input) public returns (bytes32 out) {} // nothing to see here - function functionName3(bytes32 input) returns (bytes32 out) {} + function functionName3(bytes32 input) public returns (bytes32 out) {} /// This is test function 4 - function functionName4(bytes32 input) returns (bytes32 out) {} + function functionName4(bytes32 input) public returns (bytes32 out) {} } )"; BOOST_CHECK(successParse(text)); @@ -239,7 +193,7 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) uint256 stateVar; /// This is a test function /// and it has 2 lines - function functionName1(bytes32 input) returns (bytes32 out) {} + function functionName1(bytes32 input) public returns (bytes32 out) {} } )"; BOOST_CHECK(successParse(text)); @@ -266,7 +220,7 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) } /// This is a test function /// and it has 2 lines - function fun(bytes32 input) returns (bytes32 out) {} + function fun(bytes32 input) public returns (bytes32 out) {} } )"; BOOST_CHECK(successParse(text)); @@ -334,57 +288,6 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) "Shouldn't get natspec docstring for this function"); } -BOOST_AUTO_TEST_CASE(struct_definition) -{ - char const* text = R"( - contract test { - uint256 stateVar; - struct MyStructName { - address addr; - uint256 count; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(mapping) -{ - char const* text = R"( - contract test { - mapping(address => bytes32) names; - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(mapping_in_struct) -{ - char const* text = R"( - contract test { - struct test_struct { - address addr; - uint256 count; - mapping(bytes32 => test_struct) self_reference; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) -{ - char const* text = R"( - contract test { - struct test_struct { - address addr; - mapping (uint64 => mapping (bytes32 => uint)) complex_mapping; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_CASE(variable_definition) { char const* text = R"( @@ -440,112 +343,6 @@ BOOST_AUTO_TEST_CASE(complex_expression) BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(exp_expression) -{ - char const* text = R"( - contract test { - function fun(uint256 a) { - uint256 x = 3 ** a; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(while_loop) -{ - char const* text = R"( - contract test { - function fun(uint256 a) { - while (true) { uint256 x = 1; break; continue; } x = 9; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(for_loop_vardef_initexpr) -{ - char const* text = R"( - contract test { - function fun(uint256 a) { - for (uint256 i = 0; i < 10; i++) { - uint256 x = i; break; continue; - } - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(for_loop_simple_initexpr) -{ - char const* text = R"( - contract test { - function fun(uint256 a) { - uint256 i =0; - for (i = 0; i < 10; i++) { - uint256 x = i; break; continue; - } - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(for_loop_simple_noexpr) -{ - char const* text = R"( - contract test { - function fun(uint256 a) { - uint256 i =0; - for (;;) { - uint256 x = i; break; continue; - } - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(for_loop_single_stmt_body) -{ - char const* text = R"( - contract test { - function fun(uint256 a) { - uint256 i = 0; - for (i = 0; i < 10; i++) - continue; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(if_statement) -{ - char const* text = R"( - contract test { - function fun(uint256 a) { - if (a >= 8) { return 2; } else { var b = 7; } - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(else_if_statement) -{ - char const* text = R"( - contract test { - function fun(uint256 a) returns (address b) { - if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion) { char const* text = R"( @@ -673,275 +470,70 @@ BOOST_AUTO_TEST_CASE(contract_multiple_inheritance_with_arguments) BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(placeholder_in_function_context) -{ - char const* text = R"( - contract c { - function fun() returns (uint r) { - var _ = 8; - return _ + 1; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(modifier) -{ - char const* text = R"( - contract c { - modifier mod { if (msg.sender == 0) _; } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(modifier_arguments) -{ - char const* text = R"( - contract c { - modifier mod(address a) { if (msg.sender == a) _; } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(modifier_invocation) -{ - char const* text = R"( - contract c { - modifier mod1(uint a) { if (msg.sender == a) _; } - modifier mod2 { if (msg.sender == 2) _; } - function f() mod1(7) mod2 { } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(fallback_function) -{ - char const* text = R"( - contract c { - function() { } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(event) -{ - char const* text = R"( - contract c { - event e(); - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(event_arguments) -{ - char const* text = R"( - contract c { - event e(uint a, bytes32 s); - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(event_arguments_indexed) -{ - char const* text = R"( - contract c { - event e(uint a, bytes32 indexed s, bool indexed b); - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(visibility_specifiers) -{ - char const* text = R"( - contract c { - uint private a; - uint internal b; - uint public c; - uint d; - function f() {} - function f_priv() private {} - function f_public() public {} - function f_internal() internal {} - })"; - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers) { char const* text = R"( contract c { uint private internal a; - })"; + } + )"; CHECK_PARSE_ERROR(text, "Visibility already specified as \"private\"."); text = R"( contract c { function f() private external {} - })"; + } + )"; CHECK_PARSE_ERROR(text, "Visibility already specified as \"private\"."); } -BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations) -{ - char const* text = R"( - contract c { - function c () - { - a = 1 wei; - b = 2 szabo; - c = 3 finney; - b = 4 ether; - } - uint256 a; - uint256 b; - uint256 c; - uint256 d; - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations_in_expressions) -{ - char const* text = R"( - contract c { - function c () - { - a = 1 wei * 100 wei + 7 szabo - 3; - } - uint256 a; - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(enum_valid_declaration) -{ - char const* text = R"( - contract c { - enum validEnum { Value1, Value2, Value3, Value4 } - function c () - { - a = foo.Value3; - } - uint256 a; - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(external_function) -{ - char const* text = R"( - contract c { - function x() external {} - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(arrays_in_storage) -{ - char const* text = R"( - contract c { - uint[10] a; - uint[] a2; - struct x { uint[2**20] b; y[0] c; } - struct y { uint d; mapping(uint=>x)[] e; } - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(arrays_in_events) -{ - char const* text = R"( - contract c { - event e(uint[10] a, bytes7[8] indexed b, c[3] x); - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(arrays_in_expressions) -{ - char const* text = R"( - contract c { - function f() { c[10] a = 7; uint8[10 * 2] x; } - })"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(multi_arrays) -{ - char const* text = R"( - contract c { - mapping(uint => mapping(uint => int8)[8][][9])[] x; - })"; - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_CASE(keyword_is_reserved) { auto keywords = { "abstract", "after", + "alias", + "apply", + "auto", "case", "catch", + "copyof", "default", + "define", "final", + "immutable", + "implements", "in", "inline", "let", + "macro", "match", + "mutable", "null", "of", + "override", + "partial", + "promise", + "reference", "relocatable", + "sealed", + "sizeof", "static", + "supports", "switch", "try", "type", - "typeof" + "typedef", + "typeof", + "unchecked" }; for (const auto& keyword: keywords) { auto text = std::string("contract ") + keyword + " {}"; - CHECK_PARSE_ERROR(text.c_str(), "Expected identifier but got reserved keyword"); + CHECK_PARSE_ERROR(text.c_str(), string("Expected identifier but got reserved keyword '") + keyword + "'"); } } -BOOST_AUTO_TEST_CASE(location_specifiers_for_params) -{ - char const* text = R"( - contract Foo { - function f(uint[] storage constant x, uint[] memory y) { } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(location_specifiers_for_locals) -{ - char const* text = R"( - contract Foo { - function f() { - uint[] storage x; - uint[] memory y; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(library_simple) -{ - char const* text = R"( - library Lib { - function f() { } - } - )"; - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) { char const* text = R"( @@ -986,97 +578,6 @@ BOOST_AUTO_TEST_CASE(complex_import) BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(from_is_not_keyword) -{ - // "from" is not a keyword although it is used as a keyword in import directives. - char const* text = R"( - contract from { - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(inline_array_declaration) -{ - char const* text = R"( - contract c { - uint[] a; - function f() returns (uint, uint) { - a = [1,2,3]; - return (a[3], [2,3,4][0]); - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(conditional_true_false_literal) -{ - char const* text = R"( - contract A { - function f() { - uint x = true ? 1 : 0; - uint y = false ? 0 : 1; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(conditional_with_constants) -{ - char const* text = R"( - contract A { - function f() { - uint x = 3 > 0 ? 3 : 0; - uint y = (3 > 0) ? 3 : 0; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(conditional_with_variables) -{ - char const* text = R"( - contract A { - function f() { - uint x = 3; - uint y = 1; - uint z = (x > y) ? x : y; - uint w = x > y ? x : y; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(conditional_multiple) -{ - char const* text = R"( - contract A { - function f() { - uint x = 3 < 0 ? 2 > 1 ? 2 : 1 : 7 > 2 ? 7 : 6; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(conditional_with_assignment) -{ - char const* text = R"( - contract A { - function f() { - uint y = 1; - uint x = 3 < 0 ? x = 3 : 6; - true ? x = 3 : 4; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_CASE(recursion_depth1) { string text("contract C { bytes"); @@ -1113,117 +614,6 @@ BOOST_AUTO_TEST_CASE(recursion_depth4) CHECK_PARSE_ERROR(text, "Maximum recursion depth reached during parsing"); } -BOOST_AUTO_TEST_CASE(declaring_fixed_and_ufixed_variables) -{ - char const* text = R"( - contract A { - fixed40x40 storeMe; - function f(ufixed x, fixed32x32 y) { - ufixed8x8 a; - fixed b; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(declaring_fixed_literal_variables) -{ - char const* text = R"( - contract A { - fixed40x40 pi = 3.14; - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(function_type_in_expression) -{ - char const* text = R"( - contract test { - function f(uint x, uint y) returns (uint a) {} - function g() { - function (uint, uint) internal returns (uint) f1 = f; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(function_type_as_storage_variable) -{ - char const* text = R"( - contract test { - function (uint, uint) internal returns (uint) f1; - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_assignment) -{ - char const* text = R"( - contract test { - function f(uint x, uint y) returns (uint a) {} - function (uint, uint) internal returns (uint) f1 = f; - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(function_type_in_struct) -{ - char const* text = R"( - contract test { - struct S { - function (uint x, uint y) internal returns (uint a) f; - function (uint, uint) external returns (uint) g; - uint d; - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(function_type_as_parameter) -{ - char const* text = R"( - contract test { - function f(function(uint) external returns (uint) g) internal returns (uint a) { - return g(1); - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(calling_function) -{ - char const* text = R"( - contract test { - function f() { - function() returns(function() returns(function() returns(function() returns(uint)))) x; - uint y; - y = x()()()(); - } - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(mapping_and_array_of_functions) -{ - char const* text = R"( - contract test { - mapping (address => function() internal returns (uint)) a; - mapping (address => function() external) b; - mapping (address => function() external[]) c; - function() external[] d; - } - )"; - BOOST_CHECK(successParse(text)); -} - BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 4ccc67885..6965d886a 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -66,6 +66,14 @@ BOOST_AUTO_TEST_CASE(string_escapes) BOOST_CHECK_EQUAL(scanner.currentLiteral(), "aa"); } +BOOST_AUTO_TEST_CASE(string_escapes_all) +{ + Scanner scanner(CharStream(" { \"a\\x61\\b\\f\\n\\r\\t\\v\"")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); + BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "aa\b\f\n\r\t\v"); +} + BOOST_AUTO_TEST_CASE(string_escapes_with_zero) { Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); @@ -97,6 +105,11 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x765432536763762734623472346"); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + scanner.reset(CharStream("0x1234"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x1234"); + scanner.reset(CharStream("0X1234"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); } BOOST_AUTO_TEST_CASE(octal_numbers) @@ -129,6 +142,96 @@ BOOST_AUTO_TEST_CASE(scientific_notation) BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } +BOOST_AUTO_TEST_CASE(trailing_dot) +{ + Scanner scanner(CharStream("2.5")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + scanner.reset(CharStream("2.5e10"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + scanner.reset(CharStream(".5"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + scanner.reset(CharStream(".5e10"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + scanner.reset(CharStream("2."), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::Period); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(leading_underscore_decimal_is_identifier) +{ + // Actual error is cought by SyntaxChecker. + Scanner scanner(CharStream("_1.2")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.next(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(leading_underscore_decimal_after_dot_illegal) +{ + // Actual error is cought by SyntaxChecker. + Scanner scanner(CharStream("1._2")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + + scanner.reset(CharStream("1._"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(leading_underscore_exp_are_identifier) +{ + // Actual error is cought by SyntaxChecker. + Scanner scanner(CharStream("_1e2")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(leading_underscore_exp_after_e_illegal) +{ + // Actual error is cought by SyntaxChecker. + Scanner scanner(CharStream("1e_2")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "1e_2"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(leading_underscore_hex_illegal) +{ + Scanner scanner(CharStream("0x_abc")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(fixed_number_invalid_underscore_front) +{ + // Actual error is cought by SyntaxChecker. + Scanner scanner(CharStream("12._1234_1234")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(number_literals_with_trailing_underscore_at_eos) +{ + // Actual error is cought by SyntaxChecker. + Scanner scanner(CharStream("0x123_")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + + scanner.reset(CharStream("123_"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + + scanner.reset(CharStream("12.34_"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + BOOST_AUTO_TEST_CASE(negative_numbers) { Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9 + 2e-2;")); @@ -181,7 +284,7 @@ BOOST_AUTO_TEST_CASE(locations) BOOST_AUTO_TEST_CASE(ambiguities) { // test scanning of some operators which need look-ahead - Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); + Scanner scanner(CharStream("<=" "<" "+ +=a++ =>" "<<" ">>" " >>=" ">>>" ">>>=" " >>>>>=><<=")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LessThanOrEqual); BOOST_CHECK_EQUAL(scanner.next(), Token::LessThan); BOOST_CHECK_EQUAL(scanner.next(), Token::Add); @@ -190,6 +293,15 @@ BOOST_AUTO_TEST_CASE(ambiguities) BOOST_CHECK_EQUAL(scanner.next(), Token::Inc); BOOST_CHECK_EQUAL(scanner.next(), Token::Arrow); BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); + BOOST_CHECK_EQUAL(scanner.next(), Token::SAR); + BOOST_CHECK_EQUAL(scanner.next(), Token::AssignSar); + BOOST_CHECK_EQUAL(scanner.next(), Token::SHR); + BOOST_CHECK_EQUAL(scanner.next(), Token::AssignShr); + // the last "monster" token combination + BOOST_CHECK_EQUAL(scanner.next(), Token::SHR); + BOOST_CHECK_EQUAL(scanner.next(), Token::AssignSar); + BOOST_CHECK_EQUAL(scanner.next(), Token::GreaterThan); + BOOST_CHECK_EQUAL(scanner.next(), Token::AssignShl); } BOOST_AUTO_TEST_CASE(documentation_comments_parsed_begin) @@ -359,6 +471,8 @@ BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape) BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); } +// HEX STRING LITERAL + BOOST_AUTO_TEST_CASE(valid_hex_literal) { Scanner scanner(CharStream("{ hex\"00112233FF\"")); @@ -371,30 +485,32 @@ BOOST_AUTO_TEST_CASE(invalid_short_hex_literal) { Scanner scanner(CharStream("{ hex\"00112233F\"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_space) { Scanner scanner(CharStream("{ hex\"00112233FF \"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_wrong_quotes) { Scanner scanner(CharStream("{ hex\"00112233FF'")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string) { Scanner scanner(CharStream("{ hex\"hello\"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); } +// COMMENTS + BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close) { // This used to parse as "comment", "identifier" diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 738b24bc1..6f9d4ce8c 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include using namespace std; @@ -36,6 +36,47 @@ namespace test BOOST_AUTO_TEST_SUITE(SolidityTypes) +BOOST_AUTO_TEST_CASE(int_types) +{ + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Int, 0, 0)) == *make_shared(256, IntegerType::Modifier::Signed)); + for (unsigned i = 8; i <= 256; i += 8) + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::IntM, i, 0)) == *make_shared(i, IntegerType::Modifier::Signed)); +} + +BOOST_AUTO_TEST_CASE(uint_types) +{ + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UInt, 0, 0)) == *make_shared(256, IntegerType::Modifier::Unsigned)); + for (unsigned i = 8; i <= 256; i += 8) + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UIntM, i, 0)) == *make_shared(i, IntegerType::Modifier::Unsigned)); +} + +BOOST_AUTO_TEST_CASE(byte_types) +{ + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Byte, 0, 0)) == *make_shared(1)); + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, i, 0)) == *make_shared(i)); +} + +BOOST_AUTO_TEST_CASE(fixed_types) +{ + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Fixed, 0, 0)) == *make_shared(128, 18, FixedPointType::Modifier::Signed)); + for (unsigned i = 8; i <= 256; i += 8) + { + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::FixedMxN, i, 0)) == *make_shared(i, 0, FixedPointType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::FixedMxN, i, 2)) == *make_shared(i, 2, FixedPointType::Modifier::Signed)); + } +} + +BOOST_AUTO_TEST_CASE(ufixed_types) +{ + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UFixed, 0, 0)) == *make_shared(128, 18, FixedPointType::Modifier::Unsigned)); + for (unsigned i = 8; i <= 256; i += 8) + { + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UFixedMxN, i, 0)) == *make_shared(i, 0, FixedPointType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UFixedMxN, i, 2)) == *make_shared(i, 2, FixedPointType::Modifier::Unsigned)); + } +} + BOOST_AUTO_TEST_CASE(storage_layout_simple) { MemberList members(MemberList::MemberMap({ @@ -88,12 +129,13 @@ BOOST_AUTO_TEST_CASE(storage_layout_arrays) BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared(32), 9).storageSize() == 9); } -BOOST_AUTO_TEST_CASE(type_escaping) +BOOST_AUTO_TEST_CASE(type_identifier_escaping) { BOOST_CHECK_EQUAL(Type::escapeIdentifier("("), "$_"); BOOST_CHECK_EQUAL(Type::escapeIdentifier(")"), "_$"); BOOST_CHECK_EQUAL(Type::escapeIdentifier(","), "_$_"); BOOST_CHECK_EQUAL(Type::escapeIdentifier("$"), "$$$"); + BOOST_CHECK_EQUAL(Type::escapeIdentifier(")$("), "_$$$$$_"); BOOST_CHECK_EQUAL(Type::escapeIdentifier("()"), "$__$"); BOOST_CHECK_EQUAL(Type::escapeIdentifier("(,)"), "$__$__$"); BOOST_CHECK_EQUAL(Type::escapeIdentifier("(,$,)"), "$__$_$$$_$__$"); @@ -110,21 +152,28 @@ BOOST_AUTO_TEST_CASE(type_identifiers) BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("int128")->identifier(), "t_int128"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("address")->identifier(), "t_address"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("uint8")->identifier(), "t_uint8"); - BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("ufixed8x64")->identifier(), "t_ufixed8x64"); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("ufixed64x2")->identifier(), "t_ufixed64x2"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("fixed128x8")->identifier(), "t_fixed128x8"); BOOST_CHECK_EQUAL(RationalNumberType(rational(7, 1)).identifier(), "t_rational_7_by_1"); BOOST_CHECK_EQUAL(RationalNumberType(rational(200, 77)).identifier(), "t_rational_200_by_77"); BOOST_CHECK_EQUAL(RationalNumberType(rational(2 * 200, 2 * 77)).identifier(), "t_rational_200_by_77"); + BOOST_CHECK_EQUAL(RationalNumberType(rational(-2 * 200, 2 * 77)).identifier(), "t_rational_minus_200_by_77"); BOOST_CHECK_EQUAL( StringLiteralType(Literal(SourceLocation{}, Token::StringLiteral, make_shared("abc - def"))).identifier(), "t_stringliteral_196a9142ee0d40e274a6482393c762b16dd8315713207365e1e13d8d85b74fc4" ); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("byte")->identifier(), "t_bytes1"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes8")->identifier(), "t_bytes8"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes32")->identifier(), "t_bytes32"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bool")->identifier(), "t_bool"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes")->identifier(), "t_bytes_storage_ptr"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes memory")->identifier(), "t_bytes_memory_ptr"); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes storage")->identifier(), "t_bytes_storage_ptr"); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes calldata")->identifier(), "t_bytes_calldata_ptr"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("string")->identifier(), "t_string_storage_ptr"); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("string memory")->identifier(), "t_string_memory_ptr"); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("string storage")->identifier(), "t_string_storage_ptr"); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("string calldata")->identifier(), "t_string_calldata_ptr"); ArrayType largeintArray(DataLocation::Memory, Type::fromElementaryTypeName("int128"), u256("2535301200456458802993406410752")); BOOST_CHECK_EQUAL(largeintArray.identifier(), "t_array$_t_int128_$2535301200456458802993406410752_memory_ptr"); TypePointer stringArray = make_shared(DataLocation::Storage, Type::fromElementaryTypeName("string"), u256("20")); @@ -144,11 +193,11 @@ BOOST_AUTO_TEST_CASE(type_identifiers) TupleType t({e.type(), s.type(), stringArray, nullptr}); BOOST_CHECK_EQUAL(t.identifier(), "t_tuple$_t_type$_t_enum$_Enum_$4_$_$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$_t_array$_t_string_storage_$20_storage_ptr_$__$"); - TypePointer sha3fun = make_shared(strings{}, strings{}, FunctionType::Kind::SHA3); - BOOST_CHECK_EQUAL(sha3fun->identifier(), "t_function_sha3_nonpayable$__$returns$__$"); + TypePointer keccak256fun = make_shared(strings{}, strings{}, FunctionType::Kind::KECCAK256); + BOOST_CHECK_EQUAL(keccak256fun->identifier(), "t_function_keccak256_nonpayable$__$returns$__$"); - FunctionType metaFun(TypePointers{sha3fun}, TypePointers{s.type()}); - BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_sha3_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$"); + FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()}); + BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_keccak256_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$"); TypePointer m = make_shared(Type::fromElementaryTypeName("bytes32"), s.type()); MappingType m2(Type::fromElementaryTypeName("uint64"), m); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 63c038816..1570a9d26 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -225,6 +225,71 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_CHECK(containsAtMostWarnings(result)); } +BOOST_AUTO_TEST_CASE(optimizer_enabled_not_boolean) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "optimizer": { + "enabled": "wrong" + } + }, + "sources": { + "empty": { + "content": "" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsError(result, "JSONError", "The \"enabled\" setting must be a boolean.")); +} + +BOOST_AUTO_TEST_CASE(optimizer_runs_not_a_number) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "optimizer": { + "enabled": true, + "runs": "not a number" + } + }, + "sources": { + "empty": { + "content": "" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number.")); +} + +BOOST_AUTO_TEST_CASE(optimizer_runs_not_an_unsigned_number) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "optimizer": { + "enabled": true, + "runs": -1 + } + }, + "sources": { + "empty": { + "content": "" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number.")); +} + BOOST_AUTO_TEST_CASE(basic_compilation) { char const* input = R"( @@ -238,7 +303,7 @@ BOOST_AUTO_TEST_CASE(basic_compilation) "settings": { "outputSelection": { "fileA": { - "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "metadata" ], + "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "evm.legacyAssembly", "metadata" ], "": [ "legacyAST" ] } } @@ -261,7 +326,7 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()), - "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" + "6080604052348015600f57600080fd5b50603580601d6000396000f3fe6080604052600080fdfe" ); BOOST_CHECK(contract["evm"]["assembly"].isString()); BOOST_CHECK(contract["evm"]["assembly"].asString().find( @@ -280,6 +345,34 @@ BOOST_AUTO_TEST_CASE(basic_compilation) dev::jsonCompactPrint(contract["evm"]["gasEstimates"]), "{\"creation\":{\"codeDepositCost\":\"10600\",\"executionCost\":\"66\",\"totalCost\":\"10666\"}}" ); + // Lets take the top level `.code` section (the "deployer code"), that should expose most of the features of + // the assembly JSON. What we want to check here is Operation, Push, PushTag, PushSub, PushSubSize and Tag. + BOOST_CHECK(contract["evm"]["legacyAssembly"].isObject()); + BOOST_CHECK(contract["evm"]["legacyAssembly"][".code"].isArray()); + BOOST_CHECK_EQUAL( + dev::jsonCompactPrint(contract["evm"]["legacyAssembly"][".code"]), + "[{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"80\"}," + "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"40\"}," + "{\"begin\":0,\"end\":14,\"name\":\"MSTORE\"}," + "{\"begin\":0,\"end\":14,\"name\":\"CALLVALUE\"}," + "{\"begin\":8,\"end\":17,\"name\":\"DUP1\"}," + "{\"begin\":5,\"end\":7,\"name\":\"ISZERO\"}," + "{\"begin\":5,\"end\":7,\"name\":\"PUSH [tag]\",\"value\":\"1\"}," + "{\"begin\":5,\"end\":7,\"name\":\"JUMPI\"}," + "{\"begin\":30,\"end\":31,\"name\":\"PUSH\",\"value\":\"0\"}," + "{\"begin\":27,\"end\":28,\"name\":\"DUP1\"}," + "{\"begin\":20,\"end\":32,\"name\":\"REVERT\"}," + "{\"begin\":5,\"end\":7,\"name\":\"tag\",\"value\":\"1\"}," + "{\"begin\":5,\"end\":7,\"name\":\"JUMPDEST\"}," + "{\"begin\":0,\"end\":14,\"name\":\"POP\"}," + "{\"begin\":0,\"end\":14,\"name\":\"PUSH #[$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}," + "{\"begin\":0,\"end\":14,\"name\":\"DUP1\"}," + "{\"begin\":0,\"end\":14,\"name\":\"PUSH [$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}," + "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"0\"}," + "{\"begin\":0,\"end\":14,\"name\":\"CODECOPY\"}," + "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"0\"}," + "{\"begin\":0,\"end\":14,\"name\":\"RETURN\"}]" + ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); BOOST_CHECK(result["sources"].isObject()); @@ -466,7 +559,7 @@ BOOST_AUTO_TEST_CASE(output_selection_dependent_contract) }, "sources": { "fileA": { - "content": "contract B { } contract A { function f() { new B(); } }" + "content": "contract B { } contract A { function f() public { new B(); } }" } } } @@ -495,7 +588,7 @@ BOOST_AUTO_TEST_CASE(output_selection_dependent_contract_with_import) }, "sources": { "fileA": { - "content": "import \"fileB\"; contract A { function f() { new B(); } }" + "content": "import \"fileB\"; contract A { function f() public { new B(); } }" }, "fileB": { "content": "contract B { }" @@ -556,10 +649,10 @@ BOOST_AUTO_TEST_CASE(library_filename_with_colon) }, "sources": { "fileA": { - "content": "import \"git:library.sol\"; contract A { function f() returns (uint) { return L.g(); } }" + "content": "import \"git:library.sol\"; contract A { function f() public returns (uint) { return L.g(); } }" }, "git:library.sol": { - "content": "library L { function g() returns (uint) { return 1; } }" + "content": "library L { function g() public returns (uint) { return 1; } }" } } } @@ -612,7 +705,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_entry) } )"; Json::Value result = compile(input); - BOOST_CHECK(containsError(result, "JSONError", "library entry is not a JSON object.")); + BOOST_CHECK(containsError(result, "JSONError", "Library entry is not a JSON object.")); } BOOST_AUTO_TEST_CASE(libraries_invalid_hex) @@ -706,13 +799,13 @@ BOOST_AUTO_TEST_CASE(library_linking) }, "sources": { "fileA": { - "content": "import \"library.sol\"; import \"library2.sol\"; contract A { function f() returns (uint) { L2.g(); return L.g(); } }" + "content": "import \"library.sol\"; import \"library2.sol\"; contract A { function f() public returns (uint) { L2.g(); return L.g(); } }" }, "library.sol": { - "content": "library L { function g() returns (uint) { return 1; } }" + "content": "library L { function g() public returns (uint) { return 1; } }" }, "library2.sol": { - "content": "library L2 { function g() { } }" + "content": "library L2 { function g() public { } }" } } } diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 1c2355d5f..91d1681f1 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -33,28 +32,10 @@ using namespace std; namespace fs = boost::filesystem; using namespace boost::unit_test; -template -void skipWhitespace(IteratorType& _it, IteratorType _end) +namespace { - while (_it != _end && isspace(*_it)) - ++_it; -} -template -void skipSlashes(IteratorType& _it, IteratorType _end) -{ - while (_it != _end && *_it == '/') - ++_it; -} - -void expect(string::iterator& _it, string::iterator _end, string::value_type _c) -{ - if (_it == _end || *_it != _c) - throw runtime_error(string("Invalid test expectation. Expected: \"") + _c + "\"."); - ++_it; -} - -int parseUnsignedInteger(string::iterator &_it, string::iterator _end) +int parseUnsignedInteger(string::iterator& _it, string::iterator _end) { if (_it == _end || !isdigit(*_it)) throw runtime_error("Invalid test expectation. Source location expected."); @@ -68,6 +49,8 @@ int parseUnsignedInteger(string::iterator &_it, string::iterator _end) return result; } +} + SyntaxTest::SyntaxTest(string const& _filename) { ifstream file(_filename); @@ -120,6 +103,55 @@ bool SyntaxTest::run(ostream& _stream, string const& _linePrefix, bool const _fo return true; } +void SyntaxTest::printSource(ostream& _stream, string const& _linePrefix, bool const _formatted) const +{ + if (_formatted) + { + if (m_source.empty()) + return; + + vector sourceFormatting(m_source.length(), formatting::RESET); + for (auto const& error: m_errorList) + if (error.locationStart >= 0 && error.locationEnd >= 0) + { + assert(static_cast(error.locationStart) <= m_source.length()); + assert(static_cast(error.locationEnd) <= m_source.length()); + bool isWarning = error.type == "Warning"; + for (int i = error.locationStart; i < error.locationEnd; i++) + if (isWarning) + { + if (sourceFormatting[i] == formatting::RESET) + sourceFormatting[i] = formatting::ORANGE_BACKGROUND; + } + else + sourceFormatting[i] = formatting::RED_BACKGROUND; + } + + _stream << _linePrefix << sourceFormatting.front() << m_source.front(); + for (size_t i = 1; i < m_source.length(); i++) + { + if (sourceFormatting[i] != sourceFormatting[i - 1]) + _stream << sourceFormatting[i]; + if (m_source[i] != '\n') + _stream << m_source[i]; + else + { + _stream << formatting::RESET << endl; + if (i + 1 < m_source.length()) + _stream << _linePrefix << sourceFormatting[i]; + } + } + _stream << formatting::RESET; + } + else + { + stringstream stream(m_source); + string line; + while (getline(stream, line)) + _stream << _linePrefix << line << endl; + } +} + void SyntaxTest::printErrorList( ostream& _stream, vector const& _errorList, @@ -159,19 +191,6 @@ string SyntaxTest::errorMessage(Exception const& _e) return "NONE"; } -string SyntaxTest::parseSource(istream& _stream) -{ - string source; - string line; - string const delimiter("// ----"); - while (getline(_stream, line)) - if (boost::algorithm::starts_with(line, delimiter)) - break; - else - source += line + "\n"; - return source; -} - vector SyntaxTest::parseExpectations(istream& _stream) { vector expectations; @@ -220,64 +239,3 @@ vector SyntaxTest::parseExpectations(istream& _stream) } return expectations; } - -#if BOOST_VERSION < 105900 -test_case *make_test_case( - function const& _fn, - string const& _name, - string const& /* _filename */, - size_t /* _line */ -) -{ - return make_test_case(_fn, _name); -} -#endif - -bool SyntaxTest::isTestFilename(boost::filesystem::path const& _filename) -{ - return _filename.extension().string() == ".sol" && - !boost::starts_with(_filename.string(), "~") && - !boost::starts_with(_filename.string(), "."); -} - -int SyntaxTest::registerTests( - boost::unit_test::test_suite& _suite, - boost::filesystem::path const& _basepath, - boost::filesystem::path const& _path -) -{ - int numTestsAdded = 0; - fs::path fullpath = _basepath / _path; - if (fs::is_directory(fullpath)) - { - test_suite* sub_suite = BOOST_TEST_SUITE(_path.filename().string()); - for (auto const& entry: boost::iterator_range( - fs::directory_iterator(fullpath), - fs::directory_iterator() - )) - if (fs::is_directory(entry.path()) || isTestFilename(entry.path().filename())) - numTestsAdded += registerTests(*sub_suite, _basepath, _path / entry.path().filename()); - _suite.add(sub_suite); - } - else - { - static vector> filenames; - - filenames.emplace_back(new string(_path.string())); - _suite.add(make_test_case( - [fullpath] - { - BOOST_REQUIRE_NO_THROW({ - stringstream errorStream; - if (!SyntaxTest(fullpath.string()).run(errorStream)) - BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str()); - }); - }, - _path.stem().string(), - *filenames.back(), - 0 - )); - numTestsAdded = 1; - } - return numTestsAdded; -} diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index 6159e7894..e9e36aa60 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -19,11 +19,9 @@ #include #include +#include #include -#include -#include - #include #include #include @@ -52,17 +50,24 @@ struct SyntaxTestError }; -class SyntaxTest: AnalysisFramework +class SyntaxTest: AnalysisFramework, public TestCase { public: + static std::unique_ptr create(std::string const& _filename) + { return std::unique_ptr(new SyntaxTest(_filename)); } SyntaxTest(std::string const& _filename); - bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false); + virtual bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; - std::vector const& expectations() const { return m_expectations; } - std::string const& source() const { return m_source; } - std::vector const& errorList() const { return m_errorList; } + virtual void printSource(std::ostream &_stream, std::string const &_linePrefix = "", bool const _formatted = false) const override; + virtual void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override + { + if (!m_errorList.empty()) + printErrorList(_stream, m_errorList, _linePrefix, false); + } + static std::string errorMessage(Exception const& _e); +private: static void printErrorList( std::ostream& _stream, std::vector const& _errors, @@ -70,15 +75,6 @@ public: bool const _formatted = false ); - static int registerTests( - boost::unit_test::test_suite& _suite, - boost::filesystem::path const& _basepath, - boost::filesystem::path const& _path - ); - static bool isTestFilename(boost::filesystem::path const& _filename); - static std::string errorMessage(Exception const& _e); -private: - static std::string parseSource(std::istream& _stream); static std::vector parseExpectations(std::istream& _stream); std::string m_source; diff --git a/test/libsolidity/TestCase.cpp b/test/libsolidity/TestCase.cpp new file mode 100644 index 000000000..179722698 --- /dev/null +++ b/test/libsolidity/TestCase.cpp @@ -0,0 +1,56 @@ +/* + 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 . +*/ + +#include + +#include +#include + +#include + +using namespace dev; +using namespace solidity; +using namespace dev::solidity::test; +using namespace std; + +bool TestCase::isTestFilename(boost::filesystem::path const& _filename) +{ + string extension = _filename.extension().string(); + return (extension == ".sol" || extension == ".yul") && + !boost::starts_with(_filename.string(), "~") && + !boost::starts_with(_filename.string(), "."); +} + +string TestCase::parseSource(istream& _stream) +{ + string source; + string line; + string const delimiter("// ----"); + while (getline(_stream, line)) + if (boost::algorithm::starts_with(line, delimiter)) + break; + else + source += line + "\n"; + return source; +} + +void TestCase::expect(string::iterator& _it, string::iterator _end, string::value_type _c) +{ + if (_it == _end || *_it != _c) + throw runtime_error(string("Invalid test expectation. Expected: \"") + _c + "\"."); + ++_it; +} diff --git a/test/libsolidity/TestCase.h b/test/libsolidity/TestCase.h new file mode 100644 index 000000000..3c05ae4e9 --- /dev/null +++ b/test/libsolidity/TestCase.h @@ -0,0 +1,80 @@ +/* + 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 + +#include +#include +#include + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +/** Common superclass of SyntaxTest and SemanticsTest. */ +class TestCase +{ +public: + using TestCaseCreator = std::unique_ptr(*)(std::string const&); + + virtual ~TestCase() {} + + /// Runs the test case. + /// Outputs error messages to @arg _stream. Each line of output is prefixed with @arg _linePrefix. + /// Optionally, color-coding can be enabled (if @arg _formatted is set to true). + /// @returns true, if the test case succeeds, false otherwise + virtual bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) = 0; + + /// Outputs the test contract to @arg _stream. + /// Each line of output is prefixed with @arg _linePrefix. + /// If @arg _formatted is true, color-coding may be used to indicate + /// error locations in the contract, if applicable. + virtual void printSource(std::ostream &_stream, std::string const &_linePrefix = "", bool const _formatted = false) const = 0; + /// Outputs test expectations to @arg _stream that match the actual results of the test. + /// Each line of output is prefixed with @arg _linePrefix. + virtual void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const = 0; + + static bool isTestFilename(boost::filesystem::path const& _filename); + +protected: + static std::string parseSource(std::istream& _file); + static void expect(std::string::iterator& _it, std::string::iterator _end, std::string::value_type _c); + + template + static void skipWhitespace(IteratorType& _it, IteratorType _end) + { + while (_it != _end && isspace(*_it)) + ++_it; + } + + template + static void skipSlashes(IteratorType& _it, IteratorType _end) + { + while (_it != _end && *_it == '/') + ++_it; + } + +}; + +} +} +} diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index cd0a0b01c..b7ea1efcb 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -38,91 +38,27 @@ namespace test BOOST_FIXTURE_TEST_SUITE(ViewPureChecker, AnalysisFramework) -BOOST_AUTO_TEST_CASE(smoke_test) -{ - char const* text = R"( - contract C { - uint x; - function g() pure public {} - function f() view public returns (uint) { return now; } - function h() public { x = 2; } - function i() payable public { x = 2; } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(call_internal_functions_success) -{ - char const* text = R"( - contract C { - function g() pure public { g(); } - function f() view public returns (uint) { f(); g(); } - function h() public { h(); g(); f(); } - function i() payable public { i(); h(); g(); f(); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(suggest_pure) -{ - char const* text = R"( - contract C { - function g() view public { } - } - )"; - CHECK_WARNING(text, "can be restricted to pure"); -} - -BOOST_AUTO_TEST_CASE(suggest_view) -{ - char const* text = R"( - contract C { - uint x; - function g() public returns (uint) { return x; } - } - )"; - CHECK_WARNING(text, "can be restricted to view"); -} - -BOOST_AUTO_TEST_CASE(call_internal_functions_fail) -{ - CHECK_ERROR( - "contract C{ function f() pure public { g(); } function g() view public {} }", - TypeError, - "Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires \"view\"" - ); -} - -BOOST_AUTO_TEST_CASE(write_storage_fail) -{ - CHECK_WARNING( - "contract C{ uint x; function f() view public { x = 2; } }", - "Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable." - ); -} - BOOST_AUTO_TEST_CASE(environment_access) { vector view{ "block.coinbase", "block.timestamp", - "block.blockhash(7)", "block.difficulty", "block.number", "block.gaslimit", "blockhash(7)", "gasleft()", - "msg.gas", "msg.value", "msg.sender", "tx.origin", "tx.gasprice", "this", - "address(1).balance" + "address(1).balance", }; - // ``block.blockhash`` and ``blockhash`` are tested seperately below because their usage will + if (dev::test::Options::get().evmVersion().hasStaticCall()) + view.emplace_back("address(0x4242).staticcall(\"\")"); + + // ``block.blockhash`` and ``blockhash`` are tested separately below because their usage will // produce warnings that can't be handled in a generic way. vector pure{ "msg.data", @@ -155,282 +91,29 @@ BOOST_AUTO_TEST_CASE(environment_access) "Statement has no effect." })); - CHECK_WARNING_ALLOW_MULTI( - "contract C { function f() view public { block.blockhash; } }", - (std::vector{ - "Function state mutability can be restricted to pure", - "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\"" - })); -} - -BOOST_AUTO_TEST_CASE(view_error_for_050) -{ CHECK_ERROR( - "pragma experimental \"v0.5.0\"; contract C { uint x; function f() view public { x = 2; } }", + "contract C { function f() view public { block.blockhash; } }", TypeError, - "Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable." + "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\"" ); - } -BOOST_AUTO_TEST_CASE(modifiers) -{ - string text = R"( - contract D { - uint x; - modifier purem(uint) { _; } - modifier viewm(uint) { uint a = x; _; a; } - modifier nonpayablem(uint) { x = 2; _; } - } - contract C is D { - function f() purem(0) pure public {} - function g() viewm(0) view public {} - function h() nonpayablem(0) public {} - function i() purem(x) view public {} - function j() viewm(x) view public {} - function k() nonpayablem(x) public {} - function l() purem(x = 2) public {} - function m() viewm(x = 2) public {} - function n() nonpayablem(x = 2) public {} - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(interface) -{ - string text = R"( - interface D { - function f() view external; - } - contract C is D { - function f() view external {} - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(overriding) -{ - string text = R"( - contract D { - uint x; - function f() public { x = 2; } - } - contract C is D { - function f() public {} - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(returning_structs) +BOOST_AUTO_TEST_CASE(address_staticcall) { string text = R"( contract C { - struct S { uint x; } - S s; - function f() view internal returns (S storage) { - return s; - } - function g() public { - f().x = 2; - } - function h() view public { - f(); - f().x; + function i() view public returns (bool) { + (bool success,) = address(0x4242).staticcall(""); + return success; } } )"; - CHECK_SUCCESS_NO_WARNINGS(text); + if (!dev::test::Options::get().evmVersion().hasStaticCall()) + CHECK_ERROR(text, TypeError, "\"staticcall\" is not supported by the VM version."); + else + CHECK_SUCCESS_NO_WARNINGS(text); } -BOOST_AUTO_TEST_CASE(mappings) -{ - string text = R"( - contract C { - mapping(uint => uint) a; - function f() view public { - a; - } - function g() view public { - a[2]; - } - function h() public { - a[2] = 3; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(local_storage_variables) -{ - string text = R"( - contract C { - struct S { uint a; } - S s; - function f() view public { - S storage x = s; - x; - } - function g() view public { - S storage x = s; - x = s; - } - function i() public { - s.a = 2; - } - function h() public { - S storage x = s; - x.a = 2; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(builtin_functions) -{ - string text = R"( - contract C { - function f() public { - address(this).transfer(1); - require(address(this).send(2)); - selfdestruct(address(this)); - require(address(this).delegatecall()); - require(address(this).call()); - } - function g() pure public { - bytes32 x = keccak256("abc"); - bytes32 y = sha256("abc"); - address z = ecrecover(1, 2, 3, 4); - require(true); - assert(true); - x; y; z; - } - function() payable public {} - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(function_types) -{ - string text = R"( - contract C { - function f() pure public { - function () external nonpayFun; - function () external view viewFun; - function () external pure pureFun; - - nonpayFun; - viewFun; - pureFun; - pureFun(); - } - function g() view public { - function () external view viewFun; - - viewFun(); - } - function h() public { - function () external nonpayFun; - - nonpayFun(); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(selector) -{ - string text = R"( - contract C { - uint public x; - function f() payable public { - } - function g() pure public returns (bytes4) { - return this.f.selector ^ this.x.selector; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(selector_complex) -{ - string text = R"( - contract C { - function f(C c) pure public returns (C) { - return c; - } - function g() pure public returns (bytes4) { - // By passing `this`, we read from the state, even if f itself is pure. - return f(this).f.selector; - } - } - )"; - CHECK_ERROR(text, TypeError, "reads from the environment or state and thus requires \"view\""); -} - -BOOST_AUTO_TEST_CASE(selector_complex2) -{ - string text = R"( - contract C { - function f() payable public returns (C) { - return this; - } - function g() pure public returns (bytes4) { - C x = C(0x123); - return x.f.selector; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(creation) -{ - string text = R"( - contract D {} - contract C { - function f() public { new D(); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(assembly) -{ - string text = R"( - contract C { - struct S { uint x; } - S s; - function e() pure public { - assembly { mstore(keccak256(0, 20), mul(s_slot, 2)) } - } - function f() pure public { - uint x; - assembly { x := 7 } - } - function g() view public { - assembly { for {} 1 { pop(sload(0)) } { } pop(gas) } - } - function h() view public { - assembly { function g() { pop(blockhash(20)) } } - } - function j() public { - assembly { pop(call(0, 1, 2, 3, 4, 5, 6)) } - } - function k() public { - assembly { pop(call(gas, 1, 2, 3, 4, 5, 6)) } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} BOOST_AUTO_TEST_CASE(assembly_staticcall) { @@ -447,31 +130,6 @@ BOOST_AUTO_TEST_CASE(assembly_staticcall) CHECK_SUCCESS_NO_WARNINGS(text); } -BOOST_AUTO_TEST_CASE(assembly_jump) -{ - string text = R"( - contract C { - function k() public { - assembly { jump(2) } - } - } - )"; - CHECK_WARNING(text, "low-level EVM features"); -} - -BOOST_AUTO_TEST_CASE(constant) -{ - string text = R"( - contract C { - uint constant x = 2; - function k() pure public returns (uint) { - return x; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_1.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_1.sol new file mode 100644 index 000000000..25a42db60 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_1.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; +contract C +{ + function h(uint x) public pure returns (uint) { + return x; + } + function g() public pure { + uint x; + x = h(42); + assert(x > 0); + } +} + diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_1_fail.sol new file mode 100644 index 000000000..a70aaf61d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_1_fail.sol @@ -0,0 +1,15 @@ +pragma experimental SMTChecker; +contract C +{ + function h(uint x) public pure returns (uint) { + return x; + } + function g() public pure { + uint x; + x = h(0); + assert(x > 0); + } +} + +// ---- +// Warning: (161-174): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_2.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_2.sol new file mode 100644 index 000000000..aff24b032 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_2.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; +contract C +{ + function h(uint x) public pure returns (uint) { + return k(x); + } + + function k(uint x) public pure returns (uint) { + return x; + } + function g() public pure { + uint x; + x = h(2); + assert(x > 0); + } +} + diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_2_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_2_fail.sol new file mode 100644 index 000000000..9baeb9351 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_2_fail.sol @@ -0,0 +1,19 @@ +pragma experimental SMTChecker; +contract C +{ + function h(uint x) public pure returns (uint) { + return k(x); + } + + function k(uint x) public pure returns (uint) { + return x; + } + function g() public pure { + uint x; + x = h(0); + assert(x > 0); + } +} + +// ---- +// Warning: (229-242): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple.sol new file mode 100644 index 000000000..3793f4116 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; +contract C +{ + function h(uint x) public pure returns (uint) { + return x; + } + function g() public pure { + uint x; + x = (h)(42); + assert(x > 0); + } +} + +// ---- diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple_fail.sol new file mode 100644 index 000000000..e3c805947 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple_fail.sol @@ -0,0 +1,15 @@ +pragma experimental SMTChecker; +contract C +{ + function h(uint x) public pure returns (uint) { + return x; + } + function g() public pure { + uint x; + x = (h)(0); + assert(x > 0); + } +} + +// ---- +// Warning: (163-176): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_recursive.sol b/test/libsolidity/smtCheckerTests/functions/functions_recursive.sol new file mode 100644 index 000000000..d2f8ab1db --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_recursive.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; +contract C +{ + uint a; + function g() public { + if (a > 0) + { + a = a - 1; + g(); + } + else + assert(a == 0); + } +} + +// ---- +// Warning: (111-114): Assertion checker does not support recursive function calls. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_recursive_indirect.sol b/test/libsolidity/smtCheckerTests/functions/functions_recursive_indirect.sol new file mode 100644 index 000000000..d5b83f007 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_recursive_indirect.sol @@ -0,0 +1,26 @@ +pragma experimental SMTChecker; +contract C +{ + uint a; + function f() public { + if (a > 0) + { + a = a - 1; + g(); + } + else + assert(a == 0); + } + function g() public { + if (a > 0) + { + a = a - 1; + f(); + } + else + assert(a == 0); + } +} +// ---- +// Warning: (206-209): Assertion checker does not support recursive function calls. +// Warning: (111-114): Assertion checker does not support recursive function calls. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_storage_var_1.sol b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_1.sol new file mode 100644 index 000000000..2f7563ddd --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_1.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; +contract C +{ + uint a; + function f(uint x) public { + uint y; + a = (y = x); + } + function g() public { + f(1); + assert(a > 0); + } +} + diff --git a/test/libsolidity/smtCheckerTests/functions/functions_storage_var_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_1_fail.sol new file mode 100644 index 000000000..ad7357684 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_1_fail.sol @@ -0,0 +1,16 @@ +pragma experimental SMTChecker; +contract C +{ + uint a; + function f(uint x) public { + uint y; + a = (y = x); + } + function g() public { + f(0); + assert(a > 0); + } +} + +// ---- +// Warning: (144-157): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_storage_var_2.sol b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_2.sol new file mode 100644 index 000000000..2f95d8af5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_2.sol @@ -0,0 +1,15 @@ +pragma experimental SMTChecker; +contract C +{ + uint a; + function f(uint x) public { + uint y; + a = (y = x); + } + function g() public { + f(1); + f(42); + assert(a > 1); + } +} + diff --git a/test/libsolidity/smtCheckerTests/functions/functions_storage_var_2_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_2_fail.sol new file mode 100644 index 000000000..5d972f966 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_storage_var_2_fail.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; +contract C +{ + uint a; + function f(uint x) public { + uint y; + a = (y = x); + } + function g() public { + f(1); + f(0); + assert(a > 0); + } +} + +// ---- +// Warning: (152-165): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_for.sol b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_for.sol new file mode 100644 index 000000000..7693ad811 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_for.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(bool x) public pure { require(x); for (;x;) {} } +} +// ---- +// Warning: (98-99): For loop condition is always true. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_for_only_call.sol b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_for_only_call.sol new file mode 100644 index 000000000..ed1ad73a3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_for_only_call.sol @@ -0,0 +1,7 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(bool x) public pure { for (;x;) {} } + function g() public pure { f(true); } +} diff --git a/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_if.sol b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_if.sol new file mode 100644 index 000000000..364fe8d17 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_if.sol @@ -0,0 +1,7 @@ +pragma experimental SMTChecker; +contract C +{ + function f(bool x) public pure { require(x); if (x) {} } +} +// ---- +// Warning: (95-96): Condition is always true. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_require.sol b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_require.sol new file mode 100644 index 000000000..e76badf2d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_require.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(bool x) public pure { x = true; require(x); } +} +// ---- +// Warning: (98-99): Condition is always true. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_require_only_call.sol b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_require_only_call.sol new file mode 100644 index 000000000..5cae940b5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_require_only_call.sol @@ -0,0 +1,7 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(bool x) public pure { require(x); } + function g() public pure { f(true); } +} diff --git a/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_while.sol b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_while.sol new file mode 100644 index 000000000..66396dd85 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_while.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(bool x) public pure { require(x); while (x) {} } +} +// ---- +// Warning: (99-100): While loop condition is always true. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_while_only_call.sol b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_while_only_call.sol new file mode 100644 index 000000000..5000eeb6b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_trivial_condition_while_only_call.sol @@ -0,0 +1,7 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(bool x) public pure { while (x) {} } + function g() public pure { f(true); } +} diff --git a/test/libsolidity/smtCheckerTests/special/blockhash.sol b/test/libsolidity/smtCheckerTests/special/blockhash.sol new file mode 100644 index 000000000..1c6939142 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/blockhash.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + function f() public payable { + assert(blockhash(2) > 0); + } +} +// ---- +// Warning: (79-103): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/special/difficulty.sol b/test/libsolidity/smtCheckerTests/special/difficulty.sol new file mode 100644 index 000000000..4469d4e57 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/difficulty.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint difficulty) public view { + assert(block.difficulty == difficulty); + } +} +// ---- +// Warning: (91-129): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/special/gasleft.sol b/test/libsolidity/smtCheckerTests/special/gasleft.sol new file mode 100644 index 000000000..857230feb --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/gasleft.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + function f() public view { + assert(gasleft() > 0); + uint g = gasleft(); + assert(g < gasleft()); + assert(g >= gasleft()); + } +} +// ---- +// Warning: (76-97): Assertion violation happens here +// Warning: (123-144): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/special/many.sol b/test/libsolidity/smtCheckerTests/special/many.sol new file mode 100644 index 000000000..40e5d9878 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/many.sol @@ -0,0 +1,25 @@ +pragma experimental SMTChecker; + +contract C +{ + function f() public payable { + assert(msg.sender == block.coinbase); + assert(block.difficulty == block.gaslimit); + assert(block.number == block.timestamp); + assert(tx.gasprice == msg.value); + assert(tx.origin == msg.sender); + uint x = block.number; + assert(x + 2 > block.number); + assert(now > 10); + assert(gasleft() > 100); + } +} +// ---- +// Warning: (79-115): Assertion violation happens here +// Warning: (119-161): Assertion violation happens here +// Warning: (165-204): Assertion violation happens here +// Warning: (208-240): Assertion violation happens here +// Warning: (244-275): Assertion violation happens here +// Warning: (311-316): Overflow (resulting value larger than 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) happens here +// Warning: (336-352): Assertion violation happens here +// Warning: (356-379): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/special/msg_data.sol b/test/libsolidity/smtCheckerTests/special/msg_data.sol new file mode 100644 index 000000000..7e748f094 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/msg_data.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + function f() public payable { + assert(msg.data.length > 0); + } +} +// ---- +// Warning: (86-101): Assertion checker does not yet support this expression. +// Warning: (86-94): Assertion checker does not yet support this special variable. +// Warning: (86-94): Assertion checker does not yet implement this type. +// Warning: (86-101): Internal error: Expression undefined for SMT solver. +// Warning: (79-106): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/special/msg_sender_1.sol b/test/libsolidity/smtCheckerTests/special/msg_sender_1.sol new file mode 100644 index 000000000..dd2366e2e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/msg_sender_1.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + function f() public view { + address a = msg.sender; + address b = msg.sender; + assert(a == b); + } +} diff --git a/test/libsolidity/smtCheckerTests/special/msg_sender_2.sol b/test/libsolidity/smtCheckerTests/special/msg_sender_2.sol new file mode 100644 index 000000000..ad45d0761 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/msg_sender_2.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + function f() public view { + require(msg.sender != address(0)); + address a = msg.sender; + address b = msg.sender; + assert(a == b); + } +} +// ---- +// Warning: (98-108): Assertion checker does not yet implement this expression. +// Warning: (98-108): Internal error: Expression undefined for SMT solver. diff --git a/test/libsolidity/smtCheckerTests/special/msg_sender_fail_1.sol b/test/libsolidity/smtCheckerTests/special/msg_sender_fail_1.sol new file mode 100644 index 000000000..9a4eefd52 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/msg_sender_fail_1.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(address c) public view { + address a = msg.sender; + address b = msg.sender; + assert(a == b); + assert(c == msg.sender); + } +} +// ---- +// Warning: (155-178): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/special/msg_sig.sol b/test/libsolidity/smtCheckerTests/special/msg_sig.sol new file mode 100644 index 000000000..109470a83 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/msg_sig.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + function f() public payable { + assert(msg.sig == 0x00000000); + } +} +// ---- +// Warning: (79-108): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/fixed_bytes_1.sol b/test/libsolidity/smtCheckerTests/types/fixed_bytes_1.sol new file mode 100644 index 000000000..541fff54e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/fixed_bytes_1.sol @@ -0,0 +1,16 @@ +pragma experimental SMTChecker; + +contract C +{ + bytes32 x; + function f(bytes8 y) public view { + assert(x != y); + assert(x != g()); + } + function g() public view returns (bytes32) { + return x; + } +} +// ---- +// Warning: (96-110): Assertion violation happens here +// Warning: (114-130): Assertion violation happens here diff --git a/test/libsolidity/syntaxTests/array/array_pop.sol b/test/libsolidity/syntaxTests/array/array_pop.sol new file mode 100644 index 000000000..3804f911f --- /dev/null +++ b/test/libsolidity/syntaxTests/array/array_pop.sol @@ -0,0 +1,7 @@ +contract C { + uint[] data; + function test() public { + data.pop(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/array/array_pop_arg.sol b/test/libsolidity/syntaxTests/array/array_pop_arg.sol new file mode 100644 index 000000000..bb7803e28 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/array_pop_arg.sol @@ -0,0 +1,8 @@ +contract C { + uint[] data; + function test() public { + data.pop(5); + } +} +// ---- +// TypeError: (65-76): Wrong argument count for function call: 1 arguments given but expected 0. diff --git a/test/libsolidity/syntaxTests/array/bytes_pop.sol b/test/libsolidity/syntaxTests/array/bytes_pop.sol new file mode 100644 index 000000000..cd5aa0eb6 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/bytes_pop.sol @@ -0,0 +1,7 @@ +contract C { + bytes data; + function test() public { + data.pop(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/array/dynamic_memory_array_pop.sol b/test/libsolidity/syntaxTests/array/dynamic_memory_array_pop.sol new file mode 100644 index 000000000..5a79afc93 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/dynamic_memory_array_pop.sol @@ -0,0 +1,8 @@ +contract C { + function test() public { + uint[] memory data; + data.pop(); + } +} +// ---- +// TypeError: (74-82): Member "pop" is not available in uint256[] memory outside of storage. diff --git a/test/libsolidity/syntaxTests/array/length/array_length_cannot_be_constant_function_parameter.sol b/test/libsolidity/syntaxTests/array/length/array_length_cannot_be_constant_function_parameter.sol new file mode 100644 index 000000000..593281401 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/array_length_cannot_be_constant_function_parameter.sol @@ -0,0 +1,8 @@ +contract C { + function f(uint constant LEN) public { + uint[LEN] a; + } +} +// ---- +// DeclarationError: (28-45): The "constant" keyword can only be used for state variables. +// TypeError: (69-72): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/array/length/bytes32_too_large.sol b/test/libsolidity/syntaxTests/array/length/bytes32_too_large.sol new file mode 100644 index 000000000..1742c80df --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/bytes32_too_large.sol @@ -0,0 +1,5 @@ +contract C { + bytes32[8**90] ids; +} +// ---- +// TypeError: (25-30): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/array/length/bytes32_too_large_multidim.sol b/test/libsolidity/syntaxTests/array/length/bytes32_too_large_multidim.sol new file mode 100644 index 000000000..1344574c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/bytes32_too_large_multidim.sol @@ -0,0 +1,5 @@ +contract C { + bytes32[8**90][500] ids; +} +// ---- +// TypeError: (25-30): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol b/test/libsolidity/syntaxTests/array/length/can_be_constant_in_function.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol rename to test/libsolidity/syntaxTests/array/length/can_be_constant_in_function.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol b/test/libsolidity/syntaxTests/array/length/can_be_constant_in_struct.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol rename to test/libsolidity/syntaxTests/array/length/can_be_constant_in_struct.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol b/test/libsolidity/syntaxTests/array/length/can_be_recursive_constant.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol rename to test/libsolidity/syntaxTests/array/length/can_be_recursive_constant.sol diff --git a/test/libsolidity/syntaxTests/array/length/cannot_be_function.sol b/test/libsolidity/syntaxTests/array/length/cannot_be_function.sol new file mode 100644 index 000000000..2ad97d27c --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/cannot_be_function.sol @@ -0,0 +1,6 @@ +contract C { + function f() public {} + uint[f] ids; +} +// ---- +// TypeError: (49-50): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol b/test/libsolidity/syntaxTests/array/length/cannot_be_function_call.sol similarity index 51% rename from test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol rename to test/libsolidity/syntaxTests/array/length/cannot_be_function_call.sol index a68639556..bb8cc599b 100644 --- a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol +++ b/test/libsolidity/syntaxTests/array/length/cannot_be_function_call.sol @@ -1,7 +1,7 @@ contract C { - function f(uint x) {} + function f(uint x) public {} uint constant LEN = f(); uint[LEN] ids; } // ---- -// TypeError: (77-80): Invalid array length, expected integer literal or constant expression. +// TypeError: (84-87): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol b/test/libsolidity/syntaxTests/array/length/complex_cyclic_constant.sol similarity index 90% rename from test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol rename to test/libsolidity/syntaxTests/array/length/complex_cyclic_constant.sol index 254f9f020..ee1070787 100644 --- a/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol +++ b/test/libsolidity/syntaxTests/array/length/complex_cyclic_constant.sol @@ -2,7 +2,7 @@ contract C { uint constant L2 = LEN - 10; uint constant L1 = L2 / 10; uint constant LEN = 10 + L1 * 5; - function f() { + function f() public { uint[LEN] a; } } diff --git a/test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol b/test/libsolidity/syntaxTests/array/length/const_cannot_be_fractional.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol rename to test/libsolidity/syntaxTests/array/length/const_cannot_be_fractional.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/constant_var.sol b/test/libsolidity/syntaxTests/array/length/constant_var.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/constant_var.sol rename to test/libsolidity/syntaxTests/array/length/constant_var.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol b/test/libsolidity/syntaxTests/array/length/cyclic_constant.sol similarity index 86% rename from test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol rename to test/libsolidity/syntaxTests/array/length/cyclic_constant.sol index 91ba9045d..3adc0e9ba 100644 --- a/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol +++ b/test/libsolidity/syntaxTests/array/length/cyclic_constant.sol @@ -1,6 +1,6 @@ contract C { uint constant LEN = LEN; - function f() { + function f() public { uint[LEN] a; } } diff --git a/test/libsolidity/syntaxTests/array/length/fixed_size_multidim_zero_length.sol b/test/libsolidity/syntaxTests/array/length/fixed_size_multidim_zero_length.sol new file mode 100644 index 000000000..fd8f30782 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/fixed_size_multidim_zero_length.sol @@ -0,0 +1,15 @@ +contract C { + function a() public pure returns(int[0][500] memory) {} + function b() public pure returns(uint[0][500] memory) {} + function c() public pure returns(byte[0][500] memory) {} + function d() public pure returns(bytes32[0][500] memory) {} + function e() public pure returns(bytes[0][500] memory) {} + function e() public pure returns(string[0][500] memory) {} +} +// ---- +// TypeError: (52-53): Array with zero length specified. +// TypeError: (111-112): Array with zero length specified. +// TypeError: (170-171): Array with zero length specified. +// TypeError: (232-233): Array with zero length specified. +// TypeError: (292-293): Array with zero length specified. +// TypeError: (353-354): Array with zero length specified. diff --git a/test/libsolidity/syntaxTests/array/length/fixed_size_zero_length.sol b/test/libsolidity/syntaxTests/array/length/fixed_size_zero_length.sol new file mode 100644 index 000000000..b38939e39 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/fixed_size_zero_length.sol @@ -0,0 +1,15 @@ +contract C { + int[0] a; + uint[0] b; + byte[0] c; + bytes32[0] d; + bytes[0] e; + string[0] f; +} +// ---- +// TypeError: (19-20): Array with zero length specified. +// TypeError: (32-33): Array with zero length specified. +// TypeError: (45-46): Array with zero length specified. +// TypeError: (61-62): Array with zero length specified. +// TypeError: (75-76): Array with zero length specified. +// TypeError: (90-91): Array with zero length specified. diff --git a/test/libsolidity/syntaxTests/arrayLength/inline_array.sol b/test/libsolidity/syntaxTests/array/length/inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/inline_array.sol rename to test/libsolidity/syntaxTests/array/length/inline_array.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol b/test/libsolidity/syntaxTests/array/length/invalid_expression_1.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol rename to test/libsolidity/syntaxTests/array/length/invalid_expression_1.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol b/test/libsolidity/syntaxTests/array/length/invalid_expression_2.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol rename to test/libsolidity/syntaxTests/array/length/invalid_expression_2.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol b/test/libsolidity/syntaxTests/array/length/invalid_expression_3.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol rename to test/libsolidity/syntaxTests/array/length/invalid_expression_3.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol b/test/libsolidity/syntaxTests/array/length/invalid_expression_4.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol rename to test/libsolidity/syntaxTests/array/length/invalid_expression_4.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol b/test/libsolidity/syntaxTests/array/length/invalid_expression_5.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol rename to test/libsolidity/syntaxTests/array/length/invalid_expression_5.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol b/test/libsolidity/syntaxTests/array/length/non_integer_constant_var.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol rename to test/libsolidity/syntaxTests/array/length/non_integer_constant_var.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol b/test/libsolidity/syntaxTests/array/length/not_convertible_to_integer.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol rename to test/libsolidity/syntaxTests/array/length/not_convertible_to_integer.sol diff --git a/test/libsolidity/syntaxTests/array/length/parameter_too_large.sol b/test/libsolidity/syntaxTests/array/length/parameter_too_large.sol new file mode 100644 index 000000000..02e0a7cc6 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/parameter_too_large.sol @@ -0,0 +1,5 @@ +contract C { + function f(bytes32[1263941234127518272] memory) public pure {} +} +// ---- +// TypeError: (26-61): Array is too large to be encoded. diff --git a/test/libsolidity/syntaxTests/array/length/parameter_too_large_multidim.sol b/test/libsolidity/syntaxTests/array/length/parameter_too_large_multidim.sol new file mode 100644 index 000000000..5f96ecd56 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/parameter_too_large_multidim.sol @@ -0,0 +1,11 @@ +contract C { + function f(bytes32[1263941234127518272][500] memory) public pure {} + function f(uint[2**30][] memory) public pure {} + function f(uint[2**30][2**30][] memory) public pure {} + function f(uint[2**16][2**16][] memory) public pure {} +} +// ---- +// TypeError: (26-66): Array is too large to be encoded. +// TypeError: (96-116): Array is too large to be encoded. +// TypeError: (146-173): Array is too large to be encoded. +// TypeError: (203-230): Array is too large to be encoded. diff --git a/test/libsolidity/syntaxTests/array/length/parameter_too_large_multidim_ABIv2.sol b/test/libsolidity/syntaxTests/array/length/parameter_too_large_multidim_ABIv2.sol new file mode 100644 index 000000000..de1fde3f4 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/parameter_too_large_multidim_ABIv2.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; + +contract C { + function f(bytes32[1263941234127518272][500] memory) public pure {} + function f(uint[2**30][2**30][][] memory) public pure {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (61-101): Array is too large to be encoded. +// TypeError: (131-160): Array is too large to be encoded. diff --git a/test/libsolidity/syntaxTests/arrayLength/parentheses.sol b/test/libsolidity/syntaxTests/array/length/parentheses.sol similarity index 93% rename from test/libsolidity/syntaxTests/arrayLength/parentheses.sol rename to test/libsolidity/syntaxTests/array/length/parentheses.sol index 40f55ad63..8dbcc0a46 100644 --- a/test/libsolidity/syntaxTests/arrayLength/parentheses.sol +++ b/test/libsolidity/syntaxTests/array/length/parentheses.sol @@ -21,5 +21,5 @@ contract C { uint[((2) + 1) + 1] a12; uint[(2 + 1) + ((1))] a13; uint[(((2) + 1)) + (((1)))] a14; - uint[((((2) + 1)) + (((1))))%1] a15; + uint[((((3) + 1)) + (((1))))%2] a15; } diff --git a/test/libsolidity/syntaxTests/arrayLength/pure_functions.sol b/test/libsolidity/syntaxTests/array/length/pure_functions.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/pure_functions.sol rename to test/libsolidity/syntaxTests/array/length/pure_functions.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/too_large.sol b/test/libsolidity/syntaxTests/array/length/too_large.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/too_large.sol rename to test/libsolidity/syntaxTests/array/length/too_large.sol diff --git a/test/libsolidity/syntaxTests/arrayLength/tuples.sol b/test/libsolidity/syntaxTests/array/length/tuples.sol similarity index 100% rename from test/libsolidity/syntaxTests/arrayLength/tuples.sol rename to test/libsolidity/syntaxTests/array/length/tuples.sol diff --git a/test/libsolidity/syntaxTests/array/length/uint_too_large_multidim.sol b/test/libsolidity/syntaxTests/array/length/uint_too_large_multidim.sol new file mode 100644 index 000000000..901bc28af --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/uint_too_large_multidim.sol @@ -0,0 +1,5 @@ +contract C { + uint[8**90][500] ids; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/array/no_array_pop.sol b/test/libsolidity/syntaxTests/array/no_array_pop.sol new file mode 100644 index 000000000..79a68ef12 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/no_array_pop.sol @@ -0,0 +1,8 @@ +contract C { + uint data; + function test() public { + data.pop(); + } +} +// ---- +// TypeError: (63-71): Member "pop" not found or not visible after argument-dependent lookup in uint256. diff --git a/test/libsolidity/syntaxTests/array/static_storage_array_pop.sol b/test/libsolidity/syntaxTests/array/static_storage_array_pop.sol new file mode 100644 index 000000000..8414f43dd --- /dev/null +++ b/test/libsolidity/syntaxTests/array/static_storage_array_pop.sol @@ -0,0 +1,8 @@ +contract C { + uint[3] data; + function test() public { + data.pop(); + } +} +// ---- +// TypeError: (66-74): Member "pop" not found or not visible after argument-dependent lookup in uint256[3] storage ref. diff --git a/test/libsolidity/syntaxTests/array/string_pop.sol b/test/libsolidity/syntaxTests/array/string_pop.sol new file mode 100644 index 000000000..700fda16a --- /dev/null +++ b/test/libsolidity/syntaxTests/array/string_pop.sol @@ -0,0 +1,8 @@ +contract C { + string data; + function test() public { + data.pop(); + } +} +// ---- +// TypeError: (65-73): Member "pop" not found or not visible after argument-dependent lookup in string storage ref. diff --git a/test/libsolidity/syntaxTests/array/uninitialized_storage_var.sol b/test/libsolidity/syntaxTests/array/uninitialized_storage_var.sol new file mode 100644 index 000000000..f3be90715 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/uninitialized_storage_var.sol @@ -0,0 +1,9 @@ +contract C { + function f() public { + uint[] storage x; + uint[10] storage y; + } +} +// ---- +// DeclarationError: (38-54): Uninitialized storage pointer. +// DeclarationError: (58-76): Uninitialized storage pointer. diff --git a/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol b/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol deleted file mode 100644 index 11d40f26d..000000000 --- a/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract C { - function f(uint constant LEN) { - uint[LEN] a; - } -} -// ---- -// TypeError: (62-65): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol deleted file mode 100644 index ac3abc4c4..000000000 --- a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol +++ /dev/null @@ -1,6 +0,0 @@ -contract C { - function f() {} - uint[f] ids; -} -// ---- -// TypeError: (42-43): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/constants/assign_constant_function_value.sol b/test/libsolidity/syntaxTests/constants/assign_constant_function_value.sol index 88e94e29f..0e242b304 100644 --- a/test/libsolidity/syntaxTests/constants/assign_constant_function_value.sol +++ b/test/libsolidity/syntaxTests/constants/assign_constant_function_value.sol @@ -3,4 +3,4 @@ contract C { uint constant y = x(); } // ---- -// Warning: (74-77): Initial value for constant variable has to be compile-time constant. This will fail to compile with the next breaking version change. +// TypeError: (74-77): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/assign_constant_function_value_050.sol b/test/libsolidity/syntaxTests/constants/assign_constant_function_value_050.sol deleted file mode 100644 index 2c92899d3..000000000 --- a/test/libsolidity/syntaxTests/constants/assign_constant_function_value_050.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental "v0.5.0"; - -contract C { - function () pure returns (uint) x; - uint constant y = x(); -} -// ---- -// TypeError: (105-108): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol index 08d20c3a3..9f1d97227 100644 --- a/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol @@ -1,12 +1,10 @@ contract C { uint constant a = b * c; uint constant b = 7; - uint constant c = b + uint(keccak256(d)); + uint constant c = b + uint(keccak256(abi.encodePacked(d))); uint constant d = 2 + a; } // ---- -// Warning: (98-110): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (98-110): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. // TypeError: (17-40): The value of the constant a has a cyclic dependency via c. -// TypeError: (71-111): The value of the constant c has a cyclic dependency via d. -// TypeError: (117-140): The value of the constant d has a cyclic dependency via a. +// TypeError: (71-129): The value of the constant c has a cyclic dependency via d. +// TypeError: (135-158): The value of the constant d has a cyclic dependency via a. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol index df5cd9695..cc34fad28 100644 --- a/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol @@ -1,9 +1,7 @@ contract C { uint constant a = b * c; uint constant b = 7; - uint constant c = 4 + uint(keccak256(d)); + uint constant c = 4 + uint(keccak256(abi.encode(d))); uint constant d = 2 + b; } // ---- -// Warning: (98-110): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (98-110): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. diff --git a/test/libsolidity/syntaxTests/constructor/constructible_internal_constructor_new.sol b/test/libsolidity/syntaxTests/constructor/constructible_internal_constructor.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/constructible_internal_constructor_new.sol rename to test/libsolidity/syntaxTests/constructor/constructible_internal_constructor.sol diff --git a/test/libsolidity/syntaxTests/constructor/constructible_internal_constructor_old.sol b/test/libsolidity/syntaxTests/constructor/constructible_internal_constructor_old.sol deleted file mode 100644 index 144743e38..000000000 --- a/test/libsolidity/syntaxTests/constructor/constructible_internal_constructor_old.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract C { - function C() internal {} -} -contract D is C { - function D() public {} -} -// ---- -// Warning: (14-38): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// Warning: (60-82): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_new.sol b/test/libsolidity/syntaxTests/constructor/constructor.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/constructor_new.sol rename to test/libsolidity/syntaxTests/constructor/constructor.sol diff --git a/test/libsolidity/syntaxTests/constructor/constructor_no_visibility.sol b/test/libsolidity/syntaxTests/constructor/constructor_no_visibility.sol new file mode 100644 index 000000000..586329b13 --- /dev/null +++ b/test/libsolidity/syntaxTests/constructor/constructor_no_visibility.sol @@ -0,0 +1,3 @@ +contract A { constructor() {} } +// ---- +// SyntaxError: (13-29): No visibility specified. Did you intend to add "public"? diff --git a/test/libsolidity/syntaxTests/constructor/constructor_old.sol b/test/libsolidity/syntaxTests/constructor/constructor_old.sol index 9ec6257dd..9ead6858a 100644 --- a/test/libsolidity/syntaxTests/constructor/constructor_old.sol +++ b/test/libsolidity/syntaxTests/constructor/constructor_old.sol @@ -1,3 +1,4 @@ contract A { function A() public {} } // ---- -// Warning: (13-35): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. +// SyntaxError: (13-35): Functions are not allowed to have the same name as the contract. If you intend this to be a constructor, use "constructor(...) { ... }" to define it. +// Warning: (13-35): This declaration shadows an existing declaration. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_old_050.sol b/test/libsolidity/syntaxTests/constructor/constructor_old_050.sol deleted file mode 100644 index 19e46e793..000000000 --- a/test/libsolidity/syntaxTests/constructor/constructor_old_050.sol +++ /dev/null @@ -1,4 +0,0 @@ -pragma experimental "v0.5.0"; -contract A { function A() public {} } -// ---- -// SyntaxError: (43-65): Functions are not allowed to have the same name as the contract. If you intend this to be a constructor, use "constructor(...) { ... }" to define it. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_state_mutability.sol b/test/libsolidity/syntaxTests/constructor/constructor_state_mutability.sol new file mode 100644 index 000000000..39bf6384f --- /dev/null +++ b/test/libsolidity/syntaxTests/constructor/constructor_state_mutability.sol @@ -0,0 +1,9 @@ +contract test1 { + constructor() public view {} +} +contract test2 { + constructor() public pure {} +} +// ---- +// TypeError: (19-47): Constructor must be payable or non-payable, but is "view". +// TypeError: (69-97): Constructor must be payable or non-payable, but is "pure". diff --git a/test/libsolidity/syntaxTests/constructor/constructor_state_mutability_new.sol b/test/libsolidity/syntaxTests/constructor/constructor_state_mutability_new.sol deleted file mode 100644 index 15ed0e1e7..000000000 --- a/test/libsolidity/syntaxTests/constructor/constructor_state_mutability_new.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract test1 { - constructor() constant {} -} -contract test2 { - constructor() view {} -} -contract test3 { - constructor() pure {} -} -// ---- -// TypeError: (19-44): Constructor must be payable or non-payable, but is "view". -// TypeError: (66-87): Constructor must be payable or non-payable, but is "view". -// TypeError: (109-130): Constructor must be payable or non-payable, but is "pure". diff --git a/test/libsolidity/syntaxTests/constructor/constructor_state_mutability_old.sol b/test/libsolidity/syntaxTests/constructor/constructor_state_mutability_old.sol deleted file mode 100644 index 6dbcbc974..000000000 --- a/test/libsolidity/syntaxTests/constructor/constructor_state_mutability_old.sol +++ /dev/null @@ -1,16 +0,0 @@ -contract test1 { - function test1() constant {} -} -contract test2 { - function test2() view {} -} -contract test3 { - function test3() pure {} -} -// ---- -// Warning: (21-49): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// Warning: (73-97): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// Warning: (121-145): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (21-49): Constructor must be payable or non-payable, but is "view". -// TypeError: (73-97): Constructor must be payable or non-payable, but is "view". -// TypeError: (121-145): Constructor must be payable or non-payable, but is "pure". diff --git a/test/libsolidity/syntaxTests/constructor/constructor_visibility_new.sol b/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol similarity index 71% rename from test/libsolidity/syntaxTests/constructor/constructor_visibility_new.sol rename to test/libsolidity/syntaxTests/constructor/constructor_visibility.sol index 502dc0295..f9c4b9b98 100644 --- a/test/libsolidity/syntaxTests/constructor/constructor_visibility_new.sol +++ b/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol @@ -1,5 +1,5 @@ // The constructor of a base class should not be visible in the derived class -contract A { constructor(string) public { } } +contract A { constructor(string memory) public { } } contract B is A { function f() pure public { A x = A(0); // convert from address @@ -9,4 +9,4 @@ contract B is A { } } // ---- -// TypeError: (243-247): Explicit type conversion not allowed from "string memory" to "contract A". +// TypeError: (250-254): Explicit type conversion not allowed from "string memory" to "contract A". diff --git a/test/libsolidity/syntaxTests/constructor/constructor_visibility_old.sol b/test/libsolidity/syntaxTests/constructor/constructor_visibility_old.sol deleted file mode 100644 index 847ea27b1..000000000 --- a/test/libsolidity/syntaxTests/constructor/constructor_visibility_old.sol +++ /dev/null @@ -1,13 +0,0 @@ -// The constructor of a base class should not be visible in the derived class -contract A { function A(string s) public { } } -contract B is A { - function f() pure public { - A x = A(0); // convert from address - string memory y = "ab"; - A(y); // call as a function is invalid - x; - } -} -// ---- -// Warning: (91-122): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (244-248): Explicit type conversion not allowed from "string memory" to "contract A". diff --git a/test/libsolidity/syntaxTests/constructor/constructor_without_implementation.sol b/test/libsolidity/syntaxTests/constructor/constructor_without_implementation.sol new file mode 100644 index 000000000..6bbb83cee --- /dev/null +++ b/test/libsolidity/syntaxTests/constructor/constructor_without_implementation.sol @@ -0,0 +1,5 @@ +contract C { + constructor() public; +} +// ---- +// TypeError: (14-35): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_without_implementation_new.sol b/test/libsolidity/syntaxTests/constructor/constructor_without_implementation_new.sol deleted file mode 100644 index 5e6191430..000000000 --- a/test/libsolidity/syntaxTests/constructor/constructor_without_implementation_new.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract C { - constructor(); -} -// ---- -// TypeError: (14-28): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_without_implementation_old.sol b/test/libsolidity/syntaxTests/constructor/constructor_without_implementation_old.sol deleted file mode 100644 index 72458703d..000000000 --- a/test/libsolidity/syntaxTests/constructor/constructor_without_implementation_old.sol +++ /dev/null @@ -1,6 +0,0 @@ -contract C { - function C(); -} -// ---- -// Warning: (14-27): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (14-27): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/external_constructor_new.sol b/test/libsolidity/syntaxTests/constructor/external_constructor.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/external_constructor_new.sol rename to test/libsolidity/syntaxTests/constructor/external_constructor.sol diff --git a/test/libsolidity/syntaxTests/constructor/external_constructor_old.sol b/test/libsolidity/syntaxTests/constructor/external_constructor_old.sol deleted file mode 100644 index 278693615..000000000 --- a/test/libsolidity/syntaxTests/constructor/external_constructor_old.sol +++ /dev/null @@ -1,6 +0,0 @@ -contract test { - function test() external {} -} -// ---- -// Warning: (17-44): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (17-44): Constructor must be public or internal. diff --git a/test/libsolidity/syntaxTests/constructor/function_named_constructor.sol b/test/libsolidity/syntaxTests/constructor/function_named_constructor.sol index 29784033e..68273c0a0 100644 --- a/test/libsolidity/syntaxTests/constructor/function_named_constructor.sol +++ b/test/libsolidity/syntaxTests/constructor/function_named_constructor.sol @@ -2,4 +2,4 @@ contract C { function constructor() public; } // ---- -// Warning: (17-47): This function is named "constructor" but is not the constructor of the contract. If you intend this to be a constructor, use "constructor(...) { ... }" without the "function" keyword to define it. +// ParserError: (26-37): This function is named "constructor" but is not the constructor of the contract. If you intend this to be a constructor, use "constructor(...) { ... }" without the "function" keyword to define it. diff --git a/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_new.sol b/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_new.sol rename to test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor.sol diff --git a/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted_new.sol b/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted.sol similarity index 80% rename from test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted_new.sol rename to test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted.sol index 2a199b3a5..17cb701d7 100644 --- a/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted_new.sol +++ b/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted.sol @@ -3,11 +3,11 @@ contract B { A a; constructor() public { - a = new A(this); + a = new A(address(this)); } } contract A { - constructor(address a) internal {} + constructor(address) internal {} } // ---- // TypeError: (141-146): Contract with internal constructor cannot be created directly. diff --git a/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted_old.sol b/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted_old.sol deleted file mode 100644 index 0a27e9f85..000000000 --- a/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_inverted_old.sol +++ /dev/null @@ -1,15 +0,0 @@ -// Previously, the type information for A was not yet available at the point of -// "new A". -contract B { - A a; - function B() public { - a = new A(this); - } -} -contract A { - function A(address a) internal {} -} -// ---- -// Warning: (112-155): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// Warning: (172-205): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (140-145): Contract with internal constructor cannot be created directly. diff --git a/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_old.sol b/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_old.sol deleted file mode 100644 index 2897e6f35..000000000 --- a/test/libsolidity/syntaxTests/constructor/inconstructible_internal_constructor_old.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract C { - function C() internal {} -} -contract D { - function f() public { C x = new C(); x; } -} -// ---- -// Warning: (14-38): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (83-88): Contract with internal constructor cannot be created directly. diff --git a/test/libsolidity/syntaxTests/constructor/interface_constructor.sol b/test/libsolidity/syntaxTests/constructor/interface_constructor.sol new file mode 100644 index 000000000..87585a621 --- /dev/null +++ b/test/libsolidity/syntaxTests/constructor/interface_constructor.sol @@ -0,0 +1,7 @@ +interface I { + constructor() public; +} +// ---- +// TypeError: (15-36): Functions in interfaces must be declared external. +// TypeError: (15-36): Constructor cannot be defined in interfaces. +// TypeError: (15-36): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/interface_constructor_new.sol b/test/libsolidity/syntaxTests/constructor/interface_constructor_new.sol deleted file mode 100644 index fa5d54c4f..000000000 --- a/test/libsolidity/syntaxTests/constructor/interface_constructor_new.sol +++ /dev/null @@ -1,7 +0,0 @@ -interface I { - constructor(); -} -// ---- -// Warning: (15-29): Functions in interfaces should be declared external. -// TypeError: (15-29): Constructor cannot be defined in interfaces. -// TypeError: (15-29): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/interface_constructor_old.sol b/test/libsolidity/syntaxTests/constructor/interface_constructor_old.sol deleted file mode 100644 index ddf549776..000000000 --- a/test/libsolidity/syntaxTests/constructor/interface_constructor_old.sol +++ /dev/null @@ -1,8 +0,0 @@ -interface I { - function I(); -} -// ---- -// Warning: (15-28): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// Warning: (15-28): Functions in interfaces should be declared external. -// TypeError: (15-28): Constructor cannot be defined in interfaces. -// TypeError: (15-28): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/library_constructor.sol b/test/libsolidity/syntaxTests/constructor/library_constructor.sol new file mode 100644 index 000000000..38934f8d1 --- /dev/null +++ b/test/libsolidity/syntaxTests/constructor/library_constructor.sol @@ -0,0 +1,6 @@ +library Lib { + constructor() public; +} +// ---- +// TypeError: (15-36): Constructor cannot be defined in libraries. +// TypeError: (15-36): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/library_constructor_new.sol b/test/libsolidity/syntaxTests/constructor/library_constructor_new.sol deleted file mode 100644 index 8db7e62a8..000000000 --- a/test/libsolidity/syntaxTests/constructor/library_constructor_new.sol +++ /dev/null @@ -1,6 +0,0 @@ -library Lib { - constructor(); -} -// ---- -// TypeError: (15-29): Constructor cannot be defined in libraries. -// TypeError: (15-29): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/library_constructor_old.sol b/test/libsolidity/syntaxTests/constructor/library_constructor_old.sol deleted file mode 100644 index d44990492..000000000 --- a/test/libsolidity/syntaxTests/constructor/library_constructor_old.sol +++ /dev/null @@ -1,7 +0,0 @@ -library Lib { - function Lib(); -} -// ---- -// Warning: (15-30): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (15-30): Constructor cannot be defined in libraries. -// TypeError: (15-30): Constructor must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/constructor/overriding_constructor.sol b/test/libsolidity/syntaxTests/constructor/overriding_constructor.sol index 3290a33b3..30cf3bce9 100644 --- a/test/libsolidity/syntaxTests/constructor/overriding_constructor.sol +++ b/test/libsolidity/syntaxTests/constructor/overriding_constructor.sol @@ -1,6 +1,10 @@ -// It is fine to "override" constructor of a base class since it is invisible -contract A { function A() public { } } -contract B is A { function A() public pure returns (uint8) {} } +contract A { function f() public {} } +contract B is A { + function A() public pure returns (uint8) {} + function g() public { + A.f(); + } +} // ---- -// Warning: (91-114): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// Warning: (135-178): This declaration shadows an existing declaration. +// Warning: (58-101): This declaration shadows an existing declaration. +// TypeError: (130-133): Member "f" not found or not visible after argument-dependent lookup in function () pure returns (uint8). diff --git a/test/libsolidity/syntaxTests/constructor/returns_in_constructor_new.sol b/test/libsolidity/syntaxTests/constructor/returns_in_constructor.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/returns_in_constructor_new.sol rename to test/libsolidity/syntaxTests/constructor/returns_in_constructor.sol diff --git a/test/libsolidity/syntaxTests/constructor/returns_in_constructor_old.sol b/test/libsolidity/syntaxTests/constructor/returns_in_constructor_old.sol deleted file mode 100644 index 00b3974c6..000000000 --- a/test/libsolidity/syntaxTests/constructor/returns_in_constructor_old.sol +++ /dev/null @@ -1,6 +0,0 @@ -contract test { - function test() public returns (uint a) { } -} -// ---- -// Warning: (17-60): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// TypeError: (48-56): Non-empty "returns" directive for constructor. diff --git a/test/libsolidity/syntaxTests/constructor/two_constructors_new.sol b/test/libsolidity/syntaxTests/constructor/two_constructors.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/two_constructors_new.sol rename to test/libsolidity/syntaxTests/constructor/two_constructors.sol diff --git a/test/libsolidity/syntaxTests/constructor/two_constructors_mixed.sol b/test/libsolidity/syntaxTests/constructor/two_constructors_mixed.sol deleted file mode 100644 index c757354e8..000000000 --- a/test/libsolidity/syntaxTests/constructor/two_constructors_mixed.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract test { - function test(uint) public { } - constructor() public {} -} -// ---- -// Warning: (17-47): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// DeclarationError: (49-72): More than one constructor defined. diff --git a/test/libsolidity/syntaxTests/constructor/two_constructors_old.sol b/test/libsolidity/syntaxTests/constructor/two_constructors_old.sol deleted file mode 100644 index db632ced1..000000000 --- a/test/libsolidity/syntaxTests/constructor/two_constructors_old.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract test { - function test(uint a) public { } - function test() public {} -} -// ---- -// Warning: (17-49): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// Warning: (51-76): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead. -// DeclarationError: (51-76): More than one constructor defined. diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol new file mode 100644 index 000000000..35420b6da --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol @@ -0,0 +1,5 @@ +contract C { + function f() internal pure returns (mapping(uint=>uint) storage r) { } +} +// ---- +// TypeError: (53-82): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol new file mode 100644 index 000000000..4146192f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol @@ -0,0 +1,5 @@ +contract C { + mapping(uint=>uint) m; + function f() internal view returns (mapping(uint=>uint) storage r) { r = m; } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol new file mode 100644 index 000000000..52a8b3d71 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol @@ -0,0 +1,5 @@ +contract C { + function f() internal pure returns (mapping(uint=>uint) storage) {} +} +// ---- +// TypeError: (53-80): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol new file mode 100644 index 000000000..9c5e3149d --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol @@ -0,0 +1,5 @@ +contract C { + mapping(uint=>uint) m; + function f() internal view returns (mapping(uint=>uint) storage) { return m; } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol new file mode 100644 index 000000000..cad9b8e8e --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol @@ -0,0 +1,10 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure returns (S storage) { + assembly { + } + } +} +// ---- +// TypeError: (87-96): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol index 65902cc8b..0d3db856c 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol @@ -8,7 +8,7 @@ contract C { } function g(bool flag) internal returns (S storage c) { // control flow in assembly will not be analyzed for now, - // so this will not issue a warning + // so this will not issue an error assembly { if flag { sstore(c_slot, sload(s_slot)) @@ -17,7 +17,7 @@ contract C { } function h() internal returns (S storage c) { // any reference from assembly will be sufficient for now, - // so this will not issue a warning + // so this will not issue an error assembly { sstore(s_slot, sload(c_slot)) } diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_warn.sol deleted file mode 100644 index 09c13847c..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_warn.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal pure returns (S storage) { - assembly { - } - } -} -// ---- -// Warning: (87-88): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/default_location.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/default_location.sol index 9a42192de..ec83c596e 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/default_location.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/default_location.sol @@ -1,18 +1,18 @@ contract C { struct S { bool f; } S s; - function f() internal view returns (S c) { + function f() internal view returns (S memory c) { c = s; } - function g() internal view returns (S) { + function g() internal view returns (S memory) { return s; } - function h() internal pure returns (S) { + function h() internal pure returns (S memory) { } - function i(bool flag) internal view returns (S c) { + function i(bool flag) internal view returns (S memory c) { if (flag) c = s; } - function j(bool flag) internal view returns (S) { + function j(bool flag) internal view returns (S memory) { if (flag) return s; } } diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol new file mode 100644 index 000000000..eb574c965 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol @@ -0,0 +1,52 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + do { + break; + c = s; + } while(false); + } + function g() internal view returns (S storage c) { + do { + if (s.f) { + continue; + c = s; + } + else { + } + } while(false); + } + function h() internal view returns (S storage c) { + do { + if (s.f) { + break; + } + else { + c = s; + } + } while(false); + } + function i() internal view returns (S storage c) { + do { + if (s.f) { + continue; + } + else { + c = s; + } + } while(false); + } + function j() internal view returns (S storage c) { + do { + continue; + c = s; + } while(false); + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (223-234): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (440-451): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (654-665): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (871-882): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol index 6520672cf..55c5edd30 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol @@ -23,13 +23,8 @@ contract C { } function k() internal view returns (S storage c) { do { - if (s.f) { - continue; - break; - } - else { - c = s; - } + c = s; + continue; } while(false); } } diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol deleted file mode 100644 index f1a92e9c2..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol +++ /dev/null @@ -1,35 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - do { - break; - c = s; - } while(false); - } - function g() internal view returns (S storage c) { - do { - if (s.f) { - continue; - c = s; - } - else { - } - } while(false); - } - function h() internal view returns (S storage c) { - do { - if (s.f) { - break; - continue; - } - else { - c = s; - } - } while(false); - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (223-234): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (440-451): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol deleted file mode 100644 index 3a0a30eaf..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol +++ /dev/null @@ -1,6 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c, S storage d) { c = s; d = s; return; } -} -// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_warn.sol deleted file mode 100644 index 0a5b2fbfa..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_warn.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal pure returns (S storage) { return; } - function g() internal view returns (S storage c, S storage) { c = s; return; } - function h() internal view returns (S storage, S storage d) { d = s; return; } - function i() internal pure returns (S storage, S storage) { return; } - function j() internal view returns (S storage, S storage) { return (s,s); } -} -// ---- -// Warning: (87-88): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (163-164): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (233-234): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (316-317): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (327-328): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol new file mode 100644 index 000000000..9aa580a43 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol @@ -0,0 +1,16 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + for(;; c = s) { + } + } + function g() internal view returns (S storage c) { + for(;;) { + c = s; + } + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (182-193): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_warn.sol deleted file mode 100644 index ba9a24401..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_warn.sol +++ /dev/null @@ -1,16 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - for(;; c = s) { - } - } - function g() internal view returns (S storage c) { - for(;;) { - c = s; - } - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (182-193): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol new file mode 100644 index 000000000..f3e55318e --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol @@ -0,0 +1,18 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal view returns (S storage c) { + if (flag) c = s; + } + function g(bool flag) internal returns (S storage c) { + if (flag) c = s; + else + { + if (!flag) c = s; + else s.f = true; + } + } +} +// ---- +// TypeError: (96-107): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (186-197): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_warn.sol deleted file mode 100644 index c257c252b..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_warn.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f(bool flag) internal view returns (S storage c) { - if (flag) c = s; - } - function g(bool flag) internal returns (S storage c) { - if (flag) c = s; - else - { - if (!flag) c = s; - else s.f = true; - } - } -} -// ---- -// Warning: (96-107): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (186-197): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol new file mode 100644 index 000000000..423429790 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol @@ -0,0 +1,22 @@ +contract C { + modifier revertIfNoReturn() { + _; + revert(); + } + modifier ifFlag(bool flag) { + if (flag) + _; + } + struct S { uint a; } + S s; + function f(bool flag) ifFlag(flag) internal view returns(S storage) { + return s; + } + + function g(bool flag) ifFlag(flag) revertIfNoReturn() internal view returns(S storage) { + return s; + } +} +// ---- +// TypeError: (249-258): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (367-376): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_warn.sol deleted file mode 100644 index 50c6dd992..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_warn.sol +++ /dev/null @@ -1,22 +0,0 @@ -contract C { - modifier revertIfNoReturn() { - _; - revert(); - } - modifier ifFlag(bool flag) { - if (flag) - _; - } - struct S { uint a; } - S s; - function f(bool flag) ifFlag(flag) internal view returns(S storage) { - return s; - } - - function g(bool flag) ifFlag(flag) revertIfNoReturn() internal view returns(S storage) { - return s; - } -} -// ---- -// Warning: (249-250): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (367-368): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol new file mode 100644 index 000000000..d0ad82456 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol @@ -0,0 +1,18 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + false && (c = s).f; + } + function g() internal view returns (S storage c) { + true || (c = s).f; + } + function h() internal view returns (S storage c) { + // expect error, although this is always fine + true && (false || (c = s).f); + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (176-187): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (264-275): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_warn.sol deleted file mode 100644 index 9f660f11d..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_warn.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - false && (c = s).f; - } - function g() internal view returns (S storage c) { - true || (c = s).f; - } - function h() internal view returns (S storage c) { - // expect warning, although this is always fine - true && (false || (c = s).f); - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (176-187): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (264-275): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol new file mode 100644 index 000000000..6d10287b4 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol @@ -0,0 +1,13 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal view returns (S storage c) { + flag ? (c = s).f : false; + } + function g(bool flag) internal view returns (S storage c) { + flag ? false : (c = s).f; + } +} +// ---- +// TypeError: (96-107): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (200-211): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_warn.sol deleted file mode 100644 index 57561fbba..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_warn.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f(bool flag) internal view returns (S storage c) { - flag ? (c = s).f : false; - } - function g(bool flag) internal view returns (S storage c) { - flag ? false : (c = s).f; - } -} -// ---- -// Warning: (96-107): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (200-211): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/throw_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/throw_fine.sol deleted file mode 100644 index 4cecc27cc..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/throw_fine.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal pure returns (S storage) { - throw; - } -} -// ---- -// Warning: (108-113): "throw" is deprecated in favour of "revert()", "require()" and "assert()". diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol index 0b1715608..7567f6947 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol @@ -8,5 +8,8 @@ contract C { uint a; (c, a) = f(); } + function h() internal view returns (S storage, S storage) { + return (s,s); + } } // ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_internal.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_internal.sol new file mode 100644 index 000000000..8bce0dd27 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_internal.sol @@ -0,0 +1,4 @@ +contract C { + function f() internal returns(uint[] storage); + function g() internal returns(uint[] storage s); +} diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_library.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_library.sol new file mode 100644 index 000000000..818b6a205 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_library.sol @@ -0,0 +1,4 @@ +library L { + function f() public returns(uint[] storage); + function g() public returns(uint[] storage s); +} diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol new file mode 100644 index 000000000..e7b4fae71 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol @@ -0,0 +1,11 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + while(false) { + c = s; + } + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_warn.sol deleted file mode 100644 index 26db892f7..000000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_warn.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - while(false) { - c = s; - } - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol new file mode 100644 index 000000000..78c40e534 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol @@ -0,0 +1,9 @@ +contract C { + bytes a; + bytes b; + function f() public view { + bytes storage c = a; + bytes memory d = b; + d = bytes(c); + } +} diff --git a/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol new file mode 100644 index 000000000..f7e96f35b --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol @@ -0,0 +1,9 @@ +contract C { + string a; + string b; + function f() public view { + string storage c = a; + string memory d = b; + d = string(c); + } +} diff --git a/test/libsolidity/syntaxTests/conversion/conversion_to_bytes.sol b/test/libsolidity/syntaxTests/conversion/conversion_to_bytes.sol new file mode 100644 index 000000000..3a6deff16 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/conversion_to_bytes.sol @@ -0,0 +1,5 @@ +contract test { + function f() public pure returns (bytes memory) { + return bytes("abc"); + } +} diff --git a/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol b/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol new file mode 100644 index 000000000..458adda68 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol @@ -0,0 +1,10 @@ +contract C { + int[10] x; + function f() public view { + int[](x); + int(x); + } +} +// ---- +// TypeError: (55-63): Explicit type conversion not allowed from "int256[10] storage ref" to "int256[] storage pointer". +// TypeError: (67-73): Explicit type conversion not allowed from "int256[10] storage ref" to "int256". diff --git a/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_payable.sol b/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_payable.sol new file mode 100644 index 000000000..75f7a953c --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_payable.sol @@ -0,0 +1,10 @@ +contract C { + function h() external { + } + function f() view external returns (bytes4) { + function () payable external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (105-144): Type function () external is not implicitly convertible to expected type function () payable external. diff --git a/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_pure.sol b/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_pure.sol new file mode 100644 index 000000000..8d1b08aa5 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_pure.sol @@ -0,0 +1,10 @@ +contract C { + function h() external { + } + function f() view external returns (bytes4) { + function () pure external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (105-141): Type function () external is not implicitly convertible to expected type function () pure external. diff --git a/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_view.sol b/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_view.sol new file mode 100644 index 000000000..535d6c77b --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_nonpayable_view.sol @@ -0,0 +1,10 @@ +contract C { + function h() external { + } + function f() view external returns (bytes4) { + function () view external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (105-141): Type function () external is not implicitly convertible to expected type function () view external. diff --git a/test/libsolidity/syntaxTests/conversion/function_type_payable_nonpayable.sol b/test/libsolidity/syntaxTests/conversion/function_type_payable_nonpayable.sol new file mode 100644 index 000000000..299d7e301 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_payable_nonpayable.sol @@ -0,0 +1,8 @@ +contract C { + function h() payable external { + } + function f() view external returns (bytes4) { + function () external g = this.h; + return g.selector; + } +} diff --git a/test/libsolidity/syntaxTests/conversion/function_type_payable_pure.sol b/test/libsolidity/syntaxTests/conversion/function_type_payable_pure.sol new file mode 100644 index 000000000..78bada512 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_payable_pure.sol @@ -0,0 +1,10 @@ +contract C { + function h() payable external { + } + function f() view external returns (bytes4) { + function () pure external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (113-149): Type function () payable external is not implicitly convertible to expected type function () pure external. diff --git a/test/libsolidity/syntaxTests/conversion/function_type_payable_view.sol b/test/libsolidity/syntaxTests/conversion/function_type_payable_view.sol new file mode 100644 index 000000000..f12cb301b --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_payable_view.sol @@ -0,0 +1,10 @@ +contract C { + function h() payable external { + } + function f() view external returns (bytes4) { + function () view external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (113-149): Type function () payable external is not implicitly convertible to expected type function () view external. diff --git a/test/libsolidity/syntaxTests/conversion/function_type_pure_nonpayable.sol b/test/libsolidity/syntaxTests/conversion/function_type_pure_nonpayable.sol new file mode 100644 index 000000000..7742e0c12 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_pure_nonpayable.sol @@ -0,0 +1,8 @@ +contract C { + function h() pure external { + } + function f() view external returns (bytes4) { + function () external g = this.h; + return g.selector; + } +} diff --git a/test/libsolidity/syntaxTests/conversion/function_type_pure_payable.sol b/test/libsolidity/syntaxTests/conversion/function_type_pure_payable.sol new file mode 100644 index 000000000..cd4e9b4e6 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_pure_payable.sol @@ -0,0 +1,10 @@ +contract C { + function h() pure external { + } + function f() view external returns (bytes4) { + function () payable external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (110-149): Type function () pure external is not implicitly convertible to expected type function () payable external. diff --git a/test/libsolidity/syntaxTests/conversion/function_type_pure_view.sol b/test/libsolidity/syntaxTests/conversion/function_type_pure_view.sol new file mode 100644 index 000000000..578ecdbd1 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_pure_view.sol @@ -0,0 +1,8 @@ +contract C { + function h() pure external { + } + function f() view external returns (bytes4) { + function () view external g = this.h; + return g.selector; + } +} diff --git a/test/libsolidity/syntaxTests/conversion/function_type_same.sol b/test/libsolidity/syntaxTests/conversion/function_type_same.sol new file mode 100644 index 000000000..c5ebe1ca2 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_same.sol @@ -0,0 +1,14 @@ +contract C { + int dummy; + function h_nonpayable() external { dummy = 1; } + function h_payable() payable external {} + function h_view() view external { dummy; } + function h_pure() pure external {} + function f() view external { + function () external g_nonpayable = this.h_nonpayable; g_nonpayable; + function () payable external g_payable = this.h_payable; g_payable; + function () view external g_view = this.h_view; g_view; + function () pure external g_pure = this.h_pure; g_pure; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/conversion/function_type_view_nonpayable.sol b/test/libsolidity/syntaxTests/conversion/function_type_view_nonpayable.sol new file mode 100644 index 000000000..f52aece0a --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_view_nonpayable.sol @@ -0,0 +1,10 @@ +contract C { + int dummy; + function h() view external { + dummy; + } + function f() view external returns (bytes4) { + function () external g = this.h; + return g.selector; + } +} diff --git a/test/libsolidity/syntaxTests/conversion/function_type_view_payable.sol b/test/libsolidity/syntaxTests/conversion/function_type_view_payable.sol new file mode 100644 index 000000000..3bf4bac2a --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_view_payable.sol @@ -0,0 +1,10 @@ +contract C { + function h() view external { + } + function f() view external returns (bytes4) { + function () payable external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (110-149): Type function () view external is not implicitly convertible to expected type function () payable external. diff --git a/test/libsolidity/syntaxTests/conversion/function_type_view_pure.sol b/test/libsolidity/syntaxTests/conversion/function_type_view_pure.sol new file mode 100644 index 000000000..c567a2c8d --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/function_type_view_pure.sol @@ -0,0 +1,10 @@ +contract C { + function h() view external { + } + function f() view external returns (bytes4) { + function () pure external g = this.h; + return g.selector; + } +} +// ---- +// TypeError: (110-146): Type function () view external is not implicitly convertible to expected type function () pure external. diff --git a/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol b/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol new file mode 100644 index 000000000..31e298d0d --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol @@ -0,0 +1,7 @@ +contract C { + int[10] x; + int[] y; + function f() public { + y = x; + } +} diff --git a/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol new file mode 100644 index 000000000..3aa59612f --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol @@ -0,0 +1,10 @@ +contract C { + uint[] a; + uint[] b; + function f() public view { + uint[] storage c = a; + uint[] storage d = b; + d = uint[](c); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol new file mode 100644 index 000000000..060c97078 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol @@ -0,0 +1,10 @@ +contract C { + uint[] a; + uint[] b; + function f() public view { + uint[] storage c = a; + uint[] memory d = b; + d = uint[](c); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type.sol b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type.sol new file mode 100644 index 000000000..b23fbb89e --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type.sol @@ -0,0 +1,4 @@ +library L { + struct Nested { uint y; } + function c(function(Nested memory) external returns (uint)[] storage) external pure {} +} diff --git a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol new file mode 100644 index 000000000..b80849ceb --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol @@ -0,0 +1,9 @@ +library L { + struct Nested { uint y; } + function b(function(Nested calldata) external returns (uint)[] storage) external pure {} + function d(function(Nested storage) external returns (uint)[] storage) external pure {} +} + +// ---- +// TypeError: (66-81): Data location must be "memory" for parameter in function, but "calldata" was given. +// TypeError: (159-173): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/external_function_return_parameters_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/external_function_return_parameters_no_data_location.sol new file mode 100644 index 000000000..cbcf2a6e2 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/external_function_return_parameters_no_data_location.sol @@ -0,0 +1,5 @@ +contract C { + function i() external pure returns(uint[]) {} +} +// ---- +// TypeError: (52-58): Data location must be "memory" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_calldata.sol new file mode 100644 index 000000000..781c645a0 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_calldata.sol @@ -0,0 +1,4 @@ +contract test { + function f(bytes calldata) external; +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_memory.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_memory.sol new file mode 100644 index 000000000..d30bde3f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_memory.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes memory) external; +} +// ---- +// TypeError: (31-43): Data location must be "calldata" for parameter in external function, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_storage.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_storage.sol new file mode 100644 index 000000000..7dc5ba6d5 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_storage.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes storage) external; +} +// ---- +// TypeError: (31-44): Data location must be "calldata" for parameter in external function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/function_argument_location_specifier_test_non_reference_type.sol b/test/libsolidity/syntaxTests/dataLocations/function_argument_location_specifier_test_non_reference_type.sol new file mode 100644 index 000000000..bc14aa1fe --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/function_argument_location_specifier_test_non_reference_type.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes4 memory) public; +} +// ---- +// TypeError: (31-44): Data location can only be specified for array, struct or mapping types, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/function_parameters_with_data_location_fine.sol b/test/libsolidity/syntaxTests/dataLocations/function_parameters_with_data_location_fine.sol new file mode 100644 index 000000000..2bc7b3933 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/function_parameters_with_data_location_fine.sol @@ -0,0 +1,8 @@ +contract C { + function f(uint[] memory, uint[] storage) private pure {} + function g(uint[] memory, uint[] storage) internal pure {} + function h(uint[] memory) public pure {} + function i(uint[] calldata) external pure {} + // No data location for events. + event e(uint[]); +} diff --git a/test/libsolidity/syntaxTests/dataLocations/function_return_parameters_with_data_location_fine.sol b/test/libsolidity/syntaxTests/dataLocations/function_return_parameters_with_data_location_fine.sol new file mode 100644 index 000000000..ea019198d --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/function_return_parameters_with_data_location_fine.sol @@ -0,0 +1,6 @@ +contract C { + function f() private pure returns(uint[] memory, uint[] storage b) { b = b; } + function g() internal pure returns(uint[] memory, uint[] storage b) { b = b; } + function h() public pure returns(uint[] memory) {} + function i() external pure returns(uint[] memory) {} +} diff --git a/test/libsolidity/syntaxTests/dataLocations/function_type_array_as_reference_type.sol b/test/libsolidity/syntaxTests/dataLocations/function_type_array_as_reference_type.sol new file mode 100644 index 000000000..b3856f585 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/function_type_array_as_reference_type.sol @@ -0,0 +1,8 @@ +contract C { + struct Nested { uint y; } + // ensure that we consider array of function pointers as reference type + function b(function(Nested memory) external returns (uint)[] storage) internal pure {} + function c(function(Nested memory) external returns (uint)[] memory) public pure {} + function d(function(Nested memory) external returns (uint)[] calldata) external pure {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_calldata.sol new file mode 100644 index 000000000..da3abff4e --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_calldata.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes calldata) internal; +} +// ---- +// TypeError: (31-45): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_memory.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_memory.sol new file mode 100644 index 000000000..1e5971c45 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_memory.sol @@ -0,0 +1,4 @@ +contract test { + function f(bytes memory) internal; +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_storage.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_storage.sol new file mode 100644 index 000000000..56f0fe992 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_storage.sol @@ -0,0 +1,4 @@ +contract test { + function f(bytes storage) internal; +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/internal_function_parameters_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/internal_function_parameters_no_data_location.sol new file mode 100644 index 000000000..f1c4a5504 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/internal_function_parameters_no_data_location.sol @@ -0,0 +1,5 @@ +contract C { + function g(uint[]) internal pure {} +} +// ---- +// TypeError: (28-34): Data location must be "storage" or "memory" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/internal_function_return_parameters_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/internal_function_return_parameters_no_data_location.sol new file mode 100644 index 000000000..a32995e75 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/internal_function_return_parameters_no_data_location.sol @@ -0,0 +1,5 @@ +contract C { + function g() internal pure returns(uint[]) {} +} +// ---- +// TypeError: (52-58): Data location must be "storage" or "memory" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_external_function_params_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_external_function_params_no_data_location.sol new file mode 100644 index 000000000..c20088b7f --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_external_function_params_no_data_location.sol @@ -0,0 +1,12 @@ +library L { + struct S { uint x; } + function g(uint[2]) external pure {} + function h(uint[]) external pure {} + function i(S) external pure {} + function j(mapping(uint => uint)) external pure {} +} +// ---- +// TypeError: (52-59): Data location must be "storage" or "calldata" for parameter in external function, but none was given. +// TypeError: (93-99): Data location must be "storage" or "calldata" for parameter in external function, but none was given. +// TypeError: (133-134): Data location must be "storage" or "calldata" for parameter in external function, but none was given. +// TypeError: (168-189): Data location must be "storage" or "calldata" for parameter in external function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_external_function_return_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_external_function_return_no_data_location.sol new file mode 100644 index 000000000..fa3a78213 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_external_function_return_no_data_location.sol @@ -0,0 +1,12 @@ +library L { + struct S { uint x; } + function g() external pure returns (uint[2]) {} + function h() external pure returns (uint[]) {} + function i() external pure returns (S) {} + function j() external pure returns (mapping(uint => uint)) {} +} +// ---- +// TypeError: (77-84): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (129-135): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (180-181): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (226-247): Data location must be "storage" or "memory" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_fine.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_fine.sol new file mode 100644 index 000000000..7a276f95a --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_fine.sol @@ -0,0 +1,10 @@ +library L { + struct S { uint x; } + function f(uint[] memory, uint[] storage, S storage) private pure + returns (mapping(uint => uint) storage a, S memory b, uint[] storage c) { return (a, b, c); } + function g(uint[] memory, uint[] storage) internal pure + returns (mapping(uint => uint) storage a, S memory b, uint[] storage c) { return (a, b, c); } + function h(uint[] memory, uint[] storage) public pure returns (S storage x) { return x; } + function i(uint[] calldata, uint[] storage) external pure returns (S storage x) {return x; } +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_internal_function_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_internal_function_no_data_location.sol new file mode 100644 index 000000000..68c177a8b --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_internal_function_no_data_location.sol @@ -0,0 +1,20 @@ +library L { + struct S { uint x; } + function g() internal pure returns (uint[2]) {} + function h() internal pure returns (uint[]) {} + function i() internal pure returns (S) {} + function j() internal pure returns (mapping(uint => uint)) {} + function gp(uint[2]) internal pure {} + function hp(uint[]) internal pure {} + function ip(S) internal pure {} + function jp(mapping(uint => uint)) internal pure {} +} +// ---- +// TypeError: (77-84): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (129-135): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (180-181): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (226-247): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (268-275): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (310-316): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (351-352): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (387-408): Data location must be "storage" or "memory" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_private_function_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_private_function_no_data_location.sol new file mode 100644 index 000000000..35256eae1 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_private_function_no_data_location.sol @@ -0,0 +1,20 @@ +library L { + struct S { uint x; } + function g() private pure returns (uint[2]) {} + function h() private pure returns (uint[]) {} + function i() private pure returns (S) {} + function j() private pure returns (mapping(uint => uint)) {} + function gp(uint[2]) private pure {} + function hp(uint[]) private pure {} + function ip(S) private pure {} + function jp(mapping(uint => uint)) private pure {} +} +// ---- +// TypeError: (76-83): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (127-133): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (177-178): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (222-243): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (264-271): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (305-311): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (345-346): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (380-401): Data location must be "storage" or "memory" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_public_function_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_public_function_no_data_location.sol new file mode 100644 index 000000000..f8f8dcb26 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_public_function_no_data_location.sol @@ -0,0 +1,19 @@ +library L { + struct S { uint x; } + function g() private pure returns (uint[2]) {} + function h() private pure returns (uint[]) {} + function i() private pure returns (S) {} + function j() private pure returns (mapping(uint => uint)) {} + function gp(uint[2]) private pure {} + function hp(uint[]) private pure {} + function ip(S) private pure {} + function jp(mapping(uint => uint)) private pure {}} +// ---- +// TypeError: (76-83): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (127-133): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (177-178): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (222-243): Data location must be "storage" or "memory" for return parameter in function, but none was given. +// TypeError: (264-271): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (305-311): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (345-346): Data location must be "storage" or "memory" for parameter in function, but none was given. +// TypeError: (380-401): Data location must be "storage" or "memory" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_calldata.sol new file mode 100644 index 000000000..d3ac2accb --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_calldata.sol @@ -0,0 +1,3 @@ +library test { + function f(bytes calldata) external; +} diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol new file mode 100644 index 000000000..2de0082ac --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol @@ -0,0 +1,5 @@ +library test { + function f(bytes memory) external; +} +// ---- +// TypeError: (30-42): Data location must be "storage" or "calldata" for parameter in external function, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_storage.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_storage.sol new file mode 100644 index 000000000..2ee68ef9c --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_storage.sol @@ -0,0 +1,3 @@ +library test { + function f(bytes storage) external; +} diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_calldata.sol new file mode 100644 index 000000000..c4b81f98b --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_calldata.sol @@ -0,0 +1,5 @@ +library test { + function f(bytes calldata) internal pure {} +} +// ---- +// TypeError: (30-44): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_memory.sol b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_memory.sol new file mode 100644 index 000000000..78a30f5b2 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_memory.sol @@ -0,0 +1,3 @@ +library test { + function f(bytes memory) internal pure {} +} diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_storage.sol b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_storage.sol new file mode 100644 index 000000000..b51f148b9 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_storage.sol @@ -0,0 +1,3 @@ +library test { + function f(bytes storage) internal pure {} +} diff --git a/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol new file mode 100644 index 000000000..a441b5407 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol @@ -0,0 +1,12 @@ +contract C { + int[] x; + function f() public { + int[] storage a = x; + int[] memory b; + a = b; + a = int[](b); + } +} +// ---- +// TypeError: (93-94): Type int256[] memory is not implicitly convertible to expected type int256[] storage pointer. +// TypeError: (102-110): Type int256[] memory is not implicitly convertible to expected type int256[] storage pointer. diff --git a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_no_data_location.sol new file mode 100644 index 000000000..fdd5cbaf6 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_no_data_location.sol @@ -0,0 +1,5 @@ +contract C { + function f(uint[]) private pure {} +} +// ---- +// TypeError: (28-34): Data location must be "storage" or "memory" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_no_data_location.sol new file mode 100644 index 000000000..65ec1bcef --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_no_data_location.sol @@ -0,0 +1,5 @@ +contract C { + function f() private pure returns(uint[]) {} +} +// ---- +// TypeError: (51-57): Data location must be "storage" or "memory" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_calldata.sol new file mode 100644 index 000000000..3aba870f9 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_calldata.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes calldata) public; +} +// ---- +// TypeError: (31-45): Data location must be "memory" for parameter in function, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_memory.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_memory.sol new file mode 100644 index 000000000..4eebf0167 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_memory.sol @@ -0,0 +1,4 @@ +contract test { + function f(bytes memory) public; +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_storage.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_storage.sol new file mode 100644 index 000000000..1c033a693 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_storage.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes storage) public; +} +// ---- +// TypeError: (31-44): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_parameters_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_parameters_no_data_location.sol new file mode 100644 index 000000000..f76bd6313 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_parameters_no_data_location.sol @@ -0,0 +1,5 @@ +contract C { + function h(uint[]) public pure {} +} +// ---- +// TypeError: (28-34): Data location must be "memory" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_no_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_no_data_location.sol new file mode 100644 index 000000000..6b087c346 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_no_data_location.sol @@ -0,0 +1,5 @@ +contract C { + function h() public pure returns(uint[]) {} +} +// ---- +// TypeError: (50-56): Data location must be "memory" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/variable_declaration_location_specifier_test_non_reference_type.sol b/test/libsolidity/syntaxTests/dataLocations/variable_declaration_location_specifier_test_non_reference_type.sol new file mode 100644 index 000000000..5f6daf681 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/variable_declaration_location_specifier_test_non_reference_type.sol @@ -0,0 +1,13 @@ +contract test { + function f() public { + uint storage a1; + bytes16 storage b1; + uint memory a2; + bytes16 memory b2; + } +} +// ---- +// TypeError: (48-63): Data location can only be specified for array, struct or mapping types, but "storage" was given. +// TypeError: (71-89): Data location can only be specified for array, struct or mapping types, but "storage" was given. +// TypeError: (97-111): Data location can only be specified for array, struct or mapping types, but "memory" was given. +// TypeError: (119-136): Data location can only be specified for array, struct or mapping types, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/variable_declaration_location_specifier_test_reference_type.sol b/test/libsolidity/syntaxTests/dataLocations/variable_declaration_location_specifier_test_reference_type.sol new file mode 100644 index 000000000..0fbad1555 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/variable_declaration_location_specifier_test_reference_type.sol @@ -0,0 +1,13 @@ +contract test { + uint[] a; + uint[] b; + function f() public { + uint[] storage s1 = a; + uint[] memory s2 = new uint[](42); + uint[] storage s3 = b; + s1.push(42); + s2[3] = 12; + s3.push(42); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol b/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol index 3571e8a95..f115ac606 100644 --- a/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol +++ b/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol @@ -2,4 +2,4 @@ contract C { uint constant x = 0x01 wei; } // ---- -// Warning: (32-40): Hexadecimal numbers with unit denominations are deprecated. You can use an expression of the form "0x1234 * 1 day" instead. +// TypeError: (32-40): Hexadecimal numbers cannot be used with unit denominations. You can use an expression of the form "0x1234 * 1 day" instead. diff --git a/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination_050.sol b/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination_050.sol deleted file mode 100644 index 988659995..000000000 --- a/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination_050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - uint constant x = 0x01 wei; -} -// ---- -// TypeError: (62-70): Hexadecimal numbers cannot be used with unit denominations. You can use an expression of the form "0x1234 * 1 day" instead. diff --git a/test/libsolidity/syntaxTests/denominations/denominations.sol b/test/libsolidity/syntaxTests/denominations/denominations.sol index 6d1aa2f3f..43049a144 100644 --- a/test/libsolidity/syntaxTests/denominations/denominations.sol +++ b/test/libsolidity/syntaxTests/denominations/denominations.sol @@ -1,7 +1,6 @@ contract C { uint constant a = 1 wei + 2 szabo + 3 finney + 4 ether; - uint constant b = 1 seconds + 2 minutes + 3 hours + 4 days + 5 weeks + 6 years; + uint constant b = 1 seconds + 2 minutes + 3 hours + 4 days + 5 weeks; uint constant c = 2 szabo / 1 seconds + 3 finney * 3 hours; } // ---- -// Warning: (142-149): Using "years" as a unit denomination is deprecated. diff --git a/test/libsolidity/syntaxTests/denominations/deprecated_year.sol b/test/libsolidity/syntaxTests/denominations/deprecated_year.sol index 30e86535a..691c0cb05 100644 --- a/test/libsolidity/syntaxTests/denominations/deprecated_year.sol +++ b/test/libsolidity/syntaxTests/denominations/deprecated_year.sol @@ -2,4 +2,4 @@ contract C { uint constant a = 3 years; } // ---- -// Warning: (32-39): Using "years" as a unit denomination is deprecated. +// TypeError: (32-39): Using "years" as a unit denomination is deprecated. diff --git a/test/libsolidity/syntaxTests/denominations/deprecated_year_050.sol b/test/libsolidity/syntaxTests/denominations/deprecated_year_050.sol deleted file mode 100644 index 4baaeaa34..000000000 --- a/test/libsolidity/syntaxTests/denominations/deprecated_year_050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - uint constant a = 3 years; -} -// ---- -// TypeError: (62-69): Using "years" as a unit denomination is deprecated. diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/deprecated_functions.sol index 9df2b43ca..62dfcff95 100644 --- a/test/libsolidity/syntaxTests/deprecated_functions.sol +++ b/test/libsolidity/syntaxTests/deprecated_functions.sol @@ -1,12 +1,12 @@ contract test { function f() pure public { - bytes32 x = sha3(); + bytes32 x = sha3(""); x; } function g() public { - suicide(1); + suicide(0x0000000000000000000000000000000000000001); } } // ---- -// Warning: (58-64): "sha3" has been deprecated in favour of "keccak256" -// Warning: (99-109): "suicide" has been deprecated in favour of "selfdestruct" +// TypeError: (58-66): "sha3" has been deprecated in favour of "keccak256" +// TypeError: (101-152): "suicide" has been deprecated in favour of "selfdestruct" diff --git a/test/libsolidity/syntaxTests/deprecated_functions_050.sol b/test/libsolidity/syntaxTests/deprecated_functions_050.sol deleted file mode 100644 index b28e5abbd..000000000 --- a/test/libsolidity/syntaxTests/deprecated_functions_050.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - bytes32 x = sha3(uint8(1)); - x; - } - function g() public { - suicide(1); - } -} -// ---- -// TypeError: (88-102): "sha3" has been deprecated in favour of "keccak256" -// TypeError: (88-102): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (88-102): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// TypeError: (137-147): "suicide" has been deprecated in favour of "selfdestruct" diff --git a/test/libsolidity/syntaxTests/double_variable_declaration.sol b/test/libsolidity/syntaxTests/double_variable_declaration.sol index 9ab87959c..53c5c9be8 100644 --- a/test/libsolidity/syntaxTests/double_variable_declaration.sol +++ b/test/libsolidity/syntaxTests/double_variable_declaration.sol @@ -1,8 +1,9 @@ contract test { function f() pure public { uint256 x; - if (true) { uint256 x; } + x = 1; + if (true) { uint256 x; x = 2; } } } // ---- -// DeclarationError: (71-80): Identifier already declared. +// Warning: (80-89): This declaration shadows an existing declaration. diff --git a/test/libsolidity/syntaxTests/double_variable_declaration_050.sol b/test/libsolidity/syntaxTests/double_variable_declaration_050.sol deleted file mode 100644 index 2f47e6dc9..000000000 --- a/test/libsolidity/syntaxTests/double_variable_declaration_050.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - uint256 x; - if (true) { uint256 x; } - } -} -// ---- -// Warning: (101-110): This declaration shadows an existing declaration. -// Warning: (76-85): Unused local variable. -// Warning: (101-110): Unused local variable. diff --git a/test/libsolidity/syntaxTests/emit/emit_non_event.sol b/test/libsolidity/syntaxTests/emit/emit_non_event.sol index 1df6990dc..d5045ddf9 100644 --- a/test/libsolidity/syntaxTests/emit/emit_non_event.sol +++ b/test/libsolidity/syntaxTests/emit/emit_non_event.sol @@ -1,10 +1,10 @@ contract C { uint256 Test; - function f() { + function f() public { emit Test(); } } // ---- -// TypeError: (56-62): Type is not callable -// TypeError: (56-60): Expression has to be an event invocation. +// TypeError: (63-69): Type is not callable +// TypeError: (63-67): Expression has to be an event invocation. diff --git a/test/libsolidity/syntaxTests/empty_string_var.sol b/test/libsolidity/syntaxTests/empty_string_var.sol deleted file mode 100644 index e9837590a..000000000 --- a/test/libsolidity/syntaxTests/empty_string_var.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C { - function f() { - var a = ""; - bytes1 b = bytes1(a); - bytes memory c = bytes(a); - string memory d = string(a); - } -} -// ---- -// Warning: (34-39): Use of the "var" keyword is deprecated. -// TypeError: (61-70): Explicit type conversion not allowed from "string memory" to "bytes1". diff --git a/test/libsolidity/syntaxTests/empty_struct.sol b/test/libsolidity/syntaxTests/empty_struct.sol index 12655309f..0a52fb729 100644 --- a/test/libsolidity/syntaxTests/empty_struct.sol +++ b/test/libsolidity/syntaxTests/empty_struct.sol @@ -2,4 +2,4 @@ contract test { struct A {} } // ---- -// Warning: (17-28): Defining empty structs is deprecated. +// SyntaxError: (17-28): Defining empty structs is disallowed. diff --git a/test/libsolidity/syntaxTests/empty_struct_050.sol b/test/libsolidity/syntaxTests/empty_struct_050.sol deleted file mode 100644 index 886f1f838..000000000 --- a/test/libsolidity/syntaxTests/empty_struct_050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - struct A {} -} -// ---- -// SyntaxError: (47-58): Defining empty structs is disallowed. diff --git a/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol index aaf6028a8..3f729a6a5 100644 --- a/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol @@ -4,4 +4,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (59-65): Indexed reference types cannot yet be used with ABIEncoderV2. +// TypeError: (59-73): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol index ffae5b9cc..f05b884e9 100644 --- a/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol @@ -4,4 +4,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (59-67): Indexed reference types cannot yet be used with ABIEncoderV2. +// TypeError: (59-75): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol index 69ee50174..7332cb3b1 100644 --- a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol @@ -3,4 +3,4 @@ contract c { event E(S indexed); } // ---- -// TypeError: (51-52): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. +// TypeError: (51-60): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol index a8e0837f8..a1d8cf04e 100644 --- a/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol @@ -5,4 +5,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (85-86): Indexed reference types cannot yet be used with ABIEncoderV2. +// TypeError: (85-94): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/fallback/default_visibility.sol b/test/libsolidity/syntaxTests/fallback/default_visibility.sol new file mode 100644 index 000000000..6fbb15a5d --- /dev/null +++ b/test/libsolidity/syntaxTests/fallback/default_visibility.sol @@ -0,0 +1,7 @@ +contract C { + // Check that visibility is also enforced for the fallback function. + function() {} +} +// ---- +// SyntaxError: (90-103): No visibility specified. Did you intend to add "external"? +// TypeError: (90-103): Fallback function must be defined as "external". diff --git a/test/libsolidity/syntaxTests/fallback/pure_modifier.sol b/test/libsolidity/syntaxTests/fallback/pure_modifier.sol index 20d5b0ac7..12d790d1c 100644 --- a/test/libsolidity/syntaxTests/fallback/pure_modifier.sol +++ b/test/libsolidity/syntaxTests/fallback/pure_modifier.sol @@ -1,6 +1,6 @@ contract C { uint x; - function() pure { x = 2; } + function() external pure { x = 2; } } // ---- -// TypeError: (29-55): Fallback function must be payable or non-payable, but is "pure". +// TypeError: (29-64): Fallback function must be payable or non-payable, but is "pure". diff --git a/test/libsolidity/syntaxTests/fallback/view_modifier.sol b/test/libsolidity/syntaxTests/fallback/view_modifier.sol index 44c5d204e..2497e9fa0 100644 --- a/test/libsolidity/syntaxTests/fallback/view_modifier.sol +++ b/test/libsolidity/syntaxTests/fallback/view_modifier.sol @@ -1,6 +1,6 @@ contract C { uint x; - function() view { x = 2; } + function() external view { x = 2; } } // ---- -// TypeError: (29-55): Fallback function must be payable or non-payable, but is "view". +// TypeError: (29-64): Fallback function must be payable or non-payable, but is "view". diff --git a/test/libsolidity/syntaxTests/functionCalls/named_arguments_for_functions_that_take_arbitrary_parameters.sol b/test/libsolidity/syntaxTests/functionCalls/named_arguments_for_functions_that_take_arbitrary_parameters.sol new file mode 100644 index 000000000..089e1dbf0 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/named_arguments_for_functions_that_take_arbitrary_parameters.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + abi.encodeWithSelector({selector:"abc"}); + } +} +// ---- +// TypeError: (52-92): Named arguments cannot be used for functions that take arbitrary parameters. diff --git a/test/libsolidity/syntaxTests/functionTypes/delete_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/delete_function_type.sol index a6fe6c225..2481c455c 100644 --- a/test/libsolidity/syntaxTests/functionTypes/delete_function_type.sol +++ b/test/libsolidity/syntaxTests/functionTypes/delete_function_type.sol @@ -3,15 +3,13 @@ contract C { function(uint) internal returns (uint) y; function f() public { delete x; - var a = y; + function(uint) internal returns (uint) a = y; delete a; delete y; - var c = f; + function() internal c = f; delete c; function(uint) internal returns (uint) g; delete g; } } // ---- -// Warning: (157-162): Use of the "var" keyword is deprecated. -// Warning: (212-217): Use of the "var" keyword is deprecated. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_to_function_type_calldata_parameter.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_to_function_type_calldata_parameter.sol index eb4f0693e..f22afe5ed 100644 --- a/test/libsolidity/syntaxTests/functionTypes/external_function_to_function_type_calldata_parameter.sol +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_to_function_type_calldata_parameter.sol @@ -3,7 +3,7 @@ // when converting to a function type. contract C { function f(function(bytes memory) pure external /*g*/) pure public { } - function callback(bytes) pure external {} + function callback(bytes calldata) pure external {} function g() view public { f(this.callback); } diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address_payable.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address_payable.sol new file mode 100644 index 000000000..adffb14b3 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address_payable.sol @@ -0,0 +1,7 @@ +contract C { + function f() public view returns (address payable) { + return address(this.f); + } +} +// ---- +// TypeError: (85-100): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_constructor.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor.sol index 95ebc1792..51f0b10d1 100644 --- a/test/libsolidity/syntaxTests/functionTypes/function_type_constructor.sol +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor.sol @@ -1,7 +1,7 @@ contract C { // Fool parser into parsing a constructor as a function type. - constructor() x; + constructor() public x; } // ---- -// Warning: (83-99): Modifiers of functions without implementation are ignored. -// DeclarationError: (97-98): Undeclared identifier. +// SyntaxError: (83-106): Functions without implementation cannot have modifiers. +// DeclarationError: (104-105): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_constructor_local.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor_local.sol index b89a3bb49..42697b739 100644 --- a/test/libsolidity/syntaxTests/functionTypes/function_type_constructor_local.sol +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor_local.sol @@ -5,4 +5,4 @@ contract C { } } // ---- -// ParserError: (118-119): Expected ';' but got identifier +// ParserError: (104-115): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_return_parameters_with_names.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_return_parameters_with_names.sol new file mode 100644 index 000000000..121915300 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_return_parameters_with_names.sol @@ -0,0 +1,5 @@ +contract C { + function(uint) returns (bool ret) f; +} +// ---- +// SyntaxError: (41-49): Return parameters in function types may not be named. diff --git a/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol b/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol index 10c6767c2..e7d2c9a93 100644 --- a/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol +++ b/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol @@ -1,5 +1,5 @@ contract test { - function fa(uint) {} + function fa(uint) public {} function fb(uint) internal {} function fc(uint) internal {} function fd(uint) external {} @@ -13,11 +13,14 @@ contract test { function(uint) internal internal c = fc; function(uint) external d = this.fd; function(uint) external internal e = this.fe; - function(uint) internal public f = ff; - function(uint) internal pure public g = fg; - function(uint) pure internal public h = fh; + function(uint) internal f = ff; + function(uint) internal pure g = fg; + function(uint) pure internal h = fh; } // ---- -// TypeError: (545-582): Internal or recursive type is not allowed for public state variables. -// TypeError: (588-630): Internal or recursive type is not allowed for public state variables. -// TypeError: (636-678): Internal or recursive type is not allowed for public state variables. +// Warning: (20-47): Function state mutability can be restricted to pure +// Warning: (52-81): Function state mutability can be restricted to pure +// Warning: (86-115): Function state mutability can be restricted to pure +// Warning: (120-149): Function state mutability can be restricted to pure +// Warning: (154-183): Function state mutability can be restricted to pure +// Warning: (188-217): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol b/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol deleted file mode 100644 index 67a74e546..000000000 --- a/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract C { - function(uint) returns (bool ret) f; -} -// ---- -// Warning: (41-49): Naming function type return parameters is deprecated. diff --git a/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol new file mode 100644 index 000000000..92ec4eb7f --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol @@ -0,0 +1,17 @@ +contract C { + function f() public { + (bool success,) = address(this).call(); + require(success); + (success,) = address(this).call(bytes4(0x12345678)); + require(success); + (success,) = address(this).call(uint(1)); + require(success); + (success,) = address(this).call(uint(1), uint(2)); + require(success); + } +} +// ---- +// TypeError: (65-85): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (153-171): Invalid type for argument in function call. Invalid implicit conversion from bytes4 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (240-247): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (297-333): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol new file mode 100644 index 000000000..655d5f4c2 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol @@ -0,0 +1,14 @@ +contract C { + function f() public { + (bool success,) = address(this).callcode(); + require(success); + (success,) = address(this).callcode(uint(1)); + require(success); + (success,) = address(this).callcode(uint(1), uint(2)); + require(success); + } +} +// ---- +// TypeError: (65-89): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (161-168): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (218-258): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol new file mode 100644 index 000000000..fa524b99e --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol @@ -0,0 +1,14 @@ +contract C { + function f() public { + (bool success,) = address(this).delegatecall(); + require(success); + (success,) = address(this).delegatecall(uint(1)); + require(success); + (success,) = address(this).delegatecall(uint(1), uint(2)); + require(success); + } +} +// ---- +// TypeError: (65-93): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (169-176): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (226-270): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/keccak256_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/keccak256_with_wrong_arg_count.sol new file mode 100644 index 000000000..4857bc2e4 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/keccak256_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(keccak256() != 0); + require(keccak256(uint(1)) != 0); + require(keccak256(uint(1), uint(2)) != 0); + } +} +// ---- +// TypeError: (55-66): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (100-107): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (132-159): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/globalFunctions/ripemd160_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/ripemd160_with_wrong_arg_count.sol new file mode 100644 index 000000000..da41fccd3 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/ripemd160_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(ripemd160() != 0); + require(ripemd160(uint(1)) != 0); + require(ripemd160(uint(1), uint(2)) != 0); + } +} +// ---- +// TypeError: (55-66): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (100-107): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (132-159): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/globalFunctions/sha256_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/sha256_with_wrong_arg_count.sol new file mode 100644 index 000000000..2939e7fcb --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/sha256_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(sha256() != 0); + require(sha256(uint(1)) != 0); + require(sha256(uint(1), uint(2)) != 0); + } +} +// ---- +// TypeError: (55-63): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (94-101): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (126-150): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/indexing/array_multidim_rational.sol b/test/libsolidity/syntaxTests/indexing/array_multidim_rational.sol new file mode 100644 index 000000000..df9f8223b --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/array_multidim_rational.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + bytes[32] memory a; + a[8**90][8**90][8**90*0.1]; + } +} +// ---- +// TypeError: (67-72): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (74-79): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (81-90): Type rational_const 9485...(73 digits omitted)...5712 / 5 is not implicitly convertible to expected type uint256. +// TypeError: (65-91): Index expression cannot be represented as an unsigned integer. diff --git a/test/libsolidity/syntaxTests/indexing/array_multim_overflow_index.sol b/test/libsolidity/syntaxTests/indexing/array_multim_overflow_index.sol new file mode 100644 index 000000000..9c98ad451 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/array_multim_overflow_index.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + bytes[32] memory a; + a[8**90][8**90][1 - 8**90]; + } +} +// ---- +// TypeError: (67-72): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (74-79): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (81-90): Type int_const -189...(75 digits omitted)...1423 is not implicitly convertible to expected type uint256. +// TypeError: (65-91): Index expression cannot be represented as an unsigned integer. diff --git a/test/libsolidity/syntaxTests/indexing/array_negative_index.sol b/test/libsolidity/syntaxTests/indexing/array_negative_index.sol new file mode 100644 index 000000000..019d023b5 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/array_negative_index.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + bytes[32] memory a; + a[-1]; + } +} +// ---- +// TypeError: (67-69): Type int_const -1 is not implicitly convertible to expected type uint256. diff --git a/test/libsolidity/syntaxTests/indexing/array_noninteger_index.sol b/test/libsolidity/syntaxTests/indexing/array_noninteger_index.sol new file mode 100644 index 000000000..7c0ac9fe2 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/array_noninteger_index.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + bytes[32] memory a; + a[888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888]; + } +} +// ---- +// TypeError: (67-178): Type int_const 8888...(103 digits omitted)...8888 is not implicitly convertible to expected type uint256. diff --git a/test/libsolidity/syntaxTests/indexing/array_out_of_bounds_index.sol b/test/libsolidity/syntaxTests/indexing/array_out_of_bounds_index.sol new file mode 100644 index 000000000..b00798570 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/array_out_of_bounds_index.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + bytes[32] memory a; + a[64]; + } +} +// ---- +// TypeError: (65-70): Out of bounds array access. diff --git a/test/libsolidity/syntaxTests/indexing/array_without_index.sol b/test/libsolidity/syntaxTests/indexing/array_without_index.sol new file mode 100644 index 000000000..6b1c27781 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/array_without_index.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + bytes memory a; + a[]; + } +} +// ---- +// TypeError: (61-64): Index expression cannot be omitted. diff --git a/test/libsolidity/syntaxTests/indexing/fixedbytes_negative_index.sol b/test/libsolidity/syntaxTests/indexing/fixedbytes_negative_index.sol new file mode 100644 index 000000000..123993178 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/fixedbytes_negative_index.sol @@ -0,0 +1,9 @@ +contract C { + function f() public { + bytes32 b; + b[-1]; + } +} +// ---- +// TypeError: (58-60): Type int_const -1 is not implicitly convertible to expected type uint256. +// TypeError: (56-61): Index expression cannot be represented as an unsigned integer. diff --git a/test/libsolidity/syntaxTests/indexing/fixedbytes_noninteger_index.sol b/test/libsolidity/syntaxTests/indexing/fixedbytes_noninteger_index.sol new file mode 100644 index 000000000..adf7db61b --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/fixedbytes_noninteger_index.sol @@ -0,0 +1,9 @@ +contract C { + function f() public { + bytes32 b; + b[888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888]; + } +} +// ---- +// TypeError: (58-169): Type int_const 8888...(103 digits omitted)...8888 is not implicitly convertible to expected type uint256. +// TypeError: (56-170): Index expression cannot be represented as an unsigned integer. diff --git a/test/libsolidity/syntaxTests/indexing/fixedbytes_out_of_bounds_index.sol b/test/libsolidity/syntaxTests/indexing/fixedbytes_out_of_bounds_index.sol new file mode 100644 index 000000000..8264a8b29 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/fixedbytes_out_of_bounds_index.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + bytes32 b; + b[64]; + } +} +// ---- +// TypeError: (56-61): Out of bounds array access. diff --git a/test/libsolidity/syntaxTests/indexing/fixedbytes_without_index.sol b/test/libsolidity/syntaxTests/indexing/fixedbytes_without_index.sol new file mode 100644 index 000000000..979ac8a7f --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/fixedbytes_without_index.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + bytes32 b; + b[]; + } +} +// ---- +// TypeError: (56-59): Index expression cannot be omitted. diff --git a/test/libsolidity/syntaxTests/indexing/function_type.sol b/test/libsolidity/syntaxTests/indexing/function_type.sol new file mode 100644 index 000000000..6c6c06a93 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/function_type.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + f[0]; + } +} +// ---- +// TypeError: (41-42): Indexed expression has to be a type, mapping or array (is function ()) diff --git a/test/libsolidity/syntaxTests/indexing/function_type_without_index.sol b/test/libsolidity/syntaxTests/indexing/function_type_without_index.sol new file mode 100644 index 000000000..bf511bc94 --- /dev/null +++ b/test/libsolidity/syntaxTests/indexing/function_type_without_index.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + f[]; + } +} +// ---- +// TypeError: (41-42): Indexed expression has to be a type, mapping or array (is function ()) diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol index 0b18b995b..692b18276 100644 --- a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol +++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol @@ -4,4 +4,4 @@ contract Base { contract Derived is Base(2) { } contract Derived2 is Base(), Derived() { } // ---- -// Warning: (101-107): Wrong argument count for constructor call: 0 arguments given but expected 1. +// TypeError: (101-107): Wrong argument count for constructor call: 0 arguments given but expected 1. Remove parentheses if you do not want to provide arguments here. diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol deleted file mode 100644 index db04ab8c9..000000000 --- a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental "v0.5.0"; - -contract Base { - constructor(uint) public {} -} -contract Derived is Base(2) { } -contract Derived2 is Base(), Derived() { } -// ---- -// TypeError: (132-138): Wrong argument count for constructor call: 0 arguments given but expected 1. diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_multiple_inheritance.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_multiple_inheritance.sol index 015b33e59..96be62f2d 100644 --- a/test/libsolidity/syntaxTests/inheritance/base_arguments_multiple_inheritance.sol +++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_multiple_inheritance.sol @@ -6,4 +6,4 @@ contract Derived is Base, Base1 { constructor(uint i) Base(i) public {} } // ---- -// Warning: (138-145): Base constructor arguments given twice. +// DeclarationError: (138-145): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/disallow_modifier_style_without_parentheses.sol b/test/libsolidity/syntaxTests/inheritance/disallow_modifier_style_without_parentheses.sol index 6cf68d2aa..8f5ceef89 100644 --- a/test/libsolidity/syntaxTests/inheritance/disallow_modifier_style_without_parentheses.sol +++ b/test/libsolidity/syntaxTests/inheritance/disallow_modifier_style_without_parentheses.sol @@ -1,4 +1,4 @@ contract A { constructor() public { } } contract B is A { constructor() A public { } } // ---- -// Warning: (72-73): Modifier-style base constructor call without arguments. +// DeclarationError: (72-73): Modifier-style base constructor call without arguments. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol index 24cff54de..76cc937b2 100644 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol @@ -2,4 +2,4 @@ contract A { constructor(uint) public { } } contract B is A(2) { constructor() public { } } contract C is B { constructor() A(3) public { } } // ---- -// Warning: (125-129): Base constructor arguments given twice. +// DeclarationError: (125-129): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol deleted file mode 100644 index 8d5df5bf5..000000000 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma experimental "v0.5.0"; - -contract A { constructor(uint) public { } } -contract B is A(2) { constructor() public { } } -contract C is B { constructor() A(3) public { } } -// ---- -// DeclarationError: (156-160): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol index 9ceaea5ea..4c7a684fb 100644 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol @@ -1,4 +1,4 @@ contract A { constructor(uint) public { } } contract B is A(2) { constructor() A(3) public { } } // ---- -// Warning: (79-83): Base constructor arguments given twice. +// DeclarationError: (79-83): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol deleted file mode 100644 index f9325f99d..000000000 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; - -contract A { constructor(uint) public { } } -contract B is A(2) { constructor() A(3) public { } } -// ---- -// DeclarationError: (110-114): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol index e5c2aa365..2e77e0777 100644 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol @@ -3,5 +3,5 @@ contract A is C(2) {} contract B is C(2) {} contract D is A, B { constructor() C(3) public {} } // ---- -// Warning: (122-126): Base constructor arguments given twice. -// Warning: (122-126): Base constructor arguments given twice. +// DeclarationError: (122-126): Base constructor arguments given twice. +// DeclarationError: (122-126): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol index 1abf29926..0beb15522 100644 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol @@ -3,4 +3,4 @@ contract A is C(2) {} contract B is C(2) {} contract D is A, B {} // ---- -// Warning: (87-108): Base constructor arguments given twice. +// DeclarationError: (87-108): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol index e15242db0..7142840e7 100644 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol @@ -3,4 +3,4 @@ contract A is C { constructor() C(2) public {} } contract B is C { constructor() C(2) public {} } contract D is A, B { } // ---- -// Warning: (141-163): Base constructor arguments given twice. +// DeclarationError: (141-163): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/modifiers_in_constructor_context.sol b/test/libsolidity/syntaxTests/inheritance/modifiers_in_constructor_context.sol new file mode 100644 index 000000000..d8ce0e488 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/modifiers_in_constructor_context.sol @@ -0,0 +1,9 @@ +// This generated an invalid warning on m1 in some compiler versions. +contract A { + constructor() m1 public { } + modifier m1 { _; } +} +contract B is A { + modifier m2 { _; } + constructor() A() m1 m2 public { } +} diff --git a/test/libsolidity/syntaxTests/inheritance/override/add_view.sol b/test/libsolidity/syntaxTests/inheritance/override/add_view.sol index 9973b23ec..21e437925 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/add_view.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/add_view.sol @@ -1,4 +1,4 @@ contract B { function f() public {} } -contract C is B { function f() view {} } +contract C is B { function f() public view {} } // ---- -// TypeError: (56-76): Overriding function changes state mutability from "nonpayable" to "view". +// TypeError: (56-83): Overriding function changes state mutability from "nonpayable" to "view". diff --git a/test/libsolidity/syntaxTests/inheritance/override/function_state_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/function_state_variable.sol new file mode 100644 index 000000000..023a161ae --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/function_state_variable.sol @@ -0,0 +1,2 @@ +interface ERC20 { function x() external returns (uint); } +contract C is ERC20 { uint public x; } diff --git a/test/libsolidity/syntaxTests/inheritance/override/remove_view.sol b/test/libsolidity/syntaxTests/inheritance/override/remove_view.sol index e58f6b20a..cc785858c 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/remove_view.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/remove_view.sol @@ -1,4 +1,4 @@ -contract B { function f() view {} } +contract B { function f() public view {} } contract C is B { function f() public {} } // ---- -// TypeError: (54-76): Overriding function changes state mutability from "view" to "nonpayable". +// TypeError: (61-83): Overriding function changes state mutability from "view" to "nonpayable". diff --git a/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol new file mode 100644 index 000000000..0f05cc8eb --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol @@ -0,0 +1,8 @@ +contract A { + uint public x; +} +contract C is A { + function x() public returns (uint); +} +// ---- +// DeclarationError: (50-85): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/inheritance/too_few_base_arguments.sol b/test/libsolidity/syntaxTests/inheritance/too_few_base_arguments.sol index c55c41f2e..1ce482001 100644 --- a/test/libsolidity/syntaxTests/inheritance/too_few_base_arguments.sol +++ b/test/libsolidity/syntaxTests/inheritance/too_few_base_arguments.sol @@ -6,5 +6,5 @@ contract Derived2 is Base { constructor() Base(2) public { } } // ---- -// TypeError: (74-81): Wrong argument count for constructor call: 1 arguments given but expected 2. +// TypeError: (74-81): Wrong argument count for constructor call: 1 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here. // TypeError: (130-137): Wrong argument count for modifier invocation: 1 arguments given but expected 2. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_contract.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_contract.sol new file mode 100644 index 000000000..a87a3e665 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_contract.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + let x := C + } + } +} +// ---- +// TypeError: (72-73): Expected a library. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_functiontype.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_functiontype.sol new file mode 100644 index 000000000..ecda3e994 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_functiontype.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + assembly { + let x := f + } + } +} diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol new file mode 100644 index 000000000..3c551c186 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol @@ -0,0 +1,10 @@ +library L { +} + +contract C { + function f() public pure { + assembly { + let x := L + } + } +} diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_super.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_super.sol new file mode 100644 index 000000000..bd5562d52 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_super.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + let x := super + } + } +} +// ---- +// DeclarationError: (72-77): Identifier not found. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_special.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_special.sol new file mode 100644 index 000000000..db28e5074 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_special.sol @@ -0,0 +1,13 @@ +contract C { + function f() public { + assembly { + super := 1 + f := 1 + C := 1 + } + } +} +// ---- +// TypeError: (58-63): Only local variables can be assigned to in inline assembly. +// TypeError: (75-76): Only local variables can be assigned to in inline assembly. +// TypeError: (88-89): Only local variables can be assigned to in inline assembly. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol new file mode 100644 index 000000000..ac1f541eb --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol @@ -0,0 +1,16 @@ +contract C { + function f() public pure { + assembly { + function f(a) {} + + f() + f(1) + f(1, 2) + } + } +} +// ---- +// TypeError: (87-88): Expected 1 arguments but got 0. +// SyntaxError: (87-90): Top-level expressions are not supposed to return values (this expression returns -1 values). Use ``pop()`` or assign them. +// TypeError: (108-109): Expected 1 arguments but got 2. +// SyntaxError: (108-115): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_not_found.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_not_found.sol new file mode 100644 index 000000000..57534bd6a --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_call_not_found.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + k() + } + } +} +// ---- +// DeclarationError: (63-64): Function not found. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol new file mode 100644 index 000000000..150fb9385 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + assembly { + l: + + l() + } + } +} +// ---- +// SyntaxError: (63-64): The use of labels is disallowed. Please use "if", "switch", "for" or function calls instead. +// SyntaxError: (63-64): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. +// TypeError: (73-74): Attempt to call label instead of function. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_variable.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_variable.sol new file mode 100644 index 000000000..c00718553 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_variable.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + let x := 1 + + x() + } + } +} +// ---- +// TypeError: (81-82): Attempt to call variable instead of function. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_without_call.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_without_call.sol new file mode 100644 index 000000000..8557e2fa4 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_without_call.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + function k() {} + + k + } + } +} +// ---- +// TypeError: (86-87): Function k used without being called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/empty_fun_arg.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/empty_fun_arg.sol new file mode 100644 index 000000000..e05277de6 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/empty_fun_arg.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + assembly { + function f(a, b) {} + f() + f(1,) + f(,1) + } + } +} +// ---- +// ParserError: (113-114): Literal, identifier or instruction expected. +// ParserError: (113-114): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/empty_function_name.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/empty_function_name.sol new file mode 100644 index 000000000..17995b093 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/empty_function_name.sol @@ -0,0 +1,10 @@ +contract C { + function f() public pure { + assembly { + function (a, b) {} + } + } +} +// ---- +// ParserError: (72-73): Expected identifier but got '(' +// ParserError: (79-80): Expected ';' but got '{' diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol new file mode 100644 index 000000000..715913de7 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol @@ -0,0 +1,10 @@ +contract C { + function f() public pure { + assembly { + let x := 0100 + } + } +} +// ---- +// ParserError: (72-73): Literal, identifier or instruction expected. +// ParserError: (72-73): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/missing_variable_in_assign.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/missing_variable_in_assign.sol new file mode 100644 index 000000000..c89843334 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/missing_variable_in_assign.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + let x := mload(0) + := 1 + } + } +} +// ---- +// ParserError: (87-88): Literal, identifier or instruction expected. +// ParserError: (87-88): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/overloaded_reference.sol b/test/libsolidity/syntaxTests/inlineAssembly/overloaded_reference.sol new file mode 100644 index 000000000..d1bcc9469 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/overloaded_reference.sol @@ -0,0 +1,11 @@ +contract C { + function f() pure public {} + function f(address) pure public {} + function g() pure public { + assembly { + let x := f + } + } +} +// ---- +// DeclarationError: (155-156): Multiple matching identifiers. Resolving overloaded identifiers is not supported. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference.sol new file mode 100644 index 000000000..071130931 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference.sol @@ -0,0 +1,11 @@ +contract C { + uint[] x; + function() external { + uint[] storage y = x; + assembly { + pop(y) + } + } +} +// ---- +// TypeError: (118-119): You have to use the _slot or _offset suffix to access storage reference variables. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_assignment.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_assignment.sol new file mode 100644 index 000000000..dc7421423 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_assignment.sol @@ -0,0 +1,13 @@ +contract C { + uint[] x; + function() external { + uint[] storage y = x; + assembly { + y_slot := 1 + y_offset := 2 + } + } +} +// ---- +// TypeError: (114-120): Storage variables cannot be assigned to. +// TypeError: (138-146): Storage variables cannot be assigned to. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol new file mode 100644 index 000000000..ec23a2630 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + _offset + } + } +} +// ---- +// DeclarationError: (75-82): In variable names _slot and _offset can only be used as a suffix. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol new file mode 100644 index 000000000..d493a68a5 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + _slot + } + } +} +// ---- +// DeclarationError: (75-80): In variable names _slot and _offset can only be used as a suffix. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_fine.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_fine.sol new file mode 100644 index 000000000..b01a77052 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_fine.sol @@ -0,0 +1,11 @@ +contract C { + uint[] x; + function() external { + uint[] storage y = x; + assembly { + pop(y_slot) + pop(y_offset) + } + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol new file mode 100644 index 000000000..9165654fb --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol @@ -0,0 +1,9 @@ +contract C { + function f() pure public { + assembly { + let x := f_slot + } + } +} +// ---- +// TypeError: (84-90): The suffixes _offset and _slot can only be used on storage variables. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_memory.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_memory.sol new file mode 100644 index 000000000..704b712d5 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_memory.sol @@ -0,0 +1,13 @@ +contract C { + uint[] x; + function() external { + uint[] memory y = x; + assembly { + pop(y_slot) + pop(y_offset) + } + } +} +// ---- +// TypeError: (117-123): The suffixes _offset and _slot can only be used on storage variables. +// TypeError: (141-149): The suffixes _offset and _slot can only be used on storage variables. diff --git a/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup.sol b/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup.sol index c23992e99..119df5d3f 100644 --- a/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup.sol +++ b/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup.sol @@ -1,7 +1,7 @@ contract C { - function f(uint, uint) {} - function f(uint) {} - function g() { f(1, 2, 3); } + function f(uint, uint) public {} + function f(uint) public {} + function g() public { f(1, 2, 3); } } // ---- -// TypeError: (80-81): No matching declaration found after argument-dependent lookup. +// TypeError: (101-102): No matching declaration found after argument-dependent lookup. diff --git a/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup_in_library.sol b/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup_in_library.sol index 310c4a103..d8f2eadd1 100644 --- a/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup_in_library.sol +++ b/test/libsolidity/syntaxTests/memberLookup/failed_function_lookup_in_library.sol @@ -1,9 +1,9 @@ library L { - function f(uint, uint) {} - function f(uint) {} + function f(uint, uint) public {} + function f(uint) public {} } contract C { - function g() { L.f(1, 2, 3); } + function g() public { L.f(1, 2, 3); } } // ---- -// TypeError: (94-97): Member "f" not found or not visible after argument-dependent lookup in type(library L) +// TypeError: (115-118): Member "f" not found or not visible after argument-dependent lookup in type(library L). diff --git a/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_payable.sol b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_payable.sol new file mode 100644 index 000000000..6e93626f6 --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_payable.sol @@ -0,0 +1,4 @@ +contract C { + modifier costs(uint _amount) { require(msg.value >= _amount); _; } + function f() costs(1 ether) public payable {} +} diff --git a/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_pure.sol b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_pure.sol new file mode 100644 index 000000000..398c127db --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_pure.sol @@ -0,0 +1,6 @@ +contract C { + modifier costs(uint _amount) { require(msg.value >= _amount); _; } + function f() costs(1 ether) public pure {} +} +// ---- +// TypeError: (101-115): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_view.sol b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_view.sol new file mode 100644 index 000000000..8430c5c3e --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_view.sol @@ -0,0 +1,6 @@ +contract C { + modifier costs(uint _amount) { require(msg.value >= _amount); _; } + function f() costs(1 ether) public view {} +} +// ---- +// TypeError: (101-115): This modifier uses "msg.value" and thus the function has to be payable or internal. diff --git a/test/libsolidity/syntaxTests/missing_state_variable.sol b/test/libsolidity/syntaxTests/missing_state_variable.sol index 02082a454..8b97220c5 100644 --- a/test/libsolidity/syntaxTests/missing_state_variable.sol +++ b/test/libsolidity/syntaxTests/missing_state_variable.sol @@ -4,4 +4,4 @@ contract Scope { } } // ---- -// TypeError: (101-115): Member "stateVar" not found or not visible after argument-dependent lookup in type(contract Scope) +// TypeError: (101-115): Member "stateVar" not found or not visible after argument-dependent lookup in type(contract Scope). diff --git a/test/libsolidity/syntaxTests/modifiers/base_constructor_double_invocation.sol b/test/libsolidity/syntaxTests/modifiers/base_constructor_double_invocation.sol index bdbab5d8c..49d0d7bf4 100644 --- a/test/libsolidity/syntaxTests/modifiers/base_constructor_double_invocation.sol +++ b/test/libsolidity/syntaxTests/modifiers/base_constructor_double_invocation.sol @@ -3,5 +3,5 @@ contract B is C { constructor() C(2) C(2) public {} } // ---- -// Warning: (81-85): Base constructor arguments given twice. +// DeclarationError: (81-85): Base constructor arguments given twice. // DeclarationError: (86-90): Base constructor already provided. diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol index 000319245..76bb6fc01 100644 --- a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol +++ b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol @@ -2,3 +2,5 @@ contract B { function f() mod(x) pure public { uint x = 7; } modifier mod(uint a) { if (a > 0) _; } } +// ---- +// DeclarationError: (34-35): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol deleted file mode 100644 index c19ccf2cf..000000000 --- a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma experimental "v0.5.0"; -contract B { - function f() mod(x) pure public { uint x = 7; } - modifier mod(uint a) { if (a > 0) _; } -} -// ---- -// DeclarationError: (64-65): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol deleted file mode 100644 index af1babbcc..000000000 --- a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract C -{ - modifier only_owner() { _; } - function foo() only_owner public; - function bar() public only_owner; -} -// ---- -// SyntaxError: (80-113): Functions without implementation cannot have modifiers. -// SyntaxError: (118-151): Functions without implementation cannot have modifiers. diff --git a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol index e18c5cf98..2e86fcc1e 100644 --- a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol +++ b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol @@ -9,5 +9,5 @@ contract C function bar() public only_owner; } // ---- -// Warning: (203-236): Modifiers of functions without implementation are ignored. -// Warning: (241-274): Modifiers of functions without implementation are ignored. +// SyntaxError: (203-236): Functions without implementation cannot have modifiers. +// SyntaxError: (241-274): Functions without implementation cannot have modifiers. diff --git a/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol b/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol index 2d75f29bc..307b728d3 100644 --- a/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol +++ b/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol @@ -1,5 +1,5 @@ contract C { - function f() { + function f() public { b = 5; b = 5; b = 5; @@ -265,260 +265,260 @@ contract C { } } // ---- -// DeclarationError: (34-35): Undeclared identifier. -// DeclarationError: (45-46): Undeclared identifier. -// DeclarationError: (56-57): Undeclared identifier. -// DeclarationError: (67-68): Undeclared identifier. -// DeclarationError: (78-79): Undeclared identifier. -// DeclarationError: (89-90): Undeclared identifier. -// DeclarationError: (100-101): Undeclared identifier. -// DeclarationError: (111-112): Undeclared identifier. -// DeclarationError: (122-123): Undeclared identifier. -// DeclarationError: (133-134): Undeclared identifier. -// DeclarationError: (144-145): Undeclared identifier. -// DeclarationError: (155-156): Undeclared identifier. -// DeclarationError: (166-167): Undeclared identifier. -// DeclarationError: (177-178): Undeclared identifier. -// DeclarationError: (188-189): Undeclared identifier. -// DeclarationError: (199-200): Undeclared identifier. -// DeclarationError: (210-211): Undeclared identifier. -// DeclarationError: (221-222): Undeclared identifier. -// DeclarationError: (232-233): Undeclared identifier. -// DeclarationError: (243-244): Undeclared identifier. -// DeclarationError: (254-255): Undeclared identifier. -// DeclarationError: (265-266): Undeclared identifier. -// DeclarationError: (276-277): Undeclared identifier. -// DeclarationError: (287-288): Undeclared identifier. -// DeclarationError: (298-299): Undeclared identifier. -// DeclarationError: (309-310): Undeclared identifier. -// DeclarationError: (320-321): Undeclared identifier. -// DeclarationError: (331-332): Undeclared identifier. -// DeclarationError: (342-343): Undeclared identifier. -// DeclarationError: (353-354): Undeclared identifier. -// DeclarationError: (364-365): Undeclared identifier. -// DeclarationError: (375-376): Undeclared identifier. -// DeclarationError: (386-387): Undeclared identifier. -// DeclarationError: (397-398): Undeclared identifier. -// DeclarationError: (408-409): Undeclared identifier. -// DeclarationError: (419-420): Undeclared identifier. -// DeclarationError: (430-431): Undeclared identifier. -// DeclarationError: (441-442): Undeclared identifier. -// DeclarationError: (452-453): Undeclared identifier. -// DeclarationError: (463-464): Undeclared identifier. -// DeclarationError: (474-475): Undeclared identifier. -// DeclarationError: (485-486): Undeclared identifier. -// DeclarationError: (496-497): Undeclared identifier. -// DeclarationError: (507-508): Undeclared identifier. -// DeclarationError: (518-519): Undeclared identifier. -// DeclarationError: (529-530): Undeclared identifier. -// DeclarationError: (540-541): Undeclared identifier. -// DeclarationError: (551-552): Undeclared identifier. -// DeclarationError: (562-563): Undeclared identifier. -// DeclarationError: (573-574): Undeclared identifier. -// DeclarationError: (584-585): Undeclared identifier. -// DeclarationError: (595-596): Undeclared identifier. -// DeclarationError: (606-607): Undeclared identifier. -// DeclarationError: (617-618): Undeclared identifier. -// DeclarationError: (628-629): Undeclared identifier. -// DeclarationError: (639-640): Undeclared identifier. -// DeclarationError: (650-651): Undeclared identifier. -// DeclarationError: (661-662): Undeclared identifier. -// DeclarationError: (672-673): Undeclared identifier. -// DeclarationError: (683-684): Undeclared identifier. -// DeclarationError: (694-695): Undeclared identifier. -// DeclarationError: (705-706): Undeclared identifier. -// DeclarationError: (716-717): Undeclared identifier. -// DeclarationError: (727-728): Undeclared identifier. -// DeclarationError: (738-739): Undeclared identifier. -// DeclarationError: (749-750): Undeclared identifier. -// DeclarationError: (760-761): Undeclared identifier. -// DeclarationError: (771-772): Undeclared identifier. -// DeclarationError: (782-783): Undeclared identifier. -// DeclarationError: (793-794): Undeclared identifier. -// DeclarationError: (804-805): Undeclared identifier. -// DeclarationError: (815-816): Undeclared identifier. -// DeclarationError: (826-827): Undeclared identifier. -// DeclarationError: (837-838): Undeclared identifier. -// DeclarationError: (848-849): Undeclared identifier. -// DeclarationError: (859-860): Undeclared identifier. -// DeclarationError: (870-871): Undeclared identifier. -// DeclarationError: (881-882): Undeclared identifier. -// DeclarationError: (892-893): Undeclared identifier. -// DeclarationError: (903-904): Undeclared identifier. -// DeclarationError: (914-915): Undeclared identifier. -// DeclarationError: (925-926): Undeclared identifier. -// DeclarationError: (936-937): Undeclared identifier. -// DeclarationError: (947-948): Undeclared identifier. -// DeclarationError: (958-959): Undeclared identifier. -// DeclarationError: (969-970): Undeclared identifier. -// DeclarationError: (980-981): Undeclared identifier. -// DeclarationError: (991-992): Undeclared identifier. -// DeclarationError: (1002-1003): Undeclared identifier. -// DeclarationError: (1013-1014): Undeclared identifier. -// DeclarationError: (1024-1025): Undeclared identifier. -// DeclarationError: (1035-1036): Undeclared identifier. -// DeclarationError: (1046-1047): Undeclared identifier. -// DeclarationError: (1057-1058): Undeclared identifier. -// DeclarationError: (1068-1069): Undeclared identifier. -// DeclarationError: (1079-1080): Undeclared identifier. -// DeclarationError: (1090-1091): Undeclared identifier. -// DeclarationError: (1101-1102): Undeclared identifier. -// DeclarationError: (1112-1113): Undeclared identifier. -// DeclarationError: (1123-1124): Undeclared identifier. -// DeclarationError: (1134-1135): Undeclared identifier. -// DeclarationError: (1145-1146): Undeclared identifier. -// DeclarationError: (1156-1157): Undeclared identifier. -// DeclarationError: (1167-1168): Undeclared identifier. -// DeclarationError: (1178-1179): Undeclared identifier. -// DeclarationError: (1189-1190): Undeclared identifier. -// DeclarationError: (1200-1201): Undeclared identifier. -// DeclarationError: (1211-1212): Undeclared identifier. -// DeclarationError: (1222-1223): Undeclared identifier. -// DeclarationError: (1233-1234): Undeclared identifier. -// DeclarationError: (1244-1245): Undeclared identifier. -// DeclarationError: (1255-1256): Undeclared identifier. -// DeclarationError: (1266-1267): Undeclared identifier. -// DeclarationError: (1277-1278): Undeclared identifier. -// DeclarationError: (1288-1289): Undeclared identifier. -// DeclarationError: (1299-1300): Undeclared identifier. -// DeclarationError: (1310-1311): Undeclared identifier. -// DeclarationError: (1321-1322): Undeclared identifier. -// DeclarationError: (1332-1333): Undeclared identifier. -// DeclarationError: (1343-1344): Undeclared identifier. -// DeclarationError: (1354-1355): Undeclared identifier. -// DeclarationError: (1365-1366): Undeclared identifier. -// DeclarationError: (1376-1377): Undeclared identifier. -// DeclarationError: (1387-1388): Undeclared identifier. -// DeclarationError: (1398-1399): Undeclared identifier. -// DeclarationError: (1409-1410): Undeclared identifier. -// DeclarationError: (1420-1421): Undeclared identifier. -// DeclarationError: (1431-1432): Undeclared identifier. -// DeclarationError: (1442-1443): Undeclared identifier. -// DeclarationError: (1453-1454): Undeclared identifier. -// DeclarationError: (1464-1465): Undeclared identifier. -// DeclarationError: (1475-1476): Undeclared identifier. -// DeclarationError: (1486-1487): Undeclared identifier. -// DeclarationError: (1497-1498): Undeclared identifier. -// DeclarationError: (1508-1509): Undeclared identifier. -// DeclarationError: (1519-1520): Undeclared identifier. -// DeclarationError: (1530-1531): Undeclared identifier. -// DeclarationError: (1541-1542): Undeclared identifier. -// DeclarationError: (1552-1553): Undeclared identifier. -// DeclarationError: (1563-1564): Undeclared identifier. -// DeclarationError: (1574-1575): Undeclared identifier. -// DeclarationError: (1585-1586): Undeclared identifier. -// DeclarationError: (1596-1597): Undeclared identifier. -// DeclarationError: (1607-1608): Undeclared identifier. -// DeclarationError: (1618-1619): Undeclared identifier. -// DeclarationError: (1629-1630): Undeclared identifier. -// DeclarationError: (1640-1641): Undeclared identifier. -// DeclarationError: (1651-1652): Undeclared identifier. -// DeclarationError: (1662-1663): Undeclared identifier. -// DeclarationError: (1673-1674): Undeclared identifier. -// DeclarationError: (1684-1685): Undeclared identifier. -// DeclarationError: (1695-1696): Undeclared identifier. -// DeclarationError: (1706-1707): Undeclared identifier. -// DeclarationError: (1717-1718): Undeclared identifier. -// DeclarationError: (1728-1729): Undeclared identifier. -// DeclarationError: (1739-1740): Undeclared identifier. -// DeclarationError: (1750-1751): Undeclared identifier. -// DeclarationError: (1761-1762): Undeclared identifier. -// DeclarationError: (1772-1773): Undeclared identifier. -// DeclarationError: (1783-1784): Undeclared identifier. -// DeclarationError: (1794-1795): Undeclared identifier. -// DeclarationError: (1805-1806): Undeclared identifier. -// DeclarationError: (1816-1817): Undeclared identifier. -// DeclarationError: (1827-1828): Undeclared identifier. -// DeclarationError: (1838-1839): Undeclared identifier. -// DeclarationError: (1849-1850): Undeclared identifier. -// DeclarationError: (1860-1861): Undeclared identifier. -// DeclarationError: (1871-1872): Undeclared identifier. -// DeclarationError: (1882-1883): Undeclared identifier. -// DeclarationError: (1893-1894): Undeclared identifier. -// DeclarationError: (1904-1905): Undeclared identifier. -// DeclarationError: (1915-1916): Undeclared identifier. -// DeclarationError: (1926-1927): Undeclared identifier. -// DeclarationError: (1937-1938): Undeclared identifier. -// DeclarationError: (1948-1949): Undeclared identifier. -// DeclarationError: (1959-1960): Undeclared identifier. -// DeclarationError: (1970-1971): Undeclared identifier. -// DeclarationError: (1981-1982): Undeclared identifier. -// DeclarationError: (1992-1993): Undeclared identifier. -// DeclarationError: (2003-2004): Undeclared identifier. -// DeclarationError: (2014-2015): Undeclared identifier. -// DeclarationError: (2025-2026): Undeclared identifier. -// DeclarationError: (2036-2037): Undeclared identifier. -// DeclarationError: (2047-2048): Undeclared identifier. -// DeclarationError: (2058-2059): Undeclared identifier. -// DeclarationError: (2069-2070): Undeclared identifier. -// DeclarationError: (2080-2081): Undeclared identifier. -// DeclarationError: (2091-2092): Undeclared identifier. -// DeclarationError: (2102-2103): Undeclared identifier. -// DeclarationError: (2113-2114): Undeclared identifier. -// DeclarationError: (2124-2125): Undeclared identifier. -// DeclarationError: (2135-2136): Undeclared identifier. -// DeclarationError: (2146-2147): Undeclared identifier. -// DeclarationError: (2157-2158): Undeclared identifier. -// DeclarationError: (2168-2169): Undeclared identifier. -// DeclarationError: (2179-2180): Undeclared identifier. -// DeclarationError: (2190-2191): Undeclared identifier. -// DeclarationError: (2201-2202): Undeclared identifier. -// DeclarationError: (2212-2213): Undeclared identifier. -// DeclarationError: (2223-2224): Undeclared identifier. -// DeclarationError: (2234-2235): Undeclared identifier. -// DeclarationError: (2245-2246): Undeclared identifier. -// DeclarationError: (2256-2257): Undeclared identifier. -// DeclarationError: (2267-2268): Undeclared identifier. -// DeclarationError: (2278-2279): Undeclared identifier. -// DeclarationError: (2289-2290): Undeclared identifier. -// DeclarationError: (2300-2301): Undeclared identifier. -// DeclarationError: (2311-2312): Undeclared identifier. -// DeclarationError: (2322-2323): Undeclared identifier. -// DeclarationError: (2333-2334): Undeclared identifier. -// DeclarationError: (2344-2345): Undeclared identifier. -// DeclarationError: (2355-2356): Undeclared identifier. -// DeclarationError: (2366-2367): Undeclared identifier. -// DeclarationError: (2377-2378): Undeclared identifier. -// DeclarationError: (2388-2389): Undeclared identifier. -// DeclarationError: (2399-2400): Undeclared identifier. -// DeclarationError: (2410-2411): Undeclared identifier. -// DeclarationError: (2421-2422): Undeclared identifier. -// DeclarationError: (2432-2433): Undeclared identifier. -// DeclarationError: (2443-2444): Undeclared identifier. -// DeclarationError: (2454-2455): Undeclared identifier. -// DeclarationError: (2465-2466): Undeclared identifier. -// DeclarationError: (2476-2477): Undeclared identifier. -// DeclarationError: (2487-2488): Undeclared identifier. -// DeclarationError: (2498-2499): Undeclared identifier. -// DeclarationError: (2509-2510): Undeclared identifier. -// DeclarationError: (2520-2521): Undeclared identifier. -// DeclarationError: (2531-2532): Undeclared identifier. -// DeclarationError: (2542-2543): Undeclared identifier. -// DeclarationError: (2553-2554): Undeclared identifier. -// DeclarationError: (2564-2565): Undeclared identifier. -// DeclarationError: (2575-2576): Undeclared identifier. -// DeclarationError: (2586-2587): Undeclared identifier. -// DeclarationError: (2597-2598): Undeclared identifier. -// DeclarationError: (2608-2609): Undeclared identifier. -// DeclarationError: (2619-2620): Undeclared identifier. -// DeclarationError: (2630-2631): Undeclared identifier. -// DeclarationError: (2641-2642): Undeclared identifier. -// DeclarationError: (2652-2653): Undeclared identifier. -// DeclarationError: (2663-2664): Undeclared identifier. -// DeclarationError: (2674-2675): Undeclared identifier. -// DeclarationError: (2685-2686): Undeclared identifier. -// DeclarationError: (2696-2697): Undeclared identifier. -// DeclarationError: (2707-2708): Undeclared identifier. -// DeclarationError: (2718-2719): Undeclared identifier. -// DeclarationError: (2729-2730): Undeclared identifier. -// DeclarationError: (2740-2741): Undeclared identifier. -// DeclarationError: (2751-2752): Undeclared identifier. -// DeclarationError: (2762-2763): Undeclared identifier. -// DeclarationError: (2773-2774): Undeclared identifier. -// DeclarationError: (2784-2785): Undeclared identifier. -// DeclarationError: (2795-2796): Undeclared identifier. -// DeclarationError: (2806-2807): Undeclared identifier. -// DeclarationError: (2817-2818): Undeclared identifier. -// DeclarationError: (2828-2829): Undeclared identifier. -// DeclarationError: (2839-2840): Undeclared identifier. +// DeclarationError: (41-42): Undeclared identifier. +// DeclarationError: (52-53): Undeclared identifier. +// DeclarationError: (63-64): Undeclared identifier. +// DeclarationError: (74-75): Undeclared identifier. +// DeclarationError: (85-86): Undeclared identifier. +// DeclarationError: (96-97): Undeclared identifier. +// DeclarationError: (107-108): Undeclared identifier. +// DeclarationError: (118-119): Undeclared identifier. +// DeclarationError: (129-130): Undeclared identifier. +// DeclarationError: (140-141): Undeclared identifier. +// DeclarationError: (151-152): Undeclared identifier. +// DeclarationError: (162-163): Undeclared identifier. +// DeclarationError: (173-174): Undeclared identifier. +// DeclarationError: (184-185): Undeclared identifier. +// DeclarationError: (195-196): Undeclared identifier. +// DeclarationError: (206-207): Undeclared identifier. +// DeclarationError: (217-218): Undeclared identifier. +// DeclarationError: (228-229): Undeclared identifier. +// DeclarationError: (239-240): Undeclared identifier. +// DeclarationError: (250-251): Undeclared identifier. +// DeclarationError: (261-262): Undeclared identifier. +// DeclarationError: (272-273): Undeclared identifier. +// DeclarationError: (283-284): Undeclared identifier. +// DeclarationError: (294-295): Undeclared identifier. +// DeclarationError: (305-306): Undeclared identifier. +// DeclarationError: (316-317): Undeclared identifier. +// DeclarationError: (327-328): Undeclared identifier. +// DeclarationError: (338-339): Undeclared identifier. +// DeclarationError: (349-350): Undeclared identifier. +// DeclarationError: (360-361): Undeclared identifier. +// DeclarationError: (371-372): Undeclared identifier. +// DeclarationError: (382-383): Undeclared identifier. +// DeclarationError: (393-394): Undeclared identifier. +// DeclarationError: (404-405): Undeclared identifier. +// DeclarationError: (415-416): Undeclared identifier. +// DeclarationError: (426-427): Undeclared identifier. +// DeclarationError: (437-438): Undeclared identifier. +// DeclarationError: (448-449): Undeclared identifier. +// DeclarationError: (459-460): Undeclared identifier. +// DeclarationError: (470-471): Undeclared identifier. +// DeclarationError: (481-482): Undeclared identifier. +// DeclarationError: (492-493): Undeclared identifier. +// DeclarationError: (503-504): Undeclared identifier. +// DeclarationError: (514-515): Undeclared identifier. +// DeclarationError: (525-526): Undeclared identifier. +// DeclarationError: (536-537): Undeclared identifier. +// DeclarationError: (547-548): Undeclared identifier. +// DeclarationError: (558-559): Undeclared identifier. +// DeclarationError: (569-570): Undeclared identifier. +// DeclarationError: (580-581): Undeclared identifier. +// DeclarationError: (591-592): Undeclared identifier. +// DeclarationError: (602-603): Undeclared identifier. +// DeclarationError: (613-614): Undeclared identifier. +// DeclarationError: (624-625): Undeclared identifier. +// DeclarationError: (635-636): Undeclared identifier. +// DeclarationError: (646-647): Undeclared identifier. +// DeclarationError: (657-658): Undeclared identifier. +// DeclarationError: (668-669): Undeclared identifier. +// DeclarationError: (679-680): Undeclared identifier. +// DeclarationError: (690-691): Undeclared identifier. +// DeclarationError: (701-702): Undeclared identifier. +// DeclarationError: (712-713): Undeclared identifier. +// DeclarationError: (723-724): Undeclared identifier. +// DeclarationError: (734-735): Undeclared identifier. +// DeclarationError: (745-746): Undeclared identifier. +// DeclarationError: (756-757): Undeclared identifier. +// DeclarationError: (767-768): Undeclared identifier. +// DeclarationError: (778-779): Undeclared identifier. +// DeclarationError: (789-790): Undeclared identifier. +// DeclarationError: (800-801): Undeclared identifier. +// DeclarationError: (811-812): Undeclared identifier. +// DeclarationError: (822-823): Undeclared identifier. +// DeclarationError: (833-834): Undeclared identifier. +// DeclarationError: (844-845): Undeclared identifier. +// DeclarationError: (855-856): Undeclared identifier. +// DeclarationError: (866-867): Undeclared identifier. +// DeclarationError: (877-878): Undeclared identifier. +// DeclarationError: (888-889): Undeclared identifier. +// DeclarationError: (899-900): Undeclared identifier. +// DeclarationError: (910-911): Undeclared identifier. +// DeclarationError: (921-922): Undeclared identifier. +// DeclarationError: (932-933): Undeclared identifier. +// DeclarationError: (943-944): Undeclared identifier. +// DeclarationError: (954-955): Undeclared identifier. +// DeclarationError: (965-966): Undeclared identifier. +// DeclarationError: (976-977): Undeclared identifier. +// DeclarationError: (987-988): Undeclared identifier. +// DeclarationError: (998-999): Undeclared identifier. +// DeclarationError: (1009-1010): Undeclared identifier. +// DeclarationError: (1020-1021): Undeclared identifier. +// DeclarationError: (1031-1032): Undeclared identifier. +// DeclarationError: (1042-1043): Undeclared identifier. +// DeclarationError: (1053-1054): Undeclared identifier. +// DeclarationError: (1064-1065): Undeclared identifier. +// DeclarationError: (1075-1076): Undeclared identifier. +// DeclarationError: (1086-1087): Undeclared identifier. +// DeclarationError: (1097-1098): Undeclared identifier. +// DeclarationError: (1108-1109): Undeclared identifier. +// DeclarationError: (1119-1120): Undeclared identifier. +// DeclarationError: (1130-1131): Undeclared identifier. +// DeclarationError: (1141-1142): Undeclared identifier. +// DeclarationError: (1152-1153): Undeclared identifier. +// DeclarationError: (1163-1164): Undeclared identifier. +// DeclarationError: (1174-1175): Undeclared identifier. +// DeclarationError: (1185-1186): Undeclared identifier. +// DeclarationError: (1196-1197): Undeclared identifier. +// DeclarationError: (1207-1208): Undeclared identifier. +// DeclarationError: (1218-1219): Undeclared identifier. +// DeclarationError: (1229-1230): Undeclared identifier. +// DeclarationError: (1240-1241): Undeclared identifier. +// DeclarationError: (1251-1252): Undeclared identifier. +// DeclarationError: (1262-1263): Undeclared identifier. +// DeclarationError: (1273-1274): Undeclared identifier. +// DeclarationError: (1284-1285): Undeclared identifier. +// DeclarationError: (1295-1296): Undeclared identifier. +// DeclarationError: (1306-1307): Undeclared identifier. +// DeclarationError: (1317-1318): Undeclared identifier. +// DeclarationError: (1328-1329): Undeclared identifier. +// DeclarationError: (1339-1340): Undeclared identifier. +// DeclarationError: (1350-1351): Undeclared identifier. +// DeclarationError: (1361-1362): Undeclared identifier. +// DeclarationError: (1372-1373): Undeclared identifier. +// DeclarationError: (1383-1384): Undeclared identifier. +// DeclarationError: (1394-1395): Undeclared identifier. +// DeclarationError: (1405-1406): Undeclared identifier. +// DeclarationError: (1416-1417): Undeclared identifier. +// DeclarationError: (1427-1428): Undeclared identifier. +// DeclarationError: (1438-1439): Undeclared identifier. +// DeclarationError: (1449-1450): Undeclared identifier. +// DeclarationError: (1460-1461): Undeclared identifier. +// DeclarationError: (1471-1472): Undeclared identifier. +// DeclarationError: (1482-1483): Undeclared identifier. +// DeclarationError: (1493-1494): Undeclared identifier. +// DeclarationError: (1504-1505): Undeclared identifier. +// DeclarationError: (1515-1516): Undeclared identifier. +// DeclarationError: (1526-1527): Undeclared identifier. +// DeclarationError: (1537-1538): Undeclared identifier. +// DeclarationError: (1548-1549): Undeclared identifier. +// DeclarationError: (1559-1560): Undeclared identifier. +// DeclarationError: (1570-1571): Undeclared identifier. +// DeclarationError: (1581-1582): Undeclared identifier. +// DeclarationError: (1592-1593): Undeclared identifier. +// DeclarationError: (1603-1604): Undeclared identifier. +// DeclarationError: (1614-1615): Undeclared identifier. +// DeclarationError: (1625-1626): Undeclared identifier. +// DeclarationError: (1636-1637): Undeclared identifier. +// DeclarationError: (1647-1648): Undeclared identifier. +// DeclarationError: (1658-1659): Undeclared identifier. +// DeclarationError: (1669-1670): Undeclared identifier. +// DeclarationError: (1680-1681): Undeclared identifier. +// DeclarationError: (1691-1692): Undeclared identifier. +// DeclarationError: (1702-1703): Undeclared identifier. +// DeclarationError: (1713-1714): Undeclared identifier. +// DeclarationError: (1724-1725): Undeclared identifier. +// DeclarationError: (1735-1736): Undeclared identifier. +// DeclarationError: (1746-1747): Undeclared identifier. +// DeclarationError: (1757-1758): Undeclared identifier. +// DeclarationError: (1768-1769): Undeclared identifier. +// DeclarationError: (1779-1780): Undeclared identifier. +// DeclarationError: (1790-1791): Undeclared identifier. +// DeclarationError: (1801-1802): Undeclared identifier. +// DeclarationError: (1812-1813): Undeclared identifier. +// DeclarationError: (1823-1824): Undeclared identifier. +// DeclarationError: (1834-1835): Undeclared identifier. +// DeclarationError: (1845-1846): Undeclared identifier. +// DeclarationError: (1856-1857): Undeclared identifier. +// DeclarationError: (1867-1868): Undeclared identifier. +// DeclarationError: (1878-1879): Undeclared identifier. +// DeclarationError: (1889-1890): Undeclared identifier. +// DeclarationError: (1900-1901): Undeclared identifier. +// DeclarationError: (1911-1912): Undeclared identifier. +// DeclarationError: (1922-1923): Undeclared identifier. +// DeclarationError: (1933-1934): Undeclared identifier. +// DeclarationError: (1944-1945): Undeclared identifier. +// DeclarationError: (1955-1956): Undeclared identifier. +// DeclarationError: (1966-1967): Undeclared identifier. +// DeclarationError: (1977-1978): Undeclared identifier. +// DeclarationError: (1988-1989): Undeclared identifier. +// DeclarationError: (1999-2000): Undeclared identifier. +// DeclarationError: (2010-2011): Undeclared identifier. +// DeclarationError: (2021-2022): Undeclared identifier. +// DeclarationError: (2032-2033): Undeclared identifier. +// DeclarationError: (2043-2044): Undeclared identifier. +// DeclarationError: (2054-2055): Undeclared identifier. +// DeclarationError: (2065-2066): Undeclared identifier. +// DeclarationError: (2076-2077): Undeclared identifier. +// DeclarationError: (2087-2088): Undeclared identifier. +// DeclarationError: (2098-2099): Undeclared identifier. +// DeclarationError: (2109-2110): Undeclared identifier. +// DeclarationError: (2120-2121): Undeclared identifier. +// DeclarationError: (2131-2132): Undeclared identifier. +// DeclarationError: (2142-2143): Undeclared identifier. +// DeclarationError: (2153-2154): Undeclared identifier. +// DeclarationError: (2164-2165): Undeclared identifier. +// DeclarationError: (2175-2176): Undeclared identifier. +// DeclarationError: (2186-2187): Undeclared identifier. +// DeclarationError: (2197-2198): Undeclared identifier. +// DeclarationError: (2208-2209): Undeclared identifier. +// DeclarationError: (2219-2220): Undeclared identifier. +// DeclarationError: (2230-2231): Undeclared identifier. +// DeclarationError: (2241-2242): Undeclared identifier. +// DeclarationError: (2252-2253): Undeclared identifier. +// DeclarationError: (2263-2264): Undeclared identifier. +// DeclarationError: (2274-2275): Undeclared identifier. +// DeclarationError: (2285-2286): Undeclared identifier. +// DeclarationError: (2296-2297): Undeclared identifier. +// DeclarationError: (2307-2308): Undeclared identifier. +// DeclarationError: (2318-2319): Undeclared identifier. +// DeclarationError: (2329-2330): Undeclared identifier. +// DeclarationError: (2340-2341): Undeclared identifier. +// DeclarationError: (2351-2352): Undeclared identifier. +// DeclarationError: (2362-2363): Undeclared identifier. +// DeclarationError: (2373-2374): Undeclared identifier. +// DeclarationError: (2384-2385): Undeclared identifier. +// DeclarationError: (2395-2396): Undeclared identifier. +// DeclarationError: (2406-2407): Undeclared identifier. +// DeclarationError: (2417-2418): Undeclared identifier. +// DeclarationError: (2428-2429): Undeclared identifier. +// DeclarationError: (2439-2440): Undeclared identifier. +// DeclarationError: (2450-2451): Undeclared identifier. +// DeclarationError: (2461-2462): Undeclared identifier. +// DeclarationError: (2472-2473): Undeclared identifier. +// DeclarationError: (2483-2484): Undeclared identifier. +// DeclarationError: (2494-2495): Undeclared identifier. +// DeclarationError: (2505-2506): Undeclared identifier. +// DeclarationError: (2516-2517): Undeclared identifier. +// DeclarationError: (2527-2528): Undeclared identifier. +// DeclarationError: (2538-2539): Undeclared identifier. +// DeclarationError: (2549-2550): Undeclared identifier. +// DeclarationError: (2560-2561): Undeclared identifier. +// DeclarationError: (2571-2572): Undeclared identifier. +// DeclarationError: (2582-2583): Undeclared identifier. +// DeclarationError: (2593-2594): Undeclared identifier. +// DeclarationError: (2604-2605): Undeclared identifier. +// DeclarationError: (2615-2616): Undeclared identifier. +// DeclarationError: (2626-2627): Undeclared identifier. +// DeclarationError: (2637-2638): Undeclared identifier. +// DeclarationError: (2648-2649): Undeclared identifier. +// DeclarationError: (2659-2660): Undeclared identifier. +// DeclarationError: (2670-2671): Undeclared identifier. +// DeclarationError: (2681-2682): Undeclared identifier. +// DeclarationError: (2692-2693): Undeclared identifier. +// DeclarationError: (2703-2704): Undeclared identifier. +// DeclarationError: (2714-2715): Undeclared identifier. +// DeclarationError: (2725-2726): Undeclared identifier. +// DeclarationError: (2736-2737): Undeclared identifier. +// DeclarationError: (2747-2748): Undeclared identifier. +// DeclarationError: (2758-2759): Undeclared identifier. +// DeclarationError: (2769-2770): Undeclared identifier. +// DeclarationError: (2780-2781): Undeclared identifier. +// DeclarationError: (2791-2792): Undeclared identifier. +// DeclarationError: (2802-2803): Undeclared identifier. +// DeclarationError: (2813-2814): Undeclared identifier. +// DeclarationError: (2824-2825): Undeclared identifier. +// DeclarationError: (2835-2836): Undeclared identifier. +// DeclarationError: (2846-2847): Undeclared identifier. // Warning: There are more than 256 errors. Aborting. diff --git a/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol b/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol index 2c9b8a426..fe877396b 100644 --- a/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol +++ b/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol @@ -1,5 +1,5 @@ contract C { - function f() { + function f() public { continue; continue; continue; @@ -265,260 +265,260 @@ contract C { } } // ---- -// SyntaxError: (34-42): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (48-56): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (62-70): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (76-84): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (90-98): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (104-112): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (118-126): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (132-140): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (146-154): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (160-168): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (174-182): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (188-196): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (202-210): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (216-224): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (230-238): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (244-252): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (258-266): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (272-280): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (286-294): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (300-308): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (314-322): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (328-336): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (342-350): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (356-364): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (370-378): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (384-392): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (398-406): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (412-420): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (426-434): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (440-448): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (454-462): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (468-476): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (482-490): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (496-504): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (510-518): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (524-532): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (538-546): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (552-560): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (566-574): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (580-588): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (594-602): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (608-616): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (622-630): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (636-644): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (650-658): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (664-672): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (678-686): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (692-700): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (706-714): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (720-728): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (734-742): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (748-756): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (762-770): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (776-784): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (790-798): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (804-812): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (818-826): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (832-840): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (846-854): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (860-868): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (874-882): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (888-896): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (902-910): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (916-924): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (930-938): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (944-952): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (958-966): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (972-980): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (986-994): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1000-1008): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1014-1022): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1028-1036): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1042-1050): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1056-1064): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1070-1078): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1084-1092): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1098-1106): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1112-1120): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1126-1134): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1140-1148): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1154-1162): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1168-1176): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1182-1190): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1196-1204): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1210-1218): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1224-1232): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1238-1246): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1252-1260): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1266-1274): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1280-1288): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1294-1302): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1308-1316): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1322-1330): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1336-1344): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1350-1358): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1364-1372): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1378-1386): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1392-1400): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1406-1414): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1420-1428): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1434-1442): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1448-1456): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1462-1470): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1476-1484): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1490-1498): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1504-1512): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1518-1526): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1532-1540): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1546-1554): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1560-1568): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1574-1582): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1588-1596): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1602-1610): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1616-1624): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1630-1638): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1644-1652): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1658-1666): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1672-1680): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1686-1694): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1700-1708): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1714-1722): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1728-1736): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1742-1750): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1756-1764): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1770-1778): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1784-1792): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1798-1806): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1812-1820): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1826-1834): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1840-1848): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1854-1862): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1868-1876): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1882-1890): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1896-1904): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1910-1918): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1924-1932): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1938-1946): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1952-1960): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1966-1974): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1980-1988): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (1994-2002): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2008-2016): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2022-2030): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2036-2044): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2050-2058): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2064-2072): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2078-2086): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2092-2100): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2106-2114): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2120-2128): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2134-2142): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2148-2156): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2162-2170): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2176-2184): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2190-2198): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2204-2212): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2218-2226): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2232-2240): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2246-2254): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2260-2268): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2274-2282): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2288-2296): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2302-2310): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2316-2324): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2330-2338): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2344-2352): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2358-2366): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2372-2380): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2386-2394): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2400-2408): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2414-2422): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2428-2436): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2442-2450): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2456-2464): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2470-2478): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2484-2492): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2498-2506): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2512-2520): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2526-2534): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2540-2548): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2554-2562): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2568-2576): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2582-2590): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2596-2604): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2610-2618): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2624-2632): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2638-2646): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2652-2660): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2666-2674): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2680-2688): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2694-2702): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2708-2716): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2722-2730): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2736-2744): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2750-2758): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2764-2772): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2778-2786): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2792-2800): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2806-2814): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2820-2828): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2834-2842): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2848-2856): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2862-2870): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2876-2884): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2890-2898): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2904-2912): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2918-2926): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2932-2940): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2946-2954): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2960-2968): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2974-2982): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (2988-2996): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3002-3010): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3016-3024): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3030-3038): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3044-3052): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3058-3066): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3072-3080): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3086-3094): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3100-3108): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3114-3122): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3128-3136): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3142-3150): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3156-3164): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3170-3178): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3184-3192): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3198-3206): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3212-3220): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3226-3234): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3240-3248): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3254-3262): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3268-3276): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3282-3290): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3296-3304): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3310-3318): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3324-3332): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3338-3346): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3352-3360): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3366-3374): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3380-3388): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3394-3402): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3408-3416): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3422-3430): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3436-3444): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3450-3458): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3464-3472): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3478-3486): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3492-3500): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3506-3514): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3520-3528): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3534-3542): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3548-3556): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3562-3570): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3576-3584): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3590-3598): "continue" has to be in a "for" or "while" loop. -// SyntaxError: (3604-3612): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (41-49): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (55-63): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (69-77): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (83-91): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (97-105): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (111-119): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (125-133): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (139-147): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (153-161): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (167-175): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (181-189): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (195-203): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (209-217): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (223-231): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (237-245): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (251-259): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (265-273): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (279-287): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (293-301): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (307-315): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (321-329): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (335-343): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (349-357): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (363-371): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (377-385): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (391-399): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (405-413): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (419-427): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (433-441): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (447-455): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (461-469): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (475-483): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (489-497): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (503-511): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (517-525): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (531-539): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (545-553): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (559-567): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (573-581): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (587-595): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (601-609): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (615-623): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (629-637): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (643-651): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (657-665): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (671-679): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (685-693): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (699-707): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (713-721): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (727-735): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (741-749): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (755-763): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (769-777): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (783-791): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (797-805): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (811-819): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (825-833): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (839-847): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (853-861): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (867-875): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (881-889): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (895-903): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (909-917): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (923-931): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (937-945): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (951-959): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (965-973): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (979-987): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (993-1001): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1007-1015): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1021-1029): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1035-1043): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1049-1057): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1063-1071): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1077-1085): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1091-1099): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1105-1113): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1119-1127): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1133-1141): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1147-1155): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1161-1169): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1175-1183): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1189-1197): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1203-1211): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1217-1225): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1231-1239): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1245-1253): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1259-1267): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1273-1281): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1287-1295): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1301-1309): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1315-1323): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1329-1337): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1343-1351): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1357-1365): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1371-1379): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1385-1393): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1399-1407): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1413-1421): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1427-1435): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1441-1449): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1455-1463): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1469-1477): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1483-1491): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1497-1505): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1511-1519): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1525-1533): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1539-1547): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1553-1561): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1567-1575): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1581-1589): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1595-1603): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1609-1617): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1623-1631): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1637-1645): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1651-1659): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1665-1673): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1679-1687): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1693-1701): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1707-1715): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1721-1729): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1735-1743): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1749-1757): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1763-1771): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1777-1785): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1791-1799): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1805-1813): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1819-1827): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1833-1841): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1847-1855): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1861-1869): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1875-1883): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1889-1897): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1903-1911): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1917-1925): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1931-1939): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1945-1953): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1959-1967): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1973-1981): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1987-1995): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2001-2009): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2015-2023): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2029-2037): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2043-2051): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2057-2065): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2071-2079): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2085-2093): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2099-2107): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2113-2121): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2127-2135): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2141-2149): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2155-2163): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2169-2177): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2183-2191): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2197-2205): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2211-2219): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2225-2233): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2239-2247): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2253-2261): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2267-2275): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2281-2289): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2295-2303): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2309-2317): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2323-2331): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2337-2345): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2351-2359): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2365-2373): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2379-2387): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2393-2401): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2407-2415): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2421-2429): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2435-2443): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2449-2457): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2463-2471): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2477-2485): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2491-2499): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2505-2513): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2519-2527): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2533-2541): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2547-2555): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2561-2569): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2575-2583): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2589-2597): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2603-2611): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2617-2625): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2631-2639): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2645-2653): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2659-2667): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2673-2681): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2687-2695): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2701-2709): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2715-2723): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2729-2737): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2743-2751): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2757-2765): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2771-2779): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2785-2793): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2799-2807): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2813-2821): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2827-2835): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2841-2849): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2855-2863): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2869-2877): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2883-2891): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2897-2905): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2911-2919): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2925-2933): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2939-2947): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2953-2961): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2967-2975): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2981-2989): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2995-3003): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3009-3017): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3023-3031): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3037-3045): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3051-3059): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3065-3073): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3079-3087): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3093-3101): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3107-3115): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3121-3129): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3135-3143): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3149-3157): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3163-3171): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3177-3185): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3191-3199): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3205-3213): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3219-3227): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3233-3241): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3247-3255): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3261-3269): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3275-3283): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3289-3297): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3303-3311): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3317-3325): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3331-3339): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3345-3353): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3359-3367): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3373-3381): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3387-3395): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3401-3409): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3415-3423): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3429-3437): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3443-3451): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3457-3465): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3471-3479): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3485-3493): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3499-3507): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3513-3521): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3527-3535): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3541-3549): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3555-3563): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3569-3577): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3583-3591): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3597-3605): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3611-3619): "continue" has to be in a "for" or "while" loop. // Warning: There are more than 256 errors. Aborting. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponents.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponents.sol new file mode 100644 index 000000000..3b05a54ca --- /dev/null +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponents.sol @@ -0,0 +1,25 @@ +contract C { + function f() public { + uint a = (1,2); + uint b = (1,2,3); + uint c = (1,2,3,4); + } + function g() public { + (uint a1, uint b1, uint c1, uint d1) = 1; + (uint a2, uint b2, uint c2) = 1; + (uint a3, uint b3) = 1; + } + function h() public { + (uint a1, uint b1, uint c1, uint d1) = (1,2,3); + (uint a2, uint b2, uint c2) = (1,2,3,4); + } +} +// ---- +// TypeError: (47-61): Different number of components on the left hand side (1) than on the right hand side (2). +// TypeError: (71-87): Different number of components on the left hand side (1) than on the right hand side (3). +// TypeError: (97-115): Different number of components on the left hand side (1) than on the right hand side (4). +// TypeError: (157-197): Different number of components on the left hand side (4) than on the right hand side (1). +// TypeError: (207-238): Different number of components on the left hand side (3) than on the right hand side (1). +// TypeError: (248-270): Different number of components on the left hand side (2) than on the right hand side (1). +// TypeError: (312-358): Different number of components on the left hand side (4) than on the right hand side (3). +// TypeError: (368-407): Different number of components on the left hand side (3) than on the right hand side (4). diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponentsFromReturn.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponentsFromReturn.sol new file mode 100644 index 000000000..7b556350d --- /dev/null +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponentsFromReturn.sol @@ -0,0 +1,29 @@ +contract C { + function f() public { + uint a = two(); + uint b = three(); + uint c = four(); + } + function g() public { + (uint a1, uint b1, uint c1, uint d1) = one(); + (uint a2, uint b2, uint c2) = one(); + (uint a3, uint b3) = one(); + } + function h() public { + (uint a1, uint b1, uint c1, uint d1) = three(); + (uint a2, uint b2, uint c2) = four(); + } + function one() public pure returns (uint); + function two() public pure returns (uint, uint); + function three() public pure returns (uint, uint, uint); + function four() public pure returns (uint, uint, uint, uint); +} +// ---- +// TypeError: (47-61): Different number of components on the left hand side (1) than on the right hand side (2). +// TypeError: (71-87): Different number of components on the left hand side (1) than on the right hand side (3). +// TypeError: (97-112): Different number of components on the left hand side (1) than on the right hand side (4). +// TypeError: (154-198): Different number of components on the left hand side (4) than on the right hand side (1). +// TypeError: (208-243): Different number of components on the left hand side (3) than on the right hand side (1). +// TypeError: (253-279): Different number of components on the left hand side (2) than on the right hand side (1). +// TypeError: (321-367): Different number of components on the left hand side (4) than on the right hand side (3). +// TypeError: (377-413): Different number of components on the left hand side (3) than on the right hand side (4). diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcards.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcards.sol new file mode 100644 index 000000000..b500823d3 --- /dev/null +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcards.sol @@ -0,0 +1,24 @@ +contract C { + function fn() public pure { + (uint a,) = (1,2,3); + (,uint b) = (1,2,3); + (,uint c,) = (1,2,3,4,5); + (uint d, uint e,) = (1,2,3,4); + (,uint f, uint g) = (1,2,3,4); + (,uint h, uint i,) = (1,2,3); + (uint j,) = 1; + (,uint k) = 1; + (,uint l,) = 1; + a;b;c;d;e;f;g;h;i;j;k;l; + } +} +// ---- +// TypeError: (53-72): Different number of components on the left hand side (2) than on the right hand side (3). +// TypeError: (82-101): Different number of components on the left hand side (2) than on the right hand side (3). +// TypeError: (111-135): Different number of components on the left hand side (3) than on the right hand side (5). +// TypeError: (145-174): Different number of components on the left hand side (3) than on the right hand side (4). +// TypeError: (184-213): Different number of components on the left hand side (3) than on the right hand side (4). +// TypeError: (223-251): Different number of components on the left hand side (4) than on the right hand side (3). +// TypeError: (261-274): Different number of components on the left hand side (2) than on the right hand side (1). +// TypeError: (284-297): Different number of components on the left hand side (2) than on the right hand side (1). +// TypeError: (307-321): Different number of components on the left hand side (3) than on the right hand side (1). diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcardsFromReturn.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcardsFromReturn.sol new file mode 100644 index 000000000..3224a1826 --- /dev/null +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcardsFromReturn.sol @@ -0,0 +1,31 @@ +contract C { + function fn() public pure { + (uint a,) = three(); + (,uint b) = three(); + (,uint c,) = five(); + (uint d, uint e,) = four(); + (,uint f, uint g) = four(); + (,uint h, uint i,) = three(); + (uint j,) = one(); + (,uint k) = one(); + (,uint l,) = one(); + (,uint m, uint n,) = five(); + a;b;c;d;e;f;g;h;i;j;k;l;m;n; + } + function one() public pure returns (uint); + function two() public pure returns (uint, uint); + function three() public pure returns (uint, uint, uint); + function four() public pure returns (uint, uint, uint, uint); + function five() public pure returns (uint, uint, uint, uint, uint); +} +// ---- +// TypeError: (53-72): Different number of components on the left hand side (2) than on the right hand side (3). +// TypeError: (82-101): Different number of components on the left hand side (2) than on the right hand side (3). +// TypeError: (111-130): Different number of components on the left hand side (3) than on the right hand side (5). +// TypeError: (140-166): Different number of components on the left hand side (3) than on the right hand side (4). +// TypeError: (176-202): Different number of components on the left hand side (3) than on the right hand side (4). +// TypeError: (212-240): Different number of components on the left hand side (4) than on the right hand side (3). +// TypeError: (250-267): Different number of components on the left hand side (2) than on the right hand side (1). +// TypeError: (277-294): Different number of components on the left hand side (2) than on the right hand side (1). +// TypeError: (304-322): Different number of components on the left hand side (3) than on the right hand side (1). +// TypeError: (332-359): Different number of components on the left hand side (4) than on the right hand side (5). diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiSingleVariableDeclaration.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiSingleVariableDeclaration.sol index 182ba072e..7db98577e 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiSingleVariableDeclaration.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiSingleVariableDeclaration.sol @@ -3,4 +3,4 @@ contract C { (uint a) = f(); a; } -} +} diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationComplex.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationComplex.sol index a3ce6a746..ba6e99163 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationComplex.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationComplex.sol @@ -2,10 +2,10 @@ contract D { struct S { uint a; uint b; } } contract C { - function f() internal returns (uint, uint, uint, D.S[20] storage, uint) { - (,,,D.S[10*2] storage x,) = f(); + function f() internal pure { + (,,,D.S[10*2] storage x,) = g(); x; } -} + function g() internal pure returns (uint, uint, uint, D.S[20] storage x, uint) { x = x; } +} // ---- -// Warning: (110-117): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationEmpty.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationEmpty.sol new file mode 100644 index 000000000..9618958e2 --- /dev/null +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationEmpty.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + (uint a, uint b) = f(); + (uint c) = f(); + uint d = f(); + } +} +// ---- +// TypeError: (52-74): Different number of components on the left hand side (2) than on the right hand side (0). +// TypeError: (84-98): Different number of components on the left hand side (1) than on the right hand side (0). +// TypeError: (108-120): Different number of components on the left hand side (1) than on the right hand side (0). diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationInvalid.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationInvalid.sol deleted file mode 100644 index c8686ae86..000000000 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationInvalid.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract C { - function f() internal returns (uint, uint, uint, uint) { - var (uint a, uint b,,) = f(); - a; b; - } -} -// ---- -// ParserError: (81-85): Expected identifier but got 'uint' diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationInvalidType.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationInvalidType.sol index 2b765837b..85094d001 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationInvalidType.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationInvalidType.sol @@ -3,7 +3,7 @@ contract C { (uint a, string memory b,,) = f(); a; b; } -} +} // ---- // TypeError: (85-118): Type string memory is not implicitly convertible to expected type uint256. // TypeError: (85-118): Type uint256 is not implicitly convertible to expected type string memory. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol index 3ba85f69e..1f9e52d13 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol @@ -1,5 +1,3 @@ -pragma experimental "v0.5.0"; - contract C { function f() internal { { @@ -7,6 +5,6 @@ contract C { } a; } -} +} // ---- -// DeclarationError: (130-131): Undeclared identifier. +// DeclarationError: (99-100): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol index e21181de1..45b8858b9 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol @@ -1,13 +1,11 @@ -pragma experimental "v0.5.0"; - contract C { function f() internal { { (uint a, uint b, uint c) = (a, b, c); } } -} +} // ---- -// DeclarationError: (110-111): Undeclared identifier. Did you mean "a"? -// DeclarationError: (113-114): Undeclared identifier. Did you mean "b"? -// DeclarationError: (116-117): Undeclared identifier. Did you mean "c"? +// DeclarationError: (79-80): Undeclared identifier. "a" is not (or not yet) visible at this point. +// DeclarationError: (82-83): Undeclared identifier. "b" is not (or not yet) visible at this point. +// DeclarationError: (85-86): Undeclared identifier. "c" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationSimple.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationSimple.sol index 8e06322ce..a2fcce182 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationSimple.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationSimple.sol @@ -1,12 +1,12 @@ contract C { - function f() internal returns (uint, uint, uint, uint) { + function f() internal pure returns (uint, uint, uint, uint) { (uint a, uint b,,) = f(); a; b; } - function g() internal returns (bytes memory, string storage) { - (bytes memory a, string storage b) = g(); + function g() internal pure { + (bytes memory a, string storage b) = h(); a; b; } -} + function h() internal pure returns (bytes memory, string storage s) { s = s; } +} // ---- -// Warning: (163-169): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationThatIsExpression.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationThatIsExpression.sol index 8ae0eaace..004589081 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationThatIsExpression.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationThatIsExpression.sol @@ -4,6 +4,6 @@ contract C { function f() internal pure returns (uint, uint, uint, S storage, uint, uint) { (,,,s.x[2](),,) = f(); } -} +} // ---- // TypeError: (160-168): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/oneElementTuple.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/oneElementTuple.sol new file mode 100644 index 000000000..562c7c0b0 --- /dev/null +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/oneElementTuple.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + (uint a,) = (1,); + a; + } +} +// ---- +// TypeError: (59-63): Tuple component cannot be empty. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/sameNumberOfComponents.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/sameNumberOfComponents.sol new file mode 100644 index 000000000..59eb34af6 --- /dev/null +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/sameNumberOfComponents.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + (uint a1, uint b1, uint c1, uint d1) = (1,2,3,4); + (uint a2, uint b2, uint c2) = (1,2,3); + (uint a3, uint b3) = (1,2); + a1; b1; c1; d1; a2; b2; c2; a3; b3; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/multiline_comments.sol b/test/libsolidity/syntaxTests/multiline_comments.sol new file mode 100644 index 000000000..480fde6c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/multiline_comments.sol @@ -0,0 +1,13 @@ +/* + * This is a multi-line comment + * it should create no problems + * +*/ + +contract test { + /* + * this is another multi-line comment + * + */ +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/001_name_references.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/001_name_references.sol new file mode 100644 index 000000000..dc304a1dc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/001_name_references.sol @@ -0,0 +1,4 @@ +contract test { + uint256 variable; + function f(uint256) public returns (uint out) { f(variable); test; out; } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/002_undeclared_name.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/002_undeclared_name.sol new file mode 100644 index 000000000..afe9483f6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/002_undeclared_name.sol @@ -0,0 +1,8 @@ +contract test { + uint256 variable; + function f(uint256 arg) public { + f(notfound); + } +} +// ---- +// DeclarationError: (85-93): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/003_undeclared_name_is_not_fatal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/003_undeclared_name_is_not_fatal.sol new file mode 100644 index 000000000..0f2a15260 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/003_undeclared_name_is_not_fatal.sol @@ -0,0 +1,10 @@ +contract test { + uint256 variable; + function f(uint256 arg) public { + f(notfound); + f(notfound); + } +} +// ---- +// DeclarationError: (85-93): Undeclared identifier. +// DeclarationError: (106-114): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/004_reference_to_later_declaration.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/004_reference_to_later_declaration.sol new file mode 100644 index 000000000..e112e16c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/004_reference_to_later_declaration.sol @@ -0,0 +1,6 @@ +contract test { + function g() public { f(); } + function f() public {} +} +// ---- +// Warning: (53-75): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/006_type_checking_return.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/006_type_checking_return.sol new file mode 100644 index 000000000..d0e871390 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/006_type_checking_return.sol @@ -0,0 +1,5 @@ +contract test { + function f() public returns (bool r) { return 1 >= 2; } +} +// ---- +// Warning: (20-75): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/007_type_checking_return_wrong_number.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/007_type_checking_return_wrong_number.sol new file mode 100644 index 000000000..13c70ad9e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/007_type_checking_return_wrong_number.sol @@ -0,0 +1,5 @@ +contract test { + function f() public returns (bool r1, bool r2) { return 1 >= 2; } +} +// ---- +// TypeError: (69-82): Different number of arguments in return statement than in returns declaration. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/008_type_checking_return_wrong_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/008_type_checking_return_wrong_type.sol new file mode 100644 index 000000000..a7459ae8e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/008_type_checking_return_wrong_type.sol @@ -0,0 +1,5 @@ +contract test { + function f() public returns (uint256 r) { return 1 >= 2; } +} +// ---- +// TypeError: (69-75): Return argument type bool is not implicitly convertible to expected type (type of first return variable) uint256. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/009_type_checking_function_call.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/009_type_checking_function_call.sol new file mode 100644 index 000000000..abe2beacd --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/009_type_checking_function_call.sol @@ -0,0 +1,6 @@ +contract test { + function f() public returns (bool) { return g(12, true) == 3; } + function g(uint256, bool) public returns (uint256) { } +} +// ---- +// Warning: (88-142): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/010_type_conversion_for_comparison.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/010_type_conversion_for_comparison.sol new file mode 100644 index 000000000..c0cd87d46 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/010_type_conversion_for_comparison.sol @@ -0,0 +1,6 @@ +contract test { + function f() public { uint32(2) == int64(2); } +} +// ---- +// Warning: (42-63): Statement has no effect. +// Warning: (20-66): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/011_type_conversion_for_comparison_invalid.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/011_type_conversion_for_comparison_invalid.sol new file mode 100644 index 000000000..9cbce0d06 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/011_type_conversion_for_comparison_invalid.sol @@ -0,0 +1,5 @@ +contract test { + function f() public { int32(2) == uint64(2); } +} +// ---- +// TypeError: (42-63): Operator == not compatible with types int32 and uint64 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/013_large_string_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/013_large_string_literal.sol new file mode 100644 index 000000000..7f858a4d7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/013_large_string_literal.sol @@ -0,0 +1,6 @@ +contract test { + function f() public { string memory x = "123456789012345678901234567890123"; } +} +// ---- +// Warning: (42-57): Unused local variable. +// Warning: (20-98): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/014_balance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/014_balance.sol new file mode 100644 index 000000000..e2c9a8bff --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/014_balance.sol @@ -0,0 +1,8 @@ +contract test { + function fun() public { + uint256 x = address(0).balance; + } +} +// ---- +// Warning: (52-61): Unused local variable. +// Warning: (20-89): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/015_balance_invalid.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/015_balance_invalid.sol new file mode 100644 index 000000000..18658fbee --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/015_balance_invalid.sol @@ -0,0 +1,7 @@ +contract test { + function fun() public { + address(0).balance = 7; + } +} +// ---- +// TypeError: (52-70): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/017_assignment_to_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/017_assignment_to_struct.sol new file mode 100644 index 000000000..6fbd09aea --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/017_assignment_to_struct.sol @@ -0,0 +1,11 @@ +contract test { + struct str { + mapping(uint=>uint) map; + } + str data; + function fun() public { + str storage a = data; + data = a; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/018_forward_function_reference.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/018_forward_function_reference.sol new file mode 100644 index 000000000..fd9ab7ed3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/018_forward_function_reference.sol @@ -0,0 +1,10 @@ +contract First { + function fun() public returns (bool) { + return Second(1).fun(1, true, 3) > 0; + } +} +contract Second { + function fun(uint, bool, uint) public returns (uint) { + if (First(2).fun() == true) return 1; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/019_comparison_bitop_precedence.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/019_comparison_bitop_precedence.sol new file mode 100644 index 000000000..eab272dfa --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/019_comparison_bitop_precedence.sol @@ -0,0 +1,7 @@ +contract First { + function fun() public returns (bool ret) { + return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6; + } +} +// ---- +// Warning: (21-117): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/020_comparison_of_function_types_lt_1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/020_comparison_of_function_types_lt_1.sol new file mode 100644 index 000000000..1f288ff72 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/020_comparison_of_function_types_lt_1.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (bool ret) { + return this.f < this.f; + } +} +// ---- +// TypeError: (73-88): Operator < not compatible with types function () external returns (bool) and function () external returns (bool) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/021_comparison_of_function_types_lt_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/021_comparison_of_function_types_lt_2.sol new file mode 100644 index 000000000..a6422d38e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/021_comparison_of_function_types_lt_2.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (bool ret) { + return f < f; + } +} +// ---- +// TypeError: (73-78): Operator < not compatible with types function () returns (bool) and function () returns (bool) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/022_comparison_of_function_types_gt_1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/022_comparison_of_function_types_gt_1.sol new file mode 100644 index 000000000..ee8659124 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/022_comparison_of_function_types_gt_1.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (bool ret) { + return this.f > this.f; + } +} +// ---- +// TypeError: (73-88): Operator > not compatible with types function () external returns (bool) and function () external returns (bool) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/023_comparison_of_function_types_gt_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/023_comparison_of_function_types_gt_2.sol new file mode 100644 index 000000000..590cc98bb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/023_comparison_of_function_types_gt_2.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (bool ret) { + return f > f; + } +} +// ---- +// TypeError: (73-78): Operator > not compatible with types function () returns (bool) and function () returns (bool) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/024_comparison_of_function_types_eq.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/024_comparison_of_function_types_eq.sol new file mode 100644 index 000000000..71dbec6b3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/024_comparison_of_function_types_eq.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (bool ret) { + return f == f; + } + function g() public returns (bool ret) { + return f != f; + } +} +// ---- +// Warning: (17-86): Function state mutability can be restricted to pure +// Warning: (91-160): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/025_comparison_of_mapping_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/025_comparison_of_mapping_types.sol new file mode 100644 index 000000000..b15666c0b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/025_comparison_of_mapping_types.sol @@ -0,0 +1,9 @@ +contract C { + mapping(uint => uint) x; + function f() public returns (bool ret) { + mapping(uint => uint) storage y = x; + return x == y; + } +} +// ---- +// TypeError: (147-153): Operator == not compatible with types mapping(uint256 => uint256) and mapping(uint256 => uint256) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol new file mode 100644 index 000000000..455f41891 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol @@ -0,0 +1,7 @@ +contract base { function foo() public; } +contract derived { + base b; + function foo() public { b = new base(); } +} +// ---- +// TypeError: (104-112): Trying to create an instance of an abstract contract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/030_redeclare_implemented_abstract_function_as_abstract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/030_redeclare_implemented_abstract_function_as_abstract.sol new file mode 100644 index 000000000..55bdea894 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/030_redeclare_implemented_abstract_function_as_abstract.sol @@ -0,0 +1,5 @@ +contract base { function foo() public; } +contract derived is base { function foo() public {} } +contract wrong is derived { function foo() public; } +// ---- +// TypeError: (123-145): Redeclaring an already implemented function as abstract diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/039_functions_with_identical_structs_in_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/039_functions_with_identical_structs_in_interface.sol new file mode 100644 index 000000000..3389ffe4b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/039_functions_with_identical_structs_in_interface.sol @@ -0,0 +1,11 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct S1 { int i; } + struct S2 { int i; } + function f(S1 memory) public pure {} + function f(S2 memory) public pure {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (143-179): Function overload clash during conversion to external types for arguments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/040_functions_with_different_structs_in_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/040_functions_with_different_structs_in_interface.sol new file mode 100644 index 000000000..6ff8fd6e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/040_functions_with_different_structs_in_interface.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct S1 { function() external a; } + struct S2 { bytes24 a; } + function f(S1 memory) public pure {} + function f(S2 memory) public pure {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol new file mode 100644 index 000000000..73b608aed --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol @@ -0,0 +1,9 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct S { function() internal a; } + function f(S memory) public {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (103-111): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol new file mode 100644 index 000000000..607a4a685 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol @@ -0,0 +1,9 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct S { mapping(uint => uint) a; } + function f(S memory) public {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (105-113): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol new file mode 100644 index 000000000..da73d8ddf --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct T { mapping(uint => uint) a; } + struct S { T[][2] b; } + function f(S memory) public {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (132-140): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/044_returning_multi_dimensional_arrays_new_abi.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/044_returning_multi_dimensional_arrays_new_abi.sol new file mode 100644 index 000000000..ae9416e58 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/044_returning_multi_dimensional_arrays_new_abi.sol @@ -0,0 +1,7 @@ +pragma experimental ABIEncoderV2; + +contract C { + function f() public pure returns (string[][] memory) {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol new file mode 100644 index 000000000..b9a64c2a2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns (string[][] memory) {} +} +// ---- +// TypeError: (51-68): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol new file mode 100644 index 000000000..ccee60934 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns (uint[][2] memory) {} +} +// ---- +// TypeError: (51-67): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/047_returning_arrays_in_structs_new_abi.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/047_returning_arrays_in_structs_new_abi.sol new file mode 100644 index 000000000..8ca3a53d8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/047_returning_arrays_in_structs_new_abi.sol @@ -0,0 +1,8 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct S { string[] s; } + function f() public pure returns (S memory) {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/048_returning_arrays_in_structs_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/048_returning_arrays_in_structs_arrays.sol new file mode 100644 index 000000000..48e80fcf2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/048_returning_arrays_in_structs_arrays.sol @@ -0,0 +1,6 @@ +contract C { + struct S { string[] s; } + function f() public pure returns (S memory x) {} +} +// ---- +// TypeError: (80-90): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/049_function_external_call_allowed_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/049_function_external_call_allowed_conversion.sol new file mode 100644 index 000000000..ec72adeb9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/049_function_external_call_allowed_conversion.sol @@ -0,0 +1,11 @@ +contract C {} +contract Test { + function externalCall() public { + C arg; + this.g(arg); + } + function g (C c) external {} +} +// ---- +// Warning: (125-128): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (113-141): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/050_function_external_call_not_allowed_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/050_function_external_call_not_allowed_conversion.sol new file mode 100644 index 000000000..18d75948c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/050_function_external_call_not_allowed_conversion.sol @@ -0,0 +1,10 @@ +contract C {} +contract Test { + function externalCall() public { + address arg; + this.g(arg); + } + function g (C c) external {} +} +// ---- +// TypeError: (103-106): Invalid type for argument in function call. Invalid implicit conversion from address to contract C requested. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/051_function_internal_allowed_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/051_function_internal_allowed_conversion.sol new file mode 100644 index 000000000..aedc7b0b3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/051_function_internal_allowed_conversion.sol @@ -0,0 +1,13 @@ +contract C { + uint a; +} +contract Test { + C a; + function g (C c) public {} + function internalCall() public { + g(a); + } +} +// ---- +// Warning: (68-71): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (56-82): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/052_function_internal_not_allowed_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/052_function_internal_not_allowed_conversion.sol new file mode 100644 index 000000000..c16d35eb3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/052_function_internal_not_allowed_conversion.sol @@ -0,0 +1,12 @@ +contract C { + uint a; +} +contract Test { + address a; + function g (C c) public {} + function internalCall() public { + g(a); + } +} +// ---- +// TypeError: (136-137): Invalid type for argument in function call. Invalid implicit conversion from address to contract C requested. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/053_hash_collision_in_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/053_hash_collision_in_interface.sol new file mode 100644 index 000000000..fe690e169 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/053_hash_collision_in_interface.sol @@ -0,0 +1,6 @@ +contract test { + function gsf() public { } + function tgeo() public { } +} +// ---- +// TypeError: (0-78): Function signature hash collision for tgeo() diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/054_inheritance_basic.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/054_inheritance_basic.sol new file mode 100644 index 000000000..6229a1dc5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/054_inheritance_basic.sol @@ -0,0 +1,5 @@ +contract base { uint baseMember; struct BaseType { uint element; } } +contract derived is base { + BaseType data; + function f() public { baseMember = 7; } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/055_inheritance_diamond_basic.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/055_inheritance_diamond_basic.sol new file mode 100644 index 000000000..c07e59e26 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/055_inheritance_diamond_basic.sol @@ -0,0 +1,9 @@ +contract root { function rootFunction() public {} } +contract inter1 is root { function f() public {} } +contract inter2 is root { function f() public {} } +contract derived is root, inter2, inter1 { + function g() public { f(); rootFunction(); } +} +// ---- +// Warning: (16-49): Function state mutability can be restricted to pure +// Warning: (129-151): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/056_cyclic_inheritance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/056_cyclic_inheritance.sol new file mode 100644 index 000000000..0e1ec4cb5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/056_cyclic_inheritance.sol @@ -0,0 +1,4 @@ +contract A is B { } +contract B is A { } +// ---- +// TypeError: (14-15): Definition of base has to precede definition of derived contract diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/057_legal_override_direct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/057_legal_override_direct.sol new file mode 100644 index 000000000..062507ee0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/057_legal_override_direct.sol @@ -0,0 +1,6 @@ +contract B { function f() public {} } +contract C is B { function f(uint i) public {} } +// ---- +// Warning: (67-73): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (13-35): Function state mutability can be restricted to pure +// Warning: (56-84): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/058_legal_override_indirect.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/058_legal_override_indirect.sol new file mode 100644 index 000000000..f59da4726 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/058_legal_override_indirect.sol @@ -0,0 +1,7 @@ +contract A { function f(uint a) public {} } +contract B { function f() public {} } +contract C is A, B { } +// ---- +// Warning: (24-30): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (13-41): Function state mutability can be restricted to pure +// Warning: (57-79): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/059_illegal_override_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/059_illegal_override_visibility.sol new file mode 100644 index 000000000..8c13a4785 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/059_illegal_override_visibility.sol @@ -0,0 +1,4 @@ +contract B { function f() internal {} } +contract C is B { function f() public {} } +// ---- +// TypeError: (58-80): Overriding function visibility differs. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/060_complex_inheritance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/060_complex_inheritance.sol new file mode 100644 index 000000000..c7e42238b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/060_complex_inheritance.sol @@ -0,0 +1,6 @@ +contract A { function f() public { uint8 x = C(0).g(); } } +contract B { function f() public {} function g() public returns (uint8) {} } +contract C is A, B { } +// ---- +// Warning: (35-42): Unused local variable. +// Warning: (95-133): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol new file mode 100644 index 000000000..8ebb46aa2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol @@ -0,0 +1,4 @@ +contract A { constructor(uint a) public { } } +contract B is A { } +// ---- +// Warning: (25-31): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol new file mode 100644 index 000000000..8ebb46aa2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol @@ -0,0 +1,4 @@ +contract A { constructor(uint a) public { } } +contract B is A { } +// ---- +// Warning: (25-31): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/063_implicit_derived_to_base_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/063_implicit_derived_to_base_conversion.sol new file mode 100644 index 000000000..f4667996f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/063_implicit_derived_to_base_conversion.sol @@ -0,0 +1,7 @@ +contract A { } +contract B is A { + function f() public { A a = B(1); } +} +// ---- +// Warning: (59-62): Unused local variable. +// Warning: (37-72): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/064_implicit_base_to_derived_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/064_implicit_base_to_derived_conversion.sol new file mode 100644 index 000000000..0d23ea87d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/064_implicit_base_to_derived_conversion.sol @@ -0,0 +1,6 @@ +contract A { } +contract B is A { + function f() public { B b = A(1); } +} +// ---- +// TypeError: (59-69): Type contract A is not implicitly convertible to expected type contract B. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/065_super_excludes_current_contract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/065_super_excludes_current_contract.sol new file mode 100644 index 000000000..544df1a56 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/065_super_excludes_current_contract.sol @@ -0,0 +1,11 @@ +contract A { + function b() public {} +} + +contract B is A { + function f() public { + super.f(); + } +} +// ---- +// TypeError: (95-102): Member "f" not found or not visible after argument-dependent lookup in contract super B. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/067_function_clash_with_state_variable_accessor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/067_function_clash_with_state_variable_accessor.sol new file mode 100644 index 000000000..a99682c0f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/067_function_clash_with_state_variable_accessor.sol @@ -0,0 +1,9 @@ +contract test { + function fun() public { + uint64(2); + } + uint256 foo; + function foo() public {} +} +// ---- +// DeclarationError: (90-114): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/069_base_class_state_variable_accessor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/069_base_class_state_variable_accessor.sol new file mode 100644 index 000000000..8f2c64380 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/069_base_class_state_variable_accessor.sol @@ -0,0 +1,9 @@ +// test for issue #1126 https://github.com/ethereum/cpp-ethereum/issues/1126 +contract Parent { + uint256 public m_aMember; +} +contract Child is Parent { + function foo() public returns (uint256) { return Parent.m_aMember; } +} +// ---- +// Warning: (158-226): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/070_struct_accessor_one_array_only.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/070_struct_accessor_one_array_only.sol new file mode 100644 index 000000000..6741a7fa7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/070_struct_accessor_one_array_only.sol @@ -0,0 +1,6 @@ +contract test { + struct Data { uint[15] m_array; } + Data public data; +} +// ---- +// TypeError: (58-74): Internal or recursive type is not allowed for public state variables. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/071_base_class_state_variable_internal_member.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/071_base_class_state_variable_internal_member.sol new file mode 100644 index 000000000..774ea38e8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/071_base_class_state_variable_internal_member.sol @@ -0,0 +1,8 @@ +contract Parent { + uint256 internal m_aMember; +} +contract Child is Parent { + function foo() public returns (uint256) { return Parent.m_aMember; } +} +// ---- +// Warning: (83-151): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/072_state_variable_member_of_wrong_class1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/072_state_variable_member_of_wrong_class1.sol new file mode 100644 index 000000000..dd73ac47b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/072_state_variable_member_of_wrong_class1.sol @@ -0,0 +1,11 @@ +contract Parent1 { + uint256 internal m_aMember1; +} +contract Parent2 is Parent1 { + uint256 internal m_aMember2; +} +contract Child is Parent2 { + function foo() public returns (uint256) { return Parent2.m_aMember1; } +} +// ---- +// TypeError: (200-218): Member "m_aMember1" not found or not visible after argument-dependent lookup in type(contract Parent2). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/073_state_variable_member_of_wrong_class2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/073_state_variable_member_of_wrong_class2.sol new file mode 100644 index 000000000..f2de6e72e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/073_state_variable_member_of_wrong_class2.sol @@ -0,0 +1,12 @@ +contract Parent1 { + uint256 internal m_aMember1; +} +contract Parent2 is Parent1 { + uint256 internal m_aMember2; +} +contract Child is Parent2 { + function foo() public returns (uint256) { return Child.m_aMember2; } + uint256 public m_aMember3; +} +// ---- +// TypeError: (200-216): Member "m_aMember2" not found or not visible after argument-dependent lookup in type(contract Child). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/074_fallback_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/074_fallback_function.sol new file mode 100644 index 000000000..466e80cbe --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/074_fallback_function.sol @@ -0,0 +1,4 @@ +contract C { + uint x; + function() external { x = 2; } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/075_fallback_function_with_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/075_fallback_function_with_arguments.sol new file mode 100644 index 000000000..68d409529 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/075_fallback_function_with_arguments.sol @@ -0,0 +1,6 @@ +contract C { + uint x; + function(uint a) external { x = 2; } +} +// ---- +// TypeError: (37-45): Fallback function cannot take parameters. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/076_fallback_function_in_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/076_fallback_function_in_library.sol new file mode 100644 index 000000000..25878a61c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/076_fallback_function_in_library.sol @@ -0,0 +1,5 @@ +library C { + function() external {} +} +// ---- +// TypeError: (16-38): Libraries cannot have fallback functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/077_fallback_function_with_return_parameters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/077_fallback_function_with_return_parameters.sol new file mode 100644 index 000000000..3ff7a1c41 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/077_fallback_function_with_return_parameters.sol @@ -0,0 +1,5 @@ +contract C { + function() external returns (uint) { } +} +// ---- +// TypeError: (45-51): Fallback function cannot return values. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/078_fallback_function_twice.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/078_fallback_function_twice.sol new file mode 100644 index 000000000..e5746c63b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/078_fallback_function_twice.sol @@ -0,0 +1,7 @@ +contract C { + uint x; + function() external { x = 2; } + function() external { x = 3; } +} +// ---- +// DeclarationError: (64-94): Only one fallback function is allowed. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/079_fallback_function_inheritance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/079_fallback_function_inheritance.sol new file mode 100644 index 000000000..c8c06c6ec --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/079_fallback_function_inheritance.sol @@ -0,0 +1,7 @@ +contract A { + uint x; + function() external { x = 1; } +} +contract C is A { + function() external { x = 2; } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/080_event.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/080_event.sol new file mode 100644 index 000000000..c5f9e4d05 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/080_event.sol @@ -0,0 +1,5 @@ +contract c { + event e(uint indexed a, bytes3 indexed s, bool indexed b); + function f() public { emit e(2, "abc", true); } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/081_event_too_many_indexed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/081_event_too_many_indexed.sol new file mode 100644 index 000000000..ee0af605f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/081_event_too_many_indexed.sol @@ -0,0 +1,5 @@ +contract c { + event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d); +} +// ---- +// TypeError: (17-91): More than 3 indexed arguments for event. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/082_anonymous_event_four_indexed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/082_anonymous_event_four_indexed.sol new file mode 100644 index 000000000..e8b369067 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/082_anonymous_event_four_indexed.sol @@ -0,0 +1,3 @@ +contract c { + event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d) anonymous; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/083_anonymous_event_too_many_indexed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/083_anonymous_event_too_many_indexed.sol new file mode 100644 index 000000000..d439c5b96 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/083_anonymous_event_too_many_indexed.sol @@ -0,0 +1,5 @@ +contract c { + event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous; +} +// ---- +// TypeError: (17-117): More than 4 indexed arguments for anonymous event. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/084_events_with_same_name.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/084_events_with_same_name.sol new file mode 100644 index 000000000..24f633b31 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/084_events_with_same_name.sol @@ -0,0 +1,4 @@ +contract TestIt { + event A(); + event A(uint i); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/085_events_with_same_name_unnamed_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/085_events_with_same_name_unnamed_arguments.sol new file mode 100644 index 000000000..cccd9d57e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/085_events_with_same_name_unnamed_arguments.sol @@ -0,0 +1,4 @@ +contract test { + event A(uint); + event A(uint, uint); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/086_events_with_same_name_different_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/086_events_with_same_name_different_types.sol new file mode 100644 index 000000000..fbeab7119 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/086_events_with_same_name_different_types.sol @@ -0,0 +1,4 @@ +contract test { + event A(uint); + event A(bytes); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/087_double_event_declaration.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/087_double_event_declaration.sol new file mode 100644 index 000000000..af0280c5d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/087_double_event_declaration.sol @@ -0,0 +1,6 @@ +contract test { + event A(uint i); + event A(uint i); +} +// ---- +// DeclarationError: (20-36): Event with same name and arguments defined twice. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/088_double_event_declaration_ignores_anonymous.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/088_double_event_declaration_ignores_anonymous.sol new file mode 100644 index 000000000..7d4b0ac93 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/088_double_event_declaration_ignores_anonymous.sol @@ -0,0 +1,6 @@ +contract test { + event A(uint i); + event A(uint i) anonymous; +} +// ---- +// DeclarationError: (20-36): Event with same name and arguments defined twice. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/089_double_event_declaration_ignores_indexed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/089_double_event_declaration_ignores_indexed.sol new file mode 100644 index 000000000..e6aa3e5fb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/089_double_event_declaration_ignores_indexed.sol @@ -0,0 +1,6 @@ +contract test { + event A(uint i); + event A(uint indexed i); +} +// ---- +// DeclarationError: (20-36): Event with same name and arguments defined twice. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/090_event_call.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/090_event_call.sol new file mode 100644 index 000000000..8cf50597f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/090_event_call.sol @@ -0,0 +1,5 @@ +contract c { + event e(uint a, bytes3 indexed s, bool indexed b); + function f() public { emit e(2, "abc", true); } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/091_event_function_inheritance_clash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/091_event_function_inheritance_clash.sol new file mode 100644 index 000000000..5e0f58ea2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/091_event_function_inheritance_clash.sol @@ -0,0 +1,12 @@ +contract A { + function dup() public returns (uint) { + return 1; + } +} +contract B { + event dup(); +} +contract C is A, B { +} +// ---- +// DeclarationError: (99-111): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/092_function_event_inheritance_clash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/092_function_event_inheritance_clash.sol new file mode 100644 index 000000000..c567f9920 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/092_function_event_inheritance_clash.sol @@ -0,0 +1,12 @@ +contract B { + event dup(); +} +contract A { + function dup() public returns (uint) { + return 1; + } +} +contract C is B, A { +} +// ---- +// DeclarationError: (49-111): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/093_function_event_in_contract_clash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/093_function_event_in_contract_clash.sol new file mode 100644 index 000000000..7b4fcde9f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/093_function_event_in_contract_clash.sol @@ -0,0 +1,8 @@ +contract A { + event dup(); + function dup() public returns (uint) { + return 1; + } +} +// ---- +// DeclarationError: (34-96): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/094_event_inheritance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/094_event_inheritance.sol new file mode 100644 index 000000000..b13d57551 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/094_event_inheritance.sol @@ -0,0 +1,7 @@ +contract base { + event e(uint a, bytes3 indexed s, bool indexed b); +} +contract c is base { + function f() public { emit e(2, "abc", true); } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/095_multiple_events_argument_clash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/095_multiple_events_argument_clash.sol new file mode 100644 index 000000000..791271192 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/095_multiple_events_argument_clash.sol @@ -0,0 +1,4 @@ +contract c { + event e1(uint a, uint e1, uint e2); + event e2(uint a, uint e1, uint e2); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/096_access_to_default_function_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/096_access_to_default_function_visibility.sol new file mode 100644 index 000000000..9251df736 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/096_access_to_default_function_visibility.sol @@ -0,0 +1,8 @@ +contract c { + function f() public {} +} +contract d { + function g() public { c(0).f(); } +} +// ---- +// Warning: (17-39): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/097_access_to_internal_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/097_access_to_internal_function.sol new file mode 100644 index 000000000..60d7b758e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/097_access_to_internal_function.sol @@ -0,0 +1,8 @@ +contract c { + function f() internal {} +} +contract d { + function g() public { c(0).f(); } +} +// ---- +// TypeError: (83-89): Member "f" not found or not visible after argument-dependent lookup in contract c. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/098_access_to_default_state_variable_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/098_access_to_default_state_variable_visibility.sol new file mode 100644 index 000000000..8c9d0c0f8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/098_access_to_default_state_variable_visibility.sol @@ -0,0 +1,8 @@ +contract c { + uint a; +} +contract d { + function g() public { c(0).a(); } +} +// ---- +// TypeError: (66-72): Member "a" not found or not visible after argument-dependent lookup in contract c. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/099_access_to_internal_state_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/099_access_to_internal_state_variable.sol new file mode 100644 index 000000000..60aba5741 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/099_access_to_internal_state_variable.sol @@ -0,0 +1,8 @@ +contract c { + uint public a; +} +contract d { + function g() public { c(0).a(); } +} +// ---- +// Warning: (51-84): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/100_error_count_in_named_args.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/100_error_count_in_named_args.sol new file mode 100644 index 000000000..a679c25a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/100_error_count_in_named_args.sol @@ -0,0 +1,11 @@ +contract test { + function a(uint a, uint b) public returns (uint r) { + r = a + b; + } + function b() public returns (uint r) { + r = a({a: 1}); + } +} +// ---- +// Warning: (31-37): This declaration shadows an existing declaration. +// TypeError: (153-162): Wrong argument count for function call: 1 arguments given but expected 2. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/101_empty_in_named_args.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/101_empty_in_named_args.sol new file mode 100644 index 000000000..9da11d6fc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/101_empty_in_named_args.sol @@ -0,0 +1,11 @@ +contract test { + function a(uint a, uint b) public returns (uint r) { + r = a + b; + } + function b() public returns (uint r) { + r = a({}); + } +} +// ---- +// Warning: (31-37): This declaration shadows an existing declaration. +// TypeError: (153-158): Wrong argument count for function call: 0 arguments given but expected 2. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/102_duplicate_parameter_names_in_named_args.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/102_duplicate_parameter_names_in_named_args.sol new file mode 100644 index 000000000..88402fa36 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/102_duplicate_parameter_names_in_named_args.sol @@ -0,0 +1,11 @@ +contract test { + function a(uint a, uint b) public returns (uint r) { + r = a + b; + } + function b() public returns (uint r) { + r = a({a: 1, a: 2}); + } +} +// ---- +// Warning: (31-37): This declaration shadows an existing declaration. +// TypeError: (159-160): Duplicate named argument "a". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/103_invalid_parameter_names_in_named_args.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/103_invalid_parameter_names_in_named_args.sol new file mode 100644 index 000000000..bed15186f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/103_invalid_parameter_names_in_named_args.sol @@ -0,0 +1,11 @@ +contract test { + function a(uint a, uint b) public returns (uint r) { + r = a + b; + } + function b() public returns (uint r) { + r = a({a: 1, c: 2}); + } +} +// ---- +// Warning: (31-37): This declaration shadows an existing declaration. +// TypeError: (153-168): Named argument "c" does not match function declaration. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/104_empty_name_input_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/104_empty_name_input_parameter.sol new file mode 100644 index 000000000..824543efc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/104_empty_name_input_parameter.sol @@ -0,0 +1,5 @@ +contract test { + function f(uint) public { } +} +// ---- +// Warning: (20-47): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/105_constant_input_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/105_constant_input_parameter.sol new file mode 100644 index 000000000..ba05fcb31 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/105_constant_input_parameter.sol @@ -0,0 +1,7 @@ +contract test { + function f(uint[] memory constant a) public { } +} +// ---- +// DeclarationError: (31-55): The "constant" keyword can only be used for state variables. +// TypeError: (31-55): Constants of non-value type not yet implemented. +// TypeError: (31-55): Uninitialized "constant" variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/106_empty_name_return_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/106_empty_name_return_parameter.sol new file mode 100644 index 000000000..a2ffc6e19 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/106_empty_name_return_parameter.sol @@ -0,0 +1,5 @@ +contract test { + function f() public returns (bool) { } +} +// ---- +// Warning: (20-58): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/107_empty_name_input_parameter_with_named_one.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/107_empty_name_input_parameter_with_named_one.sol new file mode 100644 index 000000000..e0efa0a08 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/107_empty_name_input_parameter_with_named_one.sol @@ -0,0 +1,7 @@ +contract test { + function f(uint, uint k) public returns (uint ret_k) { + return k; + } +} +// ---- +// Warning: (20-98): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/108_empty_name_return_parameter_with_named_one.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/108_empty_name_return_parameter_with_named_one.sol new file mode 100644 index 000000000..39ae78775 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/108_empty_name_return_parameter_with_named_one.sol @@ -0,0 +1,7 @@ +contract test { + function f() public returns (uint ret_k, uint) { + return 5; + } +} +// ---- +// TypeError: (77-85): Different number of arguments in return statement than in returns declaration. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/110_no_overflow_with_large_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/110_no_overflow_with_large_literal.sol new file mode 100644 index 000000000..9b36fa70b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/110_no_overflow_with_large_literal.sol @@ -0,0 +1,7 @@ +contract c { + constructor() public { + a = 115792089237316195423570985008687907853269984665640564039458; + } + uint256 a; +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/111_overflow_caused_by_ether_units.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/111_overflow_caused_by_ether_units.sol new file mode 100644 index 000000000..dc4cab8af --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/111_overflow_caused_by_ether_units.sol @@ -0,0 +1,8 @@ +contract c { + constructor() public { + a = 115792089237316195423570985008687907853269984665640564039458 ether; + } + uint256 a; +} +// ---- +// TypeError: (52-118): Type int_const 1157...(70 digits omitted)...0000 is not implicitly convertible to expected type uint256. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/112_exp_operator_exponent_too_big.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/112_exp_operator_exponent_too_big.sol new file mode 100644 index 000000000..2a9e6204b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/112_exp_operator_exponent_too_big.sol @@ -0,0 +1,5 @@ +contract test { + function f() public returns (uint d) { return 2 ** 10000000000; } +} +// ---- +// TypeError: (66-82): Operator ** not compatible with types int_const 2 and int_const 10000000000 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/113_exp_warn_literal_base_1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/113_exp_warn_literal_base_1.sol new file mode 100644 index 000000000..0d91fcab1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/113_exp_warn_literal_base_1.sol @@ -0,0 +1,8 @@ +contract test { + function f() pure public returns(uint) { + uint8 x = 100; + return 10**x; + } +} +// ---- +// Warning: (99-104): Result of exponentiation has type uint8 and thus might overflow. Silence this warning by converting the literal to the expected type. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/114_exp_warn_literal_base_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/114_exp_warn_literal_base_2.sol new file mode 100644 index 000000000..eb430b9ab --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/114_exp_warn_literal_base_2.sol @@ -0,0 +1,6 @@ +contract test { + function f() pure public returns(uint) { + uint8 x = 100; + return uint8(10)**x; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/115_exp_warn_literal_base_3.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/115_exp_warn_literal_base_3.sol new file mode 100644 index 000000000..01c0fc067 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/115_exp_warn_literal_base_3.sol @@ -0,0 +1,5 @@ +contract test { + function f() pure public returns(uint) { + return 2**80; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/116_shift_warn_literal_base_1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/116_shift_warn_literal_base_1.sol new file mode 100644 index 000000000..c6a4052ec --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/116_shift_warn_literal_base_1.sol @@ -0,0 +1,8 @@ +contract test { + function f() pure public returns(uint) { + uint8 x = 100; + return 10 << x; + } +} +// ---- +// Warning: (99-106): Result of shift has type uint8 and thus might overflow. Silence this warning by converting the literal to the expected type. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/117_shift_warn_literal_base_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/117_shift_warn_literal_base_2.sol new file mode 100644 index 000000000..954d1943a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/117_shift_warn_literal_base_2.sol @@ -0,0 +1,6 @@ +contract test { + function f() pure public returns(uint) { + uint8 x = 100; + return uint8(10) << x; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/118_shift_warn_literal_base_3.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/118_shift_warn_literal_base_3.sol new file mode 100644 index 000000000..5fbaa8060 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/118_shift_warn_literal_base_3.sol @@ -0,0 +1,5 @@ +contract test { + function f() pure public returns(uint) { + return 2 << 80; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/119_shift_warn_literal_base_4.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/119_shift_warn_literal_base_4.sol new file mode 100644 index 000000000..19869157c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/119_shift_warn_literal_base_4.sol @@ -0,0 +1,6 @@ +contract test { + function f() pure public returns(uint) { + uint8 x = 100; + return 10 >> x; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/124_enum_member_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/124_enum_member_access.sol new file mode 100644 index 000000000..98bc8e668 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/124_enum_member_access.sol @@ -0,0 +1,8 @@ +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor() public + { + choices = ActionChoices.GoStraight; + } + ActionChoices choices; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/125_enum_member_access_accross_contracts.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/125_enum_member_access_accross_contracts.sol new file mode 100644 index 000000000..3bed62d67 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/125_enum_member_access_accross_contracts.sol @@ -0,0 +1,10 @@ +contract Interface { + enum MyEnum { One, Two } +} +contract Impl { + function test() public returns (Interface.MyEnum) { + return Interface.MyEnum.One; + } +} +// ---- +// Warning: (72-166): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/126_enum_invalid_member_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/126_enum_invalid_member_access.sol new file mode 100644 index 000000000..e58ed1600 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/126_enum_invalid_member_access.sol @@ -0,0 +1,9 @@ +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor() public { + choices = ActionChoices.RunAroundWavingYourHands; + } + ActionChoices choices; +} +// ---- +// TypeError: (121-159): Member "RunAroundWavingYourHands" not found or not visible after argument-dependent lookup in type(enum test.ActionChoices). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/127_enum_invalid_direct_member_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/127_enum_invalid_direct_member_access.sol new file mode 100644 index 000000000..68510a0a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/127_enum_invalid_direct_member_access.sol @@ -0,0 +1,9 @@ +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor() public { + choices = Sit; + } + ActionChoices choices; +} +// ---- +// DeclarationError: (121-124): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/128_enum_explicit_conversion_is_okay.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/128_enum_explicit_conversion_is_okay.sol new file mode 100644 index 000000000..0948d5505 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/128_enum_explicit_conversion_is_okay.sol @@ -0,0 +1,10 @@ +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor() public { + a = uint256(ActionChoices.GoStraight); + b = uint64(ActionChoices.Sit); + } + uint256 a; + uint64 b; +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/129_int_to_enum_explicit_conversion_is_okay.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/129_int_to_enum_explicit_conversion_is_okay.sol new file mode 100644 index 000000000..2639decf5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/129_int_to_enum_explicit_conversion_is_okay.sol @@ -0,0 +1,10 @@ +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor() public { + a = 2; + b = ActionChoices(a); + } + uint256 a; + ActionChoices b; +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/130_enum_implicit_conversion_is_not_okay_256.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/130_enum_implicit_conversion_is_not_okay_256.sol new file mode 100644 index 000000000..01c5e93fc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/130_enum_implicit_conversion_is_not_okay_256.sol @@ -0,0 +1,9 @@ +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor() public { + a = ActionChoices.GoStraight; + } + uint256 a; +} +// ---- +// TypeError: (115-139): Type enum test.ActionChoices is not implicitly convertible to expected type uint256. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/131_enum_implicit_conversion_is_not_okay_64.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/131_enum_implicit_conversion_is_not_okay_64.sol new file mode 100644 index 000000000..4e21b9aad --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/131_enum_implicit_conversion_is_not_okay_64.sol @@ -0,0 +1,9 @@ +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor() public { + b = ActionChoices.Sit; + } + uint64 b; +} +// ---- +// TypeError: (115-132): Type enum test.ActionChoices is not implicitly convertible to expected type uint64. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/132_enum_to_enum_conversion_is_not_okay.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/132_enum_to_enum_conversion_is_not_okay.sol new file mode 100644 index 000000000..5b9ba813a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/132_enum_to_enum_conversion_is_not_okay.sol @@ -0,0 +1,9 @@ +contract test { + enum Paper { Up, Down, Left, Right } + enum Ground { North, South, West, East } + constructor() public { + Ground(Paper.Up); + } +} +// ---- +// TypeError: (137-153): Explicit type conversion not allowed from "enum test.Paper" to "enum test.Ground". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/133_enum_duplicate_values.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/133_enum_duplicate_values.sol new file mode 100644 index 000000000..996a9b787 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/133_enum_duplicate_values.sol @@ -0,0 +1,5 @@ + contract test { + enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } + } +// ---- +// DeclarationError: (66-72): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/134_enum_name_resolution_under_current_contract_name.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/134_enum_name_resolution_under_current_contract_name.sol new file mode 100644 index 000000000..4a16eee11 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/134_enum_name_resolution_under_current_contract_name.sol @@ -0,0 +1,12 @@ +contract A { + enum Foo { + First, + Second + } + + function a() public { + A.Foo; + } +} +// ---- +// Warning: (69-111): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/135_private_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/135_private_visibility.sol new file mode 100644 index 000000000..faafc6313 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/135_private_visibility.sol @@ -0,0 +1,8 @@ +contract base { + function f() private {} +} +contract derived is base { + function g() public { f(); } +} +// ---- +// DeclarationError: (99-100): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/136_private_visibility_via_explicit_base_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/136_private_visibility_via_explicit_base_access.sol new file mode 100644 index 000000000..2f94ef92b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/136_private_visibility_via_explicit_base_access.sol @@ -0,0 +1,8 @@ +contract base { + function f() private {} +} +contract derived is base { + function g() public { base.f(); } +} +// ---- +// TypeError: (99-105): Member "f" not found or not visible after argument-dependent lookup in type(contract base). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/137_external_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/137_external_visibility.sol new file mode 100644 index 000000000..214ad60ac --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/137_external_visibility.sol @@ -0,0 +1,6 @@ +contract c { + function f() external {} + function g() public { f(); } +} +// ---- +// DeclarationError: (68-69): Undeclared identifier. "f" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/138_similar_name_suggestions_expected.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/138_similar_name_suggestions_expected.sol new file mode 100644 index 000000000..ef6e933a7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/138_similar_name_suggestions_expected.sol @@ -0,0 +1,6 @@ +contract c { + function func() public {} + function g() public { fun(); } +} +// ---- +// DeclarationError: (69-72): Undeclared identifier. Did you mean "func"? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/139_no_name_suggestion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/139_no_name_suggestion.sol new file mode 100644 index 000000000..40827dcad --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/139_no_name_suggestion.sol @@ -0,0 +1,5 @@ +contract c { + function g() public { fun(); } +} +// ---- +// DeclarationError: (39-42): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/140_multiple_similar_suggestions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/140_multiple_similar_suggestions.sol new file mode 100644 index 000000000..34b4604d4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/140_multiple_similar_suggestions.sol @@ -0,0 +1,11 @@ +contract c { + function g() public { + uint var1 = 1; + uint var2 = 1; + uint var3 = 1; + uint var4 = 1; + uint var5 = varx; + } +} +// ---- +// DeclarationError: (151-155): Undeclared identifier. Did you mean "var1", "var2", "var3", "var4" or "var5"? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/141_multiple_scopes_suggestions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/141_multiple_scopes_suggestions.sol new file mode 100644 index 000000000..f94711465 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/141_multiple_scopes_suggestions.sol @@ -0,0 +1,9 @@ +contract c { + uint log9 = 2; + function g() public { + uint log8 = 3; + uint var1 = lgox; + } +} +// ---- +// DeclarationError: (101-105): Undeclared identifier. Did you mean "log8", "log9", "log0", "log1", "log2", "log3" or "log4"? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/142_inheritence_suggestions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/142_inheritence_suggestions.sol new file mode 100644 index 000000000..4231e1bdd --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/142_inheritence_suggestions.sol @@ -0,0 +1,8 @@ +contract a { function func() public {} } +contract c is a { + function g() public { + uint var1 = fun(); + } +} +// ---- +// DeclarationError: (105-108): Undeclared identifier. Did you mean "func"? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/143_no_spurious_identifier_suggestions_with_submatch.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/143_no_spurious_identifier_suggestions_with_submatch.sol new file mode 100644 index 000000000..db9f07c68 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/143_no_spurious_identifier_suggestions_with_submatch.sol @@ -0,0 +1,8 @@ +contract c { + function g() public { + uint va = 1; + uint vb = vaxyz; + } +} +// ---- +// DeclarationError: (78-83): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/144_no_spurious_identifier_suggestions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/144_no_spurious_identifier_suggestions.sol new file mode 100644 index 000000000..2316cb3d3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/144_no_spurious_identifier_suggestions.sol @@ -0,0 +1,8 @@ +contract c { + function g() public { + uint va = 1; + uint vb = x; + } +} +// ---- +// DeclarationError: (78-79): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/145_external_base_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/145_external_base_visibility.sol new file mode 100644 index 000000000..cf6804626 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/145_external_base_visibility.sol @@ -0,0 +1,8 @@ +contract base { + function f() external {} +} +contract derived is base { + function g() public { base.f(); } +} +// ---- +// TypeError: (100-106): Member "f" not found or not visible after argument-dependent lookup in type(contract base). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/146_external_argument_assign.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/146_external_argument_assign.sol new file mode 100644 index 000000000..d2c0245cf --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/146_external_argument_assign.sol @@ -0,0 +1,5 @@ +contract c { + function f(uint a) external { a = 1; } +} +// ---- +// TypeError: (47-48): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/147_external_argument_increment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/147_external_argument_increment.sol new file mode 100644 index 000000000..2bfba42bb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/147_external_argument_increment.sol @@ -0,0 +1,5 @@ +contract c { + function f(uint a) external { a++; } +} +// ---- +// TypeError: (47-48): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/148_external_argument_delete.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/148_external_argument_delete.sol new file mode 100644 index 000000000..30eb204e1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/148_external_argument_delete.sol @@ -0,0 +1,5 @@ +contract c { + function f(uint a) external { delete a; } +} +// ---- +// TypeError: (54-55): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/149_test_for_bug_override_function_with_bytearray_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/149_test_for_bug_override_function_with_bytearray_type.sol new file mode 100644 index 000000000..bc1c42674 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/149_test_for_bug_override_function_with_bytearray_type.sol @@ -0,0 +1,8 @@ +contract Vehicle { + function f(bytes calldata) external returns (uint256 r) {r = 1;} +} +contract Bike is Vehicle { + function f(bytes calldata) external returns (uint256 r) {r = 42;} +} +// ---- +// Warning: (23-87): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/150_array_with_nonconstant_length.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/150_array_with_nonconstant_length.sol new file mode 100644 index 000000000..49a1851c0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/150_array_with_nonconstant_length.sol @@ -0,0 +1,5 @@ +contract c { + function f(uint a) public { uint8[a] x; } +} +// ---- +// TypeError: (51-52): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/151_array_with_negative_length.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/151_array_with_negative_length.sol new file mode 100644 index 000000000..b87160b0f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/151_array_with_negative_length.sol @@ -0,0 +1,5 @@ +contract c { + function f(uint a) public { uint8[-1] x; } +} +// ---- +// TypeError: (51-53): Array with negative length specified. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/152_array_copy_with_different_types1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/152_array_copy_with_different_types1.sol new file mode 100644 index 000000000..a0e71847f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/152_array_copy_with_different_types1.sol @@ -0,0 +1,7 @@ +contract c { + bytes a; + uint[] b; + function f() public { b = a; } +} +// ---- +// TypeError: (70-71): Type bytes storage ref is not implicitly convertible to expected type uint256[] storage ref. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/153_array_copy_with_different_types2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/153_array_copy_with_different_types2.sol new file mode 100644 index 000000000..8d1cb1ef4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/153_array_copy_with_different_types2.sol @@ -0,0 +1,7 @@ +contract c { + uint32[] a; + uint8[] b; + function f() public { b = a; } +} +// ---- +// TypeError: (74-75): Type uint32[] storage ref is not implicitly convertible to expected type uint8[] storage ref. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/154_array_copy_with_different_types_conversion_possible.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/154_array_copy_with_different_types_conversion_possible.sol new file mode 100644 index 000000000..b15a93503 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/154_array_copy_with_different_types_conversion_possible.sol @@ -0,0 +1,5 @@ +contract c { + uint32[] a; + uint8[] b; + function f() public { a = b; } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/155_array_copy_with_different_types_static_dynamic.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/155_array_copy_with_different_types_static_dynamic.sol new file mode 100644 index 000000000..025593a5f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/155_array_copy_with_different_types_static_dynamic.sol @@ -0,0 +1,5 @@ +contract c { + uint32[] a; + uint8[80] b; + function f() public { a = b; } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/156_array_copy_with_different_types_dynamic_static.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/156_array_copy_with_different_types_dynamic_static.sol new file mode 100644 index 000000000..90aa53a0d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/156_array_copy_with_different_types_dynamic_static.sol @@ -0,0 +1,7 @@ +contract c { + uint[] a; + uint[80] b; + function f() public { b = a; } +} +// ---- +// TypeError: (73-74): Type uint256[] storage ref is not implicitly convertible to expected type uint256[80] storage ref. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/157_array_of_undeclared_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/157_array_of_undeclared_type.sol new file mode 100644 index 000000000..1409db5e1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/157_array_of_undeclared_type.sol @@ -0,0 +1,5 @@ +contract c { + a[] public foo; +} +// ---- +// DeclarationError: (17-18): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/158_storage_variable_initialization_with_incorrect_type_int.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/158_storage_variable_initialization_with_incorrect_type_int.sol new file mode 100644 index 000000000..b1ef153e8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/158_storage_variable_initialization_with_incorrect_type_int.sol @@ -0,0 +1,5 @@ +contract c { + uint8 a = 1000; +} +// ---- +// TypeError: (27-31): Type int_const 1000 is not implicitly convertible to expected type uint8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/159_storage_variable_initialization_with_incorrect_type_string.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/159_storage_variable_initialization_with_incorrect_type_string.sol new file mode 100644 index 000000000..75736d988 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/159_storage_variable_initialization_with_incorrect_type_string.sol @@ -0,0 +1,5 @@ +contract c { + uint a = "abc"; +} +// ---- +// TypeError: (26-31): Type literal_string "abc" is not implicitly convertible to expected type uint256. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/160_test_byte_is_alias_of_byte1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/160_test_byte_is_alias_of_byte1.sol new file mode 100644 index 000000000..9977c839c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/160_test_byte_is_alias_of_byte1.sol @@ -0,0 +1,7 @@ +contract c { + bytes arr; + function f() public { byte a = arr[0];} +} +// ---- +// Warning: (54-60): Unused local variable. +// Warning: (32-71): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/164_assigning_value_to_const_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/164_assigning_value_to_const_variable.sol new file mode 100644 index 000000000..4e543e70d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/164_assigning_value_to_const_variable.sol @@ -0,0 +1,6 @@ +contract Foo { + function changeIt() public { x = 9; } + uint constant x = 56; +} +// ---- +// TypeError: (48-49): Cannot assign to a constant variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/165_assigning_state_to_const_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/165_assigning_state_to_const_variable.sol new file mode 100644 index 000000000..0de15dfb1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/165_assigning_state_to_const_variable.sol @@ -0,0 +1,5 @@ +contract C { + address constant x = msg.sender; +} +// ---- +// TypeError: (38-48): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/167_constant_string_literal_disallows_assignment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/167_constant_string_literal_disallows_assignment.sol new file mode 100644 index 000000000..3f19ea3b2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/167_constant_string_literal_disallows_assignment.sol @@ -0,0 +1,10 @@ +contract Test { + string constant x = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; + function f() public { + // Even if this is made possible in the future, we should not allow assignment + // to elements of constant arrays. + x[0] = "f"; + } +} +// ---- +// TypeError: (261-265): Index access for string is not possible. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/168_assignment_to_const_var_involving_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/168_assignment_to_const_var_involving_conversion.sol new file mode 100644 index 000000000..fb31e199d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/168_assignment_to_const_var_involving_conversion.sol @@ -0,0 +1,3 @@ +contract C { + C constant x = C(0x123); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/169_assignment_to_const_var_involving_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/169_assignment_to_const_var_involving_expression.sol new file mode 100644 index 000000000..692aad9f5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/169_assignment_to_const_var_involving_expression.sol @@ -0,0 +1,3 @@ +contract C { + uint constant x = 0x123 + 0x456; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/170_assignment_to_const_var_involving_keccak.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/170_assignment_to_const_var_involving_keccak.sol new file mode 100644 index 000000000..54f022bbf --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/170_assignment_to_const_var_involving_keccak.sol @@ -0,0 +1,3 @@ +contract C { + bytes32 constant x = keccak256("abc"); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/171_assignment_to_const_array_vars.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/171_assignment_to_const_array_vars.sol new file mode 100644 index 000000000..b9e9aa7ae --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/171_assignment_to_const_array_vars.sol @@ -0,0 +1,5 @@ +contract C { + uint[3] constant x = [uint(1), 2, 3]; +} +// ---- +// TypeError: (17-53): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/172_assignment_to_const_string_bytes.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/172_assignment_to_const_string_bytes.sol new file mode 100644 index 000000000..f0e1528ce --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/172_assignment_to_const_string_bytes.sol @@ -0,0 +1,5 @@ +contract C { + bytes constant a = "\x00\x01\x02"; + bytes constant b = hex"000102"; + string constant c = "hello"; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/173_constant_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/173_constant_struct.sol new file mode 100644 index 000000000..07bf0439c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/173_constant_struct.sol @@ -0,0 +1,6 @@ +contract C { + struct S { uint x; uint[] y; } + S constant x = S(5, new uint[](4)); +} +// ---- +// TypeError: (52-86): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/174_address_is_constant.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/174_address_is_constant.sol new file mode 100644 index 000000000..10850e166 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/174_address_is_constant.sol @@ -0,0 +1,3 @@ +contract C { + address constant x = 0x1212121212121212121212121212121212121212; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/175_uninitialized_const_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/175_uninitialized_const_variable.sol new file mode 100644 index 000000000..13496d8b9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/175_uninitialized_const_variable.sol @@ -0,0 +1,5 @@ +contract Foo { + uint constant y; +} +// ---- +// TypeError: (19-34): Uninitialized "constant" variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/176_overloaded_function_cannot_resolve.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/176_overloaded_function_cannot_resolve.sol new file mode 100644 index 000000000..bcf259480 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/176_overloaded_function_cannot_resolve.sol @@ -0,0 +1,7 @@ +contract test { + function f() public returns (uint) { return 1; } + function f(uint a) public returns (uint) { return a; } + function g() public returns (uint) { return f(3, 5); } +} +// ---- +// TypeError: (176-177): No matching declaration found after argument-dependent lookup. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/177_ambiguous_overloaded_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/177_ambiguous_overloaded_function.sol new file mode 100644 index 000000000..759e02f21 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/177_ambiguous_overloaded_function.sol @@ -0,0 +1,8 @@ +contract test { + function f(uint8 a) public returns (uint) { return a; } + function f(uint a) public returns (uint) { return 2 * a; } + // literal 1 can be both converted to uint and uint8, so the call is ambiguous. + function g() public returns (uint) { return f(1); } +} +// ---- +// TypeError: (271-272): No unique declaration found after argument-dependent lookup. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/178_assignment_of_nonoverloaded_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/178_assignment_of_nonoverloaded_function.sol new file mode 100644 index 000000000..07fc1c439 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/178_assignment_of_nonoverloaded_function.sol @@ -0,0 +1,6 @@ +contract test { + function f(uint a) public returns (uint) { return 2 * a; } + function g() public returns (uint) { function (uint) returns (uint) x = f; return x(7); } +} +// ---- +// Warning: (20-78): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/179_assignment_of_overloaded_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/179_assignment_of_overloaded_function.sol new file mode 100644 index 000000000..9ed864f14 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/179_assignment_of_overloaded_function.sol @@ -0,0 +1,7 @@ +contract test { + function f() public returns (uint) { return 1; } + function f(uint a) public returns (uint) { return 2 * a; } + function g() public returns (uint) { function (uint) returns (uint) x = f; return x(7); } +} +// ---- +// TypeError: (208-209): No matching declaration found after variable lookup. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/180_external_types_clash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/180_external_types_clash.sol new file mode 100644 index 000000000..91ddcd9bc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/180_external_types_clash.sol @@ -0,0 +1,9 @@ +contract base { + enum a { X } + function f(a) public { } +} +contract test is base { + function f(uint8 a) public { } +} +// ---- +// TypeError: (37-61): Function overload clash during conversion to external types for arguments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/181_override_changes_return_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/181_override_changes_return_types.sol new file mode 100644 index 000000000..c887f2597 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/181_override_changes_return_types.sol @@ -0,0 +1,8 @@ +contract base { + function f(uint a) public returns (uint) { } +} +contract test is base { + function f(uint a) public returns (uint8) { } +} +// ---- +// TypeError: (95-140): Overriding function return types differ. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol new file mode 100644 index 000000000..cb9eb3fa8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol @@ -0,0 +1,7 @@ +contract C { + function test(uint a) public returns (uint b) { } + function test(uint a) external {} +} +// ---- +// DeclarationError: (17-66): Function with same name and arguments defined twice. +// TypeError: (17-66): Overriding function visibility differs. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/185_invalid_utf8_implicit.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/185_invalid_utf8_implicit.sol new file mode 100644 index 000000000..5440b4255 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/185_invalid_utf8_implicit.sol @@ -0,0 +1,5 @@ +contract C { + string s = "\xa0\x00"; +} +// ---- +// TypeError: (28-38): Type literal_string (contains invalid UTF-8 sequence at position 0) is not implicitly convertible to expected type string storage ref. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol new file mode 100644 index 000000000..0f67460fb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol @@ -0,0 +1,5 @@ +contract C { + string s = string("\xa0\x00"); +} +// ---- +// TypeError: (28-46): Explicit type conversion not allowed from "literal_string (contains invalid UTF-8 sequence at position 0)" to "string memory". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/187_large_utf8_codepoint.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/187_large_utf8_codepoint.sol new file mode 100644 index 000000000..5e406d0c6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/187_large_utf8_codepoint.sol @@ -0,0 +1,3 @@ +contract C { + string s = "\xf0\x9f\xa6\x84"; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/188_string_index.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/188_string_index.sol new file mode 100644 index 000000000..9d51e06b3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/188_string_index.sol @@ -0,0 +1,6 @@ +contract C { + string s; + function f() public { bytes1 a = s[2]; } +} +// ---- +// TypeError: (64-68): Index access for string is not possible. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/189_string_length.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/189_string_length.sol new file mode 100644 index 000000000..845b91566 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/189_string_length.sol @@ -0,0 +1,6 @@ +contract C { + string s; + function f() public { uint a = s.length; } +} +// ---- +// TypeError: (62-70): Member "length" not found or not visible after argument-dependent lookup in string storage ref. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/190_negative_integers_to_signed_out_of_bound.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/190_negative_integers_to_signed_out_of_bound.sol new file mode 100644 index 000000000..2e8503af4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/190_negative_integers_to_signed_out_of_bound.sol @@ -0,0 +1,5 @@ +contract test { + int8 public i = -129; +} +// ---- +// TypeError: (36-40): Type int_const -129 is not implicitly convertible to expected type int8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/191_negative_integers_to_signed_min.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/191_negative_integers_to_signed_min.sol new file mode 100644 index 000000000..211cfee21 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/191_negative_integers_to_signed_min.sol @@ -0,0 +1,3 @@ +contract test { + int8 public i = -128; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/192_positive_integers_to_signed_out_of_bound.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/192_positive_integers_to_signed_out_of_bound.sol new file mode 100644 index 000000000..d56045c2f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/192_positive_integers_to_signed_out_of_bound.sol @@ -0,0 +1,5 @@ +contract test { + int8 public j = 128; +} +// ---- +// TypeError: (36-39): Type int_const 128 is not implicitly convertible to expected type int8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/193_positive_integers_to_signed_out_of_bound_max.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/193_positive_integers_to_signed_out_of_bound_max.sol new file mode 100644 index 000000000..667013398 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/193_positive_integers_to_signed_out_of_bound_max.sol @@ -0,0 +1,3 @@ +contract test { + int8 public j = 127; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/194_negative_integers_to_unsigned.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/194_negative_integers_to_unsigned.sol new file mode 100644 index 000000000..3702f09ba --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/194_negative_integers_to_unsigned.sol @@ -0,0 +1,5 @@ +contract test { + uint8 public x = -1; +} +// ---- +// TypeError: (37-39): Type int_const -1 is not implicitly convertible to expected type uint8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/195_positive_integers_to_unsigned_out_of_bound.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/195_positive_integers_to_unsigned_out_of_bound.sol new file mode 100644 index 000000000..812162296 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/195_positive_integers_to_unsigned_out_of_bound.sol @@ -0,0 +1,5 @@ +contract test { + uint8 public x = 700; +} +// ---- +// TypeError: (37-40): Type int_const 700 is not implicitly convertible to expected type uint8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/196_integer_boolean_or.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/196_integer_boolean_or.sol new file mode 100644 index 000000000..db42786da --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/196_integer_boolean_or.sol @@ -0,0 +1,3 @@ +contract test { function() external { uint x = 1; uint y = 2; x || y; } } +// ---- +// TypeError: (62-68): Operator || not compatible with types uint256 and uint256 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/197_integer_boolean_and.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/197_integer_boolean_and.sol new file mode 100644 index 000000000..94d1c6914 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/197_integer_boolean_and.sol @@ -0,0 +1,3 @@ +contract test { function() external { uint x = 1; uint y = 2; x && y; } } +// ---- +// TypeError: (62-68): Operator && not compatible with types uint256 and uint256 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/198_integer_boolean_not.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/198_integer_boolean_not.sol new file mode 100644 index 000000000..68fe6e945 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/198_integer_boolean_not.sol @@ -0,0 +1,3 @@ +contract test { function() external { uint x = 1; !x; } } +// ---- +// TypeError: (50-52): Unary operator ! cannot be applied to type uint256 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/199_integer_unsigned_exp_signed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/199_integer_unsigned_exp_signed.sol new file mode 100644 index 000000000..fbeadfb66 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/199_integer_unsigned_exp_signed.sol @@ -0,0 +1,3 @@ +contract test { function() external { uint x = 3; int y = -4; x ** y; } } +// ---- +// TypeError: (62-68): Operator ** not compatible with types uint256 and int256 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/200_integer_signed_exp_unsigned.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/200_integer_signed_exp_unsigned.sol new file mode 100644 index 000000000..75e920854 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/200_integer_signed_exp_unsigned.sol @@ -0,0 +1,3 @@ +contract test { function() external { uint x = 3; int y = -4; y ** x; } } +// ---- +// TypeError: (62-68): Operator ** not compatible with types int256 and uint256 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/201_integer_signed_exp_signed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/201_integer_signed_exp_signed.sol new file mode 100644 index 000000000..93e5f065d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/201_integer_signed_exp_signed.sol @@ -0,0 +1,3 @@ +contract test { function() external { int x = -3; int y = -4; x ** y; } } +// ---- +// TypeError: (62-68): Operator ** not compatible with types int256 and int256 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/202_bytes_reference_compare_operators.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/202_bytes_reference_compare_operators.sol new file mode 100644 index 000000000..711b794c1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/202_bytes_reference_compare_operators.sol @@ -0,0 +1,3 @@ +contract test { bytes a; bytes b; function() external { a == b; } } +// ---- +// TypeError: (56-62): Operator == not compatible with types bytes storage ref and bytes storage ref diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol new file mode 100644 index 000000000..a74850b32 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol @@ -0,0 +1,10 @@ +contract test { + struct s {uint a;} + s x; + s y; + function() external { + x == y; + } +} +// ---- +// TypeError: (79-85): Operator == not compatible with types struct test.s storage ref and struct test.s storage ref diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/204_overwrite_memory_location_external.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/204_overwrite_memory_location_external.sol new file mode 100644 index 000000000..22d515eae --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/204_overwrite_memory_location_external.sol @@ -0,0 +1,5 @@ +contract C { + function f(uint[] memory a) external {} +} +// ---- +// TypeError: (28-43): Data location must be "calldata" for parameter in external function, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/205_overwrite_storage_location_external.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/205_overwrite_storage_location_external.sol new file mode 100644 index 000000000..3825809cc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/205_overwrite_storage_location_external.sol @@ -0,0 +1,5 @@ +contract C { + function f(uint[] storage a) external {} +} +// ---- +// TypeError: (28-44): Data location must be "calldata" for parameter in external function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/206_storage_location_local_variables.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/206_storage_location_local_variables.sol new file mode 100644 index 000000000..868d7bc84 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/206_storage_location_local_variables.sol @@ -0,0 +1,9 @@ +contract C { + uint[] m_x; + function f() public view { + uint[] storage x = m_x; + uint[] memory y; + x;y; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/207_no_mappings_in_memory_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/207_no_mappings_in_memory_array.sol new file mode 100644 index 000000000..5220ee22b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/207_no_mappings_in_memory_array.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + mapping(uint=>uint)[] memory x; + } +} +// ---- +// TypeError: (47-77): Type mapping(uint256 => uint256)[] memory is only valid in storage. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/208_assignment_mem_to_local_storage_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/208_assignment_mem_to_local_storage_variable.sol new file mode 100644 index 000000000..cf3037720 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/208_assignment_mem_to_local_storage_variable.sol @@ -0,0 +1,9 @@ +contract C { + uint[] data; + function f(uint[] memory x) public { + uint[] storage dataRef = data; + dataRef = x; + } +} +// ---- +// TypeError: (128-129): Type uint256[] memory is not implicitly convertible to expected type uint256[] storage pointer. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/209_storage_assign_to_different_local_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/209_storage_assign_to_different_local_variable.sol new file mode 100644 index 000000000..aabdcd880 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/209_storage_assign_to_different_local_variable.sol @@ -0,0 +1,12 @@ +contract C { + uint[] data; + uint8[] otherData; + function f() public { + uint8[] storage x = otherData; + uint[] storage y = data; + y = x; + // note that data = otherData works + } +} +// ---- +// TypeError: (163-164): Type uint8[] storage pointer is not implicitly convertible to expected type uint256[] storage pointer. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/210_uninitialized_mapping_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/210_uninitialized_mapping_variable.sol new file mode 100644 index 000000000..0547ace1d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/210_uninitialized_mapping_variable.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + mapping(uint => uint) storage x; + x; + } +} +// ---- +// TypeError: (47-78): Uninitialized mapping. Mappings cannot be created dynamically, you have to assign them from a state variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/211_uninitialized_mapping_array_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/211_uninitialized_mapping_array_variable.sol new file mode 100644 index 000000000..edae7549d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/211_uninitialized_mapping_array_variable.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + mapping(uint => uint)[] storage x; + x; + } +} +// ---- +// DeclarationError: (52-85): Uninitialized storage pointer. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/213_no_delete_on_storage_pointers.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/213_no_delete_on_storage_pointers.sol new file mode 100644 index 000000000..7a6fb1c7c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/213_no_delete_on_storage_pointers.sol @@ -0,0 +1,9 @@ +contract C { + uint[] data; + function f() public { + uint[] storage x = data; + delete x; + } +} +// ---- +// TypeError: (97-105): Unary operator delete cannot be applied to type uint256[] storage pointer diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/214_assignment_mem_storage_variable_directly.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/214_assignment_mem_storage_variable_directly.sol new file mode 100644 index 000000000..801eb2754 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/214_assignment_mem_storage_variable_directly.sol @@ -0,0 +1,6 @@ +contract C { + uint[] data; + function f(uint[] memory x) public { + data = x; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/215_function_argument_mem_to_storage.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/215_function_argument_mem_to_storage.sol new file mode 100644 index 000000000..984b81b14 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/215_function_argument_mem_to_storage.sol @@ -0,0 +1,9 @@ +contract C { + function f(uint[] storage x) private { + } + function g(uint[] memory x) public { + f(x); + } +} +// ---- +// TypeError: (113-114): Invalid type for argument in function call. Invalid implicit conversion from uint256[] memory to uint256[] storage pointer requested. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/216_function_argument_storage_to_mem.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/216_function_argument_storage_to_mem.sol new file mode 100644 index 000000000..c5175a410 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/216_function_argument_storage_to_mem.sol @@ -0,0 +1,10 @@ +contract C { + function f(uint[] storage x) private { + g(x); + } + function g(uint[] memory x) public { + } +} +// ---- +// Warning: (91-106): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (80-122): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/217_mem_array_assignment_changes_base_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/217_mem_array_assignment_changes_base_type.sol new file mode 100644 index 000000000..3755b9352 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/217_mem_array_assignment_changes_base_type.sol @@ -0,0 +1,10 @@ +contract C { + function f(uint8[] memory x) private { + // Such an assignment is possible in storage, but not in memory + // (because it would incur an otherwise unnecessary copy). + // This requirement might be lifted, though. + uint[] memory y = x; + } +} +// ---- +// TypeError: (256-275): Type uint8[] memory is not implicitly convertible to expected type uint256[] memory. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/219_memory_arrays_not_resizeable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/219_memory_arrays_not_resizeable.sol new file mode 100644 index 000000000..93d8cd429 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/219_memory_arrays_not_resizeable.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + uint[] memory x; + x.length = 2; + } +} +// ---- +// TypeError: (72-80): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/220_struct_constructor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/220_struct_constructor.sol new file mode 100644 index 000000000..50585c110 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/220_struct_constructor.sol @@ -0,0 +1,9 @@ +contract C { + struct S { uint a; bool x; } + function f() public { + S memory s = S(1, true); + } +} +// ---- +// Warning: (80-90): Unused local variable. +// Warning: (50-110): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/221_struct_constructor_nested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/221_struct_constructor_nested.sol new file mode 100644 index 000000000..002226825 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/221_struct_constructor_nested.sol @@ -0,0 +1,11 @@ +contract C { + struct X { uint x1; uint x2; } + struct S { uint s1; uint[3] s2; X s3; } + function f() public { + uint[3] memory s2; + S memory s = S(1, s2, X(4, 5)); + } +} +// ---- +// Warning: (153-163): Unused local variable. +// Warning: (96-190): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/222_struct_named_constructor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/222_struct_named_constructor.sol new file mode 100644 index 000000000..8ab8ee460 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/222_struct_named_constructor.sol @@ -0,0 +1,9 @@ +contract C { + struct S { uint a; bool x; } + function f() public { + S memory s = S({a: 1, x: true}); + } +} +// ---- +// Warning: (80-90): Unused local variable. +// Warning: (50-118): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/223_literal_strings.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/223_literal_strings.sol new file mode 100644 index 000000000..1dadcc4d6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/223_literal_strings.sol @@ -0,0 +1,9 @@ +contract Foo { + function f() public { + string memory long = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; + string memory short = "123"; + long; short; + } +} +// ---- +// Warning: (19-238): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/224_string_bytes_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/224_string_bytes_conversion.sol new file mode 100644 index 000000000..ed6a9b374 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/224_string_bytes_conversion.sol @@ -0,0 +1,11 @@ +contract Test { + string s; + bytes b; + function h(string calldata _s) pure external { bytes(_s).length; } + function i(string memory _s) pure internal { bytes(_s).length; } + function j() view internal { bytes(s).length; } + function k(bytes calldata _b) pure external { string(_b); } + function l(bytes memory _b) pure internal { string(_b); } + function m() view internal { string(b); } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/225_inheriting_from_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/225_inheriting_from_library.sol new file mode 100644 index 000000000..eff7bf866 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/225_inheriting_from_library.sol @@ -0,0 +1,4 @@ +library Lib {} +contract Test is Lib {} +// ---- +// TypeError: (32-35): Libraries cannot be inherited from. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/226_inheriting_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/226_inheriting_library.sol new file mode 100644 index 000000000..2d601c1cc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/226_inheriting_library.sol @@ -0,0 +1,4 @@ +contract Test {} +library Lib is Test {} +// ---- +// TypeError: (17-39): Library is not allowed to inherit. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/227_library_having_variables.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/227_library_having_variables.sol new file mode 100644 index 000000000..804ef3d38 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/227_library_having_variables.sol @@ -0,0 +1,3 @@ +library Lib { uint x; } +// ---- +// TypeError: (14-20): Library cannot have non-constant state variables diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/228_valid_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/228_valid_library.sol new file mode 100644 index 000000000..de6b0b3e9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/228_valid_library.sol @@ -0,0 +1 @@ +library Lib { uint constant x = 9; } diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/229_call_to_library_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/229_call_to_library_function.sol new file mode 100644 index 000000000..c007d9a15 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/229_call_to_library_function.sol @@ -0,0 +1,10 @@ +library Lib { + function min(uint, uint) public returns (uint); +} +contract Test { + function f() public { + uint t = Lib.min(12, 7); + } +} +// ---- +// Warning: (118-124): Unused local variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/230_creating_contract_within_the_contract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/230_creating_contract_within_the_contract.sol new file mode 100644 index 000000000..8624b0b05 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/230_creating_contract_within_the_contract.sol @@ -0,0 +1,5 @@ +contract Test { + function f() public { Test x = new Test(); } +} +// ---- +// TypeError: (51-59): Circular reference for contract creation (cannot create instance of derived or same contract). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/231_array_out_of_bound_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/231_array_out_of_bound_access.sol new file mode 100644 index 000000000..7230a0a63 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/231_array_out_of_bound_access.sol @@ -0,0 +1,9 @@ +contract c { + uint[2] dataArray; + function set5th() public returns (bool) { + dataArray[5] = 2; + return true; + } +} +// ---- +// TypeError: (90-102): Out of bounds array access. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/232_literal_string_to_storage_pointer.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/232_literal_string_to_storage_pointer.sol new file mode 100644 index 000000000..be57144ee --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/232_literal_string_to_storage_pointer.sol @@ -0,0 +1,5 @@ +contract C { + function f() public { string storage x = "abc"; } +} +// ---- +// TypeError: (39-63): Type literal_string "abc" is not implicitly convertible to expected type string storage pointer. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/233_non_initialized_references.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/233_non_initialized_references.sol new file mode 100644 index 000000000..a0b6f71e7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/233_non_initialized_references.sol @@ -0,0 +1,11 @@ +contract C { + struct s { + uint a; + } + function f() public { + s storage x; + x.a = 2; + } +} +// ---- +// DeclarationError: (84-95): Uninitialized storage pointer. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/235_abi_encode_with_large_integer_constant.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/235_abi_encode_with_large_integer_constant.sol new file mode 100644 index 000000000..fd9717f1a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/235_abi_encode_with_large_integer_constant.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public { abi.encode(2**500); } +} +// ---- +// TypeError: (55-61): Invalid rational number (too large or division by zero). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/236_cyclic_binary_dependency.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/236_cyclic_binary_dependency.sol new file mode 100644 index 000000000..c287507d7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/236_cyclic_binary_dependency.sol @@ -0,0 +1,5 @@ +contract A { function f() public { new B(); } } +contract B { function f() public { new C(); } } +contract C { function f() public { new A(); } } +// ---- +// TypeError: (131-136): Circular reference for contract creation (cannot create instance of derived or same contract). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/237_cyclic_binary_dependency_via_inheritance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/237_cyclic_binary_dependency_via_inheritance.sol new file mode 100644 index 000000000..00ee536ec --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/237_cyclic_binary_dependency_via_inheritance.sol @@ -0,0 +1,5 @@ +contract A is B { } +contract B { function f() public { new C(); } } +contract C { function f() public { new A(); } } +// ---- +// TypeError: (14-15): Definition of base has to precede definition of derived contract diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/244_tuples.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/244_tuples.sol new file mode 100644 index 000000000..d18c115d6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/244_tuples.sol @@ -0,0 +1,10 @@ +contract C { + function f() public pure { + uint a = (1); + (uint b,) = (uint8(1),2); + (uint c, uint d) = (uint32(1), 2 + a); + (uint e, ,) = (uint64(1), 2, b); + a;b;c;d;e; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/245_tuples_empty_components.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/245_tuples_empty_components.sol new file mode 100644 index 000000000..7815edea4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/245_tuples_empty_components.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + (1,,2); + } +} +// ---- +// TypeError: (47-53): Tuple component cannot be empty. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/249_tuple_compound_assignment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/249_tuple_compound_assignment.sol new file mode 100644 index 000000000..bcdbde02c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/249_tuple_compound_assignment.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (uint a, uint b) { + (a, b) += (1, 1); + } +} +// ---- +// TypeError: (72-88): Compound assignment is not allowed for tuple types. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/250_member_access_parser_ambiguity.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/250_member_access_parser_ambiguity.sol new file mode 100644 index 000000000..0ab3c1984 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/250_member_access_parser_ambiguity.sol @@ -0,0 +1,16 @@ +contract C { + struct R { uint[10][10] y; } + struct S { uint a; uint b; uint[20][20][20] c; R d; } + S data; + function f() public { + C.S storage x = data; + C.S memory y; + C.S[10] memory z; + C.S[10]; + y.a = 2; + x.c[1][2][3] = 9; + x.d.y[2][2] = 3; + z; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/251_using_for_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/251_using_for_library.sol new file mode 100644 index 000000000..c7dcdbcd7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/251_using_for_library.sol @@ -0,0 +1,4 @@ +library D { } +contract C { + using D for uint; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/252_using_for_not_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/252_using_for_not_library.sol new file mode 100644 index 000000000..4693b27f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/252_using_for_not_library.sol @@ -0,0 +1,6 @@ +contract D { } +contract C { + using D for uint; +} +// ---- +// TypeError: (38-39): Library name expected. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/253_using_for_function_exists.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/253_using_for_function_exists.sol new file mode 100644 index 000000000..9e570805f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/253_using_for_function_exists.sol @@ -0,0 +1,10 @@ +library D { function double(uint self) public returns (uint) { return 2*self; } } +contract C { + using D for uint; + function f(uint a) public { + a.double; + } +} +// ---- +// Warning: (12-79): Function state mutability can be restricted to pure +// Warning: (121-172): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/254_using_for_function_on_int.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/254_using_for_function_on_int.sol new file mode 100644 index 000000000..a8e23d0fa --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/254_using_for_function_on_int.sol @@ -0,0 +1,9 @@ +library D { function double(uint self) public returns (uint) { return 2*self; } } +contract C { + using D for uint; + function f(uint a) public returns (uint) { + return a.double(); + } +} +// ---- +// Warning: (12-79): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/255_using_for_function_on_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/255_using_for_function_on_struct.sol new file mode 100644 index 000000000..2c3deb4cd --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/255_using_for_function_on_struct.sol @@ -0,0 +1,8 @@ +library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } +contract C { + using D for D.s; + D.s x; + function f(uint a) public returns (uint) { + return x.mul(a); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/256_using_for_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/256_using_for_overload.sol new file mode 100644 index 000000000..155281f52 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/256_using_for_overload.sol @@ -0,0 +1,14 @@ +library D { + struct s { uint a; } + function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } + function mul(s storage, bytes32) public returns (bytes32) { } +} +contract C { + using D for D.s; + D.s x; + function f(uint a) public returns (uint) { + return x.mul(a); + } +} +// ---- +// Warning: (128-189): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/257_using_for_by_name.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/257_using_for_by_name.sol new file mode 100644 index 000000000..b3eab987f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/257_using_for_by_name.sol @@ -0,0 +1,8 @@ +library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } +contract C { + using D for D.s; + D.s x; + function f(uint a) public returns (uint) { + return x.mul({x: a}); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/258_using_for_mismatch.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/258_using_for_mismatch.sol new file mode 100644 index 000000000..c60ee651e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/258_using_for_mismatch.sol @@ -0,0 +1,9 @@ +library D { function double(bytes32 self) public returns (uint) { return 2; } } +contract C { + using D for uint; + function f(uint a) public returns (uint) { + return a.double(); + } +} +// ---- +// TypeError: (177-185): Member "double" not found or not visible after argument-dependent lookup in uint256. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/259_using_for_not_used.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/259_using_for_not_used.sol new file mode 100644 index 000000000..b11cefbab --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/259_using_for_not_used.sol @@ -0,0 +1,11 @@ +library D { function double(uint self) public returns (uint) { return 2; } } +contract C { + using D for uint; + function f(uint16 a) public returns (uint) { + // This is an error because the function is only bound to uint. + // Had it been bound to *, it would have worked. + return a.double(); + } +} +// ---- +// TypeError: (305-313): Member "double" not found or not visible after argument-dependent lookup in uint16. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/260_library_memory_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/260_library_memory_struct.sol new file mode 100644 index 000000000..20d8afa56 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/260_library_memory_struct.sol @@ -0,0 +1,8 @@ +pragma experimental ABIEncoderV2; +library c { + struct S { uint x; } + function f() public returns (S memory) {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// Warning: (75-116): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/261_using_for_arbitrary_mismatch.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/261_using_for_arbitrary_mismatch.sol new file mode 100644 index 000000000..b2b553507 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/261_using_for_arbitrary_mismatch.sol @@ -0,0 +1,10 @@ +library D { function double(bytes32 self) public returns (uint) { return 2; } } +contract C { + using D for *; + function f(uint a) public returns (uint) { + // Bound to a, but self type does not match. + return a.double(); + } +} +// ---- +// TypeError: (227-235): Member "double" not found or not visible after argument-dependent lookup in uint256. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/262_bound_function_in_var.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/262_bound_function_in_var.sol new file mode 100644 index 000000000..c3cc5232d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/262_bound_function_in_var.sol @@ -0,0 +1,13 @@ +library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } +contract C { + using D for D.s; + D.s x; + function f(uint a) public returns (uint) { + function (D.s storage, uint) returns (uint) g = x.mul; + g(x, a); + g(a); + } +} +// ---- +// TypeError: (218-271): Type function (struct D.s storage pointer,uint256) returns (uint256) is not implicitly convertible to expected type function (struct D.s storage pointer,uint256) returns (uint256). +// TypeError: (298-302): Wrong argument count for function call: 1 arguments given but expected 2. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/263_create_memory_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/263_create_memory_arrays.sol new file mode 100644 index 000000000..71f43992b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/263_create_memory_arrays.sol @@ -0,0 +1,14 @@ +library L { + struct R { uint[10][10] y; } + struct S { uint a; uint b; uint[20][20][20] c; R d; } +} +contract C { + function f(uint size) public { + L.S[][] memory x = new L.S[][](10); + uint[] memory y = new uint[](20); + bytes memory z = new bytes(size); + x;y;z; + } +} +// ---- +// Warning: (122-301): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/264_mapping_in_memory_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/264_mapping_in_memory_array.sol new file mode 100644 index 000000000..e45e09de8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/264_mapping_in_memory_array.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint size) public { + mapping(uint => uint) storage x = new mapping(uint => uint)[](4); + } +} +// ---- +// TypeError: (94-117): Type cannot live outside storage. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/265_new_for_non_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/265_new_for_non_array.sol new file mode 100644 index 000000000..c4b2c692e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/265_new_for_non_array.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint size) public { + uint x = new uint(7); + } +} +// ---- +// TypeError: (65-73): Contract or array type expected. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/266_invalid_args_creating_memory_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/266_invalid_args_creating_memory_array.sol new file mode 100644 index 000000000..078255e30 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/266_invalid_args_creating_memory_array.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint size) public { + uint[] memory x = new uint[](); + } +} +// ---- +// TypeError: (74-86): Wrong argument count for function call: 0 arguments given but expected 1. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/267_invalid_args_creating_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/267_invalid_args_creating_struct.sol new file mode 100644 index 000000000..35671e6f1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/267_invalid_args_creating_struct.sol @@ -0,0 +1,9 @@ +contract C { + struct S { uint a; uint b; } + + function f() public { + S memory s = S({a: 1}); + } +} +// ---- +// TypeError: (94-103): Wrong argument count for struct constructor: 1 arguments given but expected 2. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/268_function_overload_array_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/268_function_overload_array_type.sol new file mode 100644 index 000000000..4fc9d46ee --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/268_function_overload_array_type.sol @@ -0,0 +1,4 @@ +contract M { + function f(uint[] memory) public; + function f(int[] memory) public; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/269_inline_array_declaration_and_passing_implicit_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/269_inline_array_declaration_and_passing_implicit_conversion.sol new file mode 100644 index 000000000..023404f72 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/269_inline_array_declaration_and_passing_implicit_conversion.sol @@ -0,0 +1,11 @@ + contract C { + function f() public returns (uint) { + uint8 x = 7; + uint16 y = 8; + uint32 z = 9; + uint32[3] memory ending = [x, y, z]; + return (ending[1]); + } + } +// ---- +// Warning: (25-229): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/270_inline_array_declaration_and_passing_implicit_conversion_strings.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/270_inline_array_declaration_and_passing_implicit_conversion_strings.sol new file mode 100644 index 000000000..025244d3c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/270_inline_array_declaration_and_passing_implicit_conversion_strings.sol @@ -0,0 +1,10 @@ +contract C { + function f() public returns (string memory) { + string memory x = "Hello"; + string memory y = "World"; + string[2] memory z = [x, y]; + return (z[0]); + } +} +// ---- +// Warning: (17-198): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/271_inline_array_declaration_const_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/271_inline_array_declaration_const_int_conversion.sol new file mode 100644 index 000000000..e7036bdf1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/271_inline_array_declaration_const_int_conversion.sol @@ -0,0 +1,8 @@ +contract C { + function f() public returns (uint) { + uint8[4] memory z = [1,2,3,5]; + return (z[0]); + } +} +// ---- +// Warning: (17-121): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/272_inline_array_declaration_const_string_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/272_inline_array_declaration_const_string_conversion.sol new file mode 100644 index 000000000..4e92f6e11 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/272_inline_array_declaration_const_string_conversion.sol @@ -0,0 +1,8 @@ +contract C { + function f() public returns (string memory) { + string[2] memory z = ["Hello", "World"]; + return (z[0]); + } +} +// ---- +// Warning: (17-140): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/273_inline_array_declaration_no_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/273_inline_array_declaration_no_type.sol new file mode 100644 index 000000000..4d3e6aed8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/273_inline_array_declaration_no_type.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (uint) { + return ([4,5,6][1]); + } +} +// ---- +// Warning: (17-88): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/274_inline_array_declaration_no_type_strings.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/274_inline_array_declaration_no_type_strings.sol new file mode 100644 index 000000000..6d36942da --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/274_inline_array_declaration_no_type_strings.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (string memory) { + return (["foo", "man", "choo"][1]); + } +} +// ---- +// Warning: (17-112): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/275_inline_struct_declaration_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/275_inline_struct_declaration_arrays.sol new file mode 100644 index 000000000..bdf033a30 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/275_inline_struct_declaration_arrays.sol @@ -0,0 +1,12 @@ +contract C { + struct S { + uint a; + string b; + } + function f() public { + S[2] memory x = [S({a: 1, b: "fish"}), S({a: 2, b: "fish"})]; + } +} +// ---- +// Warning: (102-115): Unused local variable. +// Warning: (72-169): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/276_invalid_types_in_inline_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/276_invalid_types_in_inline_array.sol new file mode 100644 index 000000000..03d7266a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/276_invalid_types_in_inline_array.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + uint[3] memory x = [45, 'foo', true]; + } +} +// ---- +// TypeError: (66-83): Unable to deduce common type for array elements. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/277_dynamic_inline_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/277_dynamic_inline_array.sol new file mode 100644 index 000000000..e613758b5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/277_dynamic_inline_array.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + uint8[4][4] memory dyn = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]; + } +} +// ---- +// Warning: (47-69): Unused local variable. +// Warning: (17-135): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/278_lvalues_as_inline_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/278_lvalues_as_inline_array.sol new file mode 100644 index 000000000..5a39f550c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/278_lvalues_as_inline_array.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + [1, 2, 3]++; + [1, 2, 3] = [4, 5, 6]; + } +} +// ---- +// TypeError: (47-56): Inline array type cannot be declared as LValue. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/279_break_not_in_loop.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/279_break_not_in_loop.sol new file mode 100644 index 000000000..6b88da443 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/279_break_not_in_loop.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + if (true) + break; + } +} +// ---- +// SyntaxError: (69-74): "break" has to be in a "for" or "while" loop. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/280_continue_not_in_loop.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/280_continue_not_in_loop.sol new file mode 100644 index 000000000..b0e8cda91 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/280_continue_not_in_loop.sol @@ -0,0 +1,8 @@ +contract C { + function f() public { + if (true) + continue; + } +} +// ---- +// SyntaxError: (69-77): "continue" has to be in a "for" or "while" loop. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/281_continue_not_in_loop_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/281_continue_not_in_loop_2.sol new file mode 100644 index 000000000..845faf867 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/281_continue_not_in_loop_2.sol @@ -0,0 +1,10 @@ +contract C { + function f() public { + while (true) + { + } + continue; + } +} +// ---- +// SyntaxError: (88-96): "continue" has to be in a "for" or "while" loop. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/282_invalid_different_types_for_conditional_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/282_invalid_different_types_for_conditional_expression.sol new file mode 100644 index 000000000..e4e75e3f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/282_invalid_different_types_for_conditional_expression.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + true ? true : 2; + } +} +// ---- +// TypeError: (47-62): True expression's type bool doesn't match false expression's type uint8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/283_left_value_in_conditional_expression_not_supported_yet.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/283_left_value_in_conditional_expression_not_supported_yet.sol new file mode 100644 index 000000000..ef8f99300 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/283_left_value_in_conditional_expression_not_supported_yet.sol @@ -0,0 +1,10 @@ +contract C { + function f() public { + uint x; + uint y; + (true ? x : y) = 1; + } +} +// ---- +// TypeError: (80-92): Conditional expression as left value is not supported yet. +// TypeError: (80-92): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/284_conditional_expression_with_different_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/284_conditional_expression_with_different_struct.sol new file mode 100644 index 000000000..049d9e21e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/284_conditional_expression_with_different_struct.sol @@ -0,0 +1,15 @@ +contract C { + struct s1 { + uint x; + } + struct s2 { + uint x; + } + function f() public { + s1 memory x; + s2 memory y; + true ? x : y; + } +} +// ---- +// TypeError: (165-177): True expression's type struct C.s1 memory doesn't match false expression's type struct C.s2 memory. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/285_conditional_expression_with_different_function_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/285_conditional_expression_with_different_function_type.sol new file mode 100644 index 000000000..963fb7da6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/285_conditional_expression_with_different_function_type.sol @@ -0,0 +1,10 @@ +contract C { + function x(bool) public {} + function y() public {} + + function f() public { + true ? x : y; + } +} +// ---- +// TypeError: (106-118): True expression's type function (bool) doesn't match false expression's type function (). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/286_conditional_expression_with_different_enum.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/286_conditional_expression_with_different_enum.sol new file mode 100644 index 000000000..8c3126243 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/286_conditional_expression_with_different_enum.sol @@ -0,0 +1,13 @@ +contract C { + enum small { A, B, C, D } + enum big { A, B, C, D } + + function f() public { + small x; + big y; + + true ? x : y; + } +} +// ---- +// TypeError: (139-151): True expression's type enum C.small doesn't match false expression's type enum C.big. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/287_conditional_expression_with_different_mapping.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/287_conditional_expression_with_different_mapping.sol new file mode 100644 index 000000000..8139f3ed9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/287_conditional_expression_with_different_mapping.sol @@ -0,0 +1,10 @@ +contract C { + mapping(uint8 => uint8) table1; + mapping(uint32 => uint8) table2; + + function f() public { + true ? table1 : table2; + } +} +// ---- +// TypeError: (121-143): True expression's type mapping(uint8 => uint8) doesn't match false expression's type mapping(uint32 => uint8). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/288_conditional_with_all_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/288_conditional_with_all_types.sol new file mode 100644 index 000000000..e9ab08bae --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/288_conditional_with_all_types.sol @@ -0,0 +1,91 @@ +contract C { + struct s1 { + uint x; + } + s1 struct_x; + s1 struct_y; + + function fun_x() public {} + function fun_y() public {} + + enum small { A, B, C, D } + + mapping(uint8 => uint8) table1; + mapping(uint8 => uint8) table2; + + function f() public { + // integers + uint x; + uint y; + uint g = true ? x : y; + g += 1; // Avoid unused var warning + + // integer constants + uint h = true ? 1 : 3; + h += 1; // Avoid unused var warning + + // string literal + string memory i = true ? "hello" : "world"; + i = "used"; //Avoid unused var warning + } + function f2() public { + // bool + bool j = true ? true : false; + j = j && true; // Avoid unused var warning + + // real is not there yet. + + // array + byte[2] memory a; + byte[2] memory b; + byte[2] memory k = true ? a : b; + k[0] = byte(0); //Avoid unused var warning + + bytes memory e; + bytes memory f; + bytes memory l = true ? e : f; + l[0] = byte(0); // Avoid unused var warning + + // fixed bytes + bytes2 c; + bytes2 d; + bytes2 m = true ? c : d; + m &= m; + + } + function f3() public { + // contract doesn't fit in here + + // struct + struct_x = true ? struct_x : struct_y; + + // function + function () r = true ? fun_x : fun_y; + r(); // Avoid unused var warning + // enum + small enum_x; + small enum_y; + enum_x = true ? enum_x : enum_y; + + // tuple + (uint n, uint o) = true ? (1, 2) : (3, 4); + (n, o) = (o, n); // Avoid unused var warning + // mapping + mapping(uint8 => uint8) storage p = true ? table1 : table2; + p[0] = 0; // Avoid unused var warning + // typetype + uint32 q = true ? uint32(1) : uint32(2); + q += 1; // Avoid unused var warning + // modifier doesn't fit in here + + // magic doesn't fit in here + + // module doesn't fit in here + } +} +// ---- +// Warning: (1005-1019): This declaration shadows an existing declaration. +// Warning: (90-116): Function state mutability can be restricted to pure +// Warning: (121-147): Function state mutability can be restricted to pure +// Warning: (257-642): Function state mutability can be restricted to pure +// Warning: (647-1227): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/289_uint7_and_uintM_as_identifier.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/289_uint7_and_uintM_as_identifier.sol new file mode 100644 index 000000000..58e84090e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/289_uint7_and_uintM_as_identifier.sol @@ -0,0 +1,12 @@ +contract test { +string uintM = "Hello 4 you"; + function f() public { + uint8 uint7 = 3; + uint7 = 5; + string memory intM; + uint bytesM = 21; + intM; bytesM; + } +} +// ---- +// Warning: (50-197): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_1.sol new file mode 100644 index 000000000..0d0a0797e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_1.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + uintM something = 3; + } +} +// ---- +// DeclarationError: (50-55): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_2.sol new file mode 100644 index 000000000..b9590a8c8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_2.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + intM should = 4; + } +} +// ---- +// DeclarationError: (50-54): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_3.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_3.sol new file mode 100644 index 000000000..85d4c25bf --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/290_varM_disqualified_as_keyword_3.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + bytesM fail = "now"; + } +} +// ---- +// DeclarationError: (50-56): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/291_modifier_is_not_a_valid_typename.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/291_modifier_is_not_a_valid_typename.sol new file mode 100644 index 000000000..2f3143d52 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/291_modifier_is_not_a_valid_typename.sol @@ -0,0 +1,9 @@ +contract test { + modifier mod() { _; } + + function f() public { + mod g; + } +} +// ---- +// TypeError: (77-80): Name has to refer to a struct, enum or contract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/292_modifier_is_not_a_valid_typename_is_not_fatal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/292_modifier_is_not_a_valid_typename_is_not_fatal.sol new file mode 100644 index 000000000..9187c19d9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/292_modifier_is_not_a_valid_typename_is_not_fatal.sol @@ -0,0 +1,10 @@ +contract test { + modifier mod() { _; } + + function f() public { + mod g; + g = f; + } +} +// ---- +// TypeError: (77-80): Name has to refer to a struct, enum or contract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/293_function_is_not_a_valid_typename.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/293_function_is_not_a_valid_typename.sol new file mode 100644 index 000000000..390eccd97 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/293_function_is_not_a_valid_typename.sol @@ -0,0 +1,10 @@ +contract test { + function foo() public { + } + + function f() public { + foo g; + } +} +// ---- +// TypeError: (85-88): Name has to refer to a struct, enum or contract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/294_long_uint_variable_fails.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/294_long_uint_variable_fails.sol new file mode 100644 index 000000000..1e6083205 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/294_long_uint_variable_fails.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + uint99999999999999999999999999 something = 3; + } +} +// ---- +// DeclarationError: (50-80): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/295_bytes10abc_is_identifier.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/295_bytes10abc_is_identifier.sol new file mode 100644 index 000000000..8b65fc652 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/295_bytes10abc_is_identifier.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + bytes32 bytes10abc = "abc"; + } +} +// ---- +// Warning: (50-68): Unused local variable. +// Warning: (20-83): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/296_int10abc_is_identifier.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/296_int10abc_is_identifier.sol new file mode 100644 index 000000000..2678cfb98 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/296_int10abc_is_identifier.sol @@ -0,0 +1,9 @@ +contract test { + function f() public { + uint uint10abc = 3; + int int10abc = 4; + uint10abc; int10abc; + } +} +// ---- +// Warning: (20-130): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/297_library_functions_do_not_have_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/297_library_functions_do_not_have_value.sol new file mode 100644 index 000000000..918544cc0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/297_library_functions_do_not_have_value.sol @@ -0,0 +1,8 @@ +library L { function l() public {} } +contract test { + function f() public { + L.l.value; + } +} +// ---- +// TypeError: (87-96): Member "value" not found or not visible after argument-dependent lookup in function () - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/298_invalid_fixed_types_0x7_mxn.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/298_invalid_fixed_types_0x7_mxn.sol new file mode 100644 index 000000000..ea9e5d0ff --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/298_invalid_fixed_types_0x7_mxn.sol @@ -0,0 +1,5 @@ +contract test { + fixed0x7 a = .3; +} +// ---- +// DeclarationError: (20-28): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/299_invalid_fixed_types_long_invalid_identifier.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/299_invalid_fixed_types_long_invalid_identifier.sol new file mode 100644 index 000000000..9ce2b1067 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/299_invalid_fixed_types_long_invalid_identifier.sol @@ -0,0 +1,5 @@ +contract test { + fixed99999999999999999999999999999999999999x7 b = 9.5; +} +// ---- +// DeclarationError: (20-65): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/300_invalid_fixed_types_7x8_mxn.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/300_invalid_fixed_types_7x8_mxn.sol new file mode 100644 index 000000000..7c511d2fd --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/300_invalid_fixed_types_7x8_mxn.sol @@ -0,0 +1,5 @@ +contract test { + fixed7x8 c = 3.12345678; +} +// ---- +// DeclarationError: (20-28): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/301_library_instances_cannot_be_used.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/301_library_instances_cannot_be_used.sol new file mode 100644 index 000000000..dcf11a6e3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/301_library_instances_cannot_be_used.sol @@ -0,0 +1,9 @@ +library L { function l() public {} } +contract test { + function f() public { + L x; + x.l(); + } +} +// ---- +// TypeError: (100-103): Member "l" not found or not visible after argument-dependent lookup in library L. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/302_invalid_fixed_type_long.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/302_invalid_fixed_type_long.sol new file mode 100644 index 000000000..126796314 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/302_invalid_fixed_type_long.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + fixed8x888888888888888888888888888888888888888888888888888 b; + } +} +// ---- +// DeclarationError: (50-108): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol new file mode 100644 index 000000000..ddf1e5fb0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol @@ -0,0 +1,11 @@ +contract test { + function f() public { + uint64 a = 3; + int64 b = 4; + fixed c = b; + ufixed d = a; + c; d; + } +} +// ---- +// Warning: (20-147): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol new file mode 100644 index 000000000..16d2cbad2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol @@ -0,0 +1,9 @@ +contract test { + function f() public { + fixed c = 3; + ufixed d = 4; + c; d; + } +} +// ---- +// Warning: (20-104): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol new file mode 100644 index 000000000..270298601 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol @@ -0,0 +1,9 @@ +contract test { + function f() public { + fixed a = 4.5; + ufixed d = 2.5; + a; d; + } +} +// ---- +// Warning: (20-108): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/306_invalid_int_implicit_conversion_from_fixed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/306_invalid_int_implicit_conversion_from_fixed.sol new file mode 100644 index 000000000..c0a56314a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/306_invalid_int_implicit_conversion_from_fixed.sol @@ -0,0 +1,9 @@ +contract test { + function f() public { + fixed a = 4.5; + int b = a; + a; b; + } +} +// ---- +// TypeError: (73-82): Type fixed128x18 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol new file mode 100644 index 000000000..7827e57bf --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol @@ -0,0 +1,7 @@ +contract test { + function f() pure public { + ufixed16x2 a = 3.25; + fixed16x2 b = -3.25; + a; b; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/308_rational_unary_plus_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/308_rational_unary_plus_operation.sol new file mode 100644 index 000000000..f635a214d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/308_rational_unary_plus_operation.sol @@ -0,0 +1,9 @@ +contract test { + function f() pure public { + ufixed16x2 a = +3.25; + fixed16x2 b = -3.25; + a; b; + } +} +// ---- +// SyntaxError: (70-75): Use of unary + is disallowed. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol new file mode 100644 index 000000000..9fe7c6f7e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol @@ -0,0 +1,9 @@ +contract A { + function f() pure public { + ufixed16x2 a = 0.5; + ufixed256x52 b = 0.0000000000000006661338147750939242541790008544921875; + fixed16x2 c = -0.5; + fixed256x52 d = -0.0000000000000006661338147750939242541790008544921875; + a; b; c; d; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol new file mode 100644 index 000000000..441cf81e6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol @@ -0,0 +1,13 @@ +contract test { + function f() public { + ufixed256x1 a = 123456781234567979695948382928485849359686494864095409282048094275023098123.5; + ufixed256x77 b = 0.920890746623327805482905058466021565416131529487595827354393978494366605267637; + ufixed224x78 c = 0.000000000001519884736399797998492268541131529487595827354393978494366605267646; + fixed256x1 d = -123456781234567979695948382928485849359686494864095409282048094275023098123.5; + fixed256x76 e = -0.93322335481643744342575580035176794825198893968114429702091846411734101080123; + fixed256x79 g = -0.0001178860664374434257558003517679482519889396811442970209184641173410108012309; + a; b; c; d; e; g; + } +} +// ---- +// Warning: (20-707): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol new file mode 100644 index 000000000..5f0d2909f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + fixed16x2 a = 0; a; + ufixed32x1 b = 0; b; + } +} +// ---- +// Warning: (20-104): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/315_fixed_type_invalid_implicit_conversion_size.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/315_fixed_type_invalid_implicit_conversion_size.sol new file mode 100644 index 000000000..796982286 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/315_fixed_type_invalid_implicit_conversion_size.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + ufixed a = 11/4; + ufixed248x8 b = a; b; + } +} +// ---- +// TypeError: (75-92): Type ufixed128x18 is not implicitly convertible to expected type ufixed248x8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/316_fixed_type_invalid_implicit_conversion_lost_data.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/316_fixed_type_invalid_implicit_conversion_lost_data.sol new file mode 100644 index 000000000..76c0284ed --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/316_fixed_type_invalid_implicit_conversion_lost_data.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + ufixed256x1 a = 1/3; a; + } +} +// ---- +// TypeError: (50-69): Type rational_const 1 / 3 is not implicitly convertible to expected type ufixed256x1. Try converting to type ufixed256x77 or use an explicit conversion. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol new file mode 100644 index 000000000..388014579 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol @@ -0,0 +1,9 @@ +contract test { + function f() public { + ufixed256x80 a = ufixed256x80(1/3); a; + ufixed248x80 b = ufixed248x80(1/3); b; + ufixed8x1 c = ufixed8x1(1/3); c; + } +} +// ---- +// Warning: (20-182): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/318_invalid_array_declaration_with_rational.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/318_invalid_array_declaration_with_rational.sol new file mode 100644 index 000000000..3dd779ec3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/318_invalid_array_declaration_with_rational.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + uint[3.5] a; a; + } +} +// ---- +// TypeError: (55-58): Array with fractional length specified. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/319_invalid_array_declaration_with_signed_fixed_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/319_invalid_array_declaration_with_signed_fixed_type.sol new file mode 100644 index 000000000..83f0950db --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/319_invalid_array_declaration_with_signed_fixed_type.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + uint[fixed(3.5)] a; a; + } +} +// ---- +// TypeError: (55-65): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/320_invalid_array_declaration_with_unsigned_fixed_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/320_invalid_array_declaration_with_unsigned_fixed_type.sol new file mode 100644 index 000000000..26d5a85e9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/320_invalid_array_declaration_with_unsigned_fixed_type.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + uint[ufixed(3.5)] a; a; + } +} +// ---- +// TypeError: (55-66): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/321_rational_to_bytes_implicit_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/321_rational_to_bytes_implicit_conversion.sol new file mode 100644 index 000000000..d209eb76a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/321_rational_to_bytes_implicit_conversion.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + bytes32 c = 3.2; c; + } +} +// ---- +// TypeError: (50-65): Type rational_const 16 / 5 is not implicitly convertible to expected type bytes32. Try converting to type ufixed8x1 or use an explicit conversion. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/322_fixed_to_bytes_implicit_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/322_fixed_to_bytes_implicit_conversion.sol new file mode 100644 index 000000000..867364812 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/322_fixed_to_bytes_implicit_conversion.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + fixed a = 3.25; + bytes32 c = a; c; + } +} +// ---- +// TypeError: (74-87): Type fixed128x18 is not implicitly convertible to expected type bytes32. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol new file mode 100644 index 000000000..8e28d4e1f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol @@ -0,0 +1,6 @@ +contract test { + mapping(ufixed8x1 => string) fixedString; + function f() public { + fixedString[0.5] = "Half"; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol new file mode 100644 index 000000000..8aa0abc2b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol @@ -0,0 +1,7 @@ +contract test { + struct myStruct { + ufixed a; + int b; + } + myStruct a = myStruct(3.125, 3); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/325_inline_array_fixed_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/325_inline_array_fixed_types.sol new file mode 100644 index 000000000..c46297c3f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/325_inline_array_fixed_types.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + fixed[3] memory a = [fixed(3.5), fixed(-4.25), fixed(967.125)]; + } +} +// ---- +// Warning: (50-67): Unused local variable. +// Warning: (20-119): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/326_inline_array_rationals.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/326_inline_array_rationals.sol new file mode 100644 index 000000000..bdc3c2c14 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/326_inline_array_rationals.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + ufixed128x3[4] memory a = [ufixed128x3(3.5), 4.125, 2.5, 4.0]; + } +} +// ---- +// Warning: (50-73): Unused local variable. +// Warning: (20-118): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/327_rational_index_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/327_rational_index_access.sol new file mode 100644 index 000000000..46e585212 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/327_rational_index_access.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + uint[] memory a; + a[.5]; + } +} +// ---- +// TypeError: (77-79): Type rational_const 1 / 2 is not implicitly convertible to expected type uint256. Try converting to type ufixed8x1 or use an explicit conversion. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol new file mode 100644 index 000000000..35456fa6f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol @@ -0,0 +1,15 @@ +contract test { + function f() public { + ufixed64x8 a = 3.5 * 3; + ufixed64x8 b = 4 - 2.5; + ufixed64x8 c = 11 / 4; + ufixed240x5 d = 599 + 0.21875; + ufixed256x80 e = ufixed256x80(35.245 % 12.9); + ufixed256x80 f = ufixed256x80(1.2 % 2); + fixed g = 2 ** -2; + a; b; c; d; e; f; g; + } +} +// ---- +// Warning: (238-252): This declaration shadows an existing declaration. +// Warning: (20-339): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/329_rational_as_exponent_value_signed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/329_rational_as_exponent_value_signed.sol new file mode 100644 index 000000000..b835e3093 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/329_rational_as_exponent_value_signed.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + fixed g = 2 ** -2.2; + } +} +// ---- +// TypeError: (60-69): Operator ** not compatible with types int_const 2 and rational_const -11 / 5 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/330_rational_as_exponent_value_unsigned.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/330_rational_as_exponent_value_unsigned.sol new file mode 100644 index 000000000..04ddf0fd8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/330_rational_as_exponent_value_unsigned.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + ufixed b = 3 ** 2.5; + } +} +// ---- +// TypeError: (61-69): Operator ** not compatible with types int_const 3 and rational_const 5 / 2 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/331_rational_as_exponent_half.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/331_rational_as_exponent_half.sol new file mode 100644 index 000000000..4e0894c55 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/331_rational_as_exponent_half.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + 2 ** (1/2); + } +} +// ---- +// TypeError: (50-60): Operator ** not compatible with types int_const 2 and rational_const 1 / 2 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/332_rational_as_exponent_value_neg_quarter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/332_rational_as_exponent_value_neg_quarter.sol new file mode 100644 index 000000000..bc127bf51 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/332_rational_as_exponent_value_neg_quarter.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + 42 ** (-1/4); + } +} +// ---- +// TypeError: (50-62): Operator ** not compatible with types int_const 42 and rational_const -1 / 4 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/333_fixed_point_casting_exponents_15.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/333_fixed_point_casting_exponents_15.sol new file mode 100644 index 000000000..0fd5f331f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/333_fixed_point_casting_exponents_15.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + ufixed a = 3 ** ufixed(1.5); + } +} +// ---- +// TypeError: (61-77): Operator ** not compatible with types int_const 3 and ufixed128x18 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/334_fixed_point_casting_exponents_neg.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/334_fixed_point_casting_exponents_neg.sol new file mode 100644 index 000000000..03d10f7c0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/334_fixed_point_casting_exponents_neg.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + ufixed c = 42 ** fixed(-1/4); + } +} +// ---- +// TypeError: (61-78): Operator ** not compatible with types int_const 42 and fixed128x18 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/338_rational_bitnot_unary_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/338_rational_bitnot_unary_operation.sol new file mode 100644 index 000000000..44a6ab5e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/338_rational_bitnot_unary_operation.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + ~fixed(3.5); + } +} +// ---- +// TypeError: (50-61): Unary operator ~ cannot be applied to type fixed128x18 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/339_rational_bitor_binary_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/339_rational_bitor_binary_operation.sol new file mode 100644 index 000000000..29871b04c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/339_rational_bitor_binary_operation.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + fixed(1.5) | 3; + } +} +// ---- +// TypeError: (50-64): Operator | not compatible with types fixed128x18 and int_const 3 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/340_rational_bitxor_binary_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/340_rational_bitxor_binary_operation.sol new file mode 100644 index 000000000..1fa7f38f8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/340_rational_bitxor_binary_operation.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + fixed(1.75) ^ 3; + } +} +// ---- +// TypeError: (50-65): Operator ^ not compatible with types fixed128x18 and int_const 3 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/341_rational_bitand_binary_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/341_rational_bitand_binary_operation.sol new file mode 100644 index 000000000..5a433a614 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/341_rational_bitand_binary_operation.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + fixed(1.75) & 3; + } +} +// ---- +// TypeError: (50-65): Operator & not compatible with types fixed128x18 and int_const 3 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/342_missing_bool_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/342_missing_bool_conversion.sol new file mode 100644 index 000000000..5546a099a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/342_missing_bool_conversion.sol @@ -0,0 +1,7 @@ +contract test { + function b(uint a) public { + bool(a == 1); + } +} +// ---- +// Warning: (20-75): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol new file mode 100644 index 000000000..af4d048bb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol @@ -0,0 +1,8 @@ +contract test { + function f() public { + ufixed a = uint64(1) + ufixed(2); + } +} +// ---- +// Warning: (50-58): Unused local variable. +// Warning: (20-89): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/344_one_divided_by_three_integer_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/344_one_divided_by_three_integer_conversion.sol new file mode 100644 index 000000000..ffc168eb1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/344_one_divided_by_three_integer_conversion.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + uint a = 1/3; + } +} +// ---- +// TypeError: (50-62): Type rational_const 1 / 3 is not implicitly convertible to expected type uint256. Try converting to type ufixed256x77 or use an explicit conversion. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/345_unused_return_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/345_unused_return_value.sol new file mode 100644 index 000000000..7f6405056 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/345_unused_return_value.sol @@ -0,0 +1,8 @@ +contract test { + function g() public returns (uint) {} + function f() public { + g(); + } +} +// ---- +// Warning: (20-57): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol new file mode 100644 index 000000000..929e54b20 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + address(0x12).send(1); + } +} +// ---- +// Warning: (50-71): Failure condition of 'send' ignored. Consider using 'transfer' instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/347_unused_return_value_call.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/347_unused_return_value_call.sol new file mode 100644 index 000000000..994a5bdf6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/347_unused_return_value_call.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + address(0x12).call("abc"); + } +} +// ---- +// Warning: (50-75): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/348_unused_return_value_call_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/348_unused_return_value_call_value.sol new file mode 100644 index 000000000..1ac7c6f33 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/348_unused_return_value_call_value.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + address(0x12).call.value(2)("abc"); + } +} +// ---- +// Warning: (50-84): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/350_unused_return_value_delegatecall.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/350_unused_return_value_delegatecall.sol new file mode 100644 index 000000000..701b6e7db --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/350_unused_return_value_delegatecall.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + address(0x12).delegatecall("abc"); + } +} +// ---- +// Warning: (50-83): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/351_callcode_deprecated.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/351_callcode_deprecated.sol new file mode 100644 index 000000000..554f2e11e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/351_callcode_deprecated.sol @@ -0,0 +1,7 @@ +contract test { + function f() pure public { + address(0x12).callcode; + } +} +// ---- +// TypeError: (55-77): "callcode" has been deprecated in favour of "delegatecall". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/353_callcode_not_deprecated_as_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/353_callcode_not_deprecated_as_function.sol new file mode 100644 index 000000000..714014f82 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/353_callcode_not_deprecated_as_function.sol @@ -0,0 +1,5 @@ +contract test { + function callcode() pure public { + test.callcode(); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/354_payable_in_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/354_payable_in_library.sol new file mode 100644 index 000000000..410842cbc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/354_payable_in_library.sol @@ -0,0 +1,5 @@ +library test { + function f() payable public {} +} +// ---- +// TypeError: (19-49): Library functions cannot be payable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/355_payable_external.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/355_payable_external.sol new file mode 100644 index 000000000..3b75e1b75 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/355_payable_external.sol @@ -0,0 +1,3 @@ +contract test { + function f() payable external {} +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/356_payable_internal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/356_payable_internal.sol new file mode 100644 index 000000000..f6ccf6b66 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/356_payable_internal.sol @@ -0,0 +1,5 @@ +contract test { + function f() payable internal {} +} +// ---- +// TypeError: (20-52): Internal functions cannot be payable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/357_payable_private.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/357_payable_private.sol new file mode 100644 index 000000000..7b00ea6c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/357_payable_private.sol @@ -0,0 +1,5 @@ +contract test { + function f() payable private {} +} +// ---- +// TypeError: (20-51): Internal functions cannot be payable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/358_illegal_override_payable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/358_illegal_override_payable.sol new file mode 100644 index 000000000..6696772e8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/358_illegal_override_payable.sol @@ -0,0 +1,4 @@ +contract B { function f() payable public {} } +contract C is B { function f() public {} } +// ---- +// TypeError: (64-86): Overriding function changes state mutability from "payable" to "nonpayable". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/359_illegal_override_payable_nonpayable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/359_illegal_override_payable_nonpayable.sol new file mode 100644 index 000000000..99b45fdda --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/359_illegal_override_payable_nonpayable.sol @@ -0,0 +1,4 @@ +contract B { function f() public {} } +contract C is B { function f() payable public {} } +// ---- +// TypeError: (56-86): Overriding function changes state mutability from "nonpayable" to "payable". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/360_function_variable_mixin.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/360_function_variable_mixin.sol new file mode 100644 index 000000000..583e0d46e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/360_function_variable_mixin.sol @@ -0,0 +1,12 @@ +// bug #1798 (cpp-ethereum), related to #1286 (solidity) +contract attribute { + bool ok = false; +} +contract func { + function ok() public returns (bool) { return true; } +} +contract attr_func is attribute, func { + function checkOk() public returns (bool) { return ok(); } +} +// ---- +// DeclarationError: (121-173): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/361_calling_payable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/361_calling_payable.sol new file mode 100644 index 000000000..8ef4d5799 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/361_calling_payable.sol @@ -0,0 +1,6 @@ +contract receiver { function pay() payable public {} } +contract test { + function f() public { (new receiver()).pay.value(10)(); } + receiver r = new receiver(); + function g() public { r.pay.value(10)(); } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/362_calling_nonpayable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/362_calling_nonpayable.sol new file mode 100644 index 000000000..d47ea2bd5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/362_calling_nonpayable.sol @@ -0,0 +1,6 @@ +contract receiver { function nopay() public {} } +contract test { + function f() public { (new receiver()).nopay.value(10)(); } +} +// ---- +// TypeError: (91-119): Member "value" not found or not visible after argument-dependent lookup in function () external - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/363_non_payable_constructor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/363_non_payable_constructor.sol new file mode 100644 index 000000000..273819047 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/363_non_payable_constructor.sol @@ -0,0 +1,11 @@ +contract C { + constructor() public { } +} +contract D { + function f() public returns (uint) { + (new C).value(2)(); + return 2; + } +} +// ---- +// TypeError: (106-119): Member "value" not found or not visible after argument-dependent lookup in function () returns (contract C) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/366_invalid_array_as_statement.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/366_invalid_array_as_statement.sol new file mode 100644 index 000000000..cc2839cd2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/366_invalid_array_as_statement.sol @@ -0,0 +1,6 @@ +contract test { + struct S { uint x; } + constructor(uint k) public { S[k]; } +} +// ---- +// TypeError: (76-77): Integer constant expected. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/367_using_directive_for_missing_selftype.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/367_using_directive_for_missing_selftype.sol new file mode 100644 index 000000000..3d9bc3fc3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/367_using_directive_for_missing_selftype.sol @@ -0,0 +1,14 @@ +library B { + function b() public {} +} + +contract A { + using B for bytes; + + function a() public { + bytes memory x; + x.b(); + } +} +// ---- +// TypeError: (137-140): Member "b" not found or not visible after argument-dependent lookup in bytes memory. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/368_shift_constant_left_negative_rvalue.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/368_shift_constant_left_negative_rvalue.sol new file mode 100644 index 000000000..9c941a68d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/368_shift_constant_left_negative_rvalue.sol @@ -0,0 +1,5 @@ +contract C { + uint public a = 0x42 << -8; +} +// ---- +// TypeError: (33-43): Operator << not compatible with types int_const 66 and int_const -8 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/369_shift_constant_right_negative_rvalue.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/369_shift_constant_right_negative_rvalue.sol new file mode 100644 index 000000000..55f385c67 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/369_shift_constant_right_negative_rvalue.sol @@ -0,0 +1,5 @@ +contract C { + uint public a = 0x42 >> -8; +} +// ---- +// TypeError: (33-43): Operator >> not compatible with types int_const 66 and int_const -8 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/370_shift_constant_left_excessive_rvalue.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/370_shift_constant_left_excessive_rvalue.sol new file mode 100644 index 000000000..e23c7a84a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/370_shift_constant_left_excessive_rvalue.sol @@ -0,0 +1,5 @@ +contract C { + uint public a = 0x42 << 0x100000000; +} +// ---- +// TypeError: (33-52): Operator << not compatible with types int_const 66 and int_const 4294967296 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/371_shift_constant_right_excessive_rvalue.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/371_shift_constant_right_excessive_rvalue.sol new file mode 100644 index 000000000..5533644f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/371_shift_constant_right_excessive_rvalue.sol @@ -0,0 +1,5 @@ +contract C { + uint public a = 0x42 >> 0x100000000; +} +// ---- +// TypeError: (33-52): Operator >> not compatible with types int_const 66 and int_const 4294967296 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/372_shift_constant_right_fractional.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/372_shift_constant_right_fractional.sol new file mode 100644 index 000000000..38d9b051c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/372_shift_constant_right_fractional.sol @@ -0,0 +1,5 @@ +contract C { + uint public a = 0x42 >> (1 / 2); +} +// ---- +// TypeError: (33-48): Operator >> not compatible with types int_const 66 and rational_const 1 / 2 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/373_inline_assembly_unbalanced_positive_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/373_inline_assembly_unbalanced_positive_stack.sol new file mode 100644 index 000000000..e9599f4bd --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/373_inline_assembly_unbalanced_positive_stack.sol @@ -0,0 +1,10 @@ +contract test { + function f() public { + assembly { + 1 + } + } +} +// ---- +// SyntaxError: (73-74): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// DeclarationError: (59-84): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/374_inline_assembly_unbalanced_negative_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/374_inline_assembly_unbalanced_negative_stack.sol new file mode 100644 index 000000000..342afc464 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/374_inline_assembly_unbalanced_negative_stack.sol @@ -0,0 +1,10 @@ +contract test { + function f() public { + assembly { + pop + } + } +} +// ---- +// SyntaxError: (73-76): The use of non-functional instructions is disallowed. Please use functional notation instead. +// DeclarationError: (59-86): Unbalanced stack at the end of a block: 1 missing item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/375_inline_assembly_unbalanced_two_stack_load.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/375_inline_assembly_unbalanced_two_stack_load.sol new file mode 100644 index 000000000..ca1e15a92 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/375_inline_assembly_unbalanced_two_stack_load.sol @@ -0,0 +1,8 @@ +contract c { + uint8 x; + function f() public { + assembly { pop(x) } + } +} +// ---- +// TypeError: (75-76): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol new file mode 100644 index 000000000..0032f99e4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol @@ -0,0 +1,13 @@ +contract test { + modifier m { + uint a = 1; + assembly { + a := 2 + } + _; + } + function f() public m { + } +} +// ---- +// Warning: (122-151): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/377_inline_assembly_storage.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/377_inline_assembly_storage.sol new file mode 100644 index 000000000..3dfb458a1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/377_inline_assembly_storage.sol @@ -0,0 +1,10 @@ +contract test { + uint x = 1; + function f() public { + assembly { + x := 2 + } + } +} +// ---- +// TypeError: (89-90): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/378_inline_assembly_storage_in_modifiers.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/378_inline_assembly_storage_in_modifiers.sol new file mode 100644 index 000000000..b9b92d479 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/378_inline_assembly_storage_in_modifiers.sol @@ -0,0 +1,13 @@ +contract test { + uint x = 1; + modifier m { + assembly { + x := 2 + } + _; + } + function f() public m { + } +} +// ---- +// TypeError: (80-81): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/379_inline_assembly_constant_assign.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/379_inline_assembly_constant_assign.sol new file mode 100644 index 000000000..c8928804f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/379_inline_assembly_constant_assign.sol @@ -0,0 +1,10 @@ +contract test { + uint constant x = 1; + function f() public { + assembly { + x := 2 + } + } +} +// ---- +// TypeError: (98-99): Constant variables not supported by inline assembly. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/380_inline_assembly_constant_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/380_inline_assembly_constant_access.sol new file mode 100644 index 000000000..03ff9166b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/380_inline_assembly_constant_access.sol @@ -0,0 +1,10 @@ +contract test { + uint constant x = 1; + function f() public { + assembly { + let y := x + } + } +} +// ---- +// TypeError: (107-108): Constant variables not supported by inline assembly. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/381_inline_assembly_local_variable_access_out_of_functions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/381_inline_assembly_local_variable_access_out_of_functions.sol new file mode 100644 index 000000000..877f57835 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/381_inline_assembly_local_variable_access_out_of_functions.sol @@ -0,0 +1,10 @@ +contract test { + function f() public { + uint a; + assembly { + function g() -> x { x := a } + } + } +} +// ---- +// DeclarationError: (114-115): Cannot access local Solidity variables from inside an inline assembly function. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/382_inline_assembly_local_variable_access_out_of_functions_storage_ptr.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/382_inline_assembly_local_variable_access_out_of_functions_storage_ptr.sol new file mode 100644 index 000000000..65d614a3f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/382_inline_assembly_local_variable_access_out_of_functions_storage_ptr.sol @@ -0,0 +1,11 @@ +contract test { + uint[] r; + function f() public { + uint[] storage a = r; + assembly { + function g() -> x { x := a_offset } + } + } +} +// ---- +// DeclarationError: (142-150): Cannot access local Solidity variables from inside an inline assembly function. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/383_inline_assembly_storage_variable_access_out_of_functions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/383_inline_assembly_storage_variable_access_out_of_functions.sol new file mode 100644 index 000000000..abe9067a5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/383_inline_assembly_storage_variable_access_out_of_functions.sol @@ -0,0 +1,8 @@ +contract test { + uint a; + function f() pure public { + assembly { + function g() -> x { x := a_slot } + } + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/384_inline_assembly_constant_variable_via_offset.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/384_inline_assembly_constant_variable_via_offset.sol new file mode 100644 index 000000000..6470a2101 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/384_inline_assembly_constant_variable_via_offset.sol @@ -0,0 +1,10 @@ +contract test { + uint constant x = 2; + function f() pure public { + assembly { + let r := x_offset + } + } +} +// ---- +// TypeError: (112-120): Constant variables not supported by inline assembly. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/385_inline_assembly_calldata_variables.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/385_inline_assembly_calldata_variables.sol new file mode 100644 index 000000000..952b9af6a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/385_inline_assembly_calldata_variables.sol @@ -0,0 +1,9 @@ +contract C { + function f(bytes calldata bytesAsCalldata) external { + assembly { + let x := bytesAsCalldata + } + } +} +// ---- +// TypeError: (111-126): Call data elements cannot be accessed directly. Copy to a local variable first or use "calldataload" or "calldatacopy" with manually determined offsets and sizes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/387_inline_assembly_literals_on_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/387_inline_assembly_literals_on_stack.sol new file mode 100644 index 000000000..62fe71710 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/387_inline_assembly_literals_on_stack.sol @@ -0,0 +1,10 @@ +contract C { + function f() pure public { + assembly { + 1 + } + } +} +// ---- +// SyntaxError: (75-76): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// DeclarationError: (61-86): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/389_inline_assembly_bare_instructions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/389_inline_assembly_bare_instructions.sol new file mode 100644 index 000000000..7315d5d1d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/389_inline_assembly_bare_instructions.sol @@ -0,0 +1,11 @@ +contract C { + function f() view public { + assembly { + address + pop + } + } +} +// ---- +// SyntaxError: (75-82): The use of non-functional instructions is disallowed. Please use functional notation instead. +// SyntaxError: (95-98): The use of non-functional instructions is disallowed. Please use functional notation instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/391_inline_assembly_labels.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/391_inline_assembly_labels.sol new file mode 100644 index 000000000..0d7bacb4f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/391_inline_assembly_labels.sol @@ -0,0 +1,10 @@ +contract C { + function f() pure public { + assembly { + label: + } + } +} +// ---- +// SyntaxError: (75-80): The use of labels is disallowed. Please use "if", "switch", "for" or function calls instead. +// SyntaxError: (75-80): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/393_inline_assembly_jump.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/393_inline_assembly_jump.sol new file mode 100644 index 000000000..6cb35d6df --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/393_inline_assembly_jump.sol @@ -0,0 +1,9 @@ +contract C { + function f() pure public { + assembly { + jump(2) + } + } +} +// ---- +// SyntaxError: (75-82): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/395_inline_assembly_leave_items_on_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/395_inline_assembly_leave_items_on_stack.sol new file mode 100644 index 000000000..8538a2a0d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/395_inline_assembly_leave_items_on_stack.sol @@ -0,0 +1,10 @@ +contract C { + function f() pure public { + assembly { + mload(0) + } + } +} +// ---- +// SyntaxError: (75-83): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// DeclarationError: (61-93): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/396_invalid_mobile_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/396_invalid_mobile_type.sol new file mode 100644 index 000000000..536dd317c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/396_invalid_mobile_type.sol @@ -0,0 +1,8 @@ + contract C { + function f() public { + // Invalid number + [1, 78901234567890123456789012345678901234567890123456789345678901234567890012345678012345678901234567]; + } + } +// ---- +// TypeError: (93-191): Invalid rational number. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/397_warns_msg_value_in_non_payable_public_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/397_warns_msg_value_in_non_payable_public_function.sol new file mode 100644 index 000000000..c56ad25f9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/397_warns_msg_value_in_non_payable_public_function.sol @@ -0,0 +1,7 @@ +contract C { + function f() view public { + msg.value; + } +} +// ---- +// TypeError: (52-61): "msg.value" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/398_does_not_warn_msg_value_in_payable_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/398_does_not_warn_msg_value_in_payable_function.sol new file mode 100644 index 000000000..f14e86ed0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/398_does_not_warn_msg_value_in_payable_function.sol @@ -0,0 +1,5 @@ +contract C { + function f() payable public { + msg.value; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/399_does_not_warn_msg_value_in_internal_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/399_does_not_warn_msg_value_in_internal_function.sol new file mode 100644 index 000000000..8492e691e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/399_does_not_warn_msg_value_in_internal_function.sol @@ -0,0 +1,5 @@ +contract C { + function f() view internal { + msg.value; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/400_does_not_warn_msg_value_in_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/400_does_not_warn_msg_value_in_library.sol new file mode 100644 index 000000000..ce59047e2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/400_does_not_warn_msg_value_in_library.sol @@ -0,0 +1,5 @@ +library C { + function f() view public { + msg.value; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/401_does_not_warn_msg_value_in_modifier_following_non_payable_public_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/401_does_not_warn_msg_value_in_modifier_following_non_payable_public_function.sol new file mode 100644 index 000000000..dc1da7c4a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/401_does_not_warn_msg_value_in_modifier_following_non_payable_public_function.sol @@ -0,0 +1,4 @@ +contract c { + function f() pure public { } + modifier m() { msg.value; _; } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/402_assignment_to_constant.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/402_assignment_to_constant.sol new file mode 100644 index 000000000..7433bdeab --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/402_assignment_to_constant.sol @@ -0,0 +1,6 @@ +contract c { + uint constant a = 1; + function f() public { a = 2; } +} +// ---- +// TypeError: (64-65): Cannot assign to a constant variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/403_return_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/403_return_structs.sol new file mode 100644 index 000000000..2575954e7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/403_return_structs.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; +contract C { + struct S { uint a; T[] sub; } + struct T { uint[] x; } + function f() public returns (uint, S memory) { + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// Warning: (112-164): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/404_read_returned_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/404_read_returned_struct.sol new file mode 100644 index 000000000..52d1bd13d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/404_read_returned_struct.sol @@ -0,0 +1,12 @@ +pragma experimental ABIEncoderV2; +contract A { + struct T { + int x; + int y; + } + function g() public returns (T memory) { + return this.g(); + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol new file mode 100644 index 000000000..81cc7d0d4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol @@ -0,0 +1,6 @@ +contract C { + function f() public { + (0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E).transfer(2); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/406_invalid_address_checksum.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/406_invalid_address_checksum.sol new file mode 100644 index 000000000..fe4691c22 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/406_invalid_address_checksum.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + address x = 0xFA0bFc97E48458494Ccd857e1A85DC91F7F0046E; + x; + } +} +// ---- +// SyntaxError: (64-106): This looks like an address but has an invalid checksum. Correct checksummed address: "0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E". If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/407_invalid_address_no_checksum.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/407_invalid_address_no_checksum.sol new file mode 100644 index 000000000..6f4ac730d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/407_invalid_address_no_checksum.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + address x = 0xfa0bfc97e48458494ccd857e1a85dc91f7f0046e; + x; + } +} +// ---- +// SyntaxError: (64-106): This looks like an address but has an invalid checksum. Correct checksummed address: "0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E". If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/408_invalid_address_length_short.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/408_invalid_address_length_short.sol new file mode 100644 index 000000000..da5dc3803 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/408_invalid_address_length_short.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + address x = 0xA0bFc97E48458494Ccd857e1A85DC91F7F0046E; + x; + } +} +// ---- +// SyntaxError: (64-105): This looks like an address but is not exactly 40 hex digits. It is 39 hex digits. If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/409_invalid_address_length_long.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/409_invalid_address_length_long.sol new file mode 100644 index 000000000..749612c9c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/409_invalid_address_length_long.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + address x = 0xFA0bFc97E48458494Ccd857e1A85DC91F7F0046E0; + x; + } +} +// ---- +// SyntaxError: (64-107): This looks like an address but is not exactly 40 hex digits. It is 41 hex digits. If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/410_string_literal_not_convertible_to_address_as_assignment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/410_string_literal_not_convertible_to_address_as_assignment.sol new file mode 100644 index 000000000..13bd1a8fb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/410_string_literal_not_convertible_to_address_as_assignment.sol @@ -0,0 +1,6 @@ +// A previous implementation claimed the string would be an address +contract AddrString { + address public test = "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c"; +} +// ---- +// TypeError: (116-160): Type literal_string "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c" is not implicitly convertible to expected type address. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/411_string_literal_not_convertible_to_address_as_return_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/411_string_literal_not_convertible_to_address_as_return_value.sol new file mode 100644 index 000000000..d6b7b987e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/411_string_literal_not_convertible_to_address_as_return_value.sol @@ -0,0 +1,8 @@ +// A previous implementation claimed the string would be an address +contract AddrString { + function f() public returns (address) { + return "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c"; + } +} +// ---- +// TypeError: (149-193): Return argument type literal_string "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c" is not implicitly convertible to expected type (type of first return variable) address. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/412_early_exit_on_fatal_errors.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/412_early_exit_on_fatal_errors.sol new file mode 100644 index 000000000..d052dab5d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/412_early_exit_on_fatal_errors.sol @@ -0,0 +1,12 @@ +// This tests a crash that occurred because we did not stop for fatal errors. +contract C { + struct S { + ftring a; + } + S public s; + function s() public s { + } +} +// ---- +// DeclarationError: (150-179): Identifier already declared. +// DeclarationError: (114-120): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol new file mode 100644 index 000000000..ad57224cd --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol @@ -0,0 +1,12 @@ +contract C { + function f() public { + address payable addr; + uint balance = addr.balance; + (bool callSuc,) = addr.call(""); + (bool delegatecallSuc,) = addr.delegatecall(""); + bool sendRet = addr.send(1); + addr.transfer(1); + balance; callSuc; delegatecallSuc; sendRet; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/414_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/414_interface.sol new file mode 100644 index 000000000..77baf7bf3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/414_interface.sol @@ -0,0 +1,2 @@ +interface I { +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/415_interface_functions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/415_interface_functions.sol new file mode 100644 index 000000000..a5d6561e7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/415_interface_functions.sol @@ -0,0 +1,5 @@ +interface I { + function() external; + function f() external; +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/416_interface_function_bodies.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/416_interface_function_bodies.sol new file mode 100644 index 000000000..fee2525ef --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/416_interface_function_bodies.sol @@ -0,0 +1,6 @@ +interface I { + function f() external pure { + } +} +// ---- +// TypeError: (18-52): Functions in interfaces cannot have an implementation. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/417_interface_events.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/417_interface_events.sol new file mode 100644 index 000000000..5959f50df --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/417_interface_events.sol @@ -0,0 +1,3 @@ +interface I { + event E(); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/418_interface_inheritance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/418_interface_inheritance.sol new file mode 100644 index 000000000..92683cda3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/418_interface_inheritance.sol @@ -0,0 +1,6 @@ +interface A { +} +interface I is A { +} +// ---- +// TypeError: (31-32): Interfaces cannot inherit. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol new file mode 100644 index 000000000..385ed18e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol @@ -0,0 +1,6 @@ +interface I { + struct A { + int dummy; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/420_interface_variables.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/420_interface_variables.sol new file mode 100644 index 000000000..a4292c41c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/420_interface_variables.sol @@ -0,0 +1,5 @@ +interface I { + uint a; +} +// ---- +// TypeError: (18-24): Variables cannot be declared in interfaces. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/421_interface_function_parameters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/421_interface_function_parameters.sol new file mode 100644 index 000000000..9722e936c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/421_interface_function_parameters.sol @@ -0,0 +1,4 @@ +interface I { + function f(uint a) external returns (bool); +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/422_interface_enums.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/422_interface_enums.sol new file mode 100644 index 000000000..1533e7ff7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/422_interface_enums.sol @@ -0,0 +1,4 @@ +interface I { + enum A { B, C } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/423_using_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/423_using_interface.sol new file mode 100644 index 000000000..d576bb601 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/423_using_interface.sol @@ -0,0 +1,8 @@ +interface I { + function f() external; +} +contract C is I { + function f() public { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/424_using_interface_complex.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/424_using_interface_complex.sol new file mode 100644 index 000000000..a3dca996a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/424_using_interface_complex.sol @@ -0,0 +1,11 @@ +interface I { + event A(); + function f() external; + function g() external; + function() external; +} +contract C is I { + function f() public { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/425_interface_implement_public_contract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/425_interface_implement_public_contract.sol new file mode 100644 index 000000000..d85402887 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/425_interface_implement_public_contract.sol @@ -0,0 +1,7 @@ +interface I { + function f() external; +} +contract C is I { + function f() public { + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/426_throw_is_deprecated.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/426_throw_is_deprecated.sol new file mode 100644 index 000000000..24f36c5b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/426_throw_is_deprecated.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + throw; + } +} +// ---- +// SyntaxError: (52-57): "throw" is deprecated in favour of "revert()", "require()" and "assert()". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/428_bare_revert.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/428_bare_revert.sol new file mode 100644 index 000000000..8e7817ff4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/428_bare_revert.sol @@ -0,0 +1,8 @@ +contract C { + function f(uint x) pure public { + if (x > 7) + revert; + } +} +// ---- +// TypeError: (81-87): No matching declaration found after variable lookup. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/429_revert_with_reason.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/429_revert_with_reason.sol new file mode 100644 index 000000000..36c238be7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/429_revert_with_reason.sol @@ -0,0 +1,8 @@ +contract C { + function f(uint x) pure public { + if (x > 7) + revert("abc"); + else + revert(); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/430_bare_selfdestruct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/430_bare_selfdestruct.sol new file mode 100644 index 000000000..9adc3d39d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/430_bare_selfdestruct.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public { selfdestruct; } +} +// ---- +// Warning: (44-56): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/431_bare_assert.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/431_bare_assert.sol new file mode 100644 index 000000000..38cea0576 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/431_bare_assert.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public { assert; } +} +// ---- +// Warning: (44-50): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/432_bare_require.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/432_bare_require.sol new file mode 100644 index 000000000..62fe8baf3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/432_bare_require.sol @@ -0,0 +1,6 @@ +contract C { + // This is different because it does have overloads. + function f() pure public { require; } +} +// ---- +// TypeError: (101-108): No matching declaration found after variable lookup. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/433_pure_statement_in_for_loop.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/433_pure_statement_in_for_loop.sol new file mode 100644 index 000000000..8cb090bb1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/433_pure_statement_in_for_loop.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + for (uint x = 0; x < 10; true) + x++; + } +} +// ---- +// Warning: (77-81): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/434_pure_statement_check_for_regular_for_loop.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/434_pure_statement_check_for_regular_for_loop.sol new file mode 100644 index 000000000..319e42029 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/434_pure_statement_check_for_regular_for_loop.sol @@ -0,0 +1,6 @@ +contract C { + function f() pure public { + for (uint x = 0; true; x++) + {} + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/435_warn_unused_local.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/435_warn_unused_local.sol new file mode 100644 index 000000000..7d7f5728a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/435_warn_unused_local.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + uint a; + } +} +// ---- +// Warning: (52-58): Unused local variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/436_warn_unused_local_assigned.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/436_warn_unused_local_assigned.sol new file mode 100644 index 000000000..b3d283749 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/436_warn_unused_local_assigned.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + uint a = 1; + } +} +// ---- +// Warning: (52-58): Unused local variable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/437_warn_unused_function_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/437_warn_unused_function_parameter.sol new file mode 100644 index 000000000..8a36eaad0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/437_warn_unused_function_parameter.sol @@ -0,0 +1,6 @@ +contract C { + function f(uint a) pure public { + } +} +// ---- +// Warning: (28-34): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/438_unused_unnamed_function_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/438_unused_unnamed_function_parameter.sol new file mode 100644 index 000000000..5d059b93e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/438_unused_unnamed_function_parameter.sol @@ -0,0 +1,4 @@ +contract C { + function f(uint) pure public { + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/439_warn_unused_return_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/439_warn_unused_return_parameter.sol new file mode 100644 index 000000000..b1422c4f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/439_warn_unused_return_parameter.sol @@ -0,0 +1,6 @@ +contract C { + function f() pure public returns (uint a) { + } +} +// ---- +// Warning: (51-57): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/441_unused_unnamed_return_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/441_unused_unnamed_return_parameter.sol new file mode 100644 index 000000000..8c47484b7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/441_unused_unnamed_return_parameter.sol @@ -0,0 +1,4 @@ +contract C { + function f() pure public returns (uint) { + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/442_named_return_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/442_named_return_parameter.sol new file mode 100644 index 000000000..a2faf06a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/442_named_return_parameter.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public returns (uint a) { + a = 1; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/443_named_return_parameter_with_explicit_return.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/443_named_return_parameter_with_explicit_return.sol new file mode 100644 index 000000000..93851e7cf --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/443_named_return_parameter_with_explicit_return.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public returns (uint a) { + return 1; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/444_unnamed_return_parameter_with_explicit_return.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/444_unnamed_return_parameter_with_explicit_return.sol new file mode 100644 index 000000000..b552a7452 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/444_unnamed_return_parameter_with_explicit_return.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public returns (uint) { + return 1; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/445_no_unused_warning_interface_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/445_no_unused_warning_interface_arguments.sol new file mode 100644 index 000000000..203217cea --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/445_no_unused_warning_interface_arguments.sol @@ -0,0 +1,3 @@ +interface I { + function f(uint a) pure external returns (uint b); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/446_no_unused_warning_abstract_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/446_no_unused_warning_abstract_arguments.sol new file mode 100644 index 000000000..fbb6e0794 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/446_no_unused_warning_abstract_arguments.sol @@ -0,0 +1,3 @@ +contract C { + function f(uint a) pure public returns (uint b); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/447_no_unused_warnings.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/447_no_unused_warnings.sol new file mode 100644 index 000000000..f549308ac --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/447_no_unused_warnings.sol @@ -0,0 +1,6 @@ +contract C { + function f(uint a) pure public returns (uint b) { + uint c = 1; + b = a + c; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/449_no_unused_inline_asm.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/449_no_unused_inline_asm.sol new file mode 100644 index 000000000..2b39b9fdb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/449_no_unused_inline_asm.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + uint a; + assembly { + a := 1 + } + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/450_shadowing_builtins_with_functions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/450_shadowing_builtins_with_functions.sol new file mode 100644 index 000000000..33ccb3562 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/450_shadowing_builtins_with_functions.sol @@ -0,0 +1,5 @@ +contract C { + function keccak256() pure public {} +} +// ---- +// Warning: (17-52): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/451_shadowing_builtins_with_variables.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/451_shadowing_builtins_with_variables.sol new file mode 100644 index 000000000..1d6f098e7 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/451_shadowing_builtins_with_variables.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + uint msg; + msg; + } +} +// ---- +// Warning: (52-60): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/452_shadowing_builtins_with_storage_variables.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/452_shadowing_builtins_with_storage_variables.sol new file mode 100644 index 000000000..d5635887b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/452_shadowing_builtins_with_storage_variables.sol @@ -0,0 +1,5 @@ +contract C { + uint msg; +} +// ---- +// Warning: (17-25): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/453_shadowing_builtin_at_global_scope.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/453_shadowing_builtin_at_global_scope.sol new file mode 100644 index 000000000..0946dc57a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/453_shadowing_builtin_at_global_scope.sol @@ -0,0 +1,4 @@ +contract msg { +} +// ---- +// Warning: (0-16): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/454_shadowing_builtins_with_parameters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/454_shadowing_builtins_with_parameters.sol new file mode 100644 index 000000000..454929d1c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/454_shadowing_builtins_with_parameters.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint require) pure public { + require = 2; + } +} +// ---- +// Warning: (28-40): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/455_shadowing_builtins_with_return_parameters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/455_shadowing_builtins_with_return_parameters.sol new file mode 100644 index 000000000..7931053fc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/455_shadowing_builtins_with_return_parameters.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public returns (uint require) { + require = 2; + } +} +// ---- +// Warning: (51-63): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/456_shadowing_builtins_with_events.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/456_shadowing_builtins_with_events.sol new file mode 100644 index 000000000..e5b635df2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/456_shadowing_builtins_with_events.sol @@ -0,0 +1,5 @@ +contract C { + event keccak256(); +} +// ---- +// Warning: (17-35): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/457_shadowing_builtins_ignores_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/457_shadowing_builtins_ignores_struct.sol new file mode 100644 index 000000000..4c70b4ced --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/457_shadowing_builtins_ignores_struct.sol @@ -0,0 +1,5 @@ +contract C { + struct a { + uint msg; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/458_shadowing_builtins_ignores_constructor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/458_shadowing_builtins_ignores_constructor.sol new file mode 100644 index 000000000..86c0b4f0b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/458_shadowing_builtins_ignores_constructor.sol @@ -0,0 +1,3 @@ +contract C { + constructor() public {} +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/459_function_overload_is_not_shadowing.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/459_function_overload_is_not_shadowing.sol new file mode 100644 index 000000000..1b44b5c6d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/459_function_overload_is_not_shadowing.sol @@ -0,0 +1,4 @@ +contract C { + function f() pure public {} + function f(uint) pure public {} +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/460_function_override_is_not_shadowing.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/460_function_override_is_not_shadowing.sol new file mode 100644 index 000000000..c765ff008 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/460_function_override_is_not_shadowing.sol @@ -0,0 +1,4 @@ +contract D { function f() pure public {} } +contract C is D { + function f(uint) pure public {} +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/461_event_parameter_cannot_shadow_state_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/461_event_parameter_cannot_shadow_state_variable.sol new file mode 100644 index 000000000..6e1f654d9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/461_event_parameter_cannot_shadow_state_variable.sol @@ -0,0 +1,4 @@ +contract C { + address a; + event E(address a); +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/462_callable_crash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/462_callable_crash.sol new file mode 100644 index 000000000..188d00e0f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/462_callable_crash.sol @@ -0,0 +1,9 @@ +contract C { + struct S { uint a; bool x; } + S public s; + constructor() public { + 3({a: 1, x: true}); + } +} +// ---- +// TypeError: (97-115): Type is not callable diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol new file mode 100644 index 000000000..c343995f1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol @@ -0,0 +1,15 @@ +// This used to be a test for a.transfer to generate a warning +// because A does not have a payable fallback function. + +contract A { + function() payable external {} +} + +contract B { + A a; + + function() external { + address(a).transfer(100); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/467_does_not_error_transfer_regular_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/467_does_not_error_transfer_regular_function.sol new file mode 100644 index 000000000..65b4a2361 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/467_does_not_error_transfer_regular_function.sol @@ -0,0 +1,11 @@ +contract A { + function transfer() pure public {} +} + +contract B { + A a; + + function() external { + a.transfer(); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/470_specified_storage_no_warn.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/470_specified_storage_no_warn.sol new file mode 100644 index 000000000..490a00324 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/470_specified_storage_no_warn.sol @@ -0,0 +1,8 @@ +contract C { + struct S { uint a; string b; } + S x; + function f() view public { + S storage y = x; + y; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/471_unspecified_storage_fail.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/471_unspecified_storage_fail.sol new file mode 100644 index 000000000..de42ebd7c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/471_unspecified_storage_fail.sol @@ -0,0 +1,13 @@ +contract C { + struct S { uint a; } + S m_x; + uint[] m_y; + function f() view public { + S x = m_x; + uint[] y = m_y; + x; y; + } +} +// ---- +// TypeError: (104-107): Data location must be "storage" or "memory" for variable, but none was given. +// TypeError: (123-131): Data location must be "storage" or "memory" for variable, but none was given. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/473_storage_location_non_array_or_struct_disallowed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/473_storage_location_non_array_or_struct_disallowed.sol new file mode 100644 index 000000000..fe846aa0a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/473_storage_location_non_array_or_struct_disallowed.sol @@ -0,0 +1,5 @@ +contract C { + function f(uint storage a) public { } +} +// ---- +// TypeError: (28-42): Data location can only be specified for array, struct or mapping types, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/474_storage_location_non_array_or_struct_disallowed_is_not_fatal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/474_storage_location_non_array_or_struct_disallowed_is_not_fatal.sol new file mode 100644 index 000000000..e74db3756 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/474_storage_location_non_array_or_struct_disallowed_is_not_fatal.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint storage a) public { + a = f; + } +} +// ---- +// TypeError: (28-42): Data location can only be specified for array, struct or mapping types, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/475_implicit_conversion_disallowed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/475_implicit_conversion_disallowed.sol new file mode 100644 index 000000000..232e701df --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/475_implicit_conversion_disallowed.sol @@ -0,0 +1,8 @@ +contract C { + function f() public returns (bytes4) { + uint32 tmp = 1; + return tmp; + } +} +// ---- +// TypeError: (95-98): Return argument type uint32 is not implicitly convertible to expected type (type of first return variable) bytes4. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/476_too_large_arrays_for_calldata_external.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/476_too_large_arrays_for_calldata_external.sol new file mode 100644 index 000000000..78c38aaf2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/476_too_large_arrays_for_calldata_external.sol @@ -0,0 +1,6 @@ +contract C { + function f(uint[85678901234] calldata a) pure external { + } +} +// ---- +// TypeError: (28-56): Array is too large to be encoded. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/477_too_large_arrays_for_calldata_internal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/477_too_large_arrays_for_calldata_internal.sol new file mode 100644 index 000000000..7578246ee --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/477_too_large_arrays_for_calldata_internal.sol @@ -0,0 +1,6 @@ +contract C { + function f(uint[85678901234] memory a) pure internal { + } +} +// ---- +// TypeError: (28-54): Array is too large to be encoded. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/478_too_large_arrays_for_calldata_public.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/478_too_large_arrays_for_calldata_public.sol new file mode 100644 index 000000000..2831b6fbb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/478_too_large_arrays_for_calldata_public.sol @@ -0,0 +1,6 @@ +contract C { + function f(uint[85678901234] memory a) pure public { + } +} +// ---- +// TypeError: (28-54): Array is too large to be encoded. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/479_explicit_literal_to_memory_string_assignment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/479_explicit_literal_to_memory_string_assignment.sol new file mode 100644 index 000000000..508a94392 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/479_explicit_literal_to_memory_string_assignment.sol @@ -0,0 +1,6 @@ +contract C { + function f() pure public { + string memory x = "abc"; + x; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/480_explicit_literal_to_storage_string_assignment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/480_explicit_literal_to_storage_string_assignment.sol new file mode 100644 index 000000000..ee56204a8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/480_explicit_literal_to_storage_string_assignment.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + string storage x = "abc"; + } +} +// ---- +// TypeError: (52-76): Type literal_string "abc" is not implicitly convertible to expected type string storage pointer. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/481_explicit_literal_to_unspecified_string_assignment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/481_explicit_literal_to_unspecified_string_assignment.sol new file mode 100644 index 000000000..ee56204a8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/481_explicit_literal_to_unspecified_string_assignment.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + string storage x = "abc"; + } +} +// ---- +// TypeError: (52-76): Type literal_string "abc" is not implicitly convertible to expected type string storage pointer. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol new file mode 100644 index 000000000..c44fab55a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + string("abc"); + } +} +// ---- +// Warning: (52-65): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/483_modifiers_access_storage_pointer.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/483_modifiers_access_storage_pointer.sol new file mode 100644 index 000000000..be1920e94 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/483_modifiers_access_storage_pointer.sol @@ -0,0 +1,7 @@ +contract C { + struct S { uint a; } + modifier m(S storage x) { + x; + _; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/484_function_types_selector_1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/484_function_types_selector_1.sol new file mode 100644 index 000000000..41ef95c5f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/484_function_types_selector_1.sol @@ -0,0 +1,7 @@ +contract C { + function f() public view returns (bytes4) { + return f.selector; + } +} +// ---- +// TypeError: (76-86): Member "selector" not found or not visible after argument-dependent lookup in function () view returns (bytes4). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/485_function_types_selector_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/485_function_types_selector_2.sol new file mode 100644 index 000000000..d02b098d6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/485_function_types_selector_2.sol @@ -0,0 +1,9 @@ +contract C { + function g() pure internal { + } + function f() public view returns (bytes4) { + return g.selector; + } +} +// ---- +// TypeError: (115-125): Member "selector" not found or not visible after argument-dependent lookup in function () pure. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/486_function_types_selector_3.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/486_function_types_selector_3.sol new file mode 100644 index 000000000..d39fcc288 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/486_function_types_selector_3.sol @@ -0,0 +1,8 @@ +contract C { + function f() public view returns (bytes4) { + function () g; + return g.selector; + } +} +// ---- +// TypeError: (99-109): Member "selector" not found or not visible after argument-dependent lookup in function (). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/487_function_types_selector_4.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/487_function_types_selector_4.sol new file mode 100644 index 000000000..4c3c72e8c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/487_function_types_selector_4.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure external returns (bytes4) { + return this.f.selector; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/488_function_types_selector_5.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/488_function_types_selector_5.sol new file mode 100644 index 000000000..5f601db22 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/488_function_types_selector_5.sol @@ -0,0 +1,8 @@ +contract C { + function h() pure external { + } + function f() pure external returns (bytes4) { + return this.h.selector; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/489_function_types_selector_6.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/489_function_types_selector_6.sol new file mode 100644 index 000000000..0114e2821 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/489_function_types_selector_6.sol @@ -0,0 +1,8 @@ +contract C { + function h() pure external { + } + function f() view external returns (bytes4) { + function () pure external g = this.h; + return g.selector; + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/490_function_types_selector_7.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/490_function_types_selector_7.sol new file mode 100644 index 000000000..9ee7d9bb9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/490_function_types_selector_7.sol @@ -0,0 +1,9 @@ +contract C { + function h() pure external { + } + function f() view external returns (bytes4) { + function () pure external g = this.h; + return g.selector; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/491_using_this_in_constructor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/491_using_this_in_constructor.sol new file mode 100644 index 000000000..7921a1fac --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/491_using_this_in_constructor.sol @@ -0,0 +1,9 @@ +contract C { + constructor() public { + this.f(); + } + function f() pure public { + } +} +// ---- +// Warning: (48-52): "this" used in constructor. Note that external functions of a contract cannot be called while it is being constructed. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/492_do_not_crash_on_not_lvalue.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/492_do_not_crash_on_not_lvalue.sol new file mode 100644 index 000000000..902758049 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/492_do_not_crash_on_not_lvalue.sol @@ -0,0 +1,11 @@ +// This checks for a bug that caused a crash because of continued analysis. +contract C { + mapping (uint => uint) m; + function f() public { + m(1) = 2; + } +} +// ---- +// TypeError: (153-157): Type is not callable +// TypeError: (153-157): Expression has to be an lvalue. +// TypeError: (160-161): Type int_const 2 is not implicitly convertible to expected type tuple(). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/493_builtin_keccak256_reject_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/493_builtin_keccak256_reject_gas.sol new file mode 100644 index 000000000..e41139061 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/493_builtin_keccak256_reject_gas.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + keccak256.gas(); + } +} +// ---- +// TypeError: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/494_builtin_sha256_reject_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/494_builtin_sha256_reject_gas.sol new file mode 100644 index 000000000..20031ea9a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/494_builtin_sha256_reject_gas.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + sha256.gas(); + } +} +// ---- +// TypeError: (47-57): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/495_builtin_ripemd160_reject_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/495_builtin_ripemd160_reject_gas.sol new file mode 100644 index 000000000..3d37e9886 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/495_builtin_ripemd160_reject_gas.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + ripemd160.gas(); + } +} +// ---- +// TypeError: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes20). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/496_builtin_ecrecover_reject_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/496_builtin_ecrecover_reject_gas.sol new file mode 100644 index 000000000..82b6c89db --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/496_builtin_ecrecover_reject_gas.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + ecrecover.gas(); + } +} +// ---- +// TypeError: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes32,uint8,bytes32,bytes32) pure returns (address). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol new file mode 100644 index 000000000..20f33887e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol @@ -0,0 +1,3 @@ +contract C { + function f() public view returns (uint256 val) { return gasleft(); } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/498_msg_gas_deprecated.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/498_msg_gas_deprecated.sol new file mode 100644 index 000000000..5efecd224 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/498_msg_gas_deprecated.sol @@ -0,0 +1,5 @@ +contract C { + function f() public view returns (uint256 val) { return msg.gas; } +} +// ---- +// TypeError: (73-80): "msg.gas" has been deprecated in favor of "gasleft()" diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/500_gasleft_shadowing_1.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/500_gasleft_shadowing_1.sol new file mode 100644 index 000000000..66b88c49f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/500_gasleft_shadowing_1.sol @@ -0,0 +1,6 @@ +contract C { + function gasleft() public pure returns (bytes32 val) { return "abc"; } + function f() public pure returns (bytes32 val) { return gasleft(); } +} +// ---- +// Warning: (17-87): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/501_gasleft_shadowing_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/501_gasleft_shadowing_2.sol new file mode 100644 index 000000000..2679c89d8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/501_gasleft_shadowing_2.sol @@ -0,0 +1,6 @@ +contract C { + uint gasleft; + function f() public { gasleft = 42; } +} +// ---- +// Warning: (17-29): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol new file mode 100644 index 000000000..61e51eff6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + keccak256.value(); + } +} +// ---- +// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol new file mode 100644 index 000000000..11141a9b9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + sha256.value(); + } +} +// ---- +// TypeError: (47-59): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol new file mode 100644 index 000000000..d120f3ddd --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + ripemd160.value(); + } +} +// ---- +// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes20) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/505_builtin_ecrecover_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/505_builtin_ecrecover_reject_value.sol new file mode 100644 index 000000000..e0215901a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/505_builtin_ecrecover_reject_value.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + ecrecover.value(); + } +} +// ---- +// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes32,uint8,bytes32,bytes32) pure returns (address) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/506_large_storage_array_fine.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/506_large_storage_array_fine.sol new file mode 100644 index 000000000..13e6dd801 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/506_large_storage_array_fine.sol @@ -0,0 +1,3 @@ +contract C { + uint[2**64 - 1] x; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/507_large_storage_array_simple.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/507_large_storage_array_simple.sol new file mode 100644 index 000000000..3f8ee9964 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/507_large_storage_array_simple.sol @@ -0,0 +1,5 @@ +contract C { + uint[2**64] x; +} +// ---- +// Warning: (17-30): Variable covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/508_large_storage_arrays_combined.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/508_large_storage_arrays_combined.sol new file mode 100644 index 000000000..917dcec14 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/508_large_storage_arrays_combined.sol @@ -0,0 +1,5 @@ +contract C { + uint[200][200][2**30][][2**30] x; +} +// ---- +// Warning: (17-49): Variable covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/509_large_storage_arrays_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/509_large_storage_arrays_struct.sol new file mode 100644 index 000000000..656201f4d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/509_large_storage_arrays_struct.sol @@ -0,0 +1,6 @@ +contract C { + struct S { uint[2**30] x; uint[2**50] y; } + S[2**20] x; +} +// ---- +// Warning: (64-74): Variable covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/510_large_storage_array_mapping.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/510_large_storage_array_mapping.sol new file mode 100644 index 000000000..046a27f71 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/510_large_storage_array_mapping.sol @@ -0,0 +1,5 @@ +contract C { + mapping(uint => uint[2**100]) x; +} +// ---- +// Warning: (17-48): Variable covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/511_library_function_without_implementation_public.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/511_library_function_without_implementation_public.sol new file mode 100644 index 000000000..fe5e49556 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/511_library_function_without_implementation_public.sol @@ -0,0 +1,4 @@ +library L { + // This can be used as an "interface", hence it is allowed. + function f() public; +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/512_library_function_without_implementation_internal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/512_library_function_without_implementation_internal.sol new file mode 100644 index 000000000..d5dfb260c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/512_library_function_without_implementation_internal.sol @@ -0,0 +1,5 @@ +library L { + function f() internal; +} +// ---- +// TypeError: (16-38): Internal library function must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/513_library_function_without_implementation_private.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/513_library_function_without_implementation_private.sol new file mode 100644 index 000000000..70585e8c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/513_library_function_without_implementation_private.sol @@ -0,0 +1,5 @@ +library L { + function f() private; +} +// ---- +// TypeError: (16-37): Internal library function must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/514_using_for_with_non_library.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/514_using_for_with_non_library.sol new file mode 100644 index 000000000..7e9612d00 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/514_using_for_with_non_library.sol @@ -0,0 +1,10 @@ +// This tests a crash that was resolved by making the first error fatal. +library L { + struct S { uint d; } + using S for S; + function f(S memory _s) internal { + _s.d = 1; + } +} +// ---- +// TypeError: (120-121): Library name expected. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/515_experimental_pragma_empty.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/515_experimental_pragma_empty.sol new file mode 100644 index 000000000..66afb7a28 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/515_experimental_pragma_empty.sol @@ -0,0 +1,3 @@ +pragma experimental; +// ---- +// SyntaxError: (0-20): Experimental feature name is missing. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/516_experimental_pragma_unknown_number_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/516_experimental_pragma_unknown_number_literal.sol new file mode 100644 index 000000000..445c6f547 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/516_experimental_pragma_unknown_number_literal.sol @@ -0,0 +1,3 @@ +pragma experimental 123; +// ---- +// SyntaxError: (0-24): Unsupported experimental feature name. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/517_experimental_pragma_unknown_string_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/517_experimental_pragma_unknown_string_literal.sol new file mode 100644 index 000000000..48d8b9689 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/517_experimental_pragma_unknown_string_literal.sol @@ -0,0 +1,3 @@ +pragma experimental unsupportedName; +// ---- +// SyntaxError: (0-36): Unsupported experimental feature name. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/518_experimental_pragma_unknown_quoted_string_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/518_experimental_pragma_unknown_quoted_string_literal.sol new file mode 100644 index 000000000..6405f0627 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/518_experimental_pragma_unknown_quoted_string_literal.sol @@ -0,0 +1,3 @@ +pragma experimental "unsupportedName"; +// ---- +// SyntaxError: (0-38): Unsupported experimental feature name. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/519_experimental_pragma_empy_string_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/519_experimental_pragma_empy_string_literal.sol new file mode 100644 index 000000000..1a1fde9c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/519_experimental_pragma_empy_string_literal.sol @@ -0,0 +1,3 @@ +pragma experimental ""; +// ---- +// SyntaxError: (0-23): Empty experimental feature name is invalid. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/520_experimental_pragma_multiple_same_line.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/520_experimental_pragma_multiple_same_line.sol new file mode 100644 index 000000000..2eb2bf2a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/520_experimental_pragma_multiple_same_line.sol @@ -0,0 +1,3 @@ +pragma experimental unsupportedName unsupportedName; +// ---- +// SyntaxError: (0-52): Stray arguments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/521_experimental_pragma_test_warning.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/521_experimental_pragma_test_warning.sol new file mode 100644 index 000000000..5f6962f4a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/521_experimental_pragma_test_warning.sol @@ -0,0 +1,3 @@ +pragma experimental __test; +// ---- +// Warning: (0-27): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/522_experimental_pragma_duplicate.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/522_experimental_pragma_duplicate.sol new file mode 100644 index 000000000..ba772a21a --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/522_experimental_pragma_duplicate.sol @@ -0,0 +1,5 @@ +pragma experimental __test; +pragma experimental __test; +// ---- +// Warning: (0-27): Experimental features are turned on. Do not use experimental features on live deployments. +// SyntaxError: (28-55): Duplicate experimental feature name. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/523_reject_interface_creation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/523_reject_interface_creation.sol new file mode 100644 index 000000000..35bba5b31 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/523_reject_interface_creation.sol @@ -0,0 +1,8 @@ +interface I {} +contract C { + function f() public { + new I(); + } +} +// ---- +// TypeError: (62-67): Cannot instantiate an interface. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/524_accept_library_creation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/524_accept_library_creation.sol new file mode 100644 index 000000000..6a5e97af8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/524_accept_library_creation.sol @@ -0,0 +1,6 @@ +library L {} +contract C { + function f() public { + new L(); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/525_reject_interface_constructors.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/525_reject_interface_constructors.sol new file mode 100644 index 000000000..ad08eca62 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/525_reject_interface_constructors.sol @@ -0,0 +1,4 @@ +interface I {} +contract C is I(2) {} +// ---- +// TypeError: (29-33): Wrong argument count for constructor call: 1 arguments given but expected 0. Remove parentheses if you do not want to provide arguments here. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/526_fallback_marked_external.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/526_fallback_marked_external.sol new file mode 100644 index 000000000..6ac551e14 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/526_fallback_marked_external.sol @@ -0,0 +1,3 @@ +contract C { + function () external { } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/527_fallback_marked_internal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/527_fallback_marked_internal.sol new file mode 100644 index 000000000..b8e1c654f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/527_fallback_marked_internal.sol @@ -0,0 +1,5 @@ +contract C { + function () internal { } +} +// ---- +// TypeError: (17-41): Fallback function must be defined as "external". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/528_fallback_marked_private.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/528_fallback_marked_private.sol new file mode 100644 index 000000000..6038a99f1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/528_fallback_marked_private.sol @@ -0,0 +1,5 @@ +contract C { + function () private { } +} +// ---- +// TypeError: (17-40): Fallback function must be defined as "external". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/529_fallback_marked_public.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/529_fallback_marked_public.sol new file mode 100644 index 000000000..d9c1580fa --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/529_fallback_marked_public.sol @@ -0,0 +1,5 @@ +contract C { + function () public { } +} +// ---- +// TypeError: (17-39): Fallback function must be defined as "external". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/530_tuple_invalid_literal_too_large_for_uint.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/530_tuple_invalid_literal_too_large_for_uint.sol new file mode 100644 index 000000000..bbfe22066 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/530_tuple_invalid_literal_too_large_for_uint.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + uint x; + (x, ) = (1E111); + } +} +// ---- +// TypeError: (76-83): Type int_const 1000...(104 digits omitted)...0000 is not implicitly convertible to expected type tuple(uint256,). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/531_tuple_invalid_literal_too_large_unassigned.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/531_tuple_invalid_literal_too_large_unassigned.sol new file mode 100644 index 000000000..6b9cbf79b --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/531_tuple_invalid_literal_too_large_unassigned.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + uint x; + (x, ) = (1, 1E111); + } +} +// ---- +// TypeError: (80-85): Invalid rational number. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/532_tuple_invalid_literal_too_large_for_uint_multi.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/532_tuple_invalid_literal_too_large_for_uint_multi.sol new file mode 100644 index 000000000..a26f9c041 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/532_tuple_invalid_literal_too_large_for_uint_multi.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + uint x; + (x, ) = (1E111, 1); + } +} +// ---- +// TypeError: (77-82): Invalid rational number. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/533_tuple_invalid_literal_too_large_exp.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/533_tuple_invalid_literal_too_large_exp.sol new file mode 100644 index 000000000..9384ec531 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/533_tuple_invalid_literal_too_large_exp.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + (2**270, 1); + } +} +// ---- +// TypeError: (53-59): Invalid rational number. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/534_tuple_invalid_literal_too_large_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/534_tuple_invalid_literal_too_large_expression.sol new file mode 100644 index 000000000..3c322444e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/534_tuple_invalid_literal_too_large_expression.sol @@ -0,0 +1,7 @@ +contract C { + function f() pure public { + ((2**270) / 2**100, 1); + } +} +// ---- +// Warning: (52-74): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol new file mode 100644 index 000000000..01b7b294f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol @@ -0,0 +1,20 @@ +contract C { + function balance() public returns (uint) { + this.balance; // to avoid pureness warning + return 1; + } + function transfer(uint amount) public { + address(this).transfer(amount); // to avoid pureness warning + } + function() payable external { + } +} +contract D { + function f() public { + uint x = (new C()).balance(); + x; + (new C()).transfer(5); + } +} +// ---- +// Warning: (17-134): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/536_array_length_invalid_expression_negative_bool.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/536_array_length_invalid_expression_negative_bool.sol new file mode 100644 index 000000000..c92861eb4 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/536_array_length_invalid_expression_negative_bool.sol @@ -0,0 +1,5 @@ +contract C { + uint[-true] ids; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/537_array_length_invalid_expression_int_divides_bool.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/537_array_length_invalid_expression_int_divides_bool.sol new file mode 100644 index 000000000..92e3c3cfb --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/537_array_length_invalid_expression_int_divides_bool.sol @@ -0,0 +1,5 @@ +contract C { + uint[true/1] ids; +} +// ---- +// TypeError: (22-28): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/538_array_length_invalid_expression_bool_divides_int.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/538_array_length_invalid_expression_bool_divides_int.sol new file mode 100644 index 000000000..26add45ca --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/538_array_length_invalid_expression_bool_divides_int.sol @@ -0,0 +1,5 @@ +contract C { + uint[1/true] ids; +} +// ---- +// TypeError: (22-28): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/539_array_length_invalid_expression_scientific_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/539_array_length_invalid_expression_scientific_literal.sol new file mode 100644 index 000000000..a0d58f4a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/539_array_length_invalid_expression_scientific_literal.sol @@ -0,0 +1,5 @@ +contract C { + uint[1.111111E1111111111111] ids; +} +// ---- +// TypeError: (22-44): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/540_array_length_invalid_expression_division_by_zero.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/540_array_length_invalid_expression_division_by_zero.sol new file mode 100644 index 000000000..38a80867d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/540_array_length_invalid_expression_division_by_zero.sol @@ -0,0 +1,5 @@ +contract C { + uint[3/0] ids; +} +// ---- +// TypeError: (22-25): Operator / not compatible with types int_const 3 and int_const 0 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/541_warn_about_address_members_on_contract_balance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/541_warn_about_address_members_on_contract_balance.sol new file mode 100644 index 000000000..39edaa2db --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/541_warn_about_address_members_on_contract_balance.sol @@ -0,0 +1,7 @@ +contract C { + function f() view public { + this.balance; + } +} +// ---- +// TypeError: (52-64): Member "balance" not found or not visible after argument-dependent lookup in contract C. Use "address(this).balance" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/542_warn_about_address_members_on_contract_transfer.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/542_warn_about_address_members_on_contract_transfer.sol new file mode 100644 index 000000000..a44cc6d2c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/542_warn_about_address_members_on_contract_transfer.sol @@ -0,0 +1,7 @@ +contract C { + function f() view public { + this.transfer; + } +} +// ---- +// TypeError: (52-65): Member "transfer" not found or not visible after argument-dependent lookup in contract C. Use "address(this).transfer" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/543_warn_about_address_members_on_contract_send.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/543_warn_about_address_members_on_contract_send.sol new file mode 100644 index 000000000..e9e26a000 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/543_warn_about_address_members_on_contract_send.sol @@ -0,0 +1,7 @@ +contract C { + function f() view public { + this.send; + } +} +// ---- +// TypeError: (52-61): Member "send" not found or not visible after argument-dependent lookup in contract C. Use "address(this).send" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/544_warn_about_address_members_on_contract_call.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/544_warn_about_address_members_on_contract_call.sol new file mode 100644 index 000000000..16da75789 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/544_warn_about_address_members_on_contract_call.sol @@ -0,0 +1,7 @@ +contract C { + function f() view public { + this.call; + } +} +// ---- +// TypeError: (52-61): Member "call" not found or not visible after argument-dependent lookup in contract C. Use "address(this).call" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/545_warn_about_address_members_on_contract_callcode.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/545_warn_about_address_members_on_contract_callcode.sol new file mode 100644 index 000000000..9292f9c07 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/545_warn_about_address_members_on_contract_callcode.sol @@ -0,0 +1,7 @@ +contract C { + function f() view public { + this.callcode; + } +} +// ---- +// TypeError: (52-65): Member "callcode" not found or not visible after argument-dependent lookup in contract C. Use "address(this).callcode" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/546_warn_about_address_members_on_contract_delegatecall.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/546_warn_about_address_members_on_contract_delegatecall.sol new file mode 100644 index 000000000..20354991f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/546_warn_about_address_members_on_contract_delegatecall.sol @@ -0,0 +1,7 @@ +contract C { + function f() view public { + this.delegatecall; + } +} +// ---- +// TypeError: (52-69): Member "delegatecall" not found or not visible after argument-dependent lookup in contract C. Use "address(this).delegatecall" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/547_warn_about_address_members_on_non_this_contract_balance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/547_warn_about_address_members_on_non_this_contract_balance.sol new file mode 100644 index 000000000..8a4734e67 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/547_warn_about_address_members_on_non_this_contract_balance.sol @@ -0,0 +1,8 @@ +contract C { + function f() view public { + C c; + c.balance; + } +} +// ---- +// TypeError: (65-74): Member "balance" not found or not visible after argument-dependent lookup in contract C. Use "address(c).balance" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/548_warn_about_address_members_on_non_this_contract_transfer.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/548_warn_about_address_members_on_non_this_contract_transfer.sol new file mode 100644 index 000000000..e617f5404 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/548_warn_about_address_members_on_non_this_contract_transfer.sol @@ -0,0 +1,8 @@ +contract C { + function f() view public { + C c; + c.transfer; + } +} +// ---- +// TypeError: (65-75): Member "transfer" not found or not visible after argument-dependent lookup in contract C. Use "address(c).transfer" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/549_warn_about_address_members_on_non_this_contract_send.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/549_warn_about_address_members_on_non_this_contract_send.sol new file mode 100644 index 000000000..54965d4b2 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/549_warn_about_address_members_on_non_this_contract_send.sol @@ -0,0 +1,8 @@ +contract C { + function f() view public { + C c; + c.send; + } +} +// ---- +// TypeError: (65-71): Member "send" not found or not visible after argument-dependent lookup in contract C. Use "address(c).send" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/550_warn_about_address_members_on_non_this_contract_call.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/550_warn_about_address_members_on_non_this_contract_call.sol new file mode 100644 index 000000000..940f383c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/550_warn_about_address_members_on_non_this_contract_call.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + C c; + c.call; + } +} +// ---- +// TypeError: (65-71): Member "call" not found or not visible after argument-dependent lookup in contract C. Use "address(c).call" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/551_warn_about_address_members_on_non_this_contract_callcode.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/551_warn_about_address_members_on_non_this_contract_callcode.sol new file mode 100644 index 000000000..9d4725bd0 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/551_warn_about_address_members_on_non_this_contract_callcode.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + C c; + c.callcode; + } +} +// ---- +// TypeError: (65-75): Member "callcode" not found or not visible after argument-dependent lookup in contract C. Use "address(c).callcode" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/552_warn_about_address_members_on_non_this_contract_delegatecall.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/552_warn_about_address_members_on_non_this_contract_delegatecall.sol new file mode 100644 index 000000000..9941ce1f9 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/552_warn_about_address_members_on_non_this_contract_delegatecall.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public { + C c; + c.delegatecall; + } +} +// ---- +// TypeError: (65-79): Member "delegatecall" not found or not visible after argument-dependent lookup in contract C. Use "address(c).delegatecall" to access this address member. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/559_no_warning_for_using_members_that_look_like_address_members.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/559_no_warning_for_using_members_that_look_like_address_members.sol new file mode 100644 index 000000000..4c1870f10 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/559_no_warning_for_using_members_that_look_like_address_members.sol @@ -0,0 +1,6 @@ +contract C { + function transfer(uint) public; + function f() public { + this.transfer(10); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/560_event_emit_simple.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/560_event_emit_simple.sol new file mode 100644 index 000000000..445c99490 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/560_event_emit_simple.sol @@ -0,0 +1,6 @@ +contract C { + event e(); + function f() public { + emit e(); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/561_event_emit_complex.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/561_event_emit_complex.sol new file mode 100644 index 000000000..194486150 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/561_event_emit_complex.sol @@ -0,0 +1,7 @@ +contract C { + event e(uint a, string b); + function f() public { + emit e(2, "abc"); + emit e({b: "abc", a: 8}); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/562_event_emit_foreign_class.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/562_event_emit_foreign_class.sol new file mode 100644 index 000000000..afac609a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/562_event_emit_foreign_class.sol @@ -0,0 +1,7 @@ +contract A { event e(uint a, string b); } +contract C is A { + function f() public { + emit A.e(2, "abc"); + emit A.e({b: "abc", a: 8}); + } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/563_event_without_emit_deprecated.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/563_event_without_emit_deprecated.sol new file mode 100644 index 000000000..e9a566714 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/563_event_without_emit_deprecated.sol @@ -0,0 +1,8 @@ +contract C { + event e(); + function f() public { + e(); + } +} +// ---- +// TypeError: (62-65): Event invocations have to be prefixed by "emit". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/568_blockhash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/568_blockhash.sol new file mode 100644 index 000000000..f6cc63a5c --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/568_blockhash.sol @@ -0,0 +1,3 @@ +contract C { + function f() public view returns (bytes32) { return blockhash(3); } +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/569_block_blockhash_deprecated.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/569_block_blockhash_deprecated.sol new file mode 100644 index 000000000..b8f5d6a81 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/569_block_blockhash_deprecated.sol @@ -0,0 +1,7 @@ +contract C { + function f() public view returns (bytes32) { + return block.blockhash(3); + } +} +// ---- +// TypeError: (77-92): "block.blockhash()" has been deprecated in favor of "blockhash()" diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/570_function_type_undeclared_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/570_function_type_undeclared_type.sol new file mode 100644 index 000000000..962f4fe4f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/570_function_type_undeclared_type.sol @@ -0,0 +1,5 @@ +contract C { + function a(function(Nested)) external pure {} +} +// ---- +// DeclarationError: (37-43): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/571_function_type_undeclared_type_external.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/571_function_type_undeclared_type_external.sol new file mode 100644 index 000000000..735af9e9d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/571_function_type_undeclared_type_external.sol @@ -0,0 +1,5 @@ +contract C { + function a(function(Nested) external) external pure {} +} +// ---- +// DeclarationError: (37-43): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/572_function_type_undeclared_type_multi_nested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/572_function_type_undeclared_type_multi_nested.sol new file mode 100644 index 000000000..ffb467cde --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/572_function_type_undeclared_type_multi_nested.sol @@ -0,0 +1,5 @@ +contract C { + function a(function(function(function(Nested)))) external pure {} +} +// ---- +// DeclarationError: (55-61): Identifier not found or not unique. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/573_similar_name_longer_than_80_not_suggested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/573_similar_name_longer_than_80_not_suggested.sol new file mode 100644 index 000000000..c6719d8c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/573_similar_name_longer_than_80_not_suggested.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + int YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY = YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; + } +} +// ---- +// DeclarationError: (146-236): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/574_similar_name_shorter_than_80_suggested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/574_similar_name_shorter_than_80_suggested.sol new file mode 100644 index 000000000..61fb2d823 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/574_similar_name_shorter_than_80_suggested.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + int YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY = YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; + } +} +// ---- +// DeclarationError: (137-216): Undeclared identifier. Did you mean "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"? \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/575_member_member_getter_call_without_parentheses.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/575_member_member_getter_call_without_parentheses.sol new file mode 100644 index 000000000..61f431036 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/575_member_member_getter_call_without_parentheses.sol @@ -0,0 +1,19 @@ +contract A{ + function f() public pure{ + + } +} +contract B{ + A public a; +} +contract C{ + B public b; +} +contract D{ + C c; + function f() public view{ + c.b.a.f(); + } +} +// ---- +// TypeError: (170-175): Member "a" not found or not visible after argument-dependent lookup in function () view external returns (contract B). Did you intend to call the function? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/576_member_getter_call_without_parentheses.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/576_member_getter_call_without_parentheses.sol new file mode 100644 index 000000000..bdc5fdc7e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/576_member_getter_call_without_parentheses.sol @@ -0,0 +1,17 @@ +contract A{ + function f() public pure{ + + } +} +contract B{ + A public a; +} +contract C{ + B b; + function f() public view{ + b.a.f(); + } +} + +// ---- +// TypeError: (140-145): Member "f" not found or not visible after argument-dependent lookup in function () view external returns (contract A). Did you intend to call the function? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/577_member_getter_call_without_parentheses_missing_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/577_member_getter_call_without_parentheses_missing_function.sol new file mode 100644 index 000000000..d204d9268 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/577_member_getter_call_without_parentheses_missing_function.sol @@ -0,0 +1,15 @@ +contract A{ + +} +contract B{ + A public a; +} +contract C{ + B b; + function f() public view{ + b.a.f(); + } +} + +// ---- +// TypeError: (104-109): Member "f" not found or not visible after argument-dependent lookup in function () view external returns (contract A). Did you intend to call the function? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/578_private_member_getter_call_without_parentheses.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/578_private_member_getter_call_without_parentheses.sol new file mode 100644 index 000000000..e71da3722 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/578_private_member_getter_call_without_parentheses.sol @@ -0,0 +1,17 @@ +contract A{ + function f() public pure{ + + } +} +contract B{ + A private a; +} +contract C{ + B b; + function f() public view{ + b.a.f(); + } +} + +// ---- +// TypeError: (141-144): Member "a" not found or not visible after argument-dependent lookup in contract B. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/579_member_getter_call_without_parentheses_private_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/579_member_getter_call_without_parentheses_private_function.sol new file mode 100644 index 000000000..189322380 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/579_member_getter_call_without_parentheses_private_function.sol @@ -0,0 +1,17 @@ +contract A{ + function f() private pure{ + + } +} +contract B{ + A public a; +} +contract C{ + B b; + function f() public view{ + b.a.f(); + } +} + +// ---- +// TypeError: (141-146): Member "f" not found or not visible after argument-dependent lookup in function () view external returns (contract A). Did you intend to call the function? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/580_improve_name_suggestion_one_and_two_letters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/580_improve_name_suggestion_one_and_two_letters.sol new file mode 100644 index 000000000..8d2d071b8 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/580_improve_name_suggestion_one_and_two_letters.sol @@ -0,0 +1,14 @@ +contract c { + function f () public + { + a = ac; + a = cd; + a = b; + } + uint256 a; + uint256 ab; +} +// ---- +// DeclarationError: (56-58): Undeclared identifier. Did you mean "ab"? +// DeclarationError: (72-74): Undeclared identifier. +// DeclarationError: (88-89): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/581_improve_name_suggestion_three_letters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/581_improve_name_suggestion_three_letters.sol new file mode 100644 index 000000000..69f5a7e2e --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/581_improve_name_suggestion_three_letters.sol @@ -0,0 +1,12 @@ +contract c { + function f () public + { + a = abd; + a = ade; + } + uint256 a; + uint256 abc; +} +// ---- +// DeclarationError: (56-59): Undeclared identifier. Did you mean "abc" or "abi"? +// DeclarationError: (73-76): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/582_improve_name_suggestion_four_letters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/582_improve_name_suggestion_four_letters.sol new file mode 100644 index 000000000..547ea3088 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/582_improve_name_suggestion_four_letters.sol @@ -0,0 +1,17 @@ +contract c { + function f () public + { + a = land; + a = lost; + a = lang; + } + uint256 long; + uint256 abc; +} +// ---- +// DeclarationError: (52-53): Undeclared identifier. +// DeclarationError: (56-60): Undeclared identifier. Did you mean "long"? +// DeclarationError: (70-71): Undeclared identifier. +// DeclarationError: (74-78): Undeclared identifier. Did you mean "long", "log0", "log1", "log2", "log3" or "log4"? +// DeclarationError: (88-89): Undeclared identifier. +// DeclarationError: (92-96): Undeclared identifier. Did you mean "long"? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/583_abi_encode_packed_with_rational_number_constant.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/583_abi_encode_packed_with_rational_number_constant.sol new file mode 100644 index 000000000..6be591f6d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/583_abi_encode_packed_with_rational_number_constant.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public { abi.encodePacked(0/1); } +} +// ---- +// TypeError: (61-64): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/584_abi_decode_with_tuple_of_other_than_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/584_abi_decode_with_tuple_of_other_than_types.sol new file mode 100644 index 000000000..c95eeb358 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/584_abi_decode_with_tuple_of_other_than_types.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public { abi.decode("", (0)); } +} +// ---- +// TypeError: (60-61): Argument has to be a type name. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_mapping.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_mapping.sol new file mode 100644 index 000000000..61c0cc178 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_mapping.sol @@ -0,0 +1,8 @@ +contract C { + // This should probably have a better error message at some point. + // Constant mappings should not be possible in general. + mapping(uint => uint) constant x; +} +// ---- +// TypeError: (148-180): Constants of non-value type not yet implemented. +// TypeError: (148-180): Uninitialized "constant" variable. diff --git a/test/libsolidity/syntaxTests/parsing/address_constant_payable.sol b/test/libsolidity/syntaxTests/parsing/address_constant_payable.sol new file mode 100644 index 000000000..d98f4ae3d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_constant_payable.sol @@ -0,0 +1,5 @@ +contract C { + address constant payable b = address(0); +} +// ---- +// ParserError: (34-41): Expected identifier but got 'payable' diff --git a/test/libsolidity/syntaxTests/parsing/address_function_arguments_and_returns.sol b/test/libsolidity/syntaxTests/parsing/address_function_arguments_and_returns.sol new file mode 100644 index 000000000..c377600a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_function_arguments_and_returns.sol @@ -0,0 +1,4 @@ +contract C { + function f(address) public pure returns (address) {} + function g(address payable) public pure returns (address payable) {} +} diff --git a/test/libsolidity/syntaxTests/parsing/address_in_struct.sol b/test/libsolidity/syntaxTests/parsing/address_in_struct.sol new file mode 100644 index 000000000..68049b50b --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_in_struct.sol @@ -0,0 +1,6 @@ +contract C { + struct S { + address payable a; + address b; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/address_invalid_state_mutability.sol b/test/libsolidity/syntaxTests/parsing/address_invalid_state_mutability.sol new file mode 100644 index 000000000..606f5cd0e --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_invalid_state_mutability.sol @@ -0,0 +1,26 @@ +contract C { + address view m_a; + address pure m_b; + address view[] m_c; + mapping(uint => address view) m_d; + function f() public pure { + address view a; + address pure b; + a; b; + } + function g(address view) public pure {} + function h(address pure) public pure {} + function i() public pure returns (address view) {} + function j() public pure returns (address pure) {} +} +// ---- +// TypeError: (14-26): Address types can only be payable or non-payable. +// TypeError: (33-45): Address types can only be payable or non-payable. +// TypeError: (52-64): Address types can only be payable or non-payable. +// TypeError: (89-101): Address types can only be payable or non-payable. +// TypeError: (195-207): Address types can only be payable or non-payable. +// TypeError: (236-248): Address types can only be payable or non-payable. +// TypeError: (300-312): Address types can only be payable or non-payable. +// TypeError: (352-364): Address types can only be payable or non-payable. +// TypeError: (138-150): Address types can only be payable or non-payable. +// TypeError: (156-168): Address types can only be payable or non-payable. diff --git a/test/libsolidity/syntaxTests/parsing/address_nonpayable.sol b/test/libsolidity/syntaxTests/parsing/address_nonpayable.sol new file mode 100644 index 000000000..fea671387 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_nonpayable.sol @@ -0,0 +1,7 @@ +contract C { + address a; + function f(address b) public pure returns (address c) { + address d = b; + return d; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/address_payable.sol b/test/libsolidity/syntaxTests/parsing/address_payable.sol new file mode 100644 index 000000000..c29ae1b7c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable.sol @@ -0,0 +1,7 @@ +contract C { + address payable a; + function f(address payable b) public pure returns (address payable c) { + address payable d = b; + return d; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_constant.sol b/test/libsolidity/syntaxTests/parsing/address_payable_constant.sol new file mode 100644 index 000000000..154bfb54b --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_constant.sol @@ -0,0 +1,3 @@ +contract C { + address payable constant a = address(0); +} diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_conversion.sol b/test/libsolidity/syntaxTests/parsing/address_payable_conversion.sol new file mode 100644 index 000000000..bf073a52a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_conversion.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + address payable a = address payable(this); + } +} +// ---- +// ParserError: (80-87): Expected ';' but got 'payable' diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_function_type.sol b/test/libsolidity/syntaxTests/parsing/address_payable_function_type.sol new file mode 100644 index 000000000..234b528a8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_function_type.sol @@ -0,0 +1,6 @@ +contract C { + function (address payable) view internal returns (address payable) f; + function g(function (address payable) payable external returns (address payable)) public payable returns (function (address payable) payable external returns (address payable)) { + function (address payable) payable external returns (address payable) h; h; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_library.sol b/test/libsolidity/syntaxTests/parsing/address_payable_library.sol new file mode 100644 index 000000000..33787d337 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_library.sol @@ -0,0 +1,5 @@ +library L { +} +contract C { + using L for address payable; +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_local.sol b/test/libsolidity/syntaxTests/parsing/address_payable_local.sol new file mode 100644 index 000000000..544f7c21d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_local.sol @@ -0,0 +1,11 @@ +contract C { + mapping(uint => address payable) m; + mapping(uint => address payable[]) n; + function f() public view { + address payable a; + address payable[] memory b; + mapping(uint => address payable) storage c = m; + mapping(uint => address payable[]) storage d = n; + a; b; c; d; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_state_variable.sol b/test/libsolidity/syntaxTests/parsing/address_payable_state_variable.sol new file mode 100644 index 000000000..12c2468dd --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_state_variable.sol @@ -0,0 +1,8 @@ +contract C { + address payable a; + address payable public b; + address payable[] c; + address payable[] public d; + mapping(uint => address payable) e; + mapping(uint => address payable[]) f; +} diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_struct.sol b/test/libsolidity/syntaxTests/parsing/address_payable_struct.sol new file mode 100644 index 000000000..6c281bc76 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_struct.sol @@ -0,0 +1,8 @@ +contract C { + struct S { + address payable a; + address payable[] b; + mapping(uint => address payable) c; + mapping(uint => address payable[]) d; + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_type_expression.sol b/test/libsolidity/syntaxTests/parsing/address_payable_type_expression.sol new file mode 100644 index 000000000..394b39c09 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_payable_type_expression.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + address payable; + } +} +// ---- +// ParserError: (67-68): Expected identifier but got ';' diff --git a/test/libsolidity/syntaxTests/parsing/address_public_payable_error.sol b/test/libsolidity/syntaxTests/parsing/address_public_payable_error.sol new file mode 100644 index 000000000..0acf5e4be --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/address_public_payable_error.sol @@ -0,0 +1,5 @@ +contract C { + address public payable a; +} +// ---- +// ParserError: (32-39): Expected identifier but got 'payable' diff --git a/test/libsolidity/syntaxTests/parsing/arrays_in_events.sol b/test/libsolidity/syntaxTests/parsing/arrays_in_events.sol new file mode 100644 index 000000000..edbc96650 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/arrays_in_events.sol @@ -0,0 +1,3 @@ +contract c { + event e(uint[10] a, bytes7[8] indexed b, c[3] x); +} diff --git a/test/libsolidity/syntaxTests/parsing/arrays_in_expressions.sol b/test/libsolidity/syntaxTests/parsing/arrays_in_expressions.sol new file mode 100644 index 000000000..4c1f96e6e --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/arrays_in_expressions.sol @@ -0,0 +1,6 @@ +contract c { + function f() public { c[10] storage a = 7; uint8[10 * 2] storage x; } +} +// ---- +// TypeError: (39-58): Type int_const 7 is not implicitly convertible to expected type contract c[10] storage pointer. +// DeclarationError: (60-83): Uninitialized storage pointer. diff --git a/test/libsolidity/syntaxTests/parsing/arrays_in_storage.sol b/test/libsolidity/syntaxTests/parsing/arrays_in_storage.sol new file mode 100644 index 000000000..9adf6f125 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/arrays_in_storage.sol @@ -0,0 +1,6 @@ +contract c { + uint[10] a; + uint[] a2; + struct x { uint[2**20] b; y[1] c; } + struct y { uint d; mapping(uint=>x)[] e; } +} diff --git a/test/libsolidity/syntaxTests/parsing/assembly_evmasm_type.sol b/test/libsolidity/syntaxTests/parsing/assembly_evmasm_type.sol new file mode 100644 index 000000000..28a07e634 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/assembly_evmasm_type.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure { + assembly "evmasm" {} + } +} diff --git a/test/libsolidity/syntaxTests/parsing/assembly_invalid_type.sol b/test/libsolidity/syntaxTests/parsing/assembly_invalid_type.sol new file mode 100644 index 000000000..c2d39279f --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/assembly_invalid_type.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + assembly "failasm" {} + } +} +// ---- +// ParserError: (55-64): Only "evmasm" supported. diff --git a/test/libsolidity/syntaxTests/parsing/calling_function.sol b/test/libsolidity/syntaxTests/parsing/calling_function.sol new file mode 100644 index 000000000..9e88c4519 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/calling_function.sol @@ -0,0 +1,7 @@ +contract test { + function f() public { + function() returns(function() returns(function() returns(function() returns(uint)))) x; + uint y; + y = x()()()(); + } +} diff --git a/test/libsolidity/syntaxTests/parsing/conditional_multiple.sol b/test/libsolidity/syntaxTests/parsing/conditional_multiple.sol new file mode 100644 index 000000000..0e348f5b7 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/conditional_multiple.sol @@ -0,0 +1,8 @@ +contract A { + function f() public { + uint x = 3 < 0 ? 2 > 1 ? 2 : 1 : 7 > 2 ? 7 : 6; + } +} +// ---- +// Warning: (47-53): Unused local variable. +// Warning: (17-100): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/conditional_true_false_literal.sol b/test/libsolidity/syntaxTests/parsing/conditional_true_false_literal.sol new file mode 100644 index 000000000..40aaa9170 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/conditional_true_false_literal.sol @@ -0,0 +1,10 @@ +contract A { + function f() public { + uint x = true ? 1 : 0; + uint y = false ? 0 : 1; + } +} +// ---- +// Warning: (47-53): Unused local variable. +// Warning: (78-84): Unused local variable. +// Warning: (17-107): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/conditional_with_assignment.sol b/test/libsolidity/syntaxTests/parsing/conditional_with_assignment.sol new file mode 100644 index 000000000..7489aaf92 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/conditional_with_assignment.sol @@ -0,0 +1,8 @@ +contract A { + function f() public pure { + uint y = 1; + uint x = 3 < 0 ? y = 3 : 6; + true ? x = 3 : 4; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/conditional_with_constants.sol b/test/libsolidity/syntaxTests/parsing/conditional_with_constants.sol new file mode 100644 index 000000000..705fbadf3 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/conditional_with_constants.sol @@ -0,0 +1,10 @@ +contract A { + function f() public { + uint x = 3 > 0 ? 3 : 0; + uint y = (3 > 0) ? 3 : 0; + } +} +// ---- +// Warning: (47-53): Unused local variable. +// Warning: (79-85): Unused local variable. +// Warning: (17-110): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/conditional_with_variables.sol b/test/libsolidity/syntaxTests/parsing/conditional_with_variables.sol new file mode 100644 index 000000000..bbabf9578 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/conditional_with_variables.sol @@ -0,0 +1,12 @@ +contract A { + function f() public { + uint x = 3; + uint y = 1; + uint z = (x > y) ? x : y; + uint w = x > y ? x : y; + } +} +// ---- +// Warning: (87-93): Unused local variable. +// Warning: (121-127): Unused local variable. +// Warning: (17-150): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/constant_state_modifier.sol b/test/libsolidity/syntaxTests/parsing/constant_state_modifier.sol index da068351d..8fddc9888 100644 --- a/test/libsolidity/syntaxTests/parsing/constant_state_modifier.sol +++ b/test/libsolidity/syntaxTests/parsing/constant_state_modifier.sol @@ -1,7 +1,8 @@ contract C { uint s; - // this test should fail starting from 0.5.0 function f() public constant returns (uint) { return s; } } +// ---- +// ParserError: (43-51): The state mutability modifier "constant" was removed in version 0.5.0. Use "view" or "pure" instead. diff --git a/test/libsolidity/syntaxTests/parsing/constructor_allowed_this.sol b/test/libsolidity/syntaxTests/parsing/constructor_allowed_this.sol index 9f714aeab..b66253e4f 100644 --- a/test/libsolidity/syntaxTests/parsing/constructor_allowed_this.sol +++ b/test/libsolidity/syntaxTests/parsing/constructor_allowed_this.sol @@ -3,9 +3,9 @@ contract A { } } contract B { - constructor(address) public { + constructor(C) public { } - function b(address) public returns (A) { + function b(C) public returns (A) { return new A(); } } diff --git a/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol new file mode 100644 index 000000000..6d88669af --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol @@ -0,0 +1,13 @@ +contract A { + fixed40x40 storeMe; + function f(ufixed x, fixed32x32 y) public { + ufixed8x8 a; + fixed b; + } +} +// ---- +// Warning: (52-60): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (62-74): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (93-104): Unused local variable. +// Warning: (114-121): Unused local variable. +// Warning: (41-128): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/declaring_fixed_literal_variables.sol b/test/libsolidity/syntaxTests/parsing/declaring_fixed_literal_variables.sol new file mode 100644 index 000000000..b0d938a01 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/declaring_fixed_literal_variables.sol @@ -0,0 +1,5 @@ +contract A { + fixed40x40 pi = 3.14; +} +// ---- +// TypeError: (33-37): Type rational_const 157 / 50 is not implicitly convertible to expected type fixed40x40. Try converting to type ufixed16x2 or use an explicit conversion. diff --git a/test/libsolidity/syntaxTests/parsing/elemantary_non_address_payable_state_variable.sol b/test/libsolidity/syntaxTests/parsing/elemantary_non_address_payable_state_variable.sol new file mode 100644 index 000000000..41b2762b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elemantary_non_address_payable_state_variable.sol @@ -0,0 +1,29 @@ +contract C { + bool payable a; + string payable b; + int payable c; + int256 payable d; + uint payable e; + uint256 payable f; + byte payable g; + bytes payable h; + bytes32 payable i; + fixed payable j; + fixed80x80 payable k; + ufixed payable l; + ufixed80x80 payable m; +} +// ---- +// ParserError: (22-29): State mutability can only be specified for address types. +// ParserError: (44-51): State mutability can only be specified for address types. +// ParserError: (63-70): State mutability can only be specified for address types. +// ParserError: (85-92): State mutability can only be specified for address types. +// ParserError: (105-112): State mutability can only be specified for address types. +// ParserError: (128-135): State mutability can only be specified for address types. +// ParserError: (148-155): State mutability can only be specified for address types. +// ParserError: (169-176): State mutability can only be specified for address types. +// ParserError: (192-199): State mutability can only be specified for address types. +// ParserError: (213-220): State mutability can only be specified for address types. +// ParserError: (239-246): State mutability can only be specified for address types. +// ParserError: (261-268): State mutability can only be specified for address types. +// ParserError: (288-295): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_argument.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_argument.sol new file mode 100644 index 000000000..9cb0fb4f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_argument.sol @@ -0,0 +1,29 @@ +contract C { + function a(bool payable) public pure {} + function b(string payable) public pure {} + function c(int payable) public pure {} + function d(int256 payable) public pure {} + function e(uint payable) public pure {} + function f(uint256 payable) public pure {} + function g(byte payable) public pure {} + function h(bytes payable) public pure {} + function i(bytes32 payable) public pure {} + function j(fixed payable) public pure {} + function k(fixed80x80 payable) public pure {} + function l(ufixed payable) public pure {} + function m(ufixed80x80 payable) public pure {} +} +// ---- +// ParserError: (33-40): State mutability can only be specified for address types. +// ParserError: (79-86): State mutability can only be specified for address types. +// ParserError: (122-129): State mutability can only be specified for address types. +// ParserError: (168-175): State mutability can only be specified for address types. +// ParserError: (212-219): State mutability can only be specified for address types. +// ParserError: (259-266): State mutability can only be specified for address types. +// ParserError: (303-310): State mutability can only be specified for address types. +// ParserError: (348-355): State mutability can only be specified for address types. +// ParserError: (395-402): State mutability can only be specified for address types. +// ParserError: (440-447): State mutability can only be specified for address types. +// ParserError: (490-497): State mutability can only be specified for address types. +// ParserError: (536-543): State mutability can only be specified for address types. +// ParserError: (587-594): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_local.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_local.sol new file mode 100644 index 000000000..3d47f1c77 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_local.sol @@ -0,0 +1,31 @@ +contract C { + function f() public pure { + bool payable a; + string payable b; + int payable c; + int256 payable d; + uint payable e; + uint256 payable f; + byte payable g; + bytes payable h; + bytes32 payable i; + fixed payable j; + fixed80x80 payable k; + ufixed payable l; + ufixed80x80 payable m; + } +} +// ---- +// ParserError: (57-64): State mutability can only be specified for address types. +// ParserError: (83-90): State mutability can only be specified for address types. +// ParserError: (106-113): State mutability can only be specified for address types. +// ParserError: (132-139): State mutability can only be specified for address types. +// ParserError: (156-163): State mutability can only be specified for address types. +// ParserError: (183-190): State mutability can only be specified for address types. +// ParserError: (207-214): State mutability can only be specified for address types. +// ParserError: (232-239): State mutability can only be specified for address types. +// ParserError: (259-266): State mutability can only be specified for address types. +// ParserError: (284-291): State mutability can only be specified for address types. +// ParserError: (314-321): State mutability can only be specified for address types. +// ParserError: (340-347): State mutability can only be specified for address types. +// ParserError: (371-378): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_return.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_return.sol new file mode 100644 index 000000000..fc7a3c25a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_return.sol @@ -0,0 +1,29 @@ +contract C { + function a() public pure returns (bool payable) {} + function b() public pure returns (string payable) {} + function c() public pure returns (int payable) {} + function d() public pure returns (int256 payable) {} + function e() public pure returns (uint payable) {} + function f() public pure returns (uint256 payable) {} + function g() public pure returns (byte payable) {} + function h() public pure returns (bytes payable) {} + function i() public pure returns (bytes32 payable) {} + function j() public pure returns (fixed payable) {} + function k() public pure returns (fixed80x80 payable) {} + function l() public pure returns (ufixed payable) {} + function m() public pure returns (ufixed80x80 payable) {} +} +// ---- +// ParserError: (56-63): State mutability can only be specified for address types. +// ParserError: (113-120): State mutability can only be specified for address types. +// ParserError: (167-174): State mutability can only be specified for address types. +// ParserError: (224-231): State mutability can only be specified for address types. +// ParserError: (279-286): State mutability can only be specified for address types. +// ParserError: (337-344): State mutability can only be specified for address types. +// ParserError: (392-399): State mutability can only be specified for address types. +// ParserError: (448-455): State mutability can only be specified for address types. +// ParserError: (506-513): State mutability can only be specified for address types. +// ParserError: (562-569): State mutability can only be specified for address types. +// ParserError: (623-630): State mutability can only be specified for address types. +// ParserError: (680-687): State mutability can only be specified for address types. +// ParserError: (742-749): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/else_if_statement.sol b/test/libsolidity/syntaxTests/parsing/else_if_statement.sol new file mode 100644 index 000000000..c2a1aaeb7 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/else_if_statement.sol @@ -0,0 +1,7 @@ +contract test { + function fun(uint256 a) public returns (uint8 b) { + if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78; + } +} +// ---- +// Warning: (20-147): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/empty_function.sol b/test/libsolidity/syntaxTests/parsing/empty_function.sol index 218fd9a74..320a0bccd 100644 --- a/test/libsolidity/syntaxTests/parsing/empty_function.sol +++ b/test/libsolidity/syntaxTests/parsing/empty_function.sol @@ -1,10 +1,9 @@ contract test { uint256 stateVar; - function functionName(bytes20 arg1, address addr) view returns (int id) { } + function functionName(bytes20 arg1, address addr) public view returns (int id) { } } // ---- -// Warning: (36-111): No visibility specified. Defaulting to "public". // Warning: (58-70): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning: (72-84): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (100-106): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (36-111): Function state mutability can be restricted to pure +// Warning: (107-113): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (36-118): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/enum_from_interface.sol b/test/libsolidity/syntaxTests/parsing/enum_from_interface.sol new file mode 100644 index 000000000..0fe0fbaee --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_from_interface.sol @@ -0,0 +1,9 @@ +interface I { + enum Direction { Left, Right } +} + +contract D { + function f() public pure returns (I.Direction) { + return I.Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_from_interface_in_library.sol b/test/libsolidity/syntaxTests/parsing/enum_from_interface_in_library.sol new file mode 100644 index 000000000..8d9003eb6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_from_interface_in_library.sol @@ -0,0 +1,12 @@ +interface I { + enum Direction { Left, Right } +} + +library L { + function f() public pure returns (I.Direction) { + return I.Direction.Left; + } + function g() internal pure returns (I.Direction) { + return I.Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_from_library.sol b/test/libsolidity/syntaxTests/parsing/enum_from_library.sol new file mode 100644 index 000000000..ab762a82b --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_from_library.sol @@ -0,0 +1,9 @@ +library L { + enum Direction { Left, Right } +} + +contract D { + function f() public pure returns (L.Direction) { + return L.Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_inheritance_contract.sol b/test/libsolidity/syntaxTests/parsing/enum_inheritance_contract.sol new file mode 100644 index 000000000..e5b98352b --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_inheritance_contract.sol @@ -0,0 +1,9 @@ +contract C { + enum Direction { Left, Right } +} + +contract D is C { + function f() public pure returns (Direction) { + return Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_inheritance_interface.sol b/test/libsolidity/syntaxTests/parsing/enum_inheritance_interface.sol new file mode 100644 index 000000000..758587445 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_inheritance_interface.sol @@ -0,0 +1,9 @@ +interface I { + enum Direction { Left, Right } +} + +contract D is I { + function f() public pure returns (Direction) { + return Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_valid_declaration.sol b/test/libsolidity/syntaxTests/parsing/enum_valid_declaration.sol new file mode 100644 index 000000000..606f59d72 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_valid_declaration.sol @@ -0,0 +1,7 @@ +contract c { + enum validEnum { Value1, Value2, Value3, Value4 } + constructor() public { + a = validEnum.Value3; + } + validEnum a; +} diff --git a/test/libsolidity/syntaxTests/parsing/event.sol b/test/libsolidity/syntaxTests/parsing/event.sol new file mode 100644 index 000000000..2aaa873fe --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/event.sol @@ -0,0 +1,3 @@ +contract c { + event e(); +} diff --git a/test/libsolidity/syntaxTests/parsing/event_arguments.sol b/test/libsolidity/syntaxTests/parsing/event_arguments.sol new file mode 100644 index 000000000..3228853af --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/event_arguments.sol @@ -0,0 +1,3 @@ +contract c { + event e(uint a, bytes32 s); +} diff --git a/test/libsolidity/syntaxTests/parsing/event_arguments_indexed.sol b/test/libsolidity/syntaxTests/parsing/event_arguments_indexed.sol new file mode 100644 index 000000000..d603fc083 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/event_arguments_indexed.sol @@ -0,0 +1,3 @@ +contract c { + event e(uint a, bytes32 indexed s, bool indexed b); +} diff --git a/test/libsolidity/syntaxTests/parsing/exp_expression.sol b/test/libsolidity/syntaxTests/parsing/exp_expression.sol new file mode 100644 index 000000000..6b307ea07 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/exp_expression.sol @@ -0,0 +1,8 @@ +contract test { + function fun(uint256 a) public { + uint256 x = 3 ** a; + } +} +// ---- +// Warning: (61-70): Unused local variable. +// Warning: (20-86): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/external_function.sol b/test/libsolidity/syntaxTests/parsing/external_function.sol new file mode 100644 index 000000000..3aa3ceec4 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/external_function.sol @@ -0,0 +1,5 @@ +contract c { + function x() external {} +} +// ---- +// Warning: (17-41): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/fallback_function.sol b/test/libsolidity/syntaxTests/parsing/fallback_function.sol new file mode 100644 index 000000000..054f57ded --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/fallback_function.sol @@ -0,0 +1,4 @@ +contract c { + function() external { } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/for_loop_simple_initexpr.sol b/test/libsolidity/syntaxTests/parsing/for_loop_simple_initexpr.sol new file mode 100644 index 000000000..fce669ddd --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/for_loop_simple_initexpr.sol @@ -0,0 +1,12 @@ +contract test { + function fun(uint256 a) public { + uint256 i =0; + for (i = 0; i < 10; i++) { + uint256 x = i; break; continue; + } + } +} +// ---- +// Warning: (33-42): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (122-131): Unused local variable. +// Warning: (20-169): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/for_loop_simple_noexpr.sol b/test/libsolidity/syntaxTests/parsing/for_loop_simple_noexpr.sol new file mode 100644 index 000000000..4adf0948f --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/for_loop_simple_noexpr.sol @@ -0,0 +1,12 @@ +contract test { + function fun(uint256 a) public { + uint256 i =0; + for (;;) { + uint256 x = i; break; continue; + } + } + } +// ---- +// Warning: (37-46): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (122-131): Unused local variable. +// Warning: (24-177): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/for_loop_single_stmt_body.sol b/test/libsolidity/syntaxTests/parsing/for_loop_single_stmt_body.sol new file mode 100644 index 000000000..c6af519cd --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/for_loop_single_stmt_body.sol @@ -0,0 +1,10 @@ +contract test { + function fun(uint256 a) public { + uint256 i = 0; + for (i = 0; i < 10; i++) + continue; + } +} +// ---- +// Warning: (33-42): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (20-136): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/for_loop_vardef_initexpr.sol b/test/libsolidity/syntaxTests/parsing/for_loop_vardef_initexpr.sol new file mode 100644 index 000000000..c22ae42fd --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/for_loop_vardef_initexpr.sol @@ -0,0 +1,11 @@ +contract test { + function fun(uint256 a) public { + for (uint256 i = 0; i < 10; i++) { + uint256 x = i; break; continue; + } + } +} +// ---- +// Warning: (33-42): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (108-117): Unused local variable. +// Warning: (20-155): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/from_is_not_keyword.sol b/test/libsolidity/syntaxTests/parsing/from_is_not_keyword.sol new file mode 100644 index 000000000..38175572a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/from_is_not_keyword.sol @@ -0,0 +1,3 @@ +// "from" is not a keyword although it is used as a keyword in import directives. +contract from { +} diff --git a/test/libsolidity/syntaxTests/parsing/function_no_body.sol b/test/libsolidity/syntaxTests/parsing/function_no_body.sol index 0424ebd89..c4a686dcc 100644 --- a/test/libsolidity/syntaxTests/parsing/function_no_body.sol +++ b/test/libsolidity/syntaxTests/parsing/function_no_body.sol @@ -1,5 +1,3 @@ contract test { - function functionName(bytes32 input) returns (bytes32 out); + function functionName(bytes32 input) public returns (bytes32 out); } -// ---- -// Warning: (17-76): No visibility specified. Defaulting to "public". diff --git a/test/libsolidity/syntaxTests/parsing/function_normal_comments.sol b/test/libsolidity/syntaxTests/parsing/function_normal_comments.sol new file mode 100644 index 000000000..94e1e60a4 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/function_normal_comments.sol @@ -0,0 +1,9 @@ +contract test { + uint256 stateVar; + // We won't see this comment + function functionName(bytes32 input) public returns (bytes32 out) {} +} +// ---- +// Warning: (97-110): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (128-139): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (75-143): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/function_type_as_parameter.sol b/test/libsolidity/syntaxTests/parsing/function_type_as_parameter.sol new file mode 100644 index 000000000..4075d74a4 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/function_type_as_parameter.sol @@ -0,0 +1,5 @@ +contract test { + function f(function(uint) external returns (uint) g) internal returns (uint a) { + return g(1); + } +} diff --git a/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable.sol b/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable.sol new file mode 100644 index 000000000..e3d41f483 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable.sol @@ -0,0 +1,3 @@ +contract test { + function (uint, uint) internal returns (uint) f1; +} diff --git a/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable_with_assignment.sol b/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable_with_assignment.sol new file mode 100644 index 000000000..11e77f250 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable_with_assignment.sol @@ -0,0 +1,9 @@ +contract test { + function f(uint x, uint y) public returns (uint a) {} + function (uint, uint) internal returns (uint) f1 = f; +} +// ---- +// Warning: (31-37): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (39-45): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (63-69): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (20-73): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/function_type_in_expression.sol b/test/libsolidity/syntaxTests/parsing/function_type_in_expression.sol new file mode 100644 index 000000000..3defb5ea9 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/function_type_in_expression.sol @@ -0,0 +1,13 @@ +contract test { + function f(uint x, uint y) public returns (uint a) {} + function g() public { + function (uint, uint) internal returns (uint) f1 = f; + } +} +// ---- +// Warning: (31-37): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (39-45): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (63-69): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (108-156): Unused local variable. +// Warning: (20-73): Function state mutability can be restricted to pure +// Warning: (78-167): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/function_type_in_struct.sol b/test/libsolidity/syntaxTests/parsing/function_type_in_struct.sol new file mode 100644 index 000000000..c7703b47c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/function_type_in_struct.sol @@ -0,0 +1,10 @@ +contract test { + struct S { + function (uint x, uint y) internal returns (uint) f; + function (uint, uint) external returns (uint) g; + uint d; + } +} +// ---- +// Warning: (49-55): Naming function type parameters is deprecated. +// Warning: (57-63): Naming function type parameters is deprecated. diff --git a/test/libsolidity/syntaxTests/parsing/if_statement.sol b/test/libsolidity/syntaxTests/parsing/if_statement.sol new file mode 100644 index 000000000..b3269785d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/if_statement.sol @@ -0,0 +1,8 @@ +contract test { + function fun(uint256 a) public returns (uint) { + if (a >= 8) { return 2; } else { uint b = 7; } + } +} +// ---- +// Warning: (109-115): Unused local variable. +// Warning: (20-128): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/import_complex.sol b/test/libsolidity/syntaxTests/parsing/import_complex.sol new file mode 100644 index 000000000..8bbb0a883 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/import_complex.sol @@ -0,0 +1,3 @@ +import {hello, world} from "hello"; +// ---- +// ParserError: (0-35): Source "hello" not found: File not supplied initially. diff --git a/test/libsolidity/syntaxTests/parsing/import_complex_invalid_from.sol b/test/libsolidity/syntaxTests/parsing/import_complex_invalid_from.sol new file mode 100644 index 000000000..c46676065 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/import_complex_invalid_from.sol @@ -0,0 +1,3 @@ +import {hello, world} from function; +// ---- +// ParserError: (27-35): Expected import path. diff --git a/test/libsolidity/syntaxTests/parsing/import_complex_without_from.sol b/test/libsolidity/syntaxTests/parsing/import_complex_without_from.sol new file mode 100644 index 000000000..961acb22b --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/import_complex_without_from.sol @@ -0,0 +1,3 @@ +import {hello, world}; +// ---- +// ParserError: (21-22): Expected "from". diff --git a/test/libsolidity/syntaxTests/parsing/import_invalid_token.sol b/test/libsolidity/syntaxTests/parsing/import_invalid_token.sol new file mode 100644 index 000000000..df837e283 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/import_invalid_token.sol @@ -0,0 +1,3 @@ +import function; +// ---- +// ParserError: (7-15): Expected string literal (path), "*" or alias list. diff --git a/test/libsolidity/syntaxTests/parsing/import_simple.sol b/test/libsolidity/syntaxTests/parsing/import_simple.sol new file mode 100644 index 000000000..5d61a8bbf --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/import_simple.sol @@ -0,0 +1,3 @@ +import "hello"; +// ---- +// ParserError: (0-15): Source "hello" not found: File not supplied initially. diff --git a/test/libsolidity/syntaxTests/parsing/inline_array_declaration.sol b/test/libsolidity/syntaxTests/parsing/inline_array_declaration.sol new file mode 100644 index 000000000..4730f9502 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/inline_array_declaration.sol @@ -0,0 +1,8 @@ +contract c { + uint[] a; + function f() public returns (uint, uint) { + a = [1,2,3]; + return (a[3], [2,3,4][0]); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/interface_basic.sol b/test/libsolidity/syntaxTests/parsing/interface_basic.sol index c25b48bae..0742c24f6 100644 --- a/test/libsolidity/syntaxTests/parsing/interface_basic.sol +++ b/test/libsolidity/syntaxTests/parsing/interface_basic.sol @@ -1,6 +1,4 @@ interface Interface { - function f(); + function f() external; } // ---- -// Warning: (23-36): Functions in interfaces should be declared external. -// Warning: (23-36): No visibility specified. Defaulting to "public". In interfaces it defaults to external. diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal.sol new file mode 100644 index 000000000..d4d3299f8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + uint d1 = 654_321; + uint d2 = 54_321; + uint d3 = 4_321; + uint d4 = 5_43_21; + uint d5 = 1_2e10; + uint d6 = 12e1_0; + + d1; d2; d3; d4; d5; d6; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal_fail.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal_fail.sol new file mode 100644 index 000000000..8978996dc --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal_fail.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + uint D1 = 1234_; + uint D2 = 12__34; + uint D3 = 12_e34; + uint D4 = 12e_34; + } +} +// ---- +// SyntaxError: (56-61): Invalid use of underscores in number literal. No trailing underscores allowed. +// SyntaxError: (77-83): Invalid use of underscores in number literal. Only one consecutive underscores between digits allowed. +// SyntaxError: (99-105): Invalid use of underscores in number literal. No underscore at the end of the mantissa allowed. +// SyntaxError: (121-127): Invalid use of underscores in number literal. No underscore in front of exponent allowed. diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol new file mode 100644 index 000000000..4910ee829 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + fixed f1 = 3.14_15; + fixed f2 = 3_1.4_15; + + f1; f2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed_fail.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed_fail.sol new file mode 100644 index 000000000..3b91895d5 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed_fail.sol @@ -0,0 +1,17 @@ +contract C { + function f() public pure { + fixed F1 = 3.1415_; + fixed F2 = 3__1.4__15; + fixed F3 = 1_.2; + fixed F4 = 1._2; + fixed F5 = 1.2e_12; + fixed F6 = 1._; + } +} +// ---- +// SyntaxError: (57-64): Invalid use of underscores in number literal. No trailing underscores allowed. +// SyntaxError: (81-91): Invalid use of underscores in number literal. Only one consecutive underscores between digits allowed. +// SyntaxError: (108-112): Invalid use of underscores in number literal. No underscores in front of the fraction part allowed. +// SyntaxError: (129-133): Invalid use of underscores in number literal. No underscores in front of the fraction part allowed. +// SyntaxError: (150-157): Invalid use of underscores in number literal. No underscore in front of exponent allowed. +// SyntaxError: (174-177): Invalid use of underscores in number literal. No trailing underscores allowed. diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex.sol new file mode 100644 index 000000000..999a4634d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + uint x1 = 0x8765_4321; + uint x2 = 0x765_4321; + uint x3 = 0x65_4321; + uint x4 = 0x5_4321; + uint x5 = 0x123_1234_1234_1234; + uint x6 = 0x123456_1234_1234; + + x1; x2; x3; x4; x5; x6; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex_fail.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex_fail.sol new file mode 100644 index 000000000..a8a488c14 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex_fail.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + uint X1 = 0x1234__1234__1234__123; + } +} +// ---- +// SyntaxError: (56-79): Invalid use of underscores in number literal. Only one consecutive underscores between digits allowed. diff --git a/test/libsolidity/syntaxTests/parsing/library_simple.sol b/test/libsolidity/syntaxTests/parsing/library_simple.sol new file mode 100644 index 000000000..006ff3073 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/library_simple.sol @@ -0,0 +1,5 @@ +library Lib { + function f() public { } +} +// ---- +// Warning: (18-41): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations.sol b/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations.sol new file mode 100644 index 000000000..64116b882 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations.sol @@ -0,0 +1,15 @@ +contract c { + function f() public + { + a = 1 wei; + b = 2 szabo; + c = 3 finney; + b = 4 ether; + } + uint256 a; + uint256 b; + uint256 c; + uint256 d; +} +// ---- +// Warning: (170-179): This declaration shadows an existing declaration. diff --git a/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations_in_expressions.sol b/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations_in_expressions.sol new file mode 100644 index 000000000..2f2302ed2 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations_in_expressions.sol @@ -0,0 +1,7 @@ +contract c { + constructor() public + { + a = 1 wei * 100 wei + 7 szabo - 3; + } + uint256 a; +} diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals.sol new file mode 100644 index 000000000..38de7b1c6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals.sol @@ -0,0 +1,9 @@ +contract Foo { + uint[] m_x; + function f() public view { + uint[] storage x = m_x; + uint[] memory y; + x; y; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals_multi.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals_multi.sol new file mode 100644 index 000000000..d53208ef2 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals_multi.sol @@ -0,0 +1,12 @@ +contract Foo { + uint[] m_x; + function f() public view { + uint[] storage memory x = m_x; + uint[] memory storage calldata y; + x; y; + } +} +// ---- +// ParserError: (85-91): Location already specified. +// ParserError: (123-130): Location already specified. +// ParserError: (131-139): Location already specified. diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params.sol new file mode 100644 index 000000000..bf78e59c6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params.sol @@ -0,0 +1,7 @@ +contract Foo { + function f(uint[] storage constant x, uint[] memory y) internal { } +} +// ---- +// DeclarationError: (30-55): The "constant" keyword can only be used for state variables. +// TypeError: (30-55): Constants of non-value type not yet implemented. +// TypeError: (30-55): Uninitialized "constant" variable. diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params_multi.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params_multi.sol new file mode 100644 index 000000000..c6155c090 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params_multi.sol @@ -0,0 +1,6 @@ +contract Foo { + function f(uint[] storage memory constant x, uint[] memory calldata y) internal { } +} +// ---- +// ParserError: (45-51): Location already specified. +// ParserError: (78-86): Location already specified. diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_state_variables_multi.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_state_variables_multi.sol new file mode 100644 index 000000000..e34df2b22 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_state_variables_multi.sol @@ -0,0 +1,5 @@ +contract Foo { + uint[] memory storage calldata x; +} +// ---- +// ParserError: (23-29): Expected identifier but got 'memory' diff --git a/test/libsolidity/syntaxTests/parsing/mapping.sol b/test/libsolidity/syntaxTests/parsing/mapping.sol new file mode 100644 index 000000000..d6bf3f143 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping.sol @@ -0,0 +1,3 @@ +contract test { + mapping(address => bytes32) names; +} diff --git a/test/libsolidity/syntaxTests/parsing/mapping_and_array_of_functions.sol b/test/libsolidity/syntaxTests/parsing/mapping_and_array_of_functions.sol new file mode 100644 index 000000000..b7cf34e49 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_and_array_of_functions.sol @@ -0,0 +1,6 @@ +contract test { + mapping (address => function() internal returns (uint)) a; + mapping (address => function() external) b; + mapping (address => function() external[]) c; + function() external[] d; +} diff --git a/test/libsolidity/syntaxTests/parsing/mapping_from_address_payable.sol b/test/libsolidity/syntaxTests/parsing/mapping_from_address_payable.sol new file mode 100644 index 000000000..7e6f98d7c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_from_address_payable.sol @@ -0,0 +1,5 @@ +contract C { + mapping(address payable => uint) m; +} +// ---- +// ParserError: (33-40): Expected '=>' but got 'payable' diff --git a/test/libsolidity/syntaxTests/parsing/mapping_in_struct.sol b/test/libsolidity/syntaxTests/parsing/mapping_in_struct.sol new file mode 100644 index 000000000..980d57503 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_in_struct.sol @@ -0,0 +1,7 @@ +contract test { + struct test_struct { + address addr; + uint256 count; + mapping(bytes32 => test_struct) self_reference; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_1.sol new file mode 100644 index 000000000..ea2d282cc --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_1.sol @@ -0,0 +1,5 @@ +contract c { + mapping(uint[] => uint) data; +} +// ---- +// ParserError: (26-27): Expected '=>' but got '[' diff --git a/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_2.sol new file mode 100644 index 000000000..713cddeb3 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_2.sol @@ -0,0 +1,8 @@ +contract c { + struct S { + uint x; + } + mapping(S => uint) data; +} +// ---- +// ParserError: (47-48): Expected elementary type name for mapping key type diff --git a/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_3.sol new file mode 100644 index 000000000..655af9de7 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_3.sol @@ -0,0 +1,8 @@ +contract c { + struct S { + string s; + } + mapping(S => uint) data; +} +// ---- +// ParserError: (49-50): Expected elementary type name for mapping key type diff --git a/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_4.sol b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_4.sol new file mode 100644 index 000000000..f4dcb00ad --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_nonelementary_key_4.sol @@ -0,0 +1,5 @@ +contract c { + mapping(string[] => uint) data; +} +// ---- +// ParserError: (28-29): Expected '=>' but got '[' diff --git a/test/libsolidity/syntaxTests/parsing/mapping_to_mapping_in_struct.sol b/test/libsolidity/syntaxTests/parsing/mapping_to_mapping_in_struct.sol new file mode 100644 index 000000000..c06220b72 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_to_mapping_in_struct.sol @@ -0,0 +1,6 @@ +contract test { + struct test_struct { + address addr; + mapping (uint64 => mapping (bytes32 => uint)) complex_mapping; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/modifier.sol b/test/libsolidity/syntaxTests/parsing/modifier.sol new file mode 100644 index 000000000..b995ce898 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/modifier.sol @@ -0,0 +1,3 @@ +contract c { + modifier mod { if (msg.sender == 0x0000000000000000000000000000000000000000) _; } +} diff --git a/test/libsolidity/syntaxTests/parsing/modifier_arguments.sol b/test/libsolidity/syntaxTests/parsing/modifier_arguments.sol new file mode 100644 index 000000000..27b5b13b7 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/modifier_arguments.sol @@ -0,0 +1,3 @@ +contract c { + modifier mod(address a) { if (msg.sender == a) _; } +} diff --git a/test/libsolidity/syntaxTests/parsing/modifier_invocation.sol b/test/libsolidity/syntaxTests/parsing/modifier_invocation.sol new file mode 100644 index 000000000..cf986efe5 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/modifier_invocation.sol @@ -0,0 +1,7 @@ +contract c { + modifier mod1(uint a) { if (msg.sender == address(a)) _; } + modifier mod2 { if (msg.sender == address(2)) _; } + function f() public mod1(7) mod2 { } +} +// ---- +// Warning: (135-171): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/parsing/multi_arrays.sol b/test/libsolidity/syntaxTests/parsing/multi_arrays.sol new file mode 100644 index 000000000..ef20ecee6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/multi_arrays.sol @@ -0,0 +1,3 @@ +contract c { + mapping(uint => mapping(uint => int8)[8][][9])[] x; +} diff --git a/test/libsolidity/syntaxTests/parsing/multi_variable_declarations.sol b/test/libsolidity/syntaxTests/parsing/multi_variable_declarations.sol index 818999dff..56c2e2801 100644 --- a/test/libsolidity/syntaxTests/parsing/multi_variable_declarations.sol +++ b/test/libsolidity/syntaxTests/parsing/multi_variable_declarations.sol @@ -1,29 +1,13 @@ contract C { - function f() { - var (a,b,c) = g(); - var (d) = 2; - var (,e) = 3; - var (f,) = 4; - var (x,,) = g(); - var (,y,) = g(); - var () = g(); - var (,,) = g(); + function f() pure public { + (uint a, uint b, uint c) = g(); + (uint d) = 2; + (, uint e) = (3,4); + (uint h,) = (4,5); + (uint x,,) = g(); + (, uint y,) = g(); + a; b; c; d; e; h; x; y; } - function g() returns (uint, uint, uint) {} + function g() pure public returns (uint, uint, uint) {} } // ---- -// Warning: (36-37): Use of the "var" keyword is deprecated. -// Warning: (38-39): Use of the "var" keyword is deprecated. -// Warning: (40-41): Use of the "var" keyword is deprecated. -// Warning: (57-58): Use of the "var" keyword is deprecated. -// Warning: (73-74): Use of the "var" keyword is deprecated. -// Warning: (88-89): Use of the "var" keyword is deprecated. -// Warning: (104-105): Use of the "var" keyword is deprecated. -// Warning: (124-125): Use of the "var" keyword is deprecated. -// Warning: (88-89): This declaration shadows an existing declaration. -// Warning: (52-63): The type of this variable was inferred as uint8, which can hold values between 0 and 255. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (67-79): Different number of components on the left hand side (2) than on the right hand side (1). -// Warning: (67-79): The type of this variable was inferred as uint8, which can hold values between 0 and 255. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (83-95): Different number of components on the left hand side (2) than on the right hand side (1). -// Warning: (83-95): The type of this variable was inferred as uint8, which can hold values between 0 and 255. This is probably not desired. Use an explicit type to silence this warning. -// TypeError: (137-149): Too many components (3) in value for variable assignment (0) needed diff --git a/test/libsolidity/syntaxTests/parsing/multiple_event_arg_trailing_comma.sol b/test/libsolidity/syntaxTests/parsing/multiple_event_arg_trailing_comma.sol new file mode 100644 index 000000000..bfbe7e5cb --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/multiple_event_arg_trailing_comma.sol @@ -0,0 +1,6 @@ +contract test { + event Test(uint a, uint b,); + function(uint a) {} +} +// ---- +// ParserError: (45-46): Unexpected trailing comma in parameter list. diff --git a/test/libsolidity/syntaxTests/parsing/multiple_functions_natspec_documentation.sol b/test/libsolidity/syntaxTests/parsing/multiple_functions_natspec_documentation.sol new file mode 100644 index 000000000..85d9e6a8c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/multiple_functions_natspec_documentation.sol @@ -0,0 +1,24 @@ +contract test { + uint256 stateVar; + /// This is test function 1 + function functionName1(bytes32 input) public returns (bytes32 out) {} + /// This is test function 2 + function functionName2(bytes32 input) public returns (bytes32 out) {} + // nothing to see here + function functionName3(bytes32 input) public returns (bytes32 out) {} + /// This is test function 4 + function functionName4(bytes32 input) public returns (bytes32 out) {} +} +// ---- +// Warning: (97-110): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (128-139): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (203-216): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (234-245): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (304-317): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (335-346): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (410-423): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (441-452): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (74-143): Function state mutability can be restricted to pure +// Warning: (180-249): Function state mutability can be restricted to pure +// Warning: (281-350): Function state mutability can be restricted to pure +// Warning: (387-456): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/multiple_modifier_arg_trailing_comma.sol b/test/libsolidity/syntaxTests/parsing/multiple_modifier_arg_trailing_comma.sol new file mode 100644 index 000000000..eb206fb7c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/multiple_modifier_arg_trailing_comma.sol @@ -0,0 +1,6 @@ +contract test { + modifier modTest(uint a, uint b,) { _; } + function(uint a) {} +} +// ---- +// ParserError: (51-52): Unexpected trailing comma in parameter list. diff --git a/test/libsolidity/syntaxTests/parsing/multiple_return_param_trailing_comma.sol b/test/libsolidity/syntaxTests/parsing/multiple_return_param_trailing_comma.sol new file mode 100644 index 000000000..2dd8f1964 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/multiple_return_param_trailing_comma.sol @@ -0,0 +1,5 @@ +contract test { + function() returns (uint a, uint b,) {} +} +// ---- +// ParserError: (54-55): Unexpected trailing comma in parameter list. diff --git a/test/libsolidity/syntaxTests/parsing/new_address_payable.sol b/test/libsolidity/syntaxTests/parsing/new_address_payable.sol new file mode 100644 index 000000000..a52001db0 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/new_address_payable.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns(address payable[] memory m) { + m = new address payable[](10); + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/parsing/no_function_params.sol b/test/libsolidity/syntaxTests/parsing/no_function_params.sol index 020f1233b..5a024bdbf 100644 --- a/test/libsolidity/syntaxTests/parsing/no_function_params.sol +++ b/test/libsolidity/syntaxTests/parsing/no_function_params.sol @@ -1,7 +1,6 @@ contract test { uint256 stateVar; - function functionName() {} + function functionName() public {} } // ---- -// Warning: (36-62): No visibility specified. Defaulting to "public". -// Warning: (36-62): Function state mutability can be restricted to pure +// Warning: (36-69): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/overloaded_functions.sol b/test/libsolidity/syntaxTests/parsing/overloaded_functions.sol index 1a78d1551..fe050d1b8 100644 --- a/test/libsolidity/syntaxTests/parsing/overloaded_functions.sol +++ b/test/libsolidity/syntaxTests/parsing/overloaded_functions.sol @@ -1,9 +1,7 @@ contract test { - function fun(uint a) returns(uint r) { return a; } - function fun(uint a, uint b) returns(uint r) { return a + b; } + function fun(uint a) public returns(uint r) { return a; } + function fun(uint a, uint b) public returns(uint r) { return a + b; } } // ---- -// Warning: (17-67): No visibility specified. Defaulting to "public". -// Warning: (69-131): No visibility specified. Defaulting to "public". -// Warning: (17-67): Function state mutability can be restricted to pure -// Warning: (69-131): Function state mutability can be restricted to pure +// Warning: (17-74): Function state mutability can be restricted to pure +// Warning: (76-145): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/payable_accessor.sol b/test/libsolidity/syntaxTests/parsing/payable_accessor.sol index 6504004b7..0bc857841 100644 --- a/test/libsolidity/syntaxTests/parsing/payable_accessor.sol +++ b/test/libsolidity/syntaxTests/parsing/payable_accessor.sol @@ -2,4 +2,4 @@ contract test { uint payable x; } // ---- -// ParserError: (22-29): Expected identifier but got 'payable' +// ParserError: (22-29): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/placeholder_in_function_context.sol b/test/libsolidity/syntaxTests/parsing/placeholder_in_function_context.sol new file mode 100644 index 000000000..a50855c0d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/placeholder_in_function_context.sol @@ -0,0 +1,8 @@ +contract c { + function fun() public returns (uint r) { + uint _ = 8; + return _ + 1; + } +} +// ---- +// Warning: (17-105): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/pragma_illegal.sol b/test/libsolidity/syntaxTests/parsing/pragma_illegal.sol new file mode 100644 index 000000000..3395f6be8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/pragma_illegal.sol @@ -0,0 +1,4 @@ +pragma ``; +// ---- +// ParserError: (7-8): Token incompatible with Solidity parser as part of pragma directive. +// ParserError: (8-9): Token incompatible with Solidity parser as part of pragma directive. diff --git a/test/libsolidity/syntaxTests/parsing/single_function_param.sol b/test/libsolidity/syntaxTests/parsing/single_function_param.sol index 08e531f1c..955f20f0e 100644 --- a/test/libsolidity/syntaxTests/parsing/single_function_param.sol +++ b/test/libsolidity/syntaxTests/parsing/single_function_param.sol @@ -1,9 +1,8 @@ contract test { uint256 stateVar; - function functionName(bytes32 input) returns (bytes32 out) {} + function functionName(bytes32 input) public returns (bytes32 out) {} } // ---- -// Warning: (36-97): No visibility specified. Defaulting to "public". // Warning: (58-71): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (82-93): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (36-97): Function state mutability can be restricted to pure +// Warning: (89-100): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (36-104): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/struct_definition.sol b/test/libsolidity/syntaxTests/parsing/struct_definition.sol new file mode 100644 index 000000000..0c859e5d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/struct_definition.sol @@ -0,0 +1,7 @@ +contract test { + uint256 stateVar; + struct MyStructName { + address addr; + uint256 count; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/trailing_dot1.sol b/test/libsolidity/syntaxTests/parsing/trailing_dot1.sol new file mode 100644 index 000000000..d91c385a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/trailing_dot1.sol @@ -0,0 +1,7 @@ +contract test { + uint256 a = 2.2e10; + uint256 b = .5E10; + uint256 c = 4.e-2; +} +// ---- +// TypeError: (70-73): Member "e" not found or not visible after argument-dependent lookup in int_const 4. diff --git a/test/libsolidity/syntaxTests/parsing/trailing_dot2.sol b/test/libsolidity/syntaxTests/parsing/trailing_dot2.sol new file mode 100644 index 000000000..38a7ab2d6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/trailing_dot2.sol @@ -0,0 +1,7 @@ +contract test { + uint256 a = 2.2e10; + uint256 b = .5E10; + uint256 c = 2 + 2.; +} +// ---- +// ParserError: (76-77): Expected identifier but got ';' diff --git a/test/libsolidity/syntaxTests/parsing/trailing_dot3.sol b/test/libsolidity/syntaxTests/parsing/trailing_dot3.sol new file mode 100644 index 000000000..6a126cb3a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/trailing_dot3.sol @@ -0,0 +1,4 @@ +contract test { + uint a = 2. +// ---- +// ParserError: (29-29): Expected identifier but got end of source diff --git a/test/libsolidity/syntaxTests/parsing/tuples.sol b/test/libsolidity/syntaxTests/parsing/tuples.sol index 6f7397406..875556e9f 100644 --- a/test/libsolidity/syntaxTests/parsing/tuples.sol +++ b/test/libsolidity/syntaxTests/parsing/tuples.sol @@ -1,24 +1,11 @@ contract C { - function f() { + function f() public pure { uint a = (1); - var (b,) = (1,); - var (c,d) = (1, 2 + a); - var (e,) = (1, 2, b); + (uint b,) = (1,2); + (uint c, uint d) = (1, 2 + a); + (uint e,) = (1, b); (a) = 3; + a;b;c;d;e; } } // ---- -// Warning: (52-53): Use of the "var" keyword is deprecated. -// Warning: (71-72): Use of the "var" keyword is deprecated. -// Warning: (73-74): Use of the "var" keyword is deprecated. -// Warning: (97-98): Use of the "var" keyword is deprecated. -// Warning: (47-62): Different number of components on the left hand side (2) than on the right hand side (1). -// Warning: (47-62): The type of this variable was inferred as uint8, which can hold values between 0 and 255. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (66-88): The type of this variable was inferred as uint8, which can hold values between 0 and 255. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (92-112): Different number of components on the left hand side (2) than on the right hand side (3). -// Warning: (92-112): The type of this variable was inferred as uint8, which can hold values between 0 and 255. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (14-127): No visibility specified. Defaulting to "public". -// Warning: (71-72): Unused local variable. -// Warning: (73-74): Unused local variable. -// Warning: (97-98): Unused local variable. -// Warning: (14-127): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/tuples_decl_without_rhs.sol b/test/libsolidity/syntaxTests/parsing/tuples_decl_without_rhs.sol new file mode 100644 index 000000000..dba3e7acc --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/tuples_decl_without_rhs.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + (uint a, uint b, uint c); + } +} +// ---- +// ParserError: (76-77): Expected '=' but got ';' diff --git a/test/libsolidity/syntaxTests/parsing/two_exact_functions.sol b/test/libsolidity/syntaxTests/parsing/two_exact_functions.sol new file mode 100644 index 000000000..957740d06 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/two_exact_functions.sol @@ -0,0 +1,9 @@ +// with support of overloaded functions, during parsing, +// we can't determine whether they match exactly, however +// it will throw DeclarationError in following stage. +contract test { + function fun(uint a) public returns(uint r) { return a; } + function fun(uint a) public returns(uint r) { return a; } +} +// ---- +// DeclarationError: (189-246): Function with same name and arguments defined twice. diff --git a/test/libsolidity/syntaxTests/parsing/unary_plus_expression.sol b/test/libsolidity/syntaxTests/parsing/unary_plus_expression.sol new file mode 100644 index 000000000..5646c43b2 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/unary_plus_expression.sol @@ -0,0 +1,8 @@ +contract test { + function f(uint x) pure public { + uint y = +x; + y; + } +} +// ---- +// SyntaxError: (70-72): Use of unary + is disallowed. diff --git a/test/libsolidity/syntaxTests/parsing/visibility_specifiers.sol b/test/libsolidity/syntaxTests/parsing/visibility_specifiers.sol new file mode 100644 index 000000000..db890b379 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/visibility_specifiers.sol @@ -0,0 +1,14 @@ +contract c { + uint private a; + uint internal b; + uint public c; + uint d; + function f() public {} + function f_priv() private {} + function f_internal() internal {} +} +// ---- +// Warning: (58-71): This declaration shadows an existing declaration. +// Warning: (89-111): Function state mutability can be restricted to pure +// Warning: (116-144): Function state mutability can be restricted to pure +// Warning: (149-182): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/while_loop.sol b/test/libsolidity/syntaxTests/parsing/while_loop.sol new file mode 100644 index 000000000..dbb00a69c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/while_loop.sol @@ -0,0 +1,7 @@ +contract test { + function fun() public pure { + uint256 x; + while (true) { x = 1; break; continue; } x = 9; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/pragma/invalid_pragma.sol b/test/libsolidity/syntaxTests/pragma/invalid_pragma.sol new file mode 100644 index 000000000..cb2585baf --- /dev/null +++ b/test/libsolidity/syntaxTests/pragma/invalid_pragma.sol @@ -0,0 +1,3 @@ +pragma 0; +// ---- +// SyntaxError: (0-9): Invalid pragma "0" diff --git a/test/libsolidity/syntaxTests/pragma/unknown_pragma.sol b/test/libsolidity/syntaxTests/pragma/unknown_pragma.sol new file mode 100644 index 000000000..3a48edddf --- /dev/null +++ b/test/libsolidity/syntaxTests/pragma/unknown_pragma.sol @@ -0,0 +1,3 @@ +pragma thisdoesntexist; +// ---- +// SyntaxError: (0-23): Unknown pragma "thisdoesntexist" diff --git a/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number.sol b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number.sol new file mode 100644 index 000000000..9741fdfba --- /dev/null +++ b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number.sol @@ -0,0 +1,14 @@ +contract C +{ + function f() public pure returns (uint) + { + return; + } + function g() public pure returns (uint) + { + return (1, 2); + } +} +// ---- +// TypeError: (71-78): Return arguments required. +// TypeError: (143-156): Different number of arguments in return statement than in returns declaration. diff --git a/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number_named.sol b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number_named.sol new file mode 100644 index 000000000..53f2d994f --- /dev/null +++ b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number_named.sol @@ -0,0 +1,14 @@ +contract C +{ + function f() public pure returns (uint a) + { + return; + } + function g() public pure returns (uint a) + { + return (1, 2); + } +} +// ---- +// TypeError: (73-80): Return arguments required. +// TypeError: (147-160): Different number of arguments in return statement than in returns declaration. diff --git a/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number.sol b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number.sol new file mode 100644 index 000000000..4ea61c685 --- /dev/null +++ b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number.sol @@ -0,0 +1,19 @@ +contract C +{ + function f() public pure returns (uint, uint) + { + return 1; + } + function g() public pure returns (uint, uint) + { + return (1, 2, 3); + } + function h() public pure returns (uint, uint) + { + return; + } +} +// ---- +// TypeError: (77-85): Different number of arguments in return statement than in returns declaration. +// TypeError: (157-173): Different number of arguments in return statement than in returns declaration. +// TypeError: (245-252): Return arguments required. diff --git a/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number_named.sol b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number_named.sol new file mode 100644 index 000000000..860497195 --- /dev/null +++ b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number_named.sol @@ -0,0 +1,19 @@ +contract C +{ + function f() public pure returns (uint a, uint b) + { + return 1; + } + function g() public pure returns (uint a, uint b) + { + return (1, 2, 3); + } + function h() public pure returns (uint a, uint b) + { + return; + } +} +// ---- +// TypeError: (81-89): Different number of arguments in return statement than in returns declaration. +// TypeError: (165-181): Different number of arguments in return statement than in returns declaration. +// TypeError: (257-264): Return arguments required. diff --git a/test/libsolidity/syntaxTests/returnExpressions/valid_returns.sol b/test/libsolidity/syntaxTests/returnExpressions/valid_returns.sol new file mode 100644 index 000000000..e30f9173d --- /dev/null +++ b/test/libsolidity/syntaxTests/returnExpressions/valid_returns.sol @@ -0,0 +1,18 @@ +contract C +{ + function f() public pure { + return; + } + function g() public pure returns (uint) { + return 1; + } + function h() public pure returns (uint a) { + return 1; + } + function i() public pure returns (uint, uint) { + return (1, 2); + } + function j() public pure returns (uint a, uint b) { + return (1, 2); + } +} diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol index d90ec2d77..36bae6a8b 100644 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol @@ -5,4 +5,5 @@ contract test { } } // ---- -// DeclarationError: (77-83): Identifier already declared. +// Warning: (57-63): Unused local variable. +// Warning: (77-83): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol deleted file mode 100644 index 06bfe7be2..000000000 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - { uint x; } - { uint x; } - } -} -// ---- -// Warning: (87-93): Unused local variable. -// Warning: (107-113): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol index 1a5ff2f9c..0c03ec3e8 100644 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol @@ -5,4 +5,5 @@ contract test { } } // ---- -// DeclarationError: (75-81): Identifier already declared. +// Warning: (57-63): Unused local variable. +// Warning: (75-81): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol deleted file mode 100644 index 20ea03498..000000000 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - { uint x; } - uint x; - } -} -// ---- -// Warning: (87-93): Unused local variable. -// Warning: (105-111): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_same_and_disjoint_scope.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_same_and_disjoint_scope.sol new file mode 100644 index 000000000..45c5ff2dc --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_same_and_disjoint_scope.sol @@ -0,0 +1,10 @@ +contract test { + function f() pure public { + uint x; + { uint x; } + uint x; + } +} +// ---- +// Warning: (73-79): This declaration shadows an existing declaration. +// DeclarationError: (91-97): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_same_scope.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_same_scope.sol new file mode 100644 index 000000000..72c31f73c --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_same_scope.sol @@ -0,0 +1,8 @@ +contract test { + function f() pure public { + uint x; + uint x; + } +} +// ---- +// DeclarationError: (71-77): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/scoping/function_state_variable_conflict.sol b/test/libsolidity/syntaxTests/scoping/function_state_variable_conflict.sol new file mode 100644 index 000000000..d717981b9 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/function_state_variable_conflict.sol @@ -0,0 +1,6 @@ +contract C { + function f(uint) public pure {} + uint public f = 0; +} +// ---- +// DeclarationError: (53-70): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/scoping/poly_variable_declaration_same_scope.sol b/test/libsolidity/syntaxTests/scoping/poly_variable_declaration_same_scope.sol new file mode 100644 index 000000000..e414f6117 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/poly_variable_declaration_same_scope.sol @@ -0,0 +1,16 @@ +contract test { + function f() pure public { + uint x; + uint x; + uint x; + uint x; + uint x; + uint x; + } +} +// ---- +// DeclarationError: (71-77): Identifier already declared. +// DeclarationError: (87-93): Identifier already declared. +// DeclarationError: (103-109): Identifier already declared. +// DeclarationError: (119-125): Identifier already declared. +// DeclarationError: (135-141): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/scoping/scoping.sol b/test/libsolidity/syntaxTests/scoping/scoping.sol index 34b055d98..dae5a42d5 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() public { { @@ -8,4 +7,4 @@ contract test { } } // ---- -// DeclarationError: (123-124): Undeclared identifier. +// DeclarationError: (93-94): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_activation.sol b/test/libsolidity/syntaxTests/scoping/scoping_activation.sol index 7334bc49c..8522a0e30 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_activation.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_activation.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { x = 3; @@ -6,4 +5,4 @@ contract test { } } // ---- -// DeclarationError: (85-86): Undeclared identifier. Did you mean "x"? +// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol b/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol index d893a889a..8522a0e30 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol @@ -4,3 +4,5 @@ contract test { uint x; } } +// ---- +// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for.sol b/test/libsolidity/syntaxTests/scoping/scoping_for.sol index 6e5b7095e..a882d1ca8 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (uint x = 0; x < 10; x ++){ diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for2.sol b/test/libsolidity/syntaxTests/scoping/scoping_for2.sol index eb74b8ab4..f8c5c19b6 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for2.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for2.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (uint x = 0; x < 10; x ++) diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for3.sol b/test/libsolidity/syntaxTests/scoping/scoping_for3.sol index 1814cb475..81e34562c 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for3.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for3.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (uint x = 0; x < 10; x ++){ @@ -8,4 +7,4 @@ contract test { } } // ---- -// DeclarationError: (154-155): Undeclared identifier. +// DeclarationError: (124-125): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol b/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol index 3e80b3853..28b885259 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (;; y++){ @@ -7,4 +6,4 @@ contract test { } } // ---- -// DeclarationError: (93-94): Undeclared identifier. +// DeclarationError: (63-64): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_old.sol b/test/libsolidity/syntaxTests/scoping/scoping_old.sol index 83f6b60ba..70e5ee0cb 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_old.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_old.sol @@ -4,3 +4,5 @@ contract test { uint256 x = 2; } } +// ---- +// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol b/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol index 9e2c0171b..a5087c57f 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol @@ -3,3 +3,5 @@ contract test { uint a = a; } } +// ---- +// DeclarationError: (64-65): Undeclared identifier. "a" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol b/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol deleted file mode 100644 index ab3dcefb9..000000000 --- a/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - uint a = a; - } -} -// ---- -// DeclarationError: (94-95): Undeclared identifier. Did you mean "a"? diff --git a/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict.sol b/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict.sol new file mode 100644 index 000000000..0c732f7fc --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict.sol @@ -0,0 +1,6 @@ +contract C { + uint public f = 0; + function f(uint) public pure {} +} +// ---- +// DeclarationError: (40-71): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict_former_crash.sol b/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict_former_crash.sol new file mode 100644 index 000000000..fb9180c69 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict_former_crash.sol @@ -0,0 +1,14 @@ +// This used to crash with some compiler versions. +contract SomeContract { + + uint public balance = 0; + + function balance(uint number) public {} + + function doSomething() public { + balance(3); + } +} +// ---- +// DeclarationError: (106-145): Identifier already declared. +// TypeError: (185-195): Type is not callable diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_calldata.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_calldata.sol new file mode 100644 index 000000000..28d2f2e75 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_calldata.sol @@ -0,0 +1,8 @@ +// This restriction might be lifted in the future +contract C { + function f() public pure { + abi.decode("abc", (bytes calldata)); + } +} +// ---- +// ParserError: (121-129): Expected ',' but got 'calldata' diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_empty.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_empty.sol new file mode 100644 index 000000000..9972f01de --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_empty.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + abi.decode("abc", ()); + } +} +// ---- +// Warning: (52-73): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_invalid_arg_count.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_invalid_arg_count.sol new file mode 100644 index 000000000..f903e1ed4 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_invalid_arg_count.sol @@ -0,0 +1,12 @@ +contract C { + function f() public pure { + abi.decode(); + abi.decode(msg.data); + abi.decode(msg.data, uint, uint); + } +} +// ---- +// TypeError: (46-58): This function takes two arguments, but 0 were provided. +// TypeError: (64-84): This function takes two arguments, but 1 were provided. +// TypeError: (90-122): This function takes two arguments, but 3 were provided. +// TypeError: (111-115): The second argument to "abi.decode" has to be a tuple of types. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_memory.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_memory.sol new file mode 100644 index 000000000..e4667e34d --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_memory.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + abi.decode("abc", (bytes memory, uint[][2] memory)); + } +} +// ---- +// ParserError: (71-77): Expected ',' but got 'memory' diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_memory_v2.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_memory_v2.sol new file mode 100644 index 000000000..8a7462d12 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_memory_v2.sol @@ -0,0 +1,10 @@ +pragma experimental "ABIEncoderV2"; + +contract C { + struct S { uint x; uint[] b; } + function f() public pure returns (S memory, bytes memory, uint[][2] memory) { + return abi.decode("abc", (S, bytes, uint[][2])); + } +} +// ---- +// Warning: (0-35): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_nontuple.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_nontuple.sol new file mode 100644 index 000000000..d813c7122 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_nontuple.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + abi.decode("abc", uint); + abi.decode("abc", this); + abi.decode("abc", f()); + } +} +// ---- +// TypeError: (64-68): The second argument to "abi.decode" has to be a tuple of types. +// TypeError: (93-97): The second argument to "abi.decode" has to be a tuple of types. +// TypeError: (122-125): The second argument to "abi.decode" has to be a tuple of types. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_simple.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_simple.sol new file mode 100644 index 000000000..356ee91c7 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_simple.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns (uint, bytes32, C) { + return abi.decode("abc", (uint, bytes32, C)); + } +} diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_single_return.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_single_return.sol new file mode 100644 index 000000000..654b7873c --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_single_return.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns (bool) { + return abi.decode("abc", (uint)) == 2; + } +} diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_singletontuple.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_singletontuple.sol new file mode 100644 index 000000000..57eccacf2 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_singletontuple.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure returns (uint) { + return abi.decode("abc", (uint)); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_storage.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_storage.sol new file mode 100644 index 000000000..d9910b64c --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_storage.sol @@ -0,0 +1,8 @@ +// This restriction might be lifted in the future +contract C { + function f() { + abi.decode("abc", (bytes storage)); + } +} +// ---- +// ParserError: (109-116): Expected ',' but got 'storage' diff --git a/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol new file mode 100644 index 000000000..036e108aa --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol @@ -0,0 +1,9 @@ +contract C { + struct S { uint x; } + function f() public pure { + S[] memory s; + abi.encodePacked(s); + } +} +// ---- +// TypeError: (116-117): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol b/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol new file mode 100644 index 000000000..7a4d8250e --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; +contract C { + struct S { uint x; } + function f() public pure { + S[] memory s; + abi.encode(s); + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol b/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol index a6ee4bf12..c17d08497 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol @@ -7,9 +7,6 @@ contract C { function g(bytes32) pure internal {} } // ---- -// Warning: (54-72): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (54-72): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. -// Warning: (85-100): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (85-100): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. -// Warning: (113-131): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (113-131): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. +// TypeError: (64-71): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (92-99): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (123-130): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol index b94a43911..a30e428a6 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol @@ -1,6 +1,6 @@ contract C { function f() public pure { - bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f.gas, block.blockhash)); + bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f.gas, blockhash)); h; } } @@ -8,4 +8,4 @@ contract C { // TypeError: (91-100): This type cannot be encoded. // TypeError: (102-103): This type cannot be encoded. // TypeError: (105-115): This type cannot be encoded. -// TypeError: (117-132): This type cannot be encoded. +// TypeError: (117-126): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol index f1b5606ea..6e0b6db40 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol @@ -1,13 +1,13 @@ contract C { function f() public pure { - bool a = address(this).call(address(this).delegatecall, super); - bool b = address(this).delegatecall(log0, tx, mulmod); - a; b; + (bool a,) = address(this).call(abi.encode(address(this).delegatecall, super)); + (a,) = address(this).delegatecall(abi.encode(log0, tx, mulmod)); + a; } } // ---- -// TypeError: (80-106): This type cannot be encoded. -// TypeError: (108-113): This type cannot be encoded. -// TypeError: (160-164): This type cannot be encoded. -// TypeError: (166-168): This type cannot be encoded. -// TypeError: (170-176): This type cannot be encoded. +// TypeError: (94-120): This type cannot be encoded. +// TypeError: (122-127): This type cannot be encoded. +// TypeError: (184-188): This type cannot be encoded. +// TypeError: (190-192): This type cannot be encoded. +// TypeError: (194-200): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol index 05f5db0bd..a1d3f5aff 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol @@ -4,11 +4,10 @@ contract C { struct T { uint y; } T t; function f() public view { - bytes32 a = sha256(s, t); + bytes32 a = sha256(abi.encodePacked(s, t)); a; } } // ---- -// Warning: (132-144): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (139-140): This type cannot be encoded. -// TypeError: (142-143): This type cannot be encoded. +// TypeError: (156-157): This type cannot be encoded. +// TypeError: (159-160): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol index 977a7d73f..387028259 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol @@ -6,12 +6,11 @@ contract C { struct T { uint y; } T t; function f() public view { - bytes32 a = sha256(s, t); + bytes32 a = sha256(abi.encodePacked(s, t)); a; } } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// Warning: (167-179): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (174-175): This type cannot be encoded. -// TypeError: (177-178): This type cannot be encoded. +// TypeError: (191-192): This type cannot be encoded. +// TypeError: (194-195): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol index d10c17187..b50d44499 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol @@ -1,17 +1,17 @@ contract C { struct S { uint x; } S s; - struct T { } + struct T { uint y; } T t; enum A { X, Y } function f() public pure { - bool a = address(this).delegatecall(S, A, A.X, T, uint, uint[]); + bytes memory a = abi.encodePacked(S, A, A.X, T, uint, uint[]); + a; } } // ---- -// Warning: (51-63): Defining empty structs is deprecated. -// TypeError: (168-169): This type cannot be encoded. -// TypeError: (171-172): This type cannot be encoded. -// TypeError: (179-180): This type cannot be encoded. -// TypeError: (182-186): This type cannot be encoded. -// TypeError: (188-194): This type cannot be encoded. +// TypeError: (174-175): This type cannot be encoded. +// TypeError: (177-178): This type cannot be encoded. +// TypeError: (185-186): This type cannot be encoded. +// TypeError: (188-192): This type cannot be encoded. +// TypeError: (194-200): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/string/string_escapes.sol b/test/libsolidity/syntaxTests/string/string_escapes.sol new file mode 100644 index 000000000..51b90d735 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/string_escapes.sol @@ -0,0 +1,7 @@ +contract test { + function f() public pure returns (bytes32) { + bytes32 escapeCharacters = "\t\b\n\r\f\'\"\\\b"; + return escapeCharacters; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/string/string_new_line.sol b/test/libsolidity/syntaxTests/string/string_new_line.sol new file mode 100644 index 000000000..da2240f78 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/string_new_line.sol @@ -0,0 +1,9 @@ +contract test { + function f() public pure returns (bytes32) { + bytes32 escapeCharacters = "This a test + "; + return escapeCharacters; + } +} +// ---- +// ParserError: (100-112): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol b/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol new file mode 100644 index 000000000..3eaba6af0 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol @@ -0,0 +1,8 @@ +contract test { + function f() public pure returns (bytes32) { + bytes32 escapeCharacters = "text \"; + return escapeCharacters; + } +} +// ---- +// ParserError: (100-109): Expected primary expression. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/string/string_unterminated.sol b/test/libsolidity/syntaxTests/string/string_unterminated.sol new file mode 100644 index 000000000..3291781e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/string_unterminated.sol @@ -0,0 +1,7 @@ +contract test { + function f() public pure returns (bytes32) { + bytes32 escapeCharacters = "This a test + } +} +// ---- +// ParserError: (100-112): Expected primary expression. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol b/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol new file mode 100644 index 000000000..e7be50d23 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol @@ -0,0 +1,4 @@ +contract test { + function f() pure public { "abc\ +// ---- +// ParserError: (47-53): Expected primary expression. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol b/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol index 895bb6c58..e8ece3bc9 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol @@ -9,7 +9,7 @@ contract C { struct W { uint x; } - function f(T) public pure { } + function f(T memory) public pure { } } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol index 96362ef0c..e9b254534 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol @@ -9,7 +9,7 @@ contract TestContract SubStruct subStruct1; SubStruct subStruct2; } - function addTestStruct(TestStruct) public pure {} + function addTestStruct(TestStruct memory) public pure {} } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol index 4966a731e..c8f9185c1 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol @@ -1,7 +1,7 @@ contract C { struct S { uint a; S[] sub; } - function f() public pure returns (uint, S) { + function f() public pure returns (uint, S memory) { } } // ---- -// TypeError: (91-92): Internal or recursive type is not allowed for public or external functions. +// TypeError: (91-99): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol index 681139245..a8b7ac759 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol @@ -1,7 +1,7 @@ contract C { struct S { uint a; S[2][] sub; } - function f() public pure returns (uint, S) { + function f() public pure returns (uint, S memory) { } } // ---- -// TypeError: (94-95): Internal or recursive type is not allowed for public or external functions. +// TypeError: (94-102): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol index 47690d9bc..0a5b1bc8d 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol @@ -1,8 +1,8 @@ contract C { struct S { uint a; S[][][] sub; } struct T { S s; } - function f() public pure returns (uint x, T t) { + function f() public pure returns (uint x, T memory t) { } } // ---- -// TypeError: (119-122): Internal or recursive type is not allowed for public or external functions. +// TypeError: (119-129): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive_dynamic_array.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive_dynamic_array.sol new file mode 100644 index 000000000..d847f17c2 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive_dynamic_array.sol @@ -0,0 +1,7 @@ +contract Test { + struct MyStructName { + address addr; + MyStructName[] x; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive_fixed_array.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive_fixed_array.sol new file mode 100644 index 000000000..126dda4fc --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive_fixed_array.sol @@ -0,0 +1,8 @@ +contract Test { + struct MyStructName { + address addr; + MyStructName[1] x; + } +} +// ---- +// TypeError: (20-96): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_complex.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_complex.sol new file mode 100644 index 000000000..6d35a5d3d --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_complex.sol @@ -0,0 +1,18 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName4[1] x; + } + struct MyStructName2 { + MyStructName1 x; + } + struct MyStructName3 { + MyStructName2[1] x; + } + struct MyStructName4 { + MyStructName3 x; + } +} +// ---- +// TypeError: (20-121): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array1.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array1.sol new file mode 100644 index 000000000..10d7de2ce --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array1.sol @@ -0,0 +1,11 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2[] x; + } + struct MyStructName2 { + MyStructName1 x; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array2.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array2.sol new file mode 100644 index 000000000..f20510ca6 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array2.sol @@ -0,0 +1,11 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2 x; + } + struct MyStructName2 { + MyStructName1[] x; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array3.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array3.sol new file mode 100644 index 000000000..69747e71f --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_array3.sol @@ -0,0 +1,11 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2[] x; + } + struct MyStructName2 { + MyStructName1[] x; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_multi_array.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_multi_array.sol new file mode 100644 index 000000000..b35078286 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_dynamic_multi_array.sol @@ -0,0 +1,21 @@ +contract Test { + struct S1 { + S2[1][] x; + } + struct S2 { + S1 x; + } + struct T1 { + T2[][1] x; + } + struct T2 { + T1 x; + } + struct R1 { + R2[][] x; + } + struct R2 { + R1 x; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array1.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array1.sol new file mode 100644 index 000000000..2c0b90ec7 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array1.sol @@ -0,0 +1,12 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2[1] x; + } + struct MyStructName2 { + MyStructName1 x; + } +} +// ---- +// TypeError: (20-121): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array2.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array2.sol new file mode 100644 index 000000000..3178e5692 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array2.sol @@ -0,0 +1,12 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2 x; + } + struct MyStructName2 { + MyStructName1[1] x; + } +} +// ---- +// TypeError: (20-118): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array3.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array3.sol new file mode 100644 index 000000000..e34cf9bc5 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_array3.sol @@ -0,0 +1,12 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2[1] x; + } + struct MyStructName2 { + MyStructName1[1] x; + } +} +// ---- +// TypeError: (20-121): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_multi_array.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_multi_array.sol new file mode 100644 index 000000000..ed659b6eb --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive_fixed_multi_array.sol @@ -0,0 +1,12 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2[1][1] x; + } + struct MyStructName2 { + MyStructName1 x; + } +} +// ---- +// TypeError: (20-124): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive_array.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive_array.sol new file mode 100644 index 000000000..b2053b8a5 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive_array.sol @@ -0,0 +1,4 @@ +contract Test { + struct S1 { uint a; } + struct S2 { S1[1] x; S1[1] y; } +} diff --git a/test/libsolidity/syntaxTests/tight_packing_literals.sol b/test/libsolidity/syntaxTests/tight_packing_literals.sol index a190adc3f..0fc1fc087 100644 --- a/test/libsolidity/syntaxTests/tight_packing_literals.sol +++ b/test/libsolidity/syntaxTests/tight_packing_literals.sol @@ -1,33 +1,8 @@ contract C { - function f() pure public returns (bytes32) { - return keccak256(1); - } - function g() pure public returns (bytes32) { - return sha3(1); - } - function h() pure public returns (bytes32) { - return sha256(1); - } - function j() pure public returns (bytes32) { - return ripemd160(1); - } - function k() pure public returns (bytes) { + function k() pure public returns (bytes memory) { return abi.encodePacked(1); } } // ---- -// Warning: (87-88): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (77-89): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (77-89): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (161-168): "sha3" has been deprecated in favour of "keccak256" -// Warning: (166-167): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (161-168): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (161-168): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (247-248): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (240-249): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (240-249): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (331-332): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (321-333): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (321-333): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (420-421): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// TypeError: (99-100): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_050.sol b/test/libsolidity/syntaxTests/tight_packing_literals_050.sol deleted file mode 100644 index b7557d2aa..000000000 --- a/test/libsolidity/syntaxTests/tight_packing_literals_050.sol +++ /dev/null @@ -1,34 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() pure public returns (bytes32) { - return keccak256(1); - } - function g() pure public returns (bytes32) { - return sha3(1); - } - function h() pure public returns (bytes32) { - return sha256(1); - } - function j() pure public returns (bytes32) { - return ripemd160(1); - } - function k() pure public returns (bytes) { - return abi.encodePacked(1); - } -} - -// ---- -// TypeError: (117-118): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (107-119): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (107-119): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (191-198): "sha3" has been deprecated in favour of "keccak256" -// TypeError: (196-197): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (191-198): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (191-198): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (277-278): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (270-279): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (270-279): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (361-362): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (351-363): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (351-363): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (450-451): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol index 2b9b688aa..45fc1f723 100644 --- a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol +++ b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol @@ -1,30 +1,9 @@ contract C { - function f() pure public returns (bytes32) { - return keccak256(uint8(1)); - } - function g() pure public returns (bytes32) { - return sha3(uint8(1)); - } - function h() pure public returns (bytes32) { - return sha256(uint8(1)); - } - function j() pure public returns (bytes32) { - return ripemd160(uint8(1)); - } - function k() pure public returns (bytes) { + function k() pure public returns (bytes memory) { return abi.encodePacked(uint8(1)); } - function l() pure public returns (bytes) { + function l() pure public returns (bytes memory) { return abi.encode(1); } } // ---- -// Warning: (77-96): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (77-96): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (168-182): "sha3" has been deprecated in favour of "keccak256" -// Warning: (168-182): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (168-182): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (254-270): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (254-270): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (342-361): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (342-361): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. diff --git a/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol new file mode 100644 index 000000000..3cff3a9a0 --- /dev/null +++ b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol @@ -0,0 +1,11 @@ +// This used to crash in certain compiler versions. +contract CrashContract { + struct S { uint a; } + S x; + function f() public { + (x, x) = 1(x, x); + } +} +// ---- +// TypeError: (170-177): Type is not callable +// TypeError: (170-177): Type tuple() is not implicitly convertible to expected type tuple(struct CrashContract.S storage ref,struct CrashContract.S storage ref). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/err_fill_assignment.sol b/test/libsolidity/syntaxTests/tupleAssignments/err_fill_assignment.sol new file mode 100644 index 000000000..32b381bbc --- /dev/null +++ b/test/libsolidity/syntaxTests/tupleAssignments/err_fill_assignment.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure returns (uint, uint, bytes32) { + uint a; + bytes32 b; + (a,) = f(); + (,b) = f(); + } +} +// ---- +// TypeError: (103-106): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(uint256,). +// TypeError: (117-120): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(,bytes32). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol b/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol index 5b7f870bc..32b381bbc 100644 --- a/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol +++ b/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract C { function f() public pure returns (uint, uint, bytes32) { uint a; @@ -8,5 +7,5 @@ contract C { } } // ---- -// TypeError: (126-136): Different number of components on the left hand side (2) than on the right hand side (3). -// TypeError: (140-150): Different number of components on the left hand side (2) than on the right hand side (3). +// TypeError: (103-106): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(uint256,). +// TypeError: (117-120): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(,bytes32). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol b/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol index bbf21d7ea..f14641cb9 100644 --- a/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol +++ b/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract C { function g() public pure returns ( uint, diff --git a/test/libsolidity/syntaxTests/tupleAssignments/nowarn_explicit_singleton_token_expression.sol b/test/libsolidity/syntaxTests/tupleAssignments/nowarn_explicit_singleton_token_expression.sol deleted file mode 100644 index 3262781b7..000000000 --- a/test/libsolidity/syntaxTests/tupleAssignments/nowarn_explicit_singleton_token_expression.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract C { - function f() public pure { - uint a; - (a,) = (uint(1),); - } -} -// ---- -// Warning: (53-70): Different number of components on the left hand side (2) than on the right hand side (1). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/warn_fill_assignment.sol b/test/libsolidity/syntaxTests/tupleAssignments/warn_fill_assignment.sol deleted file mode 100644 index a079a5094..000000000 --- a/test/libsolidity/syntaxTests/tupleAssignments/warn_fill_assignment.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C { - function f() public pure returns (uint, uint, bytes32) { - uint a; - bytes32 b; - (a,) = f(); - (,b) = f(); - } -} -// ---- -// Warning: (96-106): Different number of components on the left hand side (2) than on the right hand side (3). -// Warning: (110-120): Different number of components on the left hand side (2) than on the right hand side (3). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/warn_fill_vardecl.sol b/test/libsolidity/syntaxTests/tupleAssignments/warn_fill_vardecl.sol deleted file mode 100644 index 1d243c7c5..000000000 --- a/test/libsolidity/syntaxTests/tupleAssignments/warn_fill_vardecl.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C { - function f() public pure returns (uint, uint, uint, uint) { - // Can later be replaced by (uint a, uint b,) = f(); - var (a,b,) = f(); - a; b; - } -} -// ---- -// Warning: (136-137): Use of the "var" keyword is deprecated. -// Warning: (138-139): Use of the "var" keyword is deprecated. -// Warning: (131-147): Different number of components on the left hand side (3) than on the right hand side (4). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/warn_multiple_storage_storage_copies_fill_left.sol b/test/libsolidity/syntaxTests/tupleAssignments/warn_multiple_storage_storage_copies_fill_left.sol deleted file mode 100644 index b2979804e..000000000 --- a/test/libsolidity/syntaxTests/tupleAssignments/warn_multiple_storage_storage_copies_fill_left.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - struct S { uint a; uint b; } - S x; S y; - function f() public { - (,x, y) = (1, 2, y, x); - } -} -// ---- -// Warning: (79-101): This assignment performs two copies to storage. Since storage copies do not first copy to a temporary location, one of them might be overwritten before the second is executed and thus may have unexpected effects. It is safer to perform the copies separately or assign to storage pointers first. -// Warning: (79-101): Different number of components on the left hand side (3) than on the right hand side (4). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/warn_multiple_storage_storage_copies_fill_right.sol b/test/libsolidity/syntaxTests/tupleAssignments/warn_multiple_storage_storage_copies_fill_right.sol deleted file mode 100644 index aa35d7d4c..000000000 --- a/test/libsolidity/syntaxTests/tupleAssignments/warn_multiple_storage_storage_copies_fill_right.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - struct S { uint a; uint b; } - S x; S y; - function f() public { - (x, y, ) = (y, x, 1, 2); - } -} -// ---- -// Warning: (79-102): This assignment performs two copies to storage. Since storage copies do not first copy to a temporary location, one of them might be overwritten before the second is executed and thus may have unexpected effects. It is safer to perform the copies separately or assign to storage pointers first. -// Warning: (79-102): Different number of components on the left hand side (3) than on the right hand side (4). diff --git a/test/libsolidity/syntaxTests/types/address/address_abi_decode.sol b/test/libsolidity/syntaxTests/types/address/address_abi_decode.sol new file mode 100644 index 000000000..7be61ad2c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_abi_decode.sol @@ -0,0 +1,6 @@ +contract C { + function f(bytes memory b) public pure returns (address payable) { + (address payable c) = abi.decode(b, (address)); + return c; + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/types/address/address_constant.sol b/test/libsolidity/syntaxTests/types/address/address_constant.sol new file mode 100644 index 000000000..0b1af9917 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_constant.sol @@ -0,0 +1,7 @@ +contract C { + address constant a = address(0); + address payable constant b = address(0); + function f() public pure returns (address, address) { + return (a,b); + } +} diff --git a/test/libsolidity/syntaxTests/types/address/address_constant_assignment.sol b/test/libsolidity/syntaxTests/types/address/address_constant_assignment.sol new file mode 100644 index 000000000..da17ae33b --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_constant_assignment.sol @@ -0,0 +1,11 @@ +contract C { + address constant a = address(0); + address payable constant b = address(0); + function f() public { + a = address(0); + b = address(0); + } +} +// ---- +// TypeError: (129-130): Cannot assign to a constant variable. +// TypeError: (153-154): Cannot assign to a constant variable. diff --git a/test/libsolidity/syntaxTests/types/address/address_in_struct_fail.sol b/test/libsolidity/syntaxTests/types/address/address_in_struct_fail.sol new file mode 100644 index 000000000..9a5b2abb6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_in_struct_fail.sol @@ -0,0 +1,11 @@ +contract A { + struct S { + address payable a; + } + S s; + function f() public { + s.a = address(this); + } +} +// ---- +// TypeError: (110-123): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/address_in_struct_fine.sol b/test/libsolidity/syntaxTests/types/address/address_in_struct_fine.sol new file mode 100644 index 000000000..5519f0ef3 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_in_struct_fine.sol @@ -0,0 +1,20 @@ +contract A { + struct S { + address a; + } + S s; + function f() public { + s.a = address(this); + } +} +contract B { + struct S { + address payable a; + } + S s; + function f() public { + s.a = address(this); + } + function() external payable { + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/types/address/address_members_in_contract.sol b/test/libsolidity/syntaxTests/types/address/address_members_in_contract.sol new file mode 100644 index 000000000..eafc82687 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_members_in_contract.sol @@ -0,0 +1,6 @@ +contract C { + function f() public returns (C) { return this; } + function g() public returns (uint) { return f().balance(); } +} +// ---- +// TypeError: (114-125): Member "balance" not found or not visible after argument-dependent lookup in contract C. Use "address(...).balance" to access this address member. diff --git a/test/libsolidity/syntaxTests/types/address/address_nonpayable_selfdestruct.sol b/test/libsolidity/syntaxTests/types/address/address_nonpayable_selfdestruct.sol new file mode 100644 index 000000000..cc680ff3e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_nonpayable_selfdestruct.sol @@ -0,0 +1,7 @@ +contract C { + function f(address a) public { + selfdestruct(a); + } +} +// ---- +// TypeError: (69-70): Invalid type for argument in function call. Invalid implicit conversion from address to address payable requested. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_external_overload.sol b/test/libsolidity/syntaxTests/types/address/address_payable_external_overload.sol new file mode 100644 index 000000000..875532c47 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_external_overload.sol @@ -0,0 +1,7 @@ +contract C { + function f(address) external pure {} + function f(address payable) external pure {} + +} +// ---- +// TypeError: (58-102): Function overload clash during conversion to external types for arguments. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_nonpayable.sol b/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_nonpayable.sol new file mode 100644 index 000000000..656005440 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_nonpayable.sol @@ -0,0 +1,10 @@ +contract C { + function f(address payable) internal pure {} + function f(address) internal pure returns (uint) {} + function g() internal pure { + address a = address(0); + uint b = f(a); // TODO: should this be valid? + b; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_payable.sol b/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_payable.sol new file mode 100644 index 000000000..84142a31b --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_payable.sol @@ -0,0 +1,10 @@ +contract C { + function f(address payable) internal pure {} + function f(address) internal pure {} + function g() internal pure { + address payable a = address(0); + f(a); + } +} +// ---- +// TypeError: (184-185): No unique declaration found after argument-dependent lookup. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_memory_array_conversion.sol b/test/libsolidity/syntaxTests/types/address/address_payable_memory_array_conversion.sol new file mode 100644 index 000000000..ec58170bb --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_memory_array_conversion.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + address payable[] memory a = new address payable[](4); + address[] memory b = new address[](4); + a = b; + b = a; + } +} +// ---- +// TypeError: (166-167): Type address[] memory is not implicitly convertible to expected type address payable[] memory. +// TypeError: (181-182): Type address payable[] memory is not implicitly convertible to expected type address[] memory. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_public_overload.sol b/test/libsolidity/syntaxTests/types/address/address_payable_public_overload.sol new file mode 100644 index 000000000..839abc265 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_public_overload.sol @@ -0,0 +1,7 @@ +contract C { + function f(address) public pure {} + function f(address payable) public pure {} + +} +// ---- +// TypeError: (56-98): Function overload clash during conversion to external types for arguments. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol new file mode 100644 index 000000000..bdf43be72 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol @@ -0,0 +1,5 @@ +contract C { + function f(address payable a) public { + selfdestruct(a); + } +} diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_storage_array_conversion.sol b/test/libsolidity/syntaxTests/types/address/address_payable_storage_array_conversion.sol new file mode 100644 index 000000000..40f85ccce --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_storage_array_conversion.sol @@ -0,0 +1,11 @@ +contract C { + address payable[] a; + address[] b; + function f() public view { + address payable[] storage c = a; + address[] storage d = b; + d = c; // TODO: this could be allowed in the future + } +} +// ---- +// TypeError: (172-173): Type address payable[] storage pointer is not implicitly convertible to expected type address[] storage pointer. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_storage_array_conversion_fail.sol b/test/libsolidity/syntaxTests/types/address/address_payable_storage_array_conversion_fail.sol new file mode 100644 index 000000000..3c3eb859d --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_payable_storage_array_conversion_fail.sol @@ -0,0 +1,11 @@ +contract C { + address payable[] a; + address[] b; + function f() public view { + address payable[] storage c = a; + address[] storage d = b; + c = d; + } +} +// ---- +// TypeError: (172-173): Type address[] storage pointer is not implicitly convertible to expected type address payable[] storage pointer. diff --git a/test/libsolidity/syntaxTests/types/address/address_to_contract.sol b/test/libsolidity/syntaxTests/types/address/address_to_contract.sol new file mode 100644 index 000000000..629a3df04 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_to_contract.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure returns (C c) { + c = C(address(2)); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_to_contract_implicitly.sol b/test/libsolidity/syntaxTests/types/address/address_to_contract_implicitly.sol new file mode 100644 index 000000000..c9e5ddf6a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_to_contract_implicitly.sol @@ -0,0 +1,7 @@ +contract C { + function f() public view { + C c = address(2); + } +} +// ---- +// TypeError: (46-62): Type address payable is not implicitly convertible to expected type contract C. diff --git a/test/libsolidity/syntaxTests/types/address/address_to_contract_payable_fallback.sol b/test/libsolidity/syntaxTests/types/address/address_to_contract_payable_fallback.sol new file mode 100644 index 000000000..6917444b8 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_to_contract_payable_fallback.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure returns (C c) { + c = C(address(2)); + } + function() external payable { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/address_to_payable_address.sol new file mode 100644 index 000000000..1aab9b51c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_to_payable_address.sol @@ -0,0 +1,10 @@ +contract C { + function f(address a) public pure { + address b; + address payable c = a; + c = b; + } +} +// ---- +// TypeError: (80-101): Type address is not implicitly convertible to expected type address payable. +// TypeError: (115-116): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/address_to_payable_address_double.sol b/test/libsolidity/syntaxTests/types/address/address_to_payable_address_double.sol new file mode 100644 index 000000000..1e755033d --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_to_payable_address_double.sol @@ -0,0 +1,7 @@ +contract C { + function f(address a) public pure returns (address payable) { + return address(address(a)); + } +} +// ---- +// TypeError: (94-113): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/types/address/address_tuple_fail.sol b/test/libsolidity/syntaxTests/types/address/address_tuple_fail.sol new file mode 100644 index 000000000..17e9e7c1f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_tuple_fail.sol @@ -0,0 +1,8 @@ +contract C { + function f() public view returns (address payable a, address b) { + (address c, address payable d) = (address(this), address(0)); + (a,b) = (c,d); + } +} +// ---- +// TypeError: (169-174): Type tuple(address,address payable) is not implicitly convertible to expected type tuple(address payable,address). diff --git a/test/libsolidity/syntaxTests/types/address/address_tuple_fine.sol b/test/libsolidity/syntaxTests/types/address/address_tuple_fine.sol new file mode 100644 index 000000000..846de1f48 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_tuple_fine.sol @@ -0,0 +1,6 @@ +contract C { + function f() public view returns (address payable a, address b) { + (address c, address payable d) = (address(this), address(0)); + (a,b) = (d,c); + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/types/address/bytes_long_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/bytes_long_to_payable_address.sol new file mode 100644 index 000000000..ef87ac558 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/bytes_long_to_payable_address.sol @@ -0,0 +1,8 @@ +contract C { + function f(bytes32 x) public pure returns (address payable) { + return address(x); + } +} +// ---- +// TypeError: (94-104): Explicit type conversion not allowed from "bytes32" to "address". +// TypeError: (94-104): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/types/address/bytes_short_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/bytes_short_to_payable_address.sol new file mode 100644 index 000000000..2aa602516 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/bytes_short_to_payable_address.sol @@ -0,0 +1,8 @@ +contract C { + function f(bytes10 x) public pure returns (address payable) { + return address(x); + } +} +// ---- +// TypeError: (94-104): Explicit type conversion not allowed from "bytes10" to "address". +// TypeError: (94-104): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol new file mode 100644 index 000000000..5b6a6714d --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol @@ -0,0 +1,5 @@ +contract C { + function f(bytes20 x) public pure returns (address payable) { + return address(x); + } +} diff --git a/test/libsolidity/syntaxTests/types/address/contract_no_fallback_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/contract_no_fallback_to_payable_address.sol new file mode 100644 index 000000000..777bce002 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/contract_no_fallback_to_payable_address.sol @@ -0,0 +1,8 @@ +contract C { + function f() public view { + address payable a = address(this); + a; + } +} +// ---- +// TypeError: (46-79): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/contract_non_payable_fallback_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/contract_non_payable_fallback_to_payable_address.sol new file mode 100644 index 000000000..6518eebb5 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/contract_non_payable_fallback_to_payable_address.sol @@ -0,0 +1,10 @@ +contract C { + function f() public view { + address payable a = address(this); + a; + } + function() external { + } +} +// ---- +// TypeError: (46-79): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address.sol new file mode 100644 index 000000000..359beeb4c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address.sol @@ -0,0 +1,9 @@ +contract C { + function f() public view { + address payable a = address(this); + a; + } + function() external payable { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address_implicitly.sol b/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address_implicitly.sol new file mode 100644 index 000000000..4b20b1c67 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address_implicitly.sol @@ -0,0 +1,10 @@ +contract C { + function f() public view { + address payable a = this; + a; + } + function() external payable { + } +} +// ---- +// TypeError: (46-70): Type contract C is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/contract_to_address.sol b/test/libsolidity/syntaxTests/types/address/contract_to_address.sol new file mode 100644 index 000000000..ec2f8184d --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/contract_to_address.sol @@ -0,0 +1,7 @@ +contract C { + function f() public view { + address a = address(this); + a; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/contract_to_address_implicitly.sol b/test/libsolidity/syntaxTests/types/address/contract_to_address_implicitly.sol new file mode 100644 index 000000000..8be9daacb --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/contract_to_address_implicitly.sol @@ -0,0 +1,8 @@ +contract C { + function f() public view { + address a = this; + a; + } +} +// ---- +// TypeError: (46-62): Type contract C is not implicitly convertible to expected type address. diff --git a/test/libsolidity/syntaxTests/types/address/literal_to_address.sol b/test/libsolidity/syntaxTests/types/address/literal_to_address.sol new file mode 100644 index 000000000..20ee56de2 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/literal_to_address.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + address a = address(0); + a = address(1); + address b = 0x0123456789012345678901234567890123456789; + b = 0x9876543210987654321098765432109876543210; + b = 0x9876_5432_1098_7654_3210_9876_5432_1098_7654_3210; + } +} diff --git a/test/libsolidity/syntaxTests/types/address/literal_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/literal_to_payable_address.sol new file mode 100644 index 000000000..97f4d85d3 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/literal_to_payable_address.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure { + address payable a = address(0); + a = address(1); + address payable b = 0x0123456789012345678901234567890123456789; + b = 0x9876543210987654321098765432109876543210; + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/types/address/nonpayable_address_to_contract_payable_fallback.sol b/test/libsolidity/syntaxTests/types/address/nonpayable_address_to_contract_payable_fallback.sol new file mode 100644 index 000000000..e13a0897f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/nonpayable_address_to_contract_payable_fallback.sol @@ -0,0 +1,10 @@ +contract C { + function f() public pure returns (C c) { + address a = address(2); + c = C(a); + } + function() external payable { + } +} +// ---- +// TypeError: (92-96): Explicit type conversion not allowed from non-payable "address" to "contract C", which has a payable fallback function. diff --git a/test/libsolidity/syntaxTests/types/address/payable_address_to_address.sol b/test/libsolidity/syntaxTests/types/address/payable_address_to_address.sol new file mode 100644 index 000000000..f5dbf937e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/payable_address_to_address.sol @@ -0,0 +1,7 @@ +contract C { + function f(address payable a) public pure { + address payable b; + address c = a; + c = b; + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol new file mode 100644 index 000000000..9a33985a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol @@ -0,0 +1,5 @@ +contract C { + function f(uint x) public pure returns (address payable) { + return address(x); + } +} diff --git a/test/libsolidity/syntaxTests/types/array_index_too_large.sol b/test/libsolidity/syntaxTests/types/array_index_too_large.sol new file mode 100644 index 000000000..06b5071f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/array_index_too_large.sol @@ -0,0 +1,8 @@ +contract C { + function f() public returns (string memory) { + // this used to cause an internal error + return (["zeppelin"][123456789012345678901234567890123456789012345678901234567890123456789012345678]); + } +} +// ---- +// TypeError: (140-218): Type int_const 1234...(70 digits omitted)...5678 is not implicitly convertible to expected type uint256. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/types/bool_ops.sol b/test/libsolidity/syntaxTests/types/bool_ops.sol new file mode 100644 index 000000000..910339064 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bool_ops.sol @@ -0,0 +1,53 @@ +contract C { + function f(bool a, bool b) public pure { + bool c; + // OK + c = !a; + c = !b; + c = a == b; + c = a != b; + c = a || b; + c = a && b; + + // Not OK + c = a > b; + c = a < b; + c = a >= b; + c = a <= b; + c = a & b; + c = a | b; + c = a ^ b; + c = ~a; + c = ~b; + c = a + b; + c = a - b; + c = -a; + c = -b; + c = a * b; + c = a / b; + c = a ** b; + c = a % b; + c = a << b; + c = a >> b; + } +} +// ---- +// TypeError: (231-236): Operator > not compatible with types bool and bool +// TypeError: (250-255): Operator < not compatible with types bool and bool +// TypeError: (269-275): Operator >= not compatible with types bool and bool +// TypeError: (289-295): Operator <= not compatible with types bool and bool +// TypeError: (309-314): Operator & not compatible with types bool and bool +// TypeError: (328-333): Operator | not compatible with types bool and bool +// TypeError: (347-352): Operator ^ not compatible with types bool and bool +// TypeError: (366-368): Unary operator ~ cannot be applied to type bool +// TypeError: (382-384): Unary operator ~ cannot be applied to type bool +// TypeError: (398-403): Operator + not compatible with types bool and bool +// TypeError: (417-422): Operator - not compatible with types bool and bool +// TypeError: (436-438): Unary operator - cannot be applied to type bool +// TypeError: (452-454): Unary operator - cannot be applied to type bool +// TypeError: (468-473): Operator * not compatible with types bool and bool +// TypeError: (487-492): Operator / not compatible with types bool and bool +// TypeError: (506-512): Operator ** not compatible with types bool and bool +// TypeError: (526-531): Operator % not compatible with types bool and bool +// TypeError: (545-551): Operator << not compatible with types bool and bool +// TypeError: (565-571): Operator >> not compatible with types bool and bool diff --git a/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol b/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol new file mode 100644 index 000000000..58828a627 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(uint256) { + return uint256(bytes1('')); + } +} +// ---- +// TypeError: (76-95): Explicit type conversion not allowed from "bytes1" to "uint256". diff --git a/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol b/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol new file mode 100644 index 000000000..77e813abb --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(uint32) { + return uint32(bytes32('')); + } +} +// ---- +// TypeError: (75-94): Explicit type conversion not allowed from "bytes32" to "uint32". diff --git a/test/libsolidity/syntaxTests/types/bytes_to_contract.sol b/test/libsolidity/syntaxTests/types/bytes_to_contract.sol index 2a3219ec5..820dbf9bd 100644 --- a/test/libsolidity/syntaxTests/types/bytes_to_contract.sol +++ b/test/libsolidity/syntaxTests/types/bytes_to_contract.sol @@ -1,7 +1,7 @@ contract C { function f() public pure { - C(bytes20(0x1234)); + C(bytes20(uint160(0x1234))); } } // ---- -// TypeError: (64-82): Explicit type conversion not allowed from "bytes20" to "contract C". +// TypeError: (64-91): Explicit type conversion not allowed from "bytes20" to "contract C". diff --git a/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol b/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol new file mode 100644 index 000000000..2963cfd27 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol @@ -0,0 +1,20 @@ +contract C { + function f() public pure returns (uint256) { + return uint256(bytes32(uint256(0))); + } + function g() public pure returns (uint128) { + return uint128(bytes16(uint128(0))); + } + function h() public pure returns (uint64) { + return uint64(bytes8(uint64(0))); + } + function i() public pure returns (uint32) { + return uint32(bytes4(uint32(0))); + } + function j() public pure returns (uint16) { + return uint16(bytes2(uint16(0))); + } + function k() public pure returns (uint8) { + return uint8(bytes1(uint8(0))); + } +} diff --git a/test/libsolidity/syntaxTests/types/bytesm.sol b/test/libsolidity/syntaxTests/types/bytesm.sol index 550760b9d..77ff75240 100644 --- a/test/libsolidity/syntaxTests/types/bytesm.sol +++ b/test/libsolidity/syntaxTests/types/bytesm.sol @@ -1,5 +1,5 @@ contract C { - byte b = byte(1); + byte b = byte(0x01); bytes1 b1 = b; bytes2 b2 = b1; bytes3 b3 = b2; diff --git a/test/libsolidity/syntaxTests/types/contract_to_base.sol b/test/libsolidity/syntaxTests/types/contract_to_base.sol new file mode 100644 index 000000000..b0a24e620 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/contract_to_base.sol @@ -0,0 +1,9 @@ +contract A {} +contract B is A {} +contract C { + function f() public { + A a = new B(); + a; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/contract_to_base_base.sol b/test/libsolidity/syntaxTests/types/contract_to_base_base.sol new file mode 100644 index 000000000..e99e5cdc9 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/contract_to_base_base.sol @@ -0,0 +1,10 @@ +contract A {} +contract B is A {} +contract C is B {} +contract D { + function f() public { + A a = new C(); + a; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/contract_to_derived.sol b/test/libsolidity/syntaxTests/types/contract_to_derived.sol new file mode 100644 index 000000000..ac8df5d1f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/contract_to_derived.sol @@ -0,0 +1,9 @@ +contract B {} +contract A is B {} +contract C { + function f() public pure { + A a = A(new B()); + } +} +// ---- +// TypeError: (85-95): Explicit type conversion not allowed from "contract B" to "contract A". diff --git a/test/libsolidity/syntaxTests/types/contract_to_unrelated_contract.sol b/test/libsolidity/syntaxTests/types/contract_to_unrelated_contract.sol new file mode 100644 index 000000000..b0a4875f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/contract_to_unrelated_contract.sol @@ -0,0 +1,9 @@ +contract A {} +contract B {} +contract C { + function f() public pure { + B b = B(new A()); + } +} +// ---- +// TypeError: (80-90): Explicit type conversion not allowed from "contract A" to "contract B". diff --git a/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_consts_exhausted.sol b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_consts_exhausted.sol new file mode 100644 index 000000000..c66697461 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_consts_exhausted.sol @@ -0,0 +1,262 @@ +contract A {} +contract Main { + A constant B = C; + A constant C = D; + A constant D = E; + A constant E = F; + A constant F = G; + A constant G = H; + A constant H = I; + A constant I = J; + A constant J = K; + A constant K = L; + A constant L = M; + A constant M = N; + A constant N = O; + A constant O = P; + A constant P = Q; + A constant Q = R; + A constant R = S; + A constant S = T; + A constant T = U; + A constant U = V; + A constant V = W; + A constant W = X; + A constant X = Y; + A constant Y = Z; + A constant Z = BA; + A constant BA = BB; + A constant BB = BC; + A constant BC = BD; + A constant BD = BE; + A constant BE = BF; + A constant BF = BG; + A constant BG = BH; + A constant BH = BI; + A constant BI = BJ; + A constant BJ = BK; + A constant BK = BL; + A constant BL = BM; + A constant BM = BN; + A constant BN = BO; + A constant BO = BP; + A constant BP = BQ; + A constant BQ = BR; + A constant BR = BS; + A constant BS = BT; + A constant BT = BU; + A constant BU = BV; + A constant BV = BW; + A constant BW = BX; + A constant BX = BY; + A constant BY = BZ; + A constant BZ = CA; + A constant CA = CB; + A constant CB = CC; + A constant CC = CD; + A constant CD = CE; + A constant CE = CF; + A constant CF = CG; + A constant CG = CH; + A constant CH = CI; + A constant CI = CJ; + A constant CJ = CK; + A constant CK = CL; + A constant CL = CM; + A constant CM = CN; + A constant CN = CO; + A constant CO = CP; + A constant CP = CQ; + A constant CQ = CR; + A constant CR = CS; + A constant CS = CT; + A constant CT = CU; + A constant CU = CV; + A constant CV = CW; + A constant CW = CX; + A constant CX = CY; + A constant CY = CZ; + A constant CZ = DA; + A constant DA = DB; + A constant DB = DC; + A constant DC = DD; + A constant DD = DE; + A constant DE = DF; + A constant DF = DG; + A constant DG = DH; + A constant DH = DI; + A constant DI = DJ; + A constant DJ = DK; + A constant DK = DL; + A constant DL = DM; + A constant DM = DN; + A constant DN = DO; + A constant DO = DP; + A constant DP = DQ; + A constant DQ = DR; + A constant DR = DS; + A constant DS = DT; + A constant DT = DU; + A constant DU = DV; + A constant DV = DW; + A constant DW = DX; + A constant DX = DY; + A constant DY = DZ; + A constant DZ = EA; + A constant EA = EB; + A constant EB = EC; + A constant EC = ED; + A constant ED = EE; + A constant EE = EF; + A constant EF = EG; + A constant EG = EH; + A constant EH = EI; + A constant EI = EJ; + A constant EJ = EK; + A constant EK = EL; + A constant EL = EM; + A constant EM = EN; + A constant EN = EO; + A constant EO = EP; + A constant EP = EQ; + A constant EQ = ER; + A constant ER = ES; + A constant ES = ET; + A constant ET = EU; + A constant EU = EV; + A constant EV = EW; + A constant EW = EX; + A constant EX = EY; + A constant EY = EZ; + A constant EZ = FA; + A constant FA = FB; + A constant FB = FC; + A constant FC = FD; + A constant FD = FE; + A constant FE = FF; + A constant FF = FG; + A constant FG = FH; + A constant FH = FI; + A constant FI = FJ; + A constant FJ = FK; + A constant FK = FL; + A constant FL = FM; + A constant FM = FN; + A constant FN = FO; + A constant FO = FP; + A constant FP = FQ; + A constant FQ = FR; + A constant FR = FS; + A constant FS = FT; + A constant FT = FU; + A constant FU = FV; + A constant FV = FW; + A constant FW = FX; + A constant FX = FY; + A constant FY = FZ; + A constant FZ = GA; + A constant GA = GB; + A constant GB = GC; + A constant GC = GD; + A constant GD = GE; + A constant GE = GF; + A constant GF = GG; + A constant GG = GH; + A constant GH = GI; + A constant GI = GJ; + A constant GJ = GK; + A constant GK = GL; + A constant GL = GM; + A constant GM = GN; + A constant GN = GO; + A constant GO = GP; + A constant GP = GQ; + A constant GQ = GR; + A constant GR = GS; + A constant GS = GT; + A constant GT = GU; + A constant GU = GV; + A constant GV = GW; + A constant GW = GX; + A constant GX = GY; + A constant GY = GZ; + A constant GZ = HA; + A constant HA = HB; + A constant HB = HC; + A constant HC = HD; + A constant HD = HE; + A constant HE = HF; + A constant HF = HG; + A constant HG = HH; + A constant HH = HI; + A constant HI = HJ; + A constant HJ = HK; + A constant HK = HL; + A constant HL = HM; + A constant HM = HN; + A constant HN = HO; + A constant HO = HP; + A constant HP = HQ; + A constant HQ = HR; + A constant HR = HS; + A constant HS = HT; + A constant HT = HU; + A constant HU = HV; + A constant HV = HW; + A constant HW = HX; + A constant HX = HY; + A constant HY = HZ; + A constant HZ = IA; + A constant IA = IB; + A constant IB = IC; + A constant IC = ID; + A constant ID = IE; + A constant IE = IF; + A constant IF = IG; + A constant IG = IH; + A constant IH = II; + A constant II = IJ; + A constant IJ = IK; + A constant IK = IL; + A constant IL = IM; + A constant IM = IN; + A constant IN = IO; + A constant IO = IP; + A constant IP = IQ; + A constant IQ = IR; + A constant IR = IS; + A constant IS = IT; + A constant IT = IU; + A constant IU = IV; + A constant IV = IW; + A constant IW = IX; + A constant IX = IY; + A constant IY = IZ; + A constant IZ = JA; + A constant JA = JB; + A constant JB = JC; + A constant JC = JD; + A constant JD = JE; + A constant JE = JF; + A constant JF = JG; + A constant JG = JH; + A constant JH = JI; + A constant JI = JJ; + A constant JJ = JK; + A constant JK = JL; + A constant JL = JM; + A constant JM = JN; + A constant JN = JO; + A constant JO = JP; + A constant JP = JQ; + A constant JQ = JR; + A constant JR = JS; + A constant JS = JT; + A constant JT = JU; + A constant JU = JV; + A constant JV = JW; + A constant JW = JX; + A constant JX = A(0x00); +} +// ---- +// DeclarationError: (6105-6123): Variable definition exhausting cyclic dependency validator. diff --git a/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_consts_good.sol b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_consts_good.sol new file mode 100644 index 000000000..7f8c61894 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_consts_good.sol @@ -0,0 +1,135 @@ +contract A {} +contract Main { + A constant B = C; + A constant C = D; + A constant D = E; + A constant E = F; + A constant F = G; + A constant G = H; + A constant H = I; + A constant I = J; + A constant J = K; + A constant K = L; + A constant L = M; + A constant M = N; + A constant N = O; + A constant O = P; + A constant P = Q; + A constant Q = R; + A constant R = S; + A constant S = T; + A constant T = U; + A constant U = V; + A constant V = W; + A constant W = X; + A constant X = Y; + A constant Y = Z; + A constant Z = BA; + A constant BA = BB; + A constant BB = BC; + A constant BC = BD; + A constant BD = BE; + A constant BE = BF; + A constant BF = BG; + A constant BG = BH; + A constant BH = BI; + A constant BI = BJ; + A constant BJ = BK; + A constant BK = BL; + A constant BL = BM; + A constant BM = BN; + A constant BN = BO; + A constant BO = BP; + A constant BP = BQ; + A constant BQ = BR; + A constant BR = BS; + A constant BS = BT; + A constant BT = BU; + A constant BU = BV; + A constant BV = BW; + A constant BW = BX; + A constant BX = BY; + A constant BY = BZ; + A constant BZ = CA; + A constant CA = CB; + A constant CB = CC; + A constant CC = CD; + A constant CD = CE; + A constant CE = CF; + A constant CF = CG; + A constant CG = CH; + A constant CH = CI; + A constant CI = CJ; + A constant CJ = CK; + A constant CK = CL; + A constant CL = CM; + A constant CM = CN; + A constant CN = CO; + A constant CO = CP; + A constant CP = CQ; + A constant CQ = CR; + A constant CR = CS; + A constant CS = CT; + A constant CT = CU; + A constant CU = CV; + A constant CV = CW; + A constant CW = CX; + A constant CX = CY; + A constant CY = CZ; + A constant CZ = DA; + A constant DA = DB; + A constant DB = DC; + A constant DC = DD; + A constant DD = DE; + A constant DE = DF; + A constant DF = DG; + A constant DG = DH; + A constant DH = DI; + A constant DI = DJ; + A constant DJ = DK; + A constant DK = DL; + A constant DL = DM; + A constant DM = DN; + A constant DN = DO; + A constant DO = DP; + A constant DP = DQ; + A constant DQ = DR; + A constant DR = DS; + A constant DS = DT; + A constant DT = DU; + A constant DU = DV; + A constant DV = DW; + A constant DW = DX; + A constant DX = DY; + A constant DY = DZ; + A constant DZ = EA; + A constant EA = EB; + A constant EB = EC; + A constant EC = ED; + A constant ED = EE; + A constant EE = EF; + A constant EF = EG; + A constant EG = EH; + A constant EH = EI; + A constant EI = EJ; + A constant EJ = EK; + A constant EK = EL; + A constant EL = EM; + A constant EM = EN; + A constant EN = EO; + A constant EO = EP; + A constant EP = EQ; + A constant EQ = ER; + A constant ER = ES; + A constant ES = ET; + A constant ET = EU; + A constant EU = EV; + A constant EV = EW; + A constant EW = EX; + A constant EX = EY; + A constant EY = EZ; + A constant EZ = FA; + A constant FA = FB; + A constant FB = FC; + A constant FC = A(0x00); +} diff --git a/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_struct_exhausted.sol b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_struct_exhausted.sol new file mode 100644 index 000000000..db0ff4af6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_struct_exhausted.sol @@ -0,0 +1,260 @@ +contract Main { + struct B { C m; } + struct C { D m; } + struct D { E m; } + struct E { F m; } + struct F { G m; } + struct G { H m; } + struct H { I m; } + struct I { J m; } + struct J { K m; } + struct K { L m; } + struct L { M m; } + struct M { N m; } + struct N { O m; } + struct O { P m; } + struct P { Q m; } + struct Q { R m; } + struct R { S m; } + struct S { T m; } + struct T { U m; } + struct U { V m; } + struct V { W m; } + struct W { X m; } + struct X { Y m; } + struct Y { Z m; } + struct Z { BA m; } + struct BA { BB m; } + struct BB { BC m; } + struct BC { BD m; } + struct BD { BE m; } + struct BE { BF m; } + struct BF { BG m; } + struct BG { BH m; } + struct BH { BI m; } + struct BI { BJ m; } + struct BJ { BK m; } + struct BK { BL m; } + struct BL { BM m; } + struct BM { BN m; } + struct BN { BO m; } + struct BO { BP m; } + struct BP { BQ m; } + struct BQ { BR m; } + struct BR { BS m; } + struct BS { BT m; } + struct BT { BU m; } + struct BU { BV m; } + struct BV { BW m; } + struct BW { BX m; } + struct BX { BY m; } + struct BY { BZ m; } + struct BZ { CA m; } + struct CA { CB m; } + struct CB { CC m; } + struct CC { CD m; } + struct CD { CE m; } + struct CE { CF m; } + struct CF { CG m; } + struct CG { CH m; } + struct CH { CI m; } + struct CI { CJ m; } + struct CJ { CK m; } + struct CK { CL m; } + struct CL { CM m; } + struct CM { CN m; } + struct CN { CO m; } + struct CO { CP m; } + struct CP { CQ m; } + struct CQ { CR m; } + struct CR { CS m; } + struct CS { CT m; } + struct CT { CU m; } + struct CU { CV m; } + struct CV { CW m; } + struct CW { CX m; } + struct CX { CY m; } + struct CY { CZ m; } + struct CZ { DA m; } + struct DA { DB m; } + struct DB { DC m; } + struct DC { DD m; } + struct DD { DE m; } + struct DE { DF m; } + struct DF { DG m; } + struct DG { DH m; } + struct DH { DI m; } + struct DI { DJ m; } + struct DJ { DK m; } + struct DK { DL m; } + struct DL { DM m; } + struct DM { DN m; } + struct DN { DO m; } + struct DO { DP m; } + struct DP { DQ m; } + struct DQ { DR m; } + struct DR { DS m; } + struct DS { DT m; } + struct DT { DU m; } + struct DU { DV m; } + struct DV { DW m; } + struct DW { DX m; } + struct DX { DY m; } + struct DY { DZ m; } + struct DZ { EA m; } + struct EA { EB m; } + struct EB { EC m; } + struct EC { ED m; } + struct ED { EE m; } + struct EE { EF m; } + struct EF { EG m; } + struct EG { EH m; } + struct EH { EI m; } + struct EI { EJ m; } + struct EJ { EK m; } + struct EK { EL m; } + struct EL { EM m; } + struct EM { EN m; } + struct EN { EO m; } + struct EO { EP m; } + struct EP { EQ m; } + struct EQ { ER m; } + struct ER { ES m; } + struct ES { ET m; } + struct ET { EU m; } + struct EU { EV m; } + struct EV { EW m; } + struct EW { EX m; } + struct EX { EY m; } + struct EY { EZ m; } + struct EZ { FA m; } + struct FA { FB m; } + struct FB { FC m; } + struct FC { FD m; } + struct FD { FE m; } + struct FE { FF m; } + struct FF { FG m; } + struct FG { FH m; } + struct FH { FI m; } + struct FI { FJ m; } + struct FJ { FK m; } + struct FK { FL m; } + struct FL { FM m; } + struct FM { FN m; } + struct FN { FO m; } + struct FO { FP m; } + struct FP { FQ m; } + struct FQ { FR m; } + struct FR { FS m; } + struct FS { FT m; } + struct FT { FU m; } + struct FU { FV m; } + struct FV { FW m; } + struct FW { FX m; } + struct FX { FY m; } + struct FY { FZ m; } + struct FZ { GA m; } + struct GA { GB m; } + struct GB { GC m; } + struct GC { GD m; } + struct GD { GE m; } + struct GE { GF m; } + struct GF { GG m; } + struct GG { GH m; } + struct GH { GI m; } + struct GI { GJ m; } + struct GJ { GK m; } + struct GK { GL m; } + struct GL { GM m; } + struct GM { GN m; } + struct GN { GO m; } + struct GO { GP m; } + struct GP { GQ m; } + struct GQ { GR m; } + struct GR { GS m; } + struct GS { GT m; } + struct GT { GU m; } + struct GU { GV m; } + struct GV { GW m; } + struct GW { GX m; } + struct GX { GY m; } + struct GY { GZ m; } + struct GZ { HA m; } + struct HA { HB m; } + struct HB { HC m; } + struct HC { HD m; } + struct HD { HE m; } + struct HE { HF m; } + struct HF { HG m; } + struct HG { HH m; } + struct HH { HI m; } + struct HI { HJ m; } + struct HJ { HK m; } + struct HK { HL m; } + struct HL { HM m; } + struct HM { HN m; } + struct HN { HO m; } + struct HO { HP m; } + struct HP { HQ m; } + struct HQ { HR m; } + struct HR { HS m; } + struct HS { HT m; } + struct HT { HU m; } + struct HU { HV m; } + struct HV { HW m; } + struct HW { HX m; } + struct HX { HY m; } + struct HY { HZ m; } + struct HZ { IA m; } + struct IA { IB m; } + struct IB { IC m; } + struct IC { ID m; } + struct ID { IE m; } + struct IE { IF m; } + struct IF { IG m; } + struct IG { IH m; } + struct IH { II m; } + struct II { IJ m; } + struct IJ { IK m; } + struct IK { IL m; } + struct IL { IM m; } + struct IM { IN m; } + struct IN { IO m; } + struct IO { IP m; } + struct IP { IQ m; } + struct IQ { IR m; } + struct IR { IS m; } + struct IS { IT m; } + struct IT { IU m; } + struct IU { IV m; } + struct IV { IW m; } + struct IW { IX m; } + struct IX { IY m; } + struct IY { IZ m; } + struct IZ { JA m; } + struct JA { JB m; } + struct JB { JC m; } + struct JC { JD m; } + struct JD { JE m; } + struct JE { JF m; } + struct JF { JG m; } + struct JG { JH m; } + struct JH { JI m; } + struct JI { JJ m; } + struct JJ { JK m; } + struct JK { JL m; } + struct JL { JM m; } + struct JM { JN m; } + struct JN { JO m; } + struct JO { JP m; } + struct JP { JQ m; } + struct JQ { JR m; } + struct JR { JS m; } + struct JS { JT m; } + struct JT { JU m; } + struct JU { JV m; } + struct JV { JW m; } + struct JW { int i; } +} +// ---- +// DeclarationError: (6091-6111): Struct definition exhausting cyclic dependency validator. diff --git a/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_struct_good.sol b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_struct_good.sol new file mode 100644 index 000000000..0419bea6e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/cyclic_dependency_check_on_struct_good.sol @@ -0,0 +1,134 @@ +contract Main { + struct B { C m; } + struct C { D m; } + struct D { E m; } + struct E { F m; } + struct F { G m; } + struct G { H m; } + struct H { I m; } + struct I { J m; } + struct J { K m; } + struct K { L m; } + struct L { M m; } + struct M { N m; } + struct N { O m; } + struct O { P m; } + struct P { Q m; } + struct Q { R m; } + struct R { S m; } + struct S { T m; } + struct T { U m; } + struct U { V m; } + struct V { W m; } + struct W { X m; } + struct X { Y m; } + struct Y { Z m; } + struct Z { BA m; } + struct BA { BB m; } + struct BB { BC m; } + struct BC { BD m; } + struct BD { BE m; } + struct BE { BF m; } + struct BF { BG m; } + struct BG { BH m; } + struct BH { BI m; } + struct BI { BJ m; } + struct BJ { BK m; } + struct BK { BL m; } + struct BL { BM m; } + struct BM { BN m; } + struct BN { BO m; } + struct BO { BP m; } + struct BP { BQ m; } + struct BQ { BR m; } + struct BR { BS m; } + struct BS { BT m; } + struct BT { BU m; } + struct BU { BV m; } + struct BV { BW m; } + struct BW { BX m; } + struct BX { BY m; } + struct BY { BZ m; } + struct BZ { CA m; } + struct CA { CB m; } + struct CB { CC m; } + struct CC { CD m; } + struct CD { CE m; } + struct CE { CF m; } + struct CF { CG m; } + struct CG { CH m; } + struct CH { CI m; } + struct CI { CJ m; } + struct CJ { CK m; } + struct CK { CL m; } + struct CL { CM m; } + struct CM { CN m; } + struct CN { CO m; } + struct CO { CP m; } + struct CP { CQ m; } + struct CQ { CR m; } + struct CR { CS m; } + struct CS { CT m; } + struct CT { CU m; } + struct CU { CV m; } + struct CV { CW m; } + struct CW { CX m; } + struct CX { CY m; } + struct CY { CZ m; } + struct CZ { DA m; } + struct DA { DB m; } + struct DB { DC m; } + struct DC { DD m; } + struct DD { DE m; } + struct DE { DF m; } + struct DF { DG m; } + struct DG { DH m; } + struct DH { DI m; } + struct DI { DJ m; } + struct DJ { DK m; } + struct DK { DL m; } + struct DL { DM m; } + struct DM { DN m; } + struct DN { DO m; } + struct DO { DP m; } + struct DP { DQ m; } + struct DQ { DR m; } + struct DR { DS m; } + struct DS { DT m; } + struct DT { DU m; } + struct DU { DV m; } + struct DV { DW m; } + struct DW { DX m; } + struct DX { DY m; } + struct DY { DZ m; } + struct DZ { EA m; } + struct EA { EB m; } + struct EB { EC m; } + struct EC { ED m; } + struct ED { EE m; } + struct EE { EF m; } + struct EF { EG m; } + struct EG { EH m; } + struct EH { EI m; } + struct EI { EJ m; } + struct EJ { EK m; } + struct EK { EL m; } + struct EL { EM m; } + struct EM { EN m; } + struct EN { EO m; } + struct EO { EP m; } + struct EP { EQ m; } + struct EQ { ER m; } + struct ER { ES m; } + struct ES { ET m; } + struct ET { EU m; } + struct EU { EV m; } + struct EV { EW m; } + struct EW { EX m; } + struct EX { EY m; } + struct EY { EZ m; } + struct EZ { FA m; } + struct FA { FB m; } + struct FB { FC m; } + struct FC { int i; } +} diff --git a/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_explicit.sol b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_explicit.sol new file mode 100644 index 000000000..ff285a079 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_explicit.sol @@ -0,0 +1,23 @@ +contract C { + function f() public pure { + bytes1 b1 = bytes1(1); + bytes2 b2 = bytes2(1); + bytes2 b3 = bytes2(256); + bytes3 b4 = bytes3(1); + bytes3 b5 = bytes3(65536); + bytes4 b6 = bytes4(1); + bytes4 b7 = bytes4(16777216); + bytes16 b8 = bytes16(1); + bytes32 b9 = bytes32(1); + } +} +// ---- +// TypeError: (60-69): Explicit type conversion not allowed from "int_const 1" to "bytes1". +// TypeError: (88-97): Explicit type conversion not allowed from "int_const 1" to "bytes2". +// TypeError: (116-127): Explicit type conversion not allowed from "int_const 256" to "bytes2". +// TypeError: (146-155): Explicit type conversion not allowed from "int_const 1" to "bytes3". +// TypeError: (174-187): Explicit type conversion not allowed from "int_const 65536" to "bytes3". +// TypeError: (206-215): Explicit type conversion not allowed from "int_const 1" to "bytes4". +// TypeError: (234-250): Explicit type conversion not allowed from "int_const 16777216" to "bytes4". +// TypeError: (270-280): Explicit type conversion not allowed from "int_const 1" to "bytes16". +// TypeError: (300-310): Explicit type conversion not allowed from "int_const 1" to "bytes32". diff --git a/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_implicit.sol b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_implicit.sol new file mode 100644 index 000000000..e472c43b2 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_implicit.sol @@ -0,0 +1,23 @@ +contract C { + function f() public pure { + bytes1 b1 = 1; + bytes2 b2 = 1; + bytes2 b3 = 256; + bytes3 b4 = 1; + bytes3 b5 = 65536; + bytes4 b6 = 1; + bytes4 b7 = 16777216; + bytes16 b8 = 1; + bytes32 b9 = 1; + } +} +// ---- +// TypeError: (48-61): Type int_const 1 is not implicitly convertible to expected type bytes1. +// TypeError: (68-81): Type int_const 1 is not implicitly convertible to expected type bytes2. +// TypeError: (88-103): Type int_const 256 is not implicitly convertible to expected type bytes2. +// TypeError: (110-123): Type int_const 1 is not implicitly convertible to expected type bytes3. +// TypeError: (130-147): Type int_const 65536 is not implicitly convertible to expected type bytes3. +// TypeError: (154-167): Type int_const 1 is not implicitly convertible to expected type bytes4. +// TypeError: (174-194): Type int_const 16777216 is not implicitly convertible to expected type bytes4. +// TypeError: (201-215): Type int_const 1 is not implicitly convertible to expected type bytes16. +// TypeError: (222-236): Type int_const 1 is not implicitly convertible to expected type bytes32. diff --git a/test/libsolidity/syntaxTests/types/empty_tuple_event.sol b/test/libsolidity/syntaxTests/types/empty_tuple_event.sol index 3e40b155a..898ee8bac 100644 --- a/test/libsolidity/syntaxTests/types/empty_tuple_event.sol +++ b/test/libsolidity/syntaxTests/types/empty_tuple_event.sol @@ -1,10 +1,8 @@ -pragma solidity ^0.4.3; contract C { event SomeEvent(); function a() public { - (SomeEvent(), 7); + (emit SomeEvent(), 7); } } // ---- -// Warning: (95-106): Invoking events without "emit" prefix is deprecated. -// Warning: (95-106): Tuple component cannot be empty. +// ParserError: (71-75): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/types/empty_tuple_event_050.sol b/test/libsolidity/syntaxTests/types/empty_tuple_event_050.sol deleted file mode 100644 index aec5ff2af..000000000 --- a/test/libsolidity/syntaxTests/types/empty_tuple_event_050.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - event SomeEvent(); - function a() public { - (SomeEvent(), 7); - } -} -// ---- -// TypeError: (101-112): Event invocations have to be prefixed by "emit". -// TypeError: (101-112): Tuple component cannot be empty. diff --git a/test/libsolidity/syntaxTests/types/empty_tuple_function.sol b/test/libsolidity/syntaxTests/types/empty_tuple_function.sol index 05b54442c..a898f84ad 100644 --- a/test/libsolidity/syntaxTests/types/empty_tuple_function.sol +++ b/test/libsolidity/syntaxTests/types/empty_tuple_function.sol @@ -1,4 +1,3 @@ -pragma solidity ^0.4.3; contract C { function f() private pure {} function a() public pure { @@ -8,5 +7,5 @@ contract C { } } // ---- -// Warning: (162-165): Tuple component cannot be empty. -// Warning: (181-184): Tuple component cannot be empty. +// TypeError: (138-141): Tuple component cannot be empty. +// TypeError: (157-160): Tuple component cannot be empty. diff --git a/test/libsolidity/syntaxTests/types/empty_tuple_function_050.sol b/test/libsolidity/syntaxTests/types/empty_tuple_function_050.sol deleted file mode 100644 index c4b9e03fd..000000000 --- a/test/libsolidity/syntaxTests/types/empty_tuple_function_050.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() private pure {} - function a() public pure { - bool x = true; - bool y = true; - (x) ? (f(), y = false) : (f(), y = false); - } -} -// ---- -// TypeError: (168-171): Tuple component cannot be empty. diff --git a/test/libsolidity/syntaxTests/types/empty_tuple_lvalue.sol b/test/libsolidity/syntaxTests/types/empty_tuple_lvalue.sol index cba30c1b8..63b039cd8 100644 --- a/test/libsolidity/syntaxTests/types/empty_tuple_lvalue.sol +++ b/test/libsolidity/syntaxTests/types/empty_tuple_lvalue.sol @@ -1,4 +1,3 @@ -pragma solidity ^0.4.3; contract C { function f() private pure {} function a() public { @@ -8,6 +7,6 @@ contract C { } } // ---- -// Warning: (146-149): Tuple component cannot be empty. -// Warning: (151-154): Tuple component cannot be empty. -// TypeError: (145-155): Type tuple(tuple(),tuple()) is not implicitly convertible to expected type tuple(uint256,uint256). +// TypeError: (122-125): Tuple component cannot be empty. +// TypeError: (127-130): Tuple component cannot be empty. +// TypeError: (121-131): Type tuple(tuple(),tuple()) is not implicitly convertible to expected type tuple(uint256,uint256). diff --git a/test/libsolidity/syntaxTests/types/empty_tuple_lvalue_050.sol b/test/libsolidity/syntaxTests/types/empty_tuple_lvalue_050.sol deleted file mode 100644 index b06917782..000000000 --- a/test/libsolidity/syntaxTests/types/empty_tuple_lvalue_050.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() private pure {} - function a() public { - uint x; - uint y; - (x, y) = (f(), f()); - } -} -// ---- -// TypeError: (152-155): Tuple component cannot be empty. diff --git a/test/libsolidity/syntaxTests/types/empty_tuple_lvalue_array.sol b/test/libsolidity/syntaxTests/types/empty_tuple_lvalue_array.sol index f8b2ae7e1..9bc21561b 100644 --- a/test/libsolidity/syntaxTests/types/empty_tuple_lvalue_array.sol +++ b/test/libsolidity/syntaxTests/types/empty_tuple_lvalue_array.sol @@ -1,4 +1,3 @@ -pragma solidity ^0.4.3; contract C { function f() private pure {} function a() public { @@ -8,4 +7,4 @@ contract C { } } // ---- -// TypeError: (146-149): Array component cannot be empty. +// TypeError: (122-125): Array component cannot be empty. diff --git a/test/libsolidity/syntaxTests/types/function_call_fail.sol b/test/libsolidity/syntaxTests/types/function_call_fail.sol new file mode 100644 index 000000000..ef52ab448 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/function_call_fail.sol @@ -0,0 +1,9 @@ +contract C { + function f(uint y) public pure { + (4(y)) = 2; + } +} +// ---- +// TypeError: (59-63): Type is not callable +// TypeError: (59-63): Expression has to be an lvalue. +// TypeError: (67-68): Type int_const 2 is not implicitly convertible to expected type tuple(). diff --git a/test/libsolidity/syntaxTests/types/function_call_fail2.sol b/test/libsolidity/syntaxTests/types/function_call_fail2.sol new file mode 100644 index 000000000..389ffce96 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/function_call_fail2.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint y) public pure returns (uint) { + (f(y)) = 2; + } +} +// ---- +// TypeError: (74-78): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol new file mode 100644 index 000000000..0d4fded1f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol @@ -0,0 +1,42 @@ +contract Test +{ + function uint256_to_uint256(uint256 x) internal pure returns (uint256) { return x; } + function uint256_to_string(uint256 x) internal pure returns (string memory) { return x == 0 ? "a" : "b"; } + function uint256_to_string_storage(uint256) internal pure returns (string storage); + function string_to_uint256(string memory x) internal pure returns (uint256) { return bytes(x).length; } + function string_to_string(string memory x) internal pure returns (string memory) { return x; } + + function uint256_uint256_to_uint256(uint256 x, uint256 y) internal pure returns (uint256) { return x + y; } + function uint256_uint256_to_string(uint256 x, uint256 y) internal pure returns (string memory) { return x == y ? "a" : "b"; } + function string_uint256_to_string(string memory x, uint256 y) internal pure returns (string memory) { return y == 0 ? "a" : x; } + function string_string_to_string(string memory x, string memory y) internal pure returns (string memory) { return bytes(x).length == 0 ? y : x; } + function uint256_string_to_string(uint256 x, string memory y) internal pure returns (string memory) { return x == 0 ? "a" : y; } + + function tests() internal pure + { + function (uint256) internal pure returns (uint256) var_uint256_to_uint256 = uint256_to_string; + function (uint256) internal pure returns (string memory) var_uint256_to_string = uint256_to_string_storage; + function (string memory) internal pure returns (uint256) var_string_to_uint256 = uint256_to_string; + function (string memory) internal pure returns (string memory) var_string_to_string = var_uint256_to_string; + + function (uint256, uint256) internal pure returns (uint256) var_uint256_uint256_to_uint256 = uint256_to_uint256; + function (string memory, uint256) internal pure returns (string memory) var_string_uint256_to_string = string_to_string; + function (string memory, string memory) internal pure returns (string memory) var_string_string_to_string = string_to_string; + + var_uint256_to_uint256(1); + var_uint256_to_string(2); + var_string_to_uint256("a"); + var_string_to_string("b"); + var_uint256_uint256_to_uint256(3, 4); + var_string_uint256_to_string("c", 7); + var_string_string_to_string("d", "e"); + } +} +// ---- +// TypeError: (1218-1311): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (uint256) pure returns (uint256). +// TypeError: (1319-1425): Type function (uint256) pure returns (string storage pointer) is not implicitly convertible to expected type function (uint256) pure returns (string memory). +// TypeError: (1433-1531): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (uint256). +// TypeError: (1539-1646): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (string memory). +// TypeError: (1655-1766): Type function (uint256) pure returns (uint256) is not implicitly convertible to expected type function (uint256,uint256) pure returns (uint256). +// TypeError: (1774-1893): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,uint256) pure returns (string memory). +// TypeError: (1901-2025): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,string memory) pure returns (string memory). diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol new file mode 100644 index 000000000..f750632ef --- /dev/null +++ b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol @@ -0,0 +1,39 @@ +contract Test +{ + function uint256_to_uint256(uint256 x) internal pure returns (uint256) { return x; } + function uint256_to_string(uint256 x) internal pure returns (string memory) { return x == 0 ? "a" : "b"; } + function string_to_uint256(string memory x) internal pure returns (uint256) { return bytes(x).length; } + function string_to_string(string memory x) internal pure returns (string memory) { return x; } + + function uint256_uint256_to_uint256(uint256 x, uint256 y) internal pure returns (uint256) { return x + y; } + function uint256_uint256_to_string(uint256 x, uint256 y) internal pure returns (string memory) { return x == y ? "a" : "b"; } + function string_uint256_to_string(string memory x, uint256 y) internal pure returns (string memory) { return y == 0 ? "a" : x; } + function string_string_to_string(string memory x, string memory y) internal pure returns (string memory) { return bytes(x).length == 0 ? y : x; } + function uint256_string_to_string(uint256 x, string memory y) internal pure returns (string memory) { return x == 0 ? "a" : y; } + + function tests() internal pure + { + function (uint256) internal pure returns (uint256) var_uint256_to_uint256 = uint256_to_uint256; + function (uint256) internal pure returns (string memory) var_uint256_to_string = uint256_to_string; + function (string memory) internal pure returns (uint256) var_string_to_uint256 = string_to_uint256; + function (string memory) internal pure returns (string memory) var_string_to_string = string_to_string; + + function (uint256, uint256) internal pure returns (uint256) var_uint256_uint256_to_uint256 = uint256_uint256_to_uint256; + function (uint256, uint256) internal pure returns (string memory) var_uint256_uint256_to_string = uint256_uint256_to_string; + function (string memory, uint256) internal pure returns (string memory) var_string_uint256_to_string = string_uint256_to_string; + function (string memory, string memory) internal pure returns (string memory) var_string_string_to_string = string_string_to_string; + function (uint256, string memory) internal pure returns (string memory) var_uint256_string_to_string = uint256_string_to_string; + + // Avoid unused variable warnings: + var_uint256_to_uint256(1); + var_uint256_to_string(2); + var_string_to_uint256("a"); + var_string_to_string("b"); + var_uint256_uint256_to_uint256(3, 4); + var_uint256_uint256_to_string(5, 6); + var_string_uint256_to_string("c", 7); + var_string_string_to_string("d", "e"); + var_uint256_string_to_string(8, "f"); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol new file mode 100644 index 000000000..818d78406 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol @@ -0,0 +1,51 @@ +contract Test +{ + function internalPureFunc(uint256 x) internal pure returns (uint256) { return x; } + function internalViewFunc(uint256 x) internal view returns (uint256) { return x; } + function internalMutableFunc(uint256 x) internal returns (uint256) { return x; } + + function externalPureFunc(uint256 x) external pure returns (uint256) { return x; } + function externalViewFunc(uint256 x) external view returns (uint256) { return x; } + function externalPayableFunc(uint256 x) external payable returns (uint256) { return x; } + function externalMutableFunc(uint256 x) external returns (uint256) { return x; } + + function funcTakesInternalPure(function(uint256) internal pure returns(uint256) a) internal returns (uint256) { return a(4); } + function funcTakesInternalView(function(uint256) internal view returns(uint256) a) internal returns (uint256) { return a(4); } + function funcTakesInternalMutable(function(uint256) internal returns(uint256) a) internal returns (uint256) { return a(4); } + + function funcTakesExternalPure(function(uint256) external pure returns(uint256) a) internal returns (uint256) { return a(4); } + function funcTakesExternalView(function(uint256) external view returns(uint256) a) internal returns (uint256) { return a(4); } + function funcTakesExternalPayable(function(uint256) external payable returns(uint256) a) internal returns (uint256) { return a(4); } + function funcTakesExternalMutable(function(uint256) external returns(uint256) a) internal returns (uint256) { return a(4); } + + function tests() internal + { + funcTakesInternalPure(internalViewFunc); // view -> pure should fail + funcTakesInternalPure(internalMutableFunc); // mutable -> pure should fail + + funcTakesInternalView(internalMutableFunc); // mutable -> view should fail + + funcTakesExternalPure(this.externalViewFunc); // view -> pure should fail + funcTakesExternalPure(this.externalPayableFunc); // payable -> pure should fail + funcTakesExternalPure(this.externalMutableFunc); // mutable -> pure should fail + + funcTakesExternalView(this.externalPayableFunc); // payable -> view should fail + funcTakesExternalView(this.externalMutableFunc); // mutable -> view should fail + + funcTakesExternalPayable(this.externalPureFunc); // pure -> payable should fail + funcTakesExternalPayable(this.externalViewFunc); // view -> payable should fail + funcTakesExternalPayable(this.externalMutableFunc); // mutable -> payable should fail + } +} +// ---- +// TypeError: (1580-1596): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) view returns (uint256) to function (uint256) pure returns (uint256) requested. +// TypeError: (1653-1672): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) pure returns (uint256) requested. +// TypeError: (1733-1752): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) view returns (uint256) requested. +// TypeError: (1813-1834): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) view external returns (uint256) to function (uint256) pure external returns (uint256) requested. +// TypeError: (1891-1915): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) payable external returns (uint256) to function (uint256) pure external returns (uint256) requested. +// TypeError: (1975-1999): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) external returns (uint256) to function (uint256) pure external returns (uint256) requested. +// TypeError: (2060-2084): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) payable external returns (uint256) to function (uint256) view external returns (uint256) requested. +// TypeError: (2144-2168): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) external returns (uint256) to function (uint256) view external returns (uint256) requested. +// TypeError: (2232-2253): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) pure external returns (uint256) to function (uint256) payable external returns (uint256) requested. +// TypeError: (2316-2337): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) view external returns (uint256) to function (uint256) payable external returns (uint256) requested. +// TypeError: (2400-2424): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) external returns (uint256) to function (uint256) payable external returns (uint256) requested. diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol new file mode 100644 index 000000000..4ee515fc4 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol @@ -0,0 +1,46 @@ +contract Test +{ + uint y; + function internalPureFunc(uint256 x) internal pure returns (uint256) { return x; } + function internalViewFunc(uint256 x) internal view returns (uint256) { return x + y; } + function internalMutableFunc(uint256 x) internal returns (uint256) { y = x; return x; } + + function externalPureFunc(uint256 x) external pure returns (uint256) { return x; } + function externalViewFunc(uint256 x) external view returns (uint256) { return x + y; } + function externalPayableFunc(uint256 x) external payable returns (uint256) { return x + y; } + function externalMutableFunc(uint256 x) external returns (uint256) { y = x; return x; } + + function funcTakesInternalPure(function(uint256) internal pure returns(uint256) a) internal pure returns (uint256) { return a(4); } + function funcTakesInternalView(function(uint256) internal view returns(uint256) a) internal view returns (uint256) { return a(4); } + function funcTakesInternalMutable(function(uint256) internal returns(uint256) a) internal returns (uint256) { return a(4); } + + function funcTakesExternalPure(function(uint256) external pure returns(uint256) a) internal pure returns (uint256) { return a(4); } + function funcTakesExternalView(function(uint256) external view returns(uint256) a) internal view returns (uint256) { return a(4); } + function funcTakesExternalPayable(function(uint256) external payable returns(uint256) a) internal returns (uint256) { return a(4); } + function funcTakesExternalMutable(function(uint256) external returns(uint256) a) internal returns (uint256) { return a(4); } + + function tests() internal + { + funcTakesInternalPure(internalPureFunc); + + funcTakesInternalView(internalPureFunc); + funcTakesInternalView(internalViewFunc); + + funcTakesInternalMutable(internalPureFunc); + funcTakesInternalMutable(internalViewFunc); + funcTakesInternalMutable(internalMutableFunc); + + funcTakesExternalPure(this.externalPureFunc); + + funcTakesExternalView(this.externalPureFunc); + funcTakesExternalView(this.externalViewFunc); + + funcTakesExternalPayable(this.externalPayableFunc); + + funcTakesExternalMutable(this.externalPureFunc); + funcTakesExternalMutable(this.externalViewFunc); + funcTakesExternalMutable(this.externalPayableFunc); + funcTakesExternalMutable(this.externalMutableFunc); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_explicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_explicit.sol new file mode 100644 index 000000000..e1e9850df --- /dev/null +++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_explicit.sol @@ -0,0 +1,31 @@ +contract C { + function f() public pure { + bytes1 b1 = bytes1(0x1); + bytes1 b2 = bytes1(0x100); + bytes2 b3 = bytes2(0xFF); + bytes2 b4 = bytes2(0x100); + bytes2 b5 = bytes2(0x10000); + bytes3 b6 = bytes3(0xFFFF); + bytes3 b7 = bytes3(0x10000); + bytes3 b8 = bytes3(0x1000000); + bytes4 b9 = bytes4(0xFFFFFF); + bytes4 b10 = bytes4(0x1000000); + bytes4 b11 = bytes4(0x100000000); + bytes16 b12 = bytes16(0x1); + bytes32 b13 = bytes32(0x1); + } +} +// ---- +// TypeError: (60-71): Explicit type conversion not allowed from "int_const 1" to "bytes1". +// TypeError: (90-103): Explicit type conversion not allowed from "int_const 256" to "bytes1". +// TypeError: (122-134): Explicit type conversion not allowed from "int_const 255" to "bytes2". +// TypeError: (153-166): Explicit type conversion not allowed from "int_const 256" to "bytes2". +// TypeError: (185-200): Explicit type conversion not allowed from "int_const 65536" to "bytes2". +// TypeError: (219-233): Explicit type conversion not allowed from "int_const 65535" to "bytes3". +// TypeError: (252-267): Explicit type conversion not allowed from "int_const 65536" to "bytes3". +// TypeError: (286-303): Explicit type conversion not allowed from "int_const 16777216" to "bytes3". +// TypeError: (322-338): Explicit type conversion not allowed from "int_const 16777215" to "bytes4". +// TypeError: (358-375): Explicit type conversion not allowed from "int_const 16777216" to "bytes4". +// TypeError: (395-414): Explicit type conversion not allowed from "int_const 4294967296" to "bytes4". +// TypeError: (435-447): Explicit type conversion not allowed from "int_const 1" to "bytes16". +// TypeError: (468-480): Explicit type conversion not allowed from "int_const 1" to "bytes32". diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_implicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_implicit.sol new file mode 100644 index 000000000..44ed93184 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_implicit.sol @@ -0,0 +1,31 @@ +contract C { + function f() public pure { + bytes1 b1 = 0x1; + bytes1 b2 = 0x100; + bytes2 b3 = 0xFF; + bytes2 b4 = 0x100; + bytes2 b5 = 0x10000; + bytes3 b6 = 0xFFFF; + bytes3 b7 = 0x10000; + bytes3 b8 = 0x1000000; + bytes4 b9 = 0xFFFFFF; + bytes4 b10 = 0x1000000; + bytes4 b11 = 0x100000000; + bytes16 b12 = 0x1; + bytes32 b13 = 0x1; + } +} +// ---- +// TypeError: (48-63): Type int_const 1 is not implicitly convertible to expected type bytes1. +// TypeError: (70-87): Type int_const 256 is not implicitly convertible to expected type bytes1. +// TypeError: (94-110): Type int_const 255 is not implicitly convertible to expected type bytes2. +// TypeError: (117-134): Type int_const 256 is not implicitly convertible to expected type bytes2. +// TypeError: (141-160): Type int_const 65536 is not implicitly convertible to expected type bytes2. +// TypeError: (167-185): Type int_const 65535 is not implicitly convertible to expected type bytes3. +// TypeError: (192-211): Type int_const 65536 is not implicitly convertible to expected type bytes3. +// TypeError: (218-239): Type int_const 16777216 is not implicitly convertible to expected type bytes3. +// TypeError: (246-266): Type int_const 16777215 is not implicitly convertible to expected type bytes4. +// TypeError: (273-295): Type int_const 16777216 is not implicitly convertible to expected type bytes4. +// TypeError: (302-326): Type int_const 4294967296 is not implicitly convertible to expected type bytes4. +// TypeError: (333-350): Type int_const 1 is not implicitly convertible to expected type bytes16. +// TypeError: (357-374): Type int_const 1 is not implicitly convertible to expected type bytes32. diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_explicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_explicit.sol new file mode 100644 index 000000000..4e18640cc --- /dev/null +++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_explicit.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + bytes1 b1 = bytes1(0x01); + bytes1 b2 = bytes1(0xFF); + bytes2 b3 = bytes2(0x0100); + bytes2 b4 = bytes2(0xFFFF); + bytes3 b5 = bytes3(0x010000); + bytes3 b6 = bytes3(0xFFFFFF); + bytes4 b7 = bytes4(0x01000000); + bytes4 b8 = bytes4(0xFFFFFFFF); + b1; b2; b3; b4; b5; b6; b7; b8; + } +} diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_implicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_implicit.sol new file mode 100644 index 000000000..daf0bf561 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_implicit.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + bytes1 b1 = 0x01; + bytes1 b2 = 0xFF; + bytes2 b3 = 0x0100; + bytes2 b4 = 0xFFFF; + bytes3 b5 = 0x010000; + bytes3 b6 = 0xFFFFFF; + bytes4 b7 = 0x01000000; + bytes4 b8 = 0xFFFFFFFF; + b1; b2; b3; b4; b5; b6; b7; b8; + } +} diff --git a/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol b/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol new file mode 100644 index 000000000..f31b4cc0c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol @@ -0,0 +1,6 @@ +contract C { + bytes20 x; + function f(bytes16 b) public view { + b[uint8(x[2])]; + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol new file mode 100644 index 000000000..2b5e6b054 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol @@ -0,0 +1,6 @@ +contract C { + function f(mapping(uint => uint) storage) external pure { + } +} +// ---- +// TypeError: (28-57): Data location must be "calldata" for parameter in external function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol new file mode 100644 index 000000000..3c021515c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol @@ -0,0 +1,5 @@ +contract C { + function f(mapping(uint => uint) storage) internal pure { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol new file mode 100644 index 000000000..63733d711 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol @@ -0,0 +1,5 @@ +contract C { + function f(mapping(uint => uint) storage) private pure { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol new file mode 100644 index 000000000..32f11fe91 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol @@ -0,0 +1,6 @@ +contract C { + function f(mapping(uint => uint) storage) public pure { + } +} +// ---- +// TypeError: (28-57): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol new file mode 100644 index 000000000..0863653cc --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol @@ -0,0 +1,6 @@ +contract C { + function f(mapping(uint => uint)[] storage) external pure { + } +} +// ---- +// TypeError: (28-59): Data location must be "calldata" for parameter in external function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol new file mode 100644 index 000000000..352d09823 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol @@ -0,0 +1,5 @@ +contract C { + function f(mapping(uint => uint)[] storage) internal pure { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol new file mode 100644 index 000000000..332dbe6c0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol @@ -0,0 +1,5 @@ +contract C { + function f(mapping(uint => uint)[] storage) private pure { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol new file mode 100644 index 000000000..99c83d8ac --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol @@ -0,0 +1,6 @@ +contract C { + function f(mapping(uint => uint)[] storage) public pure { + } +} +// ---- +// TypeError: (28-59): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol new file mode 100644 index 000000000..a329c91ee --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol @@ -0,0 +1,11 @@ +contract test { + mapping(uint=>uint) map; + function fun() public view { + mapping(uint=>uint) storage a = map; + mapping(uint=>uint) storage b = map; + b = a; + (b) = a; + (b, b) = (a, a); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol new file mode 100644 index 000000000..1323afe6f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol @@ -0,0 +1,14 @@ +contract test { + mapping(uint=>uint) map; + function fun() public { + mapping(uint=>uint) storage a = map; + map = a; + (map) = a; + (map, map) = (a, a); + } +} +// ---- +// TypeError: (126-129): Mappings cannot be assigned to. +// TypeError: (144-147): Mappings cannot be assigned to. +// TypeError: (163-166): Mappings cannot be assigned to. +// TypeError: (168-171): Mappings cannot be assigned to. diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol new file mode 100644 index 000000000..b89241ed8 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol @@ -0,0 +1,17 @@ +contract test { + struct str { + mapping(uint=>uint) map; + } + str data; + function fun() public { + mapping(uint=>uint) storage a = data.map; + data.map = a; + (data.map) = a; + (data.map, data.map) = (a, a); + } +} +// ---- +// TypeError: (172-180): Mappings cannot be assigned to. +// TypeError: (195-203): Mappings cannot be assigned to. +// TypeError: (219-227): Mappings cannot be assigned to. +// TypeError: (229-237): Mappings cannot be assigned to. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol new file mode 100644 index 000000000..34f957019 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol @@ -0,0 +1,7 @@ +contract C { + function f(function(mapping(uint=>uint) storage) external) public pure { + } +} +// ---- +// TypeError: (37-64): Data location must be "memory" for parameter in function, but "storage" was given. +// TypeError: (37-64): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol new file mode 100644 index 000000000..01e2322e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol @@ -0,0 +1,4 @@ +contract C { + function f(function(mapping(uint=>uint) storage) internal) internal pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol new file mode 100644 index 000000000..aed9b3878 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol @@ -0,0 +1,7 @@ +contract C { + function f(function() external returns (mapping(uint=>uint) storage)) public pure { + } +} +// ---- +// TypeError: (57-84): Data location must be "memory" for return parameter in function, but "storage" was given. +// TypeError: (57-84): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol new file mode 100644 index 000000000..bd298e5d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol @@ -0,0 +1,4 @@ +contract C { + function f(function() internal returns (mapping(uint=>uint) storage)) internal pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol new file mode 100644 index 000000000..1098008d4 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint) storage) external pure { + } +} +// ---- +// TypeError: (27-56): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol new file mode 100644 index 000000000..1228b6b6f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint) storage) internal pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol new file mode 100644 index 000000000..5eaff16bb --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint) storage) private pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol new file mode 100644 index 000000000..dedd4f685 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint) storage) public pure { + } +} +// ---- +// TypeError: (27-56): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol new file mode 100644 index 000000000..da5a911b5 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint)[] storage) external pure { + } +} +// ---- +// TypeError: (27-58): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol new file mode 100644 index 000000000..55c1cea04 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint)[] storage) internal pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol new file mode 100644 index 000000000..d37d65045 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint)[] storage) private pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol new file mode 100644 index 000000000..adb62203c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint)[] storage) public pure { + } +} +// ---- +// TypeError: (27-58): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol new file mode 100644 index 000000000..1e7568192 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol @@ -0,0 +1,10 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) external pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} +// ---- +// TypeError: (27-58): Type is required to live outside storage. +// TypeError: (60-91): Type is required to live outside storage. +// TypeError: (123-152): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol new file mode 100644 index 000000000..d0fca6bf6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol @@ -0,0 +1,6 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol new file mode 100644 index 000000000..13c2000f7 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol @@ -0,0 +1,6 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) private pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol new file mode 100644 index 000000000..357751a0f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol @@ -0,0 +1,10 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) public pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} +// ---- +// TypeError: (27-58): Type is required to live outside storage. +// TypeError: (60-91): Type is required to live outside storage. +// TypeError: (121-150): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol new file mode 100644 index 000000000..0c29ebd8b --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol @@ -0,0 +1,6 @@ +contract c { + function f1(mapping(uint => uint)[] calldata) pure external {} +} +// ---- +// TypeError: (29-61): Type is required to live outside storage. +// TypeError: (29-61): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol new file mode 100644 index 000000000..fe021bd06 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol @@ -0,0 +1,6 @@ +contract C { + function f() external pure returns (mapping(uint=>uint)[] storage m) { + } +} +// ---- +// TypeError: (53-84): Data location must be "memory" for return parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol new file mode 100644 index 000000000..8837c745b --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol @@ -0,0 +1,16 @@ +contract C { + mapping(uint=>uint)[] m; + function f() internal view returns (mapping(uint=>uint)[] storage) { + return m; + } + function g() private view returns (mapping(uint=>uint)[] storage) { + return m; + } + function h() internal view returns (mapping(uint=>uint)[] storage r) { + r = m; + } + function i() private view returns (mapping(uint=>uint)[] storage r) { + (r,r) = (m,m); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol new file mode 100644 index 000000000..1eb9d03b1 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure returns (mapping(uint=>uint)[] storage m) { + } +} +// ---- +// TypeError: (51-82): Data location must be "memory" for return parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_calldata.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_calldata.sol new file mode 100644 index 000000000..deff7c14d --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_calldata.sol @@ -0,0 +1,9 @@ +contract c { + mapping(uint => uint) y; + function f() view public { + mapping(uint => uint) calldata x = y; + x; + } +} +// ---- +// TypeError: (81-113): Data location must be "storage" for variable, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_default.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_default.sol new file mode 100644 index 000000000..e5253f000 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_default.sol @@ -0,0 +1,9 @@ +contract c { + mapping(uint => uint) y; + function f() view public { + mapping(uint => uint) x = y; + x; + } +} +// ---- +// TypeError: (81-104): Data location must be "storage" for variable, but none was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol new file mode 100644 index 000000000..c050f8e91 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol @@ -0,0 +1,6 @@ +contract c { + function f1(mapping(uint => uint) calldata) pure external returns (mapping(uint => uint) memory) {} +} +// ---- +// TypeError: (29-59): Type is required to live outside storage. +// TypeError: (29-59): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_internal.sol new file mode 100644 index 000000000..17f2f7128 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_internal.sol @@ -0,0 +1,4 @@ +contract c { + function f4(mapping(uint => uint) memory) pure internal {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol new file mode 100644 index 000000000..b63868b89 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol @@ -0,0 +1,6 @@ +contract c { + function f3(mapping(uint => uint) memory) view public {} +} +// ---- +// TypeError: (29-57): Type is required to live outside storage. +// TypeError: (29-57): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_memory.sol new file mode 100644 index 000000000..600ae6693 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_memory.sol @@ -0,0 +1,9 @@ +contract c { + mapping(uint => uint) y; + function f() view public { + mapping(uint => uint) memory x = y; + x; + } +} +// ---- +// TypeError: (81-111): Data location must be "storage" for variable, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_dynamic_key.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_dynamic_key.sol new file mode 100644 index 000000000..825ee09a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_dynamic_key.sol @@ -0,0 +1,3 @@ +contract c { + mapping(string => uint) data; +} diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_dynamic_key_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_dynamic_key_public.sol new file mode 100644 index 000000000..9fb575afd --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_dynamic_key_public.sol @@ -0,0 +1,5 @@ +contract c { + mapping(string => uint) public data; +} +// ---- +// TypeError: (14-49): Dynamically-sized keys for public mappings are not supported. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_external.sol new file mode 100644 index 000000000..17e646ceb --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_external.sol @@ -0,0 +1,6 @@ +contract C { + function f() external pure returns (mapping(uint=>uint) storage m) { + } +} +// ---- +// TypeError: (53-82): Data location must be "memory" for return parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol new file mode 100644 index 000000000..4912836ef --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol @@ -0,0 +1,16 @@ +contract C { + mapping(uint=>uint) m; + function f() internal view returns (mapping(uint=>uint) storage) { + return m; + } + function g() private view returns (mapping(uint=>uint) storage) { + return m; + } + function h() internal view returns (mapping(uint=>uint) storage r) { + r = m; + } + function i() private view returns (mapping(uint=>uint) storage r) { + (r,r) = (m,m); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public.sol new file mode 100644 index 000000000..cf5ec4ff9 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure returns (mapping(uint=>uint) storage m) { + } +} +// ---- +// TypeError: (51-80): Data location must be "memory" for return parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol new file mode 100644 index 000000000..35c3abc9f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns (mapping(uint=>uint) memory m) { + } +} +// ---- +// TypeError: (51-79): Type is required to live outside storage. +// TypeError: (51-79): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/no_singleton_tuple.sol b/test/libsolidity/syntaxTests/types/no_singleton_tuple.sol new file mode 100644 index 000000000..62a58f838 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/no_singleton_tuple.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure { + uint a; + (a,) = (uint(1),); + } +} +// ---- +// TypeError: (60-70): Tuple component cannot be empty. diff --git a/test/libsolidity/syntaxTests/types/rational_negative_numerator_negative_exp.sol b/test/libsolidity/syntaxTests/types/rational_negative_numerator_negative_exp.sol new file mode 100644 index 000000000..b694992c6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_negative_numerator_negative_exp.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns (int) { + return (-1 / 2) ** -1; + } +} diff --git a/test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol similarity index 66% rename from test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol rename to test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol index 6785f580a..058db2e9d 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol @@ -4,9 +4,6 @@ contract c { a = 4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4; a = -4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4 ** 4; a = 4 ** (-(2 ** 4 ** 4 ** 4 ** 4 ** 4)); - a = 0 ** 1E1233; // fine - a = 1 ** 1E1233; // fine - a = -1 ** 1E1233; // fine a = 2 ** 1E1233; a = -2 ** 1E1233; a = 2 ** -1E1233; @@ -28,23 +25,23 @@ contract c { // TypeError: (116-153): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 // TypeError: (116-153): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. // TypeError: (167-203): Operator ** not compatible with types int_const 4 and int_const -179...(302 digits omitted)...7216 -// TypeError: (317-328): Operator ** not compatible with types int_const 2 and int_const 1000...(1226 digits omitted)...0000 -// TypeError: (342-354): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000 -// TypeError: (368-380): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000 -// TypeError: (394-407): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000 -// TypeError: (421-432): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2 -// TypeError: (421-432): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (446-458): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2 -// TypeError: (446-458): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (472-484): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2 -// TypeError: (472-484): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (498-511): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2 -// TypeError: (498-511): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (525-541): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 -// TypeError: (525-541): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (555-572): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 -// TypeError: (555-572): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (586-603): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 -// TypeError: (586-603): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (617-635): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 -// TypeError: (617-635): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (217-228): Operator ** not compatible with types int_const 2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (242-254): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (268-280): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (294-307): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (321-332): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2 +// TypeError: (321-332): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (346-358): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2 +// TypeError: (346-358): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (372-384): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2 +// TypeError: (372-384): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (398-411): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2 +// TypeError: (398-411): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (425-441): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (425-441): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (455-472): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (455-472): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (486-503): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (486-503): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (517-535): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (517-535): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fine.sol b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fine.sol new file mode 100644 index 000000000..66d02eb9a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fine.sol @@ -0,0 +1,9 @@ +contract c { + function f() public pure { + int a; + a = 0 ** 1E1233; + a = 1 ** 1E1233; + a = -1 ** 1E1233; + a = 0E123456789; + } +} diff --git a/test/libsolidity/syntaxTests/types/rational_number_huge.sol b/test/libsolidity/syntaxTests/types/rational_number_huge.sol new file mode 100644 index 000000000..378de2012 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_huge.sol @@ -0,0 +1,10 @@ +contract C { + function f(uint y) public pure { + // fits FixedBytes with exactly 32-bytes + y = 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000; // FixedBytes (32) + + // fits exactly into FixedBytes (32), ensures underscored literals won't hurt + y = 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff_00000000; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/rational_number_huge_fail.sol b/test/libsolidity/syntaxTests/types/rational_number_huge_fail.sol new file mode 100644 index 000000000..08e506562 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_huge_fail.sol @@ -0,0 +1,8 @@ +contract C { + function f(uint y) public pure { + // one byte too long for storing in Fixedbytes (would require 33 bytes) + y = 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000001; + } +} +// ---- +// TypeError: (142-209): Type int_const 1852...(71 digits omitted)...7281 is not implicitly convertible to expected type uint256. diff --git a/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol new file mode 100644 index 000000000..66bd9a8ea --- /dev/null +++ b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol @@ -0,0 +1,4 @@ +contract C { + fixed8x80 a = -1e-100; +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol b/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol new file mode 100644 index 000000000..f70c89edc --- /dev/null +++ b/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(bytes1) { + return bytes1(uint256(0)); + } +} +// ---- +// TypeError: (75-93): Explicit type conversion not allowed from "uint256" to "bytes1". diff --git a/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol b/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol new file mode 100644 index 000000000..4153c5c35 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(bytes32) { + return bytes32(uint32(0)); + } +} +// ---- +// TypeError: (76-94): Explicit type conversion not allowed from "uint32" to "bytes32". diff --git a/test/libsolidity/syntaxTests/types/unnamed_tuple_decl.sol b/test/libsolidity/syntaxTests/types/unnamed_tuple_decl.sol new file mode 100644 index 000000000..36b3df9fe --- /dev/null +++ b/test/libsolidity/syntaxTests/types/unnamed_tuple_decl.sol @@ -0,0 +1,16 @@ +contract C { + function f() internal pure {} + function g() internal pure returns (uint) { return 1; } + function h() internal pure returns (uint, uint) { return (1, 2); } + + function test() internal pure { + var () = f(); + var () = g(); + var (,) = h(); + } +} + +// ---- +// SyntaxError: (223-235): The use of the "var" keyword is disallowed. The declaration part of the statement can be removed, since it is empty. +// SyntaxError: (245-257): The use of the "var" keyword is disallowed. The declaration part of the statement can be removed, since it is empty. +// SyntaxError: (267-280): The use of the "var" keyword is disallowed. The declaration part of the statement can be removed, since it is empty. diff --git a/test/libsolidity/syntaxTests/types/var_empty_decl_0.sol b/test/libsolidity/syntaxTests/types/var_empty_decl_0.sol new file mode 100644 index 000000000..51b949def --- /dev/null +++ b/test/libsolidity/syntaxTests/types/var_empty_decl_0.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + var (); + var (,); + } +} +// ---- +// SyntaxError: (52-58): The use of the "var" keyword is disallowed. The declaration part of the statement can be removed, since it is empty. +// SyntaxError: (68-75): The use of the "var" keyword is disallowed. The declaration part of the statement can be removed, since it is empty. diff --git a/test/libsolidity/syntaxTests/types/var_empty_decl_1.sol b/test/libsolidity/syntaxTests/types/var_empty_decl_1.sol new file mode 100644 index 000000000..20a004ff9 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/var_empty_decl_1.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure { + var a; + a.NeverReachedByParser(); + } +} +// ---- +// TypeError: (52-57): Use of the "var" keyword is disallowed. diff --git a/test/libsolidity/syntaxTests/types/var_empty_decl_2.sol b/test/libsolidity/syntaxTests/types/var_empty_decl_2.sol new file mode 100644 index 000000000..de2abc9ae --- /dev/null +++ b/test/libsolidity/syntaxTests/types/var_empty_decl_2.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + var (b, c); + b.WeMustNotReachHere(); + c.FailsToLookupToo(); + } +} +// ---- +// TypeError: (52-62): Use of the "var" keyword is disallowed. diff --git a/test/libsolidity/syntaxTests/types/var_empty_decl_3.sol b/test/libsolidity/syntaxTests/types/var_empty_decl_3.sol new file mode 100644 index 000000000..26ee824e4 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/var_empty_decl_3.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + var (d, e,); + } +} +// ---- +// TypeError: (52-63): Use of the "var" keyword is disallowed. diff --git a/test/libsolidity/syntaxTests/types/var_type_suggest.sol b/test/libsolidity/syntaxTests/types/var_type_suggest.sol new file mode 100644 index 000000000..cc35fdd64 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/var_type_suggest.sol @@ -0,0 +1,35 @@ +contract C { + function h() internal pure returns (uint, uint, uint) { + return (1, 2, 4); + } + function g(uint x) internal pure returns (uint) { + return x; + } + function f() internal pure { + var i = 31415; + var t = "string"; + var g2 = g; + var myblockhash = block.blockhash; + var (a, b) = (2, "troi"); + var (x,, z) = h(); + var (c, d) = (""); + var (k, l) = (2); + var (m, n) = 1; + var (o, p) = ""; + } +} +// ---- +// SyntaxError: (224-237): Use of the "var" keyword is disallowed. Use explicit declaration `uint16 i = ...´ instead. +// SyntaxError: (247-263): Use of the "var" keyword is disallowed. Use explicit declaration `string memory t = ...´ instead. +// SyntaxError: (273-283): Use of the "var" keyword is disallowed. Use explicit declaration `function (uint256) pure returns (uint256) g2 = ...´ instead. +// SyntaxError: (293-326): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. +// SyntaxError: (336-360): Use of the "var" keyword is disallowed. Use explicit declaration `(uint8 a, string memory b) = ...´ instead. +// SyntaxError: (370-387): Use of the "var" keyword is disallowed. Use explicit declaration `(uint256 x, , uint256 z) = ...´ instead. +// TypeError: (397-414): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (397-414): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. +// TypeError: (424-440): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (424-440): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. +// TypeError: (450-464): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (450-464): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. +// TypeError: (474-489): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (474-489): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. diff --git a/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_explicit.sol b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_explicit.sol new file mode 100644 index 000000000..5d606089a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_explicit.sol @@ -0,0 +1,30 @@ +contract C { + function f() public pure { + bytes1 b1 = bytes1(0); + bytes2 b2 = bytes2(0); + bytes3 b3 = bytes3(0); + bytes4 b4 = bytes4(0); + bytes8 b8 = bytes8(0); + bytes16 b16 = bytes16(0); + bytes32 b32 = bytes32(0); + b1; b2; b3; b4; b8; b16; b32; + } + function g() public pure { + bytes1 b1 = bytes1(0x000); + bytes2 b2 = bytes2(0x00000); + bytes3 b3 = bytes3(0x0000000); + bytes4 b4 = bytes4(0x000000000); + bytes8 b8 = bytes8(0x00000000000000000); + b1; b2; b3; b4; b8; + } + function h() public pure { + bytes1 b1 = bytes1(0x0); + bytes2 b2 = bytes2(0x0); + bytes3 b3 = bytes3(0x0); + bytes4 b4 = bytes4(0x0); + bytes8 b8 = bytes8(0x0); + bytes16 b16 = bytes16(0x0); + bytes32 b32 = bytes32(0x0); + b1; b2; b3; b4; b8; b16; b32; + } +} diff --git a/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_implicit.sol b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_implicit.sol new file mode 100644 index 000000000..48be0655f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_implicit.sol @@ -0,0 +1,30 @@ +contract C { + function f() public pure { + bytes1 b1 = 0; + bytes2 b2 = 0; + bytes3 b3 = 0; + bytes4 b4 = 0; + bytes8 b8 = 0; + bytes16 b16 = 0; + bytes32 b32 = 0; + b1; b2; b3; b4; b8; b16; b32; + } + function g() public pure { + bytes1 b1 = 0x000; + bytes2 b2 = 0x00000; + bytes3 b3 = 0x0000000; + bytes4 b4 = 0x000000000; + bytes8 b8 = 0x00000000000000000; + b1; b2; b3; b4; b8; + } + function h() public pure { + bytes1 b1 = 0x0; + bytes2 b2 = 0x0; + bytes3 b3 = 0x0; + bytes4 b4 = 0x0; + bytes8 b8 = 0x0; + bytes16 b16 = 0x0; + bytes32 b32 = 0x0; + b1; b2; b3; b4; b8; b16; b32; + } +} diff --git a/test/libsolidity/syntaxTests/unicode_escape_literals.sol b/test/libsolidity/syntaxTests/unicode_escape_literals.sol new file mode 100644 index 000000000..a340487b1 --- /dev/null +++ b/test/libsolidity/syntaxTests/unicode_escape_literals.sol @@ -0,0 +1,31 @@ +contract test { + + function oneByteUTF8() public pure returns (bytes32) { + bytes32 usdollar = "aaa\u0024aaa"; + return usdollar; + } + + function twoBytesUTF8() public pure returns (bytes32) { + bytes32 cent = "aaa\u00A2aaa"; + return cent; + } + + function threeBytesUTF8() public pure returns (bytes32) { + bytes32 eur = "aaa\u20ACaaa"; + return eur; + } + + function together() public pure returns (bytes32) { + bytes32 res = "\u0024\u00A2\u20AC"; + return res; + } + + // this function returns an invalid unicode character + function invalidLiteral() public pure returns(bytes32) { + bytes32 invalid = "\u00xx"; + return invalid; + } + +} +// ---- +// ParserError: (678-681): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/unterminatedBlocks/one_dot.sol b/test/libsolidity/syntaxTests/unterminatedBlocks/one_dot.sol new file mode 100644 index 000000000..a678f0042 --- /dev/null +++ b/test/libsolidity/syntaxTests/unterminatedBlocks/one_dot.sol @@ -0,0 +1,4 @@ +contract c { + function f() pure public { 1. +// ---- +// ParserError: (47-47): Expected identifier but got end of source \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/unterminatedBlocks/one_dot_x.sol b/test/libsolidity/syntaxTests/unterminatedBlocks/one_dot_x.sol new file mode 100644 index 000000000..3cc59374c --- /dev/null +++ b/test/libsolidity/syntaxTests/unterminatedBlocks/one_dot_x.sol @@ -0,0 +1,5 @@ +contract test { + function f() pure public { 1.x; } +} +// ---- +// TypeError: (47-50): Member "x" not found or not visible after argument-dependent lookup in int_const 1. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/unterminatedBlocks/zero_dot.sol b/test/libsolidity/syntaxTests/unterminatedBlocks/zero_dot.sol new file mode 100644 index 000000000..6ba2b4c22 --- /dev/null +++ b/test/libsolidity/syntaxTests/unterminatedBlocks/zero_dot.sol @@ -0,0 +1,4 @@ +contract c { + function f() pure public { 0. +// ---- +// ParserError: (47-47): Expected identifier but got end of source \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/unterminatedBlocks/zero_dot_x.sol b/test/libsolidity/syntaxTests/unterminatedBlocks/zero_dot_x.sol new file mode 100644 index 000000000..8648bce24 --- /dev/null +++ b/test/libsolidity/syntaxTests/unterminatedBlocks/zero_dot_x.sol @@ -0,0 +1,5 @@ +contract test { + function f() pure public { 0.x; } +} +// ---- +// TypeError: (47-50): Member "x" not found or not visible after argument-dependent lookup in int_const 0. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/upper_case_hex_literals.sol b/test/libsolidity/syntaxTests/upper_case_hex_literals.sol new file mode 100644 index 000000000..0842c2ec1 --- /dev/null +++ b/test/libsolidity/syntaxTests/upper_case_hex_literals.sol @@ -0,0 +1,9 @@ +contract test { + + function f() public pure returns (uint256) { + uint256 a = 0x1234aAbcC; + uint256 b = 0x1234ABCDEF; + return a + b; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/variableDeclaration/do_while.sol b/test/libsolidity/syntaxTests/variableDeclaration/do_while.sol new file mode 100644 index 000000000..8fc48b334 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/do_while.sol @@ -0,0 +1,12 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + do + uint y; + while (x > 0); + } +} +// ---- +// SyntaxError: (81-87): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/else.sol b/test/libsolidity/syntaxTests/variableDeclaration/else.sol new file mode 100644 index 000000000..914e0c0c0 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/else.sol @@ -0,0 +1,13 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + if (x > 0) + {uint y;} + else + uint z; + } +} +// ---- +// SyntaxError: (109-115): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/for.sol b/test/libsolidity/syntaxTests/variableDeclaration/for.sol new file mode 100644 index 000000000..bc137f935 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/for.sol @@ -0,0 +1,11 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + for (uint i = 0; i < x; ++i) + uint y; + } +} +// ---- +// SyntaxError: (107-113): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/if.sol b/test/libsolidity/syntaxTests/variableDeclaration/if.sol new file mode 100644 index 000000000..75ab20266 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/if.sol @@ -0,0 +1,11 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + if (x > 0) + uint y; + } +} +// ---- +// SyntaxError: (89-95): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/while.sol b/test/libsolidity/syntaxTests/variableDeclaration/while.sol new file mode 100644 index 000000000..2997d80c8 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/while.sol @@ -0,0 +1,11 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + while (x > 0) + uint y; + } +} +// ---- +// SyntaxError: (92-98): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode.sol b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode.sol index ca7db42e4..e0e031c2a 100644 --- a/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode.sol +++ b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode.sol @@ -1,5 +1,5 @@ contract C { - function f() pure public returns (bytes r) { + function f() pure public returns (bytes memory r) { r = abi.encode(1, 2); r = abi.encodePacked(f()); r = abi.encodeWithSelector(0x12345678, 1); diff --git a/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode_arguments.sol b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode_arguments.sol index 547362c3f..cc845d513 100644 --- a/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode_arguments.sol +++ b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode_arguments.sol @@ -3,34 +3,34 @@ contract C { function gView() public view returns (uint) { return x; } function gNonPayable() public returns (uint) { x = 4; return 0; } - function f1() view public returns (bytes) { + function f1() view public returns (bytes memory) { return abi.encode(gView()); } - function f2() view public returns (bytes) { + function f2() view public returns (bytes memory) { return abi.encodePacked(gView()); } - function f3() view public returns (bytes) { + function f3() view public returns (bytes memory) { return abi.encodeWithSelector(0x12345678, gView()); } - function f4() view public returns (bytes) { + function f4() view public returns (bytes memory) { return abi.encodeWithSignature("f(uint256)", gView()); } - function g1() public returns (bytes) { + function g1() public returns (bytes memory) { return abi.encode(gNonPayable()); } - function g2() public returns (bytes) { + function g2() public returns (bytes memory) { return abi.encodePacked(gNonPayable()); } - function g3() public returns (bytes) { + function g3() public returns (bytes memory) { return abi.encodeWithSelector(0x12345678, gNonPayable()); } - function g4() public returns (bytes) { + function g4() public returns (bytes memory) { return abi.encodeWithSignature("f(uint256)", gNonPayable()); } // This will generate the only warning. - function check() public returns (bytes) { + function check() public returns (bytes memory) { return abi.encode(2); } } // ---- -// Warning: (1044-1121): Function state mutability can be restricted to pure +// Warning: (1100-1184): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol new file mode 100644 index 000000000..0a11dc3ae --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol @@ -0,0 +1,23 @@ +contract C { + struct S { uint x; } + S s; + function e() pure public { + assembly { mstore(keccak256(0, 20), mul(s_slot, 2)) } + } + function f() pure public { + uint x; + assembly { x := 7 } + } + function g() view public { + assembly { for {} 1 { pop(sload(0)) } { } pop(gas) } + } + function h() view public { + assembly { function g() { pop(blockhash(20)) } } + } + function j() public { + assembly { pop(call(0, 1, 2, 3, 4, 5, 6)) } + } + function k() public { + assembly { pop(call(gas, 1, 2, 3, 4, 5, 6)) } + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol new file mode 100644 index 000000000..2503a3198 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -0,0 +1,20 @@ +contract C { + function f() public { + address(this).transfer(1); + require(address(this).send(2)); + selfdestruct(address(this)); + (bool success,) = address(this).delegatecall(""); + require(success); + (success,) = address(this).call(""); + require(success); + } + function g() pure public { + bytes32 x = keccak256("abc"); + bytes32 y = sha256("abc"); + address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4))); + require(true); + assert(true); + x; y; z; + } + function() payable external {} +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol new file mode 100644 index 000000000..4a651d211 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol @@ -0,0 +1,21 @@ +contract C { + function f() view public { + bytes32 x = keccak256("abc"); + bytes32 y = sha256("abc"); + address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4))); + require(true); + assert(true); + x; y; z; + } + function g() public { + bytes32 x = keccak256("abc"); + bytes32 y = sha256("abc"); + address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4))); + require(true); + assert(true); + x; y; z; + } +} +// ---- +// Warning: (17-288): Function state mutability can be restricted to pure +// Warning: (293-559): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol new file mode 100644 index 000000000..5356f0b8c --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol @@ -0,0 +1,27 @@ +contract C { + function f() view public { + address(this).transfer(1); + } + function g() view public { + require(address(this).send(2)); + } + function h() view public { + selfdestruct(address(this)); + } + function i() view public { + (bool success,) = address(this).delegatecall(""); + require(success); + } + function j() view public { + (bool success,) = address(this).call(""); + require(success); + } + function() payable external { + } +} +// ---- +// TypeError: (52-77): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError: (132-153): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError: (201-228): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError: (293-323): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError: (414-436): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_fail.sol new file mode 100644 index 000000000..e21037bd9 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_fail.sol @@ -0,0 +1,10 @@ +contract C { + uint x; + function f() pure public { g(); } + function g() view public { x; } + function h() view public { i(); } + function i() public { x = 2; } +} +// ---- +// TypeError: (56-59): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError: (130-133): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_success.sol b/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_success.sol new file mode 100644 index 000000000..5aa21ce1a --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_success.sol @@ -0,0 +1,6 @@ +contract C { + function g() pure public { g(); } + function f() view public returns (uint) { f(); g(); } + function h() public { h(); g(); f(); } + function i() payable public { i(); h(); g(); f(); } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/constant.sol b/test/libsolidity/syntaxTests/viewPureChecker/constant.sol new file mode 100644 index 000000000..36d934977 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/constant.sol @@ -0,0 +1,6 @@ +contract C { + uint constant x = 2; + function k() pure public returns (uint) { + return x; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/constant_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/constant_restrict_warning.sol new file mode 100644 index 000000000..a4b4a3536 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/constant_restrict_warning.sol @@ -0,0 +1,12 @@ +contract C { + uint constant x = 2; + function f() view public returns (uint) { + return x; + } + function g() public returns (uint) { + return x; + } +} +// ---- +// Warning: (42-107): Function state mutability can be restricted to pure +// Warning: (112-172): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/viewPureChecker/creation_no_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/creation_no_restrict_warning.sol new file mode 100644 index 000000000..d80edd1bc --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/creation_no_restrict_warning.sol @@ -0,0 +1,4 @@ +contract D {} +contract C { + function f() public { new D(); } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/creation_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/creation_view_fail.sol new file mode 100644 index 000000000..08e45ea1e --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/creation_view_fail.sol @@ -0,0 +1,6 @@ +contract D {} +contract C { + function f() public view { new D(); } +} +// ---- +// TypeError: (58-65): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/function_types.sol b/test/libsolidity/syntaxTests/viewPureChecker/function_types.sol new file mode 100644 index 000000000..929438896 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/function_types.sol @@ -0,0 +1,22 @@ +contract C { + function f() pure public { + function () external nonpayFun; + function () external view viewFun; + function () external pure pureFun; + + nonpayFun; + viewFun; + pureFun; + pureFun(); + } + function g() view public { + function () external view viewFun; + + viewFun(); + } + function h() public { + function () external nonpayFun; + + nonpayFun(); + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/function_types_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/function_types_fail.sol new file mode 100644 index 000000000..d00f65c9b --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/function_types_fail.sol @@ -0,0 +1,18 @@ +contract C { + function f() pure public { + function () external nonpayFun; + nonpayFun(); + } + function g() pure public { + function () external view viewFun; + viewFun(); + } + function h() view public { + function () external nonpayFun; + nonpayFun(); + } +} +// ---- +// TypeError: (92-103): Function declared as pure, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError: (193-202): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError: (289-300): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/interface.sol b/test/libsolidity/syntaxTests/viewPureChecker/interface.sol new file mode 100644 index 000000000..0874e78a2 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/interface.sol @@ -0,0 +1,6 @@ +interface D { + function f() view external; +} +contract C is D { + function f() view external {} +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables.sol b/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables.sol new file mode 100644 index 000000000..7d01118ae --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables.sol @@ -0,0 +1,19 @@ +contract C { + struct S { uint a; } + S s; + function f() view public { + S storage x = s; + x; + } + function g() view public { + S storage x = s; + x = s; + } + function i() public { + s.a = 2; + } + function h() public { + S storage x = s; + x.a = 2; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables_fail.sol new file mode 100644 index 000000000..0ff1ac241 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/local_storage_variables_fail.sol @@ -0,0 +1,15 @@ +contract C { + struct S { uint a; } + S s; + function f() pure public { + S storage x = s; + x; + } + function g() view public { + S storage x = s; + x.a = 1; + } +} +// ---- +// TypeError: (100-101): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError: (184-187): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/mappings.sol b/test/libsolidity/syntaxTests/viewPureChecker/mappings.sol new file mode 100644 index 000000000..eb0ccbfb9 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/mappings.sol @@ -0,0 +1,12 @@ +contract C { + mapping(uint => uint) a; + function f() view public { + a; + } + function g() view public { + a[2]; + } + function h() public { + a[2] = 3; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/modifiers.sol b/test/libsolidity/syntaxTests/viewPureChecker/modifiers.sol new file mode 100644 index 000000000..f8f6b2cbf --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/modifiers.sol @@ -0,0 +1,17 @@ +contract D { + uint x; + modifier purem(uint) { _; } + modifier viewm(uint) { uint a = x; _; a; } + modifier nonpayablem(uint) { x = 2; _; } +} +contract C is D { + function f() purem(0) pure public {} + function g() viewm(0) view public {} + function h() nonpayablem(0) public {} + function i() purem(x) view public {} + function j() viewm(x) view public {} + function k() nonpayablem(x) public {} + function l() purem(x = 2) public {} + function m() viewm(x = 2) public {} + function n() nonpayablem(x = 2) public {} +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/modifiers_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/modifiers_fail.sol new file mode 100644 index 000000000..513850f77 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/modifiers_fail.sol @@ -0,0 +1,12 @@ +contract D { + uint x; + modifier viewm(uint) { uint a = x; _; a; } + modifier nonpayablem(uint) { x = 2; _; } +} +contract C is D { + function f() viewm(0) pure public {} + function g() nonpayablem(0) view public {} +} +// ---- +// TypeError: (154-162): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError: (195-209): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier.sol b/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier.sol new file mode 100644 index 000000000..160b20a74 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier.sol @@ -0,0 +1,6 @@ +contract C { + modifier m(uint _amount, uint _avail) { require(_avail >= _amount); _; } + function f() m(1 ether, msg.value) public pure {} +} +// ---- +// TypeError: (118-127): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier_view.sol new file mode 100644 index 000000000..613b01980 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier_view.sol @@ -0,0 +1,6 @@ +contract C { + modifier m(uint _amount, uint _avail) { require(_avail >= _amount); _; } + function f() m(1 ether, msg.value) public view {} +} +// ---- +// TypeError: (118-127): "msg.value" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/overriding_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/overriding_fail.sol new file mode 100644 index 000000000..61702495b --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/overriding_fail.sol @@ -0,0 +1,16 @@ +contract D { + uint x; + function f() public view { x; } + function g() public pure {} +} +contract C1 is D { + function f() public {} + function g() public view {} +} +contract C2 is D { + function g() public {} +} +// ---- +// TypeError: (118-140): Overriding function changes state mutability from "view" to "nonpayable". +// TypeError: (145-172): Overriding function changes state mutability from "pure" to "view". +// TypeError: (198-220): Overriding function changes state mutability from "pure" to "nonpayable". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/overriding_no_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/overriding_no_restrict_warning.sol new file mode 100644 index 000000000..c82c79083 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/overriding_no_restrict_warning.sol @@ -0,0 +1,7 @@ +contract D { + uint x; + function f() public { x = 2; } +} +contract C is D { + function f() public {} +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/read_storage_pure_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/read_storage_pure_fail.sol new file mode 100644 index 000000000..785656b91 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/read_storage_pure_fail.sol @@ -0,0 +1,8 @@ +contract C { + uint x; + function f() public pure returns (uint) { + return x; + } +} +// ---- +// TypeError: (86-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/returning_structs_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/returning_structs_fail.sol new file mode 100644 index 000000000..e04d08254 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/returning_structs_fail.sol @@ -0,0 +1,13 @@ +contract C { + struct S { uint x; } + S s; + function f() pure internal returns (S storage) { + return s; + } + function g() pure public { + f().x; + } +} +// ---- +// TypeError: (115-116): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError: (163-168): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/returning_structs_no_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/returning_structs_no_restrict_warning.sol new file mode 100644 index 000000000..9b4eb4669 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/returning_structs_no_restrict_warning.sol @@ -0,0 +1,14 @@ +contract C { + struct S { uint x; } + S s; + function f() view internal returns (S storage) { + return s; + } + function g() public { + f().x = 2; + } + function h() view public { + f(); + f().x; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/selector.sol b/test/libsolidity/syntaxTests/viewPureChecker/selector.sol new file mode 100644 index 000000000..c4e30075c --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/selector.sol @@ -0,0 +1,12 @@ +contract C { + uint public x; + function f() payable public { + } + function g() pure public returns (bytes4) { + return this.f.selector ^ this.x.selector; + } + function h() view public returns (bytes4) { + x; + return this.f.selector ^ this.x.selector; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/selector_complex.sol b/test/libsolidity/syntaxTests/viewPureChecker/selector_complex.sol new file mode 100644 index 000000000..311dec4a4 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/selector_complex.sol @@ -0,0 +1,11 @@ +contract C { + function f(C c) pure public returns (C) { + return c; + } + function g() pure public returns (bytes4) { + // By passing `this`, we read from the state, even if f itself is pure. + return f(this).f.selector; + } +} +// ---- +// TypeError: (228-232): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/selector_complex2.sol b/test/libsolidity/syntaxTests/viewPureChecker/selector_complex2.sol new file mode 100644 index 000000000..d1543fed5 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/selector_complex2.sol @@ -0,0 +1,9 @@ +contract C { + function f() payable public returns (C) { + return this; + } + function g() pure public returns (bytes4) { + C x = C(0x123); + return x.f.selector; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/smoke_test.sol b/test/libsolidity/syntaxTests/viewPureChecker/smoke_test.sol new file mode 100644 index 000000000..0e397efcc --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/smoke_test.sol @@ -0,0 +1,7 @@ +contract C { + uint x; + function g() pure public {} + function f() view public returns (uint) { return now; } + function h() public { x = 2; } + function i() payable public { x = 2; } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/suggest_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/suggest_pure.sol new file mode 100644 index 000000000..87719eb3b --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/suggest_pure.sol @@ -0,0 +1,5 @@ +contract C { + function g() view public { } +} +// ---- +// Warning: (17-45): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/viewPureChecker/suggest_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/suggest_view.sol new file mode 100644 index 000000000..c045dfc4c --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/suggest_view.sol @@ -0,0 +1,6 @@ +contract C { + uint x; + function g() public returns (uint) { return x; } +} +// ---- +// Warning: (29-77): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/viewPureChecker/write_storage_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/write_storage_fail.sol new file mode 100644 index 000000000..3fed4d297 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/write_storage_fail.sol @@ -0,0 +1,6 @@ +contract C { + uint x; + function f() view public { x = 2; } +} +// ---- +// TypeError: (56-57): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/visibility/function_no_visibility.sol b/test/libsolidity/syntaxTests/visibility/function_no_visibility.sol new file mode 100644 index 000000000..4fc7900fe --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/function_no_visibility.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure { } +} +// ---- +// SyntaxError: (17-38): No visibility specified. Did you intend to add "public"? diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_default.sol b/test/libsolidity/syntaxTests/visibility/interface/function_default.sol index 72ce3b40c..b7e96e5ec 100644 --- a/test/libsolidity/syntaxTests/visibility/interface/function_default.sol +++ b/test/libsolidity/syntaxTests/visibility/interface/function_default.sol @@ -2,5 +2,5 @@ interface I { function f(); } // ---- -// Warning: (15-28): Functions in interfaces should be declared external. -// Warning: (15-28): No visibility specified. Defaulting to "public". In interfaces it defaults to external. +// SyntaxError: (15-28): No visibility specified. Did you intend to add "external"? +// TypeError: (15-28): Functions in interfaces must be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_default050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_default050.sol deleted file mode 100644 index 513df26b3..000000000 --- a/test/libsolidity/syntaxTests/visibility/interface/function_default050.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma experimental "v0.5.0"; -interface I { - function f(); -} -// ---- -// SyntaxError: (45-58): No visibility specified. -// TypeError: (45-58): Functions in interfaces must be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_external050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_external.sol similarity index 61% rename from test/libsolidity/syntaxTests/visibility/interface/function_external050.sol rename to test/libsolidity/syntaxTests/visibility/interface/function_external.sol index 3f0a9acab..ed409e589 100644 --- a/test/libsolidity/syntaxTests/visibility/interface/function_external050.sol +++ b/test/libsolidity/syntaxTests/visibility/interface/function_external.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; interface I { function f() external; } diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_internal.sol b/test/libsolidity/syntaxTests/visibility/interface/function_internal.sol index ac62e69b2..06c1547a9 100644 --- a/test/libsolidity/syntaxTests/visibility/interface/function_internal.sol +++ b/test/libsolidity/syntaxTests/visibility/interface/function_internal.sol @@ -2,4 +2,4 @@ interface I { function f() internal; } // ---- -// TypeError: (15-37): Functions in interfaces cannot be internal or private. +// TypeError: (15-37): Functions in interfaces must be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_private.sol b/test/libsolidity/syntaxTests/visibility/interface/function_private.sol index 881e647e1..98198c3d1 100644 --- a/test/libsolidity/syntaxTests/visibility/interface/function_private.sol +++ b/test/libsolidity/syntaxTests/visibility/interface/function_private.sol @@ -2,4 +2,4 @@ interface I { function f() private; } // ---- -// TypeError: (15-36): Functions in interfaces cannot be internal or private. +// TypeError: (15-36): Functions in interfaces must be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_public.sol b/test/libsolidity/syntaxTests/visibility/interface/function_public.sol index 891d9fdf3..a8cea199b 100644 --- a/test/libsolidity/syntaxTests/visibility/interface/function_public.sol +++ b/test/libsolidity/syntaxTests/visibility/interface/function_public.sol @@ -2,4 +2,4 @@ interface I { function f() public; } // ---- -// Warning: (15-35): Functions in interfaces should be declared external. +// TypeError: (15-35): Functions in interfaces must be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol deleted file mode 100644 index e0c040956..000000000 --- a/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; -interface I { - function f() public; -} -// ---- -// TypeError: (45-65): Functions in interfaces must be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/interface_contract_function_default.sol b/test/libsolidity/syntaxTests/visibility/interface/interface_contract_function_default.sol new file mode 100644 index 000000000..b1a820eda --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/interface_contract_function_default.sol @@ -0,0 +1,12 @@ +// State of the syntax checker has to be reset after the interface +// was visited. The suggested visibility for g() should not be external. +interface I { + function f(); +} +contract C { + function g(); +} +// ---- +// SyntaxError: (158-171): No visibility specified. Did you intend to add "external"? +// SyntaxError: (191-204): No visibility specified. Did you intend to add "public"? +// TypeError: (158-171): Functions in interfaces must be declared external. diff --git a/test/libjulia/Common.cpp b/test/libyul/Common.cpp similarity index 75% rename from test/libjulia/Common.cpp rename to test/libyul/Common.cpp index 24519b015..d224bdcd6 100644 --- a/test/libjulia/Common.cpp +++ b/test/libyul/Common.cpp @@ -16,14 +16,14 @@ */ /** * @date 2017 - * Common functions the iulia tests. + * Common functions the Yul tests. */ -#include +#include #include -#include +#include #include @@ -37,10 +37,10 @@ #include using namespace std; -using namespace dev::julia; +using namespace dev::yul; using namespace dev::solidity; -void dev::julia::test::printErrors(ErrorList const& _errors, Scanner const& _scanner) +void dev::yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner) { SourceReferenceFormatter formatter(cout, [&](std::string const&) -> Scanner const& { return _scanner; }); @@ -52,9 +52,9 @@ void dev::julia::test::printErrors(ErrorList const& _errors, Scanner const& _sca } -pair, shared_ptr> dev::julia::test::parse(string const& _source, bool _julia) +pair, shared_ptr> dev::yul::test::parse(string const& _source, bool _yul) { - auto flavour = _julia ? assembly::AsmFlavour::IULIA : assembly::AsmFlavour::Strict; + auto flavour = _yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict; ErrorList errors; ErrorReporter errorReporter(errors); auto scanner = make_shared(CharStream(_source), ""); @@ -83,13 +83,13 @@ pair, shared_ptr> dev::julia::test: return {}; } -assembly::Block dev::julia::test::disambiguate(string const& _source, bool _julia) +assembly::Block dev::yul::test::disambiguate(string const& _source, bool _yul) { - auto result = parse(_source, _julia); - return boost::get(Disambiguator(*result.second)(*result.first)); + auto result = parse(_source, _yul); + return boost::get(Disambiguator(*result.second, {})(*result.first)); } -string dev::julia::test::format(string const& _source, bool _julia) +string dev::yul::test::format(string const& _source, bool _yul) { - return assembly::AsmPrinter(_julia)(*parse(_source, _julia).first); + return assembly::AsmPrinter(_yul)(*parse(_source, _yul).first); } diff --git a/test/libjulia/Common.h b/test/libyul/Common.h similarity index 86% rename from test/libjulia/Common.h rename to test/libyul/Common.h index 1371101cb..ee191494d 100644 --- a/test/libjulia/Common.h +++ b/test/libyul/Common.h @@ -16,7 +16,7 @@ */ /** * @date 2017 - * Common functions the iulia tests. + * Common functions the Yul tests. */ #pragma once @@ -39,16 +39,16 @@ namespace assembly struct AsmAnalysisInfo; } } -namespace julia +namespace yul { namespace test { void printErrors(solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); std::pair, std::shared_ptr> -parse(std::string const& _source, bool _julia = true); -solidity::assembly::Block disambiguate(std::string const& _source, bool _julia = true); -std::string format(std::string const& _source, bool _julia = true); +parse(std::string const& _source, bool _yul = true); +solidity::assembly::Block disambiguate(std::string const& _source, bool _yul = true); +std::string format(std::string const& _source, bool _yul = true); } } diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp new file mode 100644 index 000000000..66810298e --- /dev/null +++ b/test/libyul/Inliner.cpp @@ -0,0 +1,111 @@ +/* + 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 . +*/ +/** + * @date 2017 + * Unit tests for the Yul function inliner. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::yul; +using namespace dev::yul::test; +using namespace dev::solidity; + +namespace +{ +string inlinableFunctions(string const& _source) +{ + auto ast = disambiguate(_source); + + InlinableExpressionFunctionFinder funFinder; + funFinder(ast); + + vector functionNames; + for (auto const& f: funFinder.inlinableFunctions()) + functionNames.emplace_back(f.first.str()); + return boost::algorithm::join(functionNames, ","); +} + +} + + +BOOST_AUTO_TEST_SUITE(YulInlinableFunctionFilter) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{ }"), ""); +} + +BOOST_AUTO_TEST_CASE(simple) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 } }"), "f"); + BOOST_CHECK_EQUAL(inlinableFunctions("{" + "function g(a:u256) -> b:u256 { b := a }" + "function f() -> x:u256 { x := g(2:u256) }" + "}"), "g,f"); +} + +BOOST_AUTO_TEST_CASE(simple_inside_structures) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{" + "switch 2:u256 " + "case 2:u256 {" + "function g(a:u256) -> b:u256 { b := a }" + "function f() -> x:u256 { x := g(2:u256) }" + "}" + "}"), "g,f"); + BOOST_CHECK_EQUAL(inlinableFunctions("{" + "for {" + "function g(a:u256) -> b:u256 { b := a }" + "} 1:u256 {" + "function f() -> x:u256 { x := g(2:u256) }" + "}" + "{" + "function h() -> y:u256 { y := 2:u256 }" + "}" + "}"), "h,g,f"); +} + +BOOST_AUTO_TEST_CASE(negative) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 {} } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := f() } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := x } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256, y:u256 { x := 2:u256 } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions( + "{ function g() -> x:u256, y:u256 {} function f(y:u256) -> x:u256 { x,y := g() } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f(y:u256) -> x:u256 { y := 2:u256 } }"), ""); +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/Parser.cpp b/test/libyul/Parser.cpp similarity index 98% rename from test/libjulia/Parser.cpp rename to test/libyul/Parser.cpp index 96261decc..3f329d282 100644 --- a/test/libjulia/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -16,7 +16,7 @@ */ /** * @date 2017 - * Unit tests for parsing Julia. + * Unit tests for parsing Yul. */ #include @@ -52,7 +52,7 @@ bool parse(string const& _source, ErrorReporter& errorReporter) try { auto scanner = make_shared(CharStream(_source)); - auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::IULIA).parse(scanner, false); + auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::Yul).parse(scanner, false); if (parserResult) { assembly::AsmAnalysisInfo analysisInfo; @@ -61,7 +61,7 @@ bool parse(string const& _source, ErrorReporter& errorReporter) errorReporter, dev::test::Options::get().evmVersion(), boost::none, - assembly::AsmFlavour::IULIA + assembly::AsmFlavour::Yul )).analyze(*parserResult); } } @@ -119,7 +119,7 @@ do \ BOOST_CHECK(searchErrorMessage(err, (substring))); \ } while(0) -BOOST_AUTO_TEST_SUITE(JuliaParser) +BOOST_AUTO_TEST_SUITE(YulParser) BOOST_AUTO_TEST_CASE(smoke_test) { @@ -267,7 +267,7 @@ BOOST_AUTO_TEST_CASE(recursion_depth) BOOST_AUTO_TEST_CASE(multiple_assignment) { CHECK_ERROR("{ let x:u256 function f() -> a:u256, b:u256 {} 123:u256, x := f() }", ParserError, "Label name / variable name must precede \",\" (multiple assignment)."); - CHECK_ERROR("{ let x:u256 function f() -> a:u256, b:u256 {} x, 123:u256 := f() }", ParserError, "Variable name expected in multiple assignemnt."); + CHECK_ERROR("{ let x:u256 function f() -> a:u256, b:u256 {} x, 123:u256 := f() }", ParserError, "Variable name expected in multiple assignment."); /// NOTE: Travis hiccups if not having a variable char const* text = R"( diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp new file mode 100644 index 000000000..03cd6446d --- /dev/null +++ b/test/libyul/YulOptimizerTest.cpp @@ -0,0 +1,295 @@ +/* + 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 . +*/ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace dev; +using namespace dev::yul; +using namespace dev::yul::test; +using namespace dev::solidity; +using namespace dev::solidity::test; +using namespace std; + +YulOptimizerTest::YulOptimizerTest(string const& _filename) +{ + boost::filesystem::path path(_filename); + + if (path.empty() || std::next(path.begin()) == path.end() || std::next(std::next(path.begin())) == path.end()) + BOOST_THROW_EXCEPTION(runtime_error("Filename path has to contain a directory: \"" + _filename + "\".")); + m_optimizerStep = std::prev(std::prev(path.end()))->string(); + + ifstream file(_filename); + if (!file) + BOOST_THROW_EXCEPTION(runtime_error("Cannot open test case: \"" + _filename + "\".")); + file.exceptions(ios::badbit); + + string line; + while (getline(file, line)) + { + if (boost::algorithm::starts_with(line, "// ----")) + break; + if (m_source.empty() && boost::algorithm::starts_with(line, "// yul")) + m_yul = true; + m_source += line + "\n"; + } + while (getline(file, line)) + if (boost::algorithm::starts_with(line, "// ")) + m_expectation += line.substr(3) + "\n"; + else + m_expectation += line + "\n"; +} + +bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + assembly::AsmPrinter printer{m_yul}; + shared_ptr ast; + shared_ptr analysisInfo; + if (!parse(_stream, _linePrefix, _formatted)) + return false; + + if (m_optimizerStep == "disambiguator") + disambiguate(); + else if (m_optimizerStep == "blockFlattener") + { + disambiguate(); + BlockFlattener{}(*m_ast); + } + else if (m_optimizerStep == "varDeclPropagator") + { + disambiguate(); + VarDeclPropagator{}(*m_ast); + } + else if (m_optimizerStep == "commonSubexpressionEliminator") + { + disambiguate(); + (CommonSubexpressionEliminator{})(*m_ast); + } + else if (m_optimizerStep == "expressionSplitter") + { + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + } + else if (m_optimizerStep == "expressionJoiner") + { + disambiguate(); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "splitJoin") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + ExpressionJoiner::run(*m_ast); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "functionGrouper") + { + disambiguate(); + (FunctionGrouper{})(*m_ast); + } + else if (m_optimizerStep == "functionHoister") + { + disambiguate(); + (FunctionHoister{})(*m_ast); + } + else if (m_optimizerStep == "expressionInliner") + { + disambiguate(); + ExpressionInliner(*m_ast).run(); + } + else if (m_optimizerStep == "fullInliner") + { + disambiguate(); + (FunctionHoister{})(*m_ast); + (FunctionGrouper{})(*m_ast); + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + FullInliner(*m_ast, nameDispenser).run(); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "mainFunction") + { + disambiguate(); + (FunctionGrouper{})(*m_ast); + (MainFunction{})(*m_ast); + } + else if (m_optimizerStep == "rematerialiser") + { + disambiguate(); + (Rematerialiser{})(*m_ast); + } + else if (m_optimizerStep == "expressionSimplifier") + { + disambiguate(); + ExpressionSimplifier::run(*m_ast); + } + else if (m_optimizerStep == "fullSimplify") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + CommonSubexpressionEliminator{}(*m_ast); + ExpressionSimplifier::run(*m_ast); + UnusedPruner::runUntilStabilised(*m_ast); + ExpressionJoiner::run(*m_ast); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "unusedPruner") + { + disambiguate(); + UnusedPruner::runUntilStabilised(*m_ast); + } + else if (m_optimizerStep == "ssaTransform") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + SSATransform::run(*m_ast, nameDispenser); + } + else if (m_optimizerStep == "redundantAssignEliminator") + { + disambiguate(); + RedundantAssignEliminator::run(*m_ast); + } + else if (m_optimizerStep == "ssaPlusCleanup") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + SSATransform::run(*m_ast, nameDispenser); + RedundantAssignEliminator::run(*m_ast); + } + else if (m_optimizerStep == "fullSuite") + OptimiserSuite::run(*m_ast, *m_analysisInfo); + else + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; + return false; + } + + m_obtainedResult = m_optimizerStep + "\n" + printer(*m_ast) + "\n"; + + if (m_expectation != m_obtainedResult) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Expected result:" << endl; + // TODO could compute a simple diff with highlighted lines + printIndented(_stream, m_expectation, nextIndentLevel); + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Obtained result:" << endl; + printIndented(_stream, m_obtainedResult, nextIndentLevel); + return false; + } + return true; +} + +void YulOptimizerTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const +{ + printIndented(_stream, m_source, _linePrefix); +} + +void YulOptimizerTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const +{ + printIndented(_stream, m_obtainedResult, _linePrefix); +} + +void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const +{ + stringstream output(_output); + string line; + while (getline(output, line)) + _stream << _linePrefix << line << endl; +} + +bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + assembly::AsmFlavour flavour = m_yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict; + ErrorList errors; + ErrorReporter errorReporter(errors); + shared_ptr scanner = make_shared(CharStream(m_source), ""); + m_ast = assembly::Parser(errorReporter, flavour).parse(scanner, false); + if (!m_ast || !errorReporter.errors().empty()) + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; + printErrors(_stream, errorReporter.errors(), *scanner); + return false; + } + m_analysisInfo = make_shared(); + assembly::AsmAnalyzer analyzer( + *m_analysisInfo, + errorReporter, + dev::test::Options::get().evmVersion(), + boost::none, + flavour + ); + if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error analyzing source." << endl; + printErrors(_stream, errorReporter.errors(), *scanner); + return false; + } + return true; +} + +void YulOptimizerTest::disambiguate() +{ + *m_ast = boost::get(Disambiguator(*m_analysisInfo)(*m_ast)); + m_analysisInfo.reset(); +} + +void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors, Scanner const& _scanner) +{ + SourceReferenceFormatter formatter(_stream, [&](string const&) -> Scanner const& { return _scanner; }); + + for (auto const& error: _errors) + formatter.printExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error" + ); +} diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h new file mode 100644 index 000000000..7db17ceb7 --- /dev/null +++ b/test/libyul/YulOptimizerTest.h @@ -0,0 +1,75 @@ +/* + 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 + + +namespace dev +{ +namespace solidity +{ +class Scanner; +class Error; +using ErrorList = std::vector>; +namespace assembly +{ +struct AsmAnalysisInfo; +struct Block; +} +} +namespace yul +{ +namespace test +{ + +class YulOptimizerTest: public solidity::test::TestCase +{ +public: + static std::unique_ptr create(std::string const& _filename) + { + return std::unique_ptr(new YulOptimizerTest(_filename)); + } + + explicit YulOptimizerTest(std::string const& _filename); + + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + + void printSource(std::ostream& _stream, std::string const &_linePrefix = "", bool const _formatted = false) const override; + void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; + +private: + void printIndented(std::ostream& _stream, std::string const& _output, std::string const& _linePrefix = "") const; + bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); + void disambiguate(); + + static void printErrors(std::ostream& _stream, solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); + + std::string m_source; + bool m_yul = false; + std::string m_optimizerStep; + std::string m_expectation; + + std::shared_ptr m_ast; + std::shared_ptr m_analysisInfo; + std::string m_obtainedResult; +}; + +} +} +} diff --git a/test/libyul/yulOptimizerTests/blockFlattener/basic.yul b/test/libyul/yulOptimizerTests/blockFlattener/basic.yul new file mode 100644 index 000000000..adcaedd07 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/basic.yul @@ -0,0 +1,20 @@ +{ + let _1 := mload(0) + let f_a := mload(1) + let f_r + { + f_a := mload(f_a) + f_r := add(f_a, calldatasize()) + } + let z := mload(2) +} +// ---- +// blockFlattener +// { +// let _1 := mload(0) +// let f_a := mload(1) +// let f_r +// f_a := mload(f_a) +// f_r := add(f_a, calldatasize()) +// let z := mload(2) +// } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul new file mode 100644 index 000000000..07bd5c18f --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul @@ -0,0 +1,19 @@ +{ + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + a := add(a, 1) + } +} +// ---- +// blockFlattener +// { +// for { +// let a := 1 +// } +// iszero(eq(a, 10)) +// { +// a := add(a, 1) +// } +// { +// a := add(a, 1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul new file mode 100644 index 000000000..4d6ccf0e8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul @@ -0,0 +1,20 @@ +{ + if add(mload(7), sload(mload(3))) + { + let y := add(mload(3), 3) + { + y := add(y, 7) + } + } + let t := add(3, 9) +} +// ---- +// blockFlattener +// { +// if add(mload(7), sload(mload(3))) +// { +// let y := add(mload(3), 3) +// y := add(y, 7) +// } +// let t := add(3, 9) +// } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul b/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul new file mode 100644 index 000000000..ae2a066ba --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul @@ -0,0 +1,28 @@ +{ + let a := 3 + let b := 4 + { + a := add(b, 3) + let c := 5 + { + b := add(b, 4) + { + c := add(a, 5) + } + b := add(a, b) + } + a := add(a, c) + } +} +// ---- +// blockFlattener +// { +// let a := 3 +// let b := 4 +// a := add(b, 3) +// let c := 5 +// b := add(b, 4) +// c := add(a, 5) +// b := add(a, b) +// a := add(a, c) +// } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul new file mode 100644 index 000000000..2df4f9d09 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul @@ -0,0 +1,22 @@ +{ + let a := 1 + switch calldataload(0) + case 0 { { { mstore(0, 1) } } a := 8 } + default { a := 3 { a := 4 } } + a := 5 +} +// ---- +// blockFlattener +// { +// let a := 1 +// switch calldataload(0) +// case 0 { +// mstore(0, 1) +// a := 8 +// } +// default { +// a := 3 +// a := 4 +// } +// a := 5 +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul new file mode 100644 index 000000000..c59bced76 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul @@ -0,0 +1,24 @@ +{ + let a := 1 let b := codesize() + for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) } { + mstore(1, codesize()) + } + mstore(1, codesize()) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := 1 +// let b := codesize() +// for { +// } +// lt(1, b) +// { +// mstore(1, b) +// a := add(a, b) +// } +// { +// mstore(1, b) +// } +// mstore(1, b) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul new file mode 100644 index 000000000..5b8200d9c --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul @@ -0,0 +1,15 @@ +{ + let b := 1 + if b { b := 1 } + let c := 1 +} +// ---- +// commonSubexpressionEliminator +// { +// let b := 1 +// if b +// { +// b := b +// } +// let c := 1 +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/case2.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/case2.yul new file mode 100644 index 000000000..fd8b4bc81 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/case2.yul @@ -0,0 +1,52 @@ +{ + let _13 := 0x20 + let _14 := allocate(_13) + pop(_14) + let _15 := 2 + let _16 := 3 + let _17 := 0x40 + let _18 := allocate(_17) + let _19 := array_index_access(_18, _16) + mstore(_19, _15) + function allocate(size) -> p + { + let _1 := 0x40 + let p_2 := mload(_1) + p := p_2 + let _20 := add(p_2, size) + mstore(_1, _20) + } + function array_index_access(array, index) -> p_1 + { + let _21 := 0x20 + let _22 := mul(index, _21) + p_1 := add(array, _22) + } +} +// ---- +// commonSubexpressionEliminator +// { +// let _13 := 0x20 +// let _14 := allocate(_13) +// pop(_14) +// let _15 := 2 +// let _16 := 3 +// let _17 := 0x40 +// let _18 := allocate(_17) +// let _19 := array_index_access(_18, _16) +// mstore(_19, _15) +// function allocate(size) -> p +// { +// let _1 := 0x40 +// let p_2 := mload(_1) +// p := p_2 +// let _20 := add(p_2, size) +// mstore(_1, _20) +// } +// function array_index_access(array, index) -> p_1 +// { +// let _21 := 0x20 +// let _22 := mul(index, _21) +// p_1 := add(array, _22) +// } +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul new file mode 100644 index 000000000..28e840cff --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul @@ -0,0 +1,52 @@ +{ + function allocate(size) -> p + { + let _1 := 0x40 + p := mload(_1) + let _2 := add(p, size) + let _3 := 0x40 + mstore(_3, _2) + } + function array_index_access(array, index) -> p_1 + { + let _4 := 0x20 + let _5 := mul(index, _4) + p_1 := add(array, _5) + } + let _6 := 0x20 + let _7 := allocate(_6) + pop(_7) + let _8 := 0x40 + let x := allocate(_8) + let _9 := 2 + let _10 := 3 + let _11 := array_index_access(x, _10) + mstore(_11, _9) +} +// ---- +// commonSubexpressionEliminator +// { +// function allocate(size) -> p +// { +// let _1 := 0x40 +// p := mload(_1) +// let _2 := add(p, size) +// let _3 := _1 +// mstore(_1, _2) +// } +// function array_index_access(array, index) -> p_1 +// { +// let _4 := 0x20 +// let _5 := mul(index, _4) +// p_1 := add(array, _5) +// } +// let _6 := 0x20 +// let _7 := allocate(_6) +// pop(_7) +// let _8 := 0x40 +// let x := allocate(_8) +// let _9 := 2 +// let _10 := 3 +// let _11 := array_index_access(x, _10) +// mstore(_11, _9) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul new file mode 100644 index 000000000..cb0ca38dd --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul @@ -0,0 +1,10 @@ +{ + let a := mload(1) + let b := mload(1) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mload(1) +// let b := mload(1) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul new file mode 100644 index 000000000..ebc17446c --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul @@ -0,0 +1,10 @@ +{ + let a := gas() + let b := gas() +} +// ---- +// commonSubexpressionEliminator +// { +// let a := gas() +// let b := gas() +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/scopes.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/scopes.yul new file mode 100644 index 000000000..49b4c9164 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/scopes.yul @@ -0,0 +1,25 @@ +{ + let a := 10 + let x := 20 + { + let b := calldataload(0) + let d := calldataload(1) + x := d + } + // We had a bug where "calldataload(0)" was incorrectly replaced by "b" + mstore(0, calldataload(0)) + mstore(0, x) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := 10 +// let x := 20 +// { +// let b := calldataload(0) +// let d := calldataload(1) +// x := d +// } +// mstore(0, calldataload(0)) +// mstore(0, x) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul new file mode 100644 index 000000000..b94572294 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// commonSubexpressionEliminator +// { +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul new file mode 100644 index 000000000..684272f57 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul @@ -0,0 +1,10 @@ +{ + let a := mul(1, codesize()) + let b := mul(1, codesize()) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mul(1, codesize()) +// let b := a +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/variable_for_variable.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/variable_for_variable.yul new file mode 100644 index 000000000..ab94afc22 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/variable_for_variable.yul @@ -0,0 +1,27 @@ +{ + + let a := mload(0) + let b := add(a, 7) + let c := a + let d := c + let x := add(a, b) + // CSE has to recognize equality with x here. + let y := add(d, add(c, 7)) + // some reassignments + b := mload(a) + a := b + mstore(2, a) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mload(0) +// let b := add(a, 7) +// let c := a +// let d := a +// let x := add(a, b) +// let y := x +// b := mload(a) +// a := b +// mstore(2, b) +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul new file mode 100644 index 000000000..6875abec6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul @@ -0,0 +1,28 @@ +// yul +{ + { let a:u256, b:u256 } + { + for { let a:u256 } a { a := a } { + let b:u256 := a + } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256 +// } +// { +// for { +// let a_1:u256 +// } +// a_1 +// { +// a_1 := a_1 +// } +// { +// let b_2:u256 := a_1 +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul new file mode 100644 index 000000000..df49b92a7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul @@ -0,0 +1,22 @@ +// yul +{ + { let a:u256, b:u256, c:u256, d:u256, f:u256 } + { + function f(a:u256) -> c:u256, d:u256 { + let b:u256, c_1:u256 := f(a) + } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256, d:u256, f:u256 +// } +// { +// function f_1(a_2:u256) -> c_3:u256, d_4:u256 +// { +// let b_5:u256, c_1:u256 := f_1(a_2) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul new file mode 100644 index 000000000..bc3aa30f9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul @@ -0,0 +1,22 @@ +// yul +{ + { let a:u256, b:u256, c:u256 } + { + let a:bool + if a { let b:bool := a } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256 +// } +// { +// let a_1:bool +// if a_1 +// { +// let b_2:bool := a_1 +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/long_names.yul b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul new file mode 100644 index 000000000..933e1e8ff --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul @@ -0,0 +1,12 @@ +// yul +{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } } +// ---- +// disambiguator +// { +// { +// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 +// } +// { +// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh_1:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/smoke.yul b/test/libyul/yulOptimizerTests/disambiguator/smoke.yul new file mode 100644 index 000000000..d6cd8a619 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// disambiguator +// { +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul b/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul new file mode 100644 index 000000000..e55f4cd3e --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul @@ -0,0 +1,6 @@ +// yul +{ } +// ---- +// disambiguator +// { +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul new file mode 100644 index 000000000..e62e957f8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul @@ -0,0 +1,27 @@ +// yul +{ + { let a:u256, b:u256, c:u256 } + { + let a:u256 + switch a + case 0:u256 { let b:u256 := a } + default { let c:u256 := a } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256 +// } +// { +// let a_1:u256 +// switch a_1 +// case 0:u256 { +// let b_2:u256 := a_1 +// } +// default { +// let c_3:u256 := a_1 +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables.yul b/test/libyul/yulOptimizerTests/disambiguator/variables.yul new file mode 100644 index 000000000..65bd4c8f8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/variables.yul @@ -0,0 +1,12 @@ +// yul +{ { let a:u256 } { let a:u256 } } +// ---- +// disambiguator +// { +// { +// let a:u256 +// } +// { +// let a_1:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul new file mode 100644 index 000000000..e462442a9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul @@ -0,0 +1,13 @@ +// yul +{ { let a:u256 let a_1:u256 } { let a:u256 } } +// ---- +// disambiguator +// { +// { +// let a:u256 +// let a_1:u256 +// } +// { +// let a_2:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul new file mode 100644 index 000000000..839692bc6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul @@ -0,0 +1,24 @@ +// yul +{ + { let c:u256 let b:u256 } + function f(a:u256, c:u256) -> b:u256 { let x:u256 } + { + let a:u256 let x:u256 + } +} +// ---- +// disambiguator +// { +// { +// let c:u256 +// let b:u256 +// } +// function f(a:u256, c_1:u256) -> b_2:u256 +// { +// let x:u256 +// } +// { +// let a_3:u256 +// let x_4:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/complex_with_evm.yul b/test/libyul/yulOptimizerTests/expressionInliner/complex_with_evm.yul new file mode 100644 index 000000000..519a2af85 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/complex_with_evm.yul @@ -0,0 +1,13 @@ +{ + function f(a) -> x { x := add(a, a) } + let y := f(calldatasize()) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := add(a, a) +// } +// let y := add(calldatasize(), calldatasize()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/double_calls.yul b/test/libyul/yulOptimizerTests/expressionInliner/double_calls.yul new file mode 100644 index 000000000..e1da8e074 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/double_calls.yul @@ -0,0 +1,18 @@ +{ + function f(a) -> x { x := add(a, a) } + function g(b, c) -> y { y := mul(mload(c), f(b)) } + let y := g(calldatasize(), 7) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := add(a, a) +// } +// function g(b, c) -> y +// { +// y := mul(mload(c), add(b, b)) +// } +// let y_1 := mul(mload(7), add(calldatasize(), calldatasize())) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/double_recursive_calls.yul b/test/libyul/yulOptimizerTests/expressionInliner/double_recursive_calls.yul new file mode 100644 index 000000000..082cb53fa --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/double_recursive_calls.yul @@ -0,0 +1,18 @@ +{ + function f(a, r) -> x { x := g(a, g(r, r)) } + function g(b, s) -> y { y := f(b, f(s, s)) } + let y := g(calldatasize(), 7) +} +// ---- +// expressionInliner +// { +// function f(a, r) -> x +// { +// x := g(a, f(r, f(r, r))) +// } +// function g(b, s) -> y +// { +// y := f(b, g(s, f(s, f(s, s)))) +// } +// let y_1 := f(calldatasize(), g(7, f(7, f(7, 7)))) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/no_inline_mload.yul b/test/libyul/yulOptimizerTests/expressionInliner/no_inline_mload.yul new file mode 100644 index 000000000..0fb43a9d0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/no_inline_mload.yul @@ -0,0 +1,14 @@ +// Does not inline because mload could be moved out of sequence +{ + function f(a) -> x { x := a } + let y := f(mload(2)) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := a +// } +// let y := f(mload(2)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul b/test/libyul/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul new file mode 100644 index 000000000..7fdad6c41 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul @@ -0,0 +1,27 @@ +// The calls to g and h cannot be moved because g and h are not movable. Therefore, the call +// to f is not inlined. +{ + function f(a, b) -> x { x := add(b, a) } + function g() -> y { y := mload(0) mstore(0, 4) } + function h() -> z { mstore(0, 4) z := mload(0) } + let r := f(g(), h()) +} +// ---- +// expressionInliner +// { +// function f(a, b) -> x +// { +// x := add(b, a) +// } +// function g() -> y +// { +// y := mload(0) +// mstore(0, 4) +// } +// function h() -> z +// { +// mstore(0, 4) +// z := mload(0) +// } +// let r := f(g(), h()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/simple.yul b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul new file mode 100644 index 000000000..c186eafda --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul @@ -0,0 +1,14 @@ +// yul +{ + function f() -> x:u256 { x := 2:u256 } + let y:u256 := f() +} +// ---- +// expressionInliner +// { +// function f() -> x:u256 +// { +// x := 2:u256 +// } +// let y:u256 := 2:u256 +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul new file mode 100644 index 000000000..b5f4d5159 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul @@ -0,0 +1,14 @@ +// yul +{ + function f(a:u256) -> x:u256 { x := a } + let y:u256 := f(7:u256) +} +// ---- +// expressionInliner +// { +// function f(a:u256) -> x:u256 +// { +// x := a +// } +// let y:u256 := 7:u256 +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul b/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul new file mode 100644 index 000000000..a1349511c --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul @@ -0,0 +1,21 @@ +{ + let a := mload(3) + let b := sload(a) + let c := mload(7) + let d := add(c, b) + if d { + let x := mload(3) + let y := add(x, 3) + } + let z := 3 + let t := add(z, 9) +} +// ---- +// expressionJoiner +// { +// if add(mload(7), sload(mload(3))) +// { +// let y := add(mload(3), 3) +// } +// let t := add(3, 9) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul b/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul new file mode 100644 index 000000000..0d407c7ca --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul @@ -0,0 +1,13 @@ +{ + let a := mload(3) + let b := mload(6) + let x := mul(add(b, a), mload(2)) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let a := mload(3) +// let b := mload(6) +// sstore(mul(add(b, a), mload(2)), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul new file mode 100644 index 000000000..fd53ca51d --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul @@ -0,0 +1,11 @@ +{ + let a := mload(2) + let b := mload(6) + let x := mul(add(b, a), 2) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// sstore(mul(add(mload(6), mload(2)), 2), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul new file mode 100644 index 000000000..078a12a56 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul @@ -0,0 +1,11 @@ +{ + // This is not joined because a is referenced multiple times + let a := mload(2) + let b := add(a, a) +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// let b := add(a, a) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul new file mode 100644 index 000000000..965e07e97 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul @@ -0,0 +1,15 @@ +{ + // We have an interleaved "add" here, so we cannot inline "a" + // (note that this component does not analyze whether + // functions are pure or not) + let a := mload(2) + let b := mload(6) + let x := mul(a, add(2, b)) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// sstore(mul(a, add(2, mload(6))), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul new file mode 100644 index 000000000..c577e1820 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul @@ -0,0 +1,12 @@ +{ + let a := mload(2) + let b := mload(6) + let x := mul(add(a, b), 2) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// sstore(mul(add(a, mload(6)), 2), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul new file mode 100644 index 000000000..a781bb2a7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul @@ -0,0 +1,19 @@ +{ + // The component will remove the empty block after + // it has handled the outer block. + // The idea behind this test is that the component + // does not perform replacements across blocks because + // they usually have contents, but adding contents + // will reduce the scope of the test. + let a := mload(2) + let x := calldataload(a) + { + } + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let x := calldataload(mload(2)) +// sstore(x, 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul new file mode 100644 index 000000000..75218a5c4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul @@ -0,0 +1,15 @@ +{ + for { let b := mload(1) } b {} {} +} +// ---- +// expressionJoiner +// { +// for { +// let b := mload(1) +// } +// b +// { +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul new file mode 100644 index 000000000..d5f7d8fa6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul @@ -0,0 +1,16 @@ +{ + let a := mload(0) + for { } a {} {} +} +// ---- +// expressionJoiner +// { +// let a := mload(0) +// for { +// } +// a +// { +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul b/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul new file mode 100644 index 000000000..c74112115 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul @@ -0,0 +1,16 @@ +{ + // This is not joined because a is referenced multiple times + function f(a) -> x { + a := mload(2) + x := add(a, 3) + } +} +// ---- +// expressionJoiner +// { +// function f(a) -> x +// { +// a := mload(2) +// x := add(a, 3) +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul b/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul new file mode 100644 index 000000000..1e502353d --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul @@ -0,0 +1,13 @@ +{ + // This is not joined because a is referenced multiple times + let a := mload(2) + let b := mload(a) + a := 4 +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// let b := mload(a) +// a := 4 +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul b/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul new file mode 100644 index 000000000..b03bcf45a --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul @@ -0,0 +1,10 @@ +{ + let a := mload(2) + let x := calldataload(a) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// sstore(calldataload(mload(2)), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul b/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul new file mode 100644 index 000000000..3b433f78b --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul @@ -0,0 +1,13 @@ +{ + let a := mload(3) + let b := sload(a) + let c := mload(7) + let d := add(b, c) + sstore(d, 0) +} +// ---- +// expressionJoiner +// { +// let b := sload(mload(3)) +// sstore(add(b, mload(7)), 0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul b/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul new file mode 100644 index 000000000..c0e2c6f22 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionJoiner +// { +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul b/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul new file mode 100644 index 000000000..0e4e540e1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul @@ -0,0 +1,28 @@ +{ + let a := mload(3) + let b := sload(a) + let c := mload(7) + let d := add(c, b) + switch d + case 3 { + let x := mload(3) + let y := add(x, 3) + } + default { + sstore(1, 0) + } + let z := 3 + let t := add(z, 9) +} +// ---- +// expressionJoiner +// { +// switch add(mload(7), sload(mload(3))) +// case 3 { +// let y := add(mload(3), 3) +// } +// default { +// sstore(1, 0) +// } +// let t := add(3, 9) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul b/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul new file mode 100644 index 000000000..7b722be18 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul @@ -0,0 +1,12 @@ +{ + let a := mload(2) + let b := mload(6) + let c := mload(7) + let x := mul(add(c, b), a) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// sstore(mul(add(mload(7), mload(6)), mload(2)), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul new file mode 100644 index 000000000..0b55adc51 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul @@ -0,0 +1,6 @@ +{ let a := add(7, sub(mload(0), 7)) } +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul new file mode 100644 index 000000000..bd1a5a53d --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul @@ -0,0 +1,6 @@ +{ let a := add(1, mul(3, 4)) } +// ---- +// expressionSimplifier +// { +// let a := 13 +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul new file mode 100644 index 000000000..f61906226 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul @@ -0,0 +1,6 @@ +{ let a := sub(calldataload(0), calldataload(0)) } +// ---- +// expressionSimplifier +// { +// let a := 0 +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul new file mode 100644 index 000000000..e91403cd8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul @@ -0,0 +1,6 @@ +{ let a := sub(calldataload(1), calldataload(0)) } +// ---- +// expressionSimplifier +// { +// let a := sub(calldataload(1), calldataload(0)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul new file mode 100644 index 000000000..d35686cd3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul @@ -0,0 +1,10 @@ +{ + let a := mload(0) + let b := sub(a, a) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// let b := 0 +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul new file mode 100644 index 000000000..c2ca504a1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul @@ -0,0 +1,12 @@ +{ + function f() -> a {} + let b := add(7, sub(f(), 7)) +} +// ---- +// expressionSimplifier +// { +// function f() -> a +// { +// } +// let b := f() +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul new file mode 100644 index 000000000..42c378269 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul @@ -0,0 +1,16 @@ +{ + for { let a := 10 } iszero(eq(a, 0)) { a := add(a, 1) } {} +} +// ---- +// expressionSimplifier +// { +// for { +// let a := 10 +// } +// iszero(iszero(a)) +// { +// a := add(a, 1) +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul new file mode 100644 index 000000000..e6d845528 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul @@ -0,0 +1,10 @@ +{ + let a := mload(sub(7, 7)) + let b := sub(a, 0) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// let b := a +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul new file mode 100644 index 000000000..88714ce0a --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul @@ -0,0 +1,8 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 8))) +} +// ---- +// expressionSimplifier +// { +// mstore(0, and(calldataload(0), 255)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul new file mode 100644 index 000000000..4d52abe85 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul @@ -0,0 +1,8 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 255))) +} +// ---- +// expressionSimplifier +// { +// mstore(0, and(calldataload(0), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul new file mode 100644 index 000000000..53270b723 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul @@ -0,0 +1,12 @@ +{ + function f(a) -> b { } + let c := sub(f(0), f(1)) +} +// ---- +// expressionSimplifier +// { +// function f(a) -> b +// { +// } +// let c := sub(f(0), f(1)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul new file mode 100644 index 000000000..6ab65d294 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul @@ -0,0 +1,16 @@ +{ + function f1() -> a { } + function f2() -> b { } + let c := sub(f1(), f2()) +} +// ---- +// expressionSimplifier +// { +// function f1() -> a +// { +// } +// function f2() -> b +// { +// } +// let c := sub(f1(), f2()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul new file mode 100644 index 000000000..ab1bd1287 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul @@ -0,0 +1,13 @@ +// Even if the functions pass the equality check, they are not movable. +{ + function f() -> a { } + let b := sub(f(), f()) +} +// ---- +// expressionSimplifier +// { +// function f() -> a +// { +// } +// let b := sub(f(), f()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul new file mode 100644 index 000000000..fc61c3df7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul @@ -0,0 +1,10 @@ +// The first argument of div is not constant. +// keccak256 is not movable. +{ + let a := div(keccak256(0, 0), 0) +} +// ---- +// expressionSimplifier +// { +// let a := div(keccak256(0, 0), 0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul new file mode 100644 index 000000000..6353cda98 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul @@ -0,0 +1,8 @@ +{ + let a := add(0, mload(0)) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul new file mode 100644 index 000000000..88420e923 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionSimplifier +// { +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul b/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul new file mode 100644 index 000000000..d021129fe --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul @@ -0,0 +1,40 @@ +{ + let x := calldataload(0) + if mul(add(x, 2), 3) { + for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { + let b := mul(add(a, 2), 4) + sstore(b, mul(b, 2)) + } + } +} +// ---- +// expressionSplitter +// { +// let _1 := 0 +// let x := calldataload(_1) +// let _2 := 3 +// let _3 := 2 +// let _4 := add(x, _3) +// let _5 := mul(_4, _2) +// if _5 +// { +// for { +// let a := 2 +// } +// lt(a, mload(a)) +// { +// let _6 := 2 +// let _7 := mul(a, _6) +// a := add(a, _7) +// } +// { +// let _8 := 4 +// let _9 := 2 +// let _10 := add(a, _9) +// let b := mul(_10, _8) +// let _11 := 2 +// let _12 := mul(b, _11) +// sstore(b, _12) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/inside_function.yul b/test/libyul/yulOptimizerTests/expressionSplitter/inside_function.yul new file mode 100644 index 000000000..53bbcea76 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/inside_function.yul @@ -0,0 +1,29 @@ +{ + let x := mul(f(0, mload(7)), 3) + function f(a, b) -> c { + c := mul(a, mload(add(b, c))) + } + sstore(x, f(mload(2), mload(2))) +} +// ---- +// expressionSplitter +// { +// let _1 := 3 +// let _2 := 7 +// let _3 := mload(_2) +// let _4 := 0 +// let _5 := f(_4, _3) +// let x := mul(_5, _1) +// function f(a, b) -> c +// { +// let _6 := add(b, c) +// let _7 := mload(_6) +// c := mul(a, _7) +// } +// let _8 := 2 +// let _9 := mload(_8) +// let _10 := 2 +// let _11 := mload(_10) +// let _12 := f(_11, _9) +// sstore(x, _12) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/smoke.yul b/test/libyul/yulOptimizerTests/expressionSplitter/smoke.yul new file mode 100644 index 000000000..f69f60b63 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionSplitter +// { +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/switch.yul b/test/libyul/yulOptimizerTests/expressionSplitter/switch.yul new file mode 100644 index 000000000..aee7976f3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/switch.yul @@ -0,0 +1,33 @@ +{ + let x := 8 + switch add(2, calldataload(0)) + case 0 { sstore(0, mload(2)) } + default { mstore(0, mload(3)) } + x := add(mload(3), 4) +} +// ---- +// expressionSplitter +// { +// let x := 8 +// let _1 := 0 +// let _2 := calldataload(_1) +// let _3 := 2 +// let _4 := add(_3, _2) +// switch _4 +// case 0 { +// let _5 := 2 +// let _6 := mload(_5) +// let _7 := 0 +// sstore(_7, _6) +// } +// default { +// let _8 := 3 +// let _9 := mload(_8) +// let _10 := 0 +// mstore(_10, _9) +// } +// let _11 := 4 +// let _12 := 3 +// let _13 := mload(_12) +// x := add(_13, _11) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/trivial.yul b/test/libyul/yulOptimizerTests/expressionSplitter/trivial.yul new file mode 100644 index 000000000..bff70cd88 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/trivial.yul @@ -0,0 +1,14 @@ +{ + mstore(add(calldataload(2), mload(3)), 8) +} +// ---- +// expressionSplitter +// { +// let _1 := 8 +// let _2 := 3 +// let _3 := mload(_2) +// let _4 := 2 +// let _5 := calldataload(_4) +// let _6 := add(_5, _3) +// mstore(_6, _1) +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul new file mode 100644 index 000000000..ee7f5bf59 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul @@ -0,0 +1,30 @@ +{ + function f(a) -> b, c { let x := mload(a) b := sload(x) c := 3 } + let a1 := calldataload(0) + let b3, c3 := f(a1) + let b4, c4 := f(c3) +} +// ---- +// fullInliner +// { +// { +// let f_a := calldataload(0) +// let f_b +// let f_c +// f_b := sload(mload(f_a)) +// f_c := 3 +// let b3 := f_b +// let f_a_2 := f_c +// let f_b_3 +// let f_c_4 +// f_b_3 := sload(mload(f_a_2)) +// f_c_4 := 3 +// let b4 := f_b_3 +// let c4 := f_c_4 +// } +// function f(a) -> b, c +// { +// b := sload(mload(a)) +// c := 3 +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul new file mode 100644 index 000000000..00bb6577e --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul @@ -0,0 +1,30 @@ +// This tests that splitting the expression inside the condition works properly. +{ + if gt(f(mload(1)), mload(0)) { + sstore(0, 2) + } + function f(a) -> r { + a := mload(a) + r := add(a, calldatasize()) + } +} +// ---- +// fullInliner +// { +// { +// let _2 := mload(0) +// let f_a := mload(1) +// let f_r +// f_a := mload(f_a) +// f_r := add(f_a, calldatasize()) +// if gt(f_r, _2) +// { +// sstore(0, 2) +// } +// } +// function f(a) -> r +// { +// a := mload(a) +// r := add(a, calldatasize()) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul new file mode 100644 index 000000000..0972ac569 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul @@ -0,0 +1,43 @@ +{ + function f(a) -> b { + let x := mload(a) + b := sload(x) + let c := 3 + mstore(mul(a, b), mload(x)) + let y := add(a, x) + sstore(y, 10) + } + let a := mload(2) + let a2 := 2 + // This should not be inlined because it is not a constant + let r := f(a) + // This should be inlined because it is a constant + let t := f(a2) +} +// ---- +// fullInliner +// { +// { +// let a_1 := mload(2) +// let a2 := 2 +// let r := f(a_1) +// let f_a := a2 +// let f_b +// let f_x := mload(f_a) +// f_b := sload(f_x) +// let f_c := 3 +// mstore(mul(f_a, f_b), mload(f_x)) +// let f_y := add(f_a, f_x) +// sstore(f_y, 10) +// let t := f_b +// } +// function f(a) -> b +// { +// let x := mload(a) +// b := sload(x) +// let c := 3 +// mstore(mul(a, b), mload(x)) +// let y := add(a, x) +// sstore(y, 10) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul new file mode 100644 index 000000000..3302a35c9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul @@ -0,0 +1,36 @@ +{ + function f(a) -> b { + let x := mload(a) + b := sload(x) + let c := 3 + mstore(mul(a, b), mload(x)) + let y := add(a, x) + sstore(y, 10) + } + // Single-use functions are always inlined. + let r := f(mload(1)) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(1) +// let f_b +// let f_x := mload(f_a) +// f_b := sload(f_x) +// let f_c := 3 +// mstore(mul(f_a, f_b), mload(f_x)) +// let f_y := add(f_a, f_x) +// sstore(f_y, 10) +// let r := f_b +// } +// function f(a) -> b +// { +// let x := mload(a) +// b := sload(x) +// let c := 3 +// mstore(mul(a, b), mload(x)) +// let y := add(a, x) +// sstore(y, 10) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul new file mode 100644 index 000000000..644e91264 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul @@ -0,0 +1,25 @@ +{ + function verylongfunctionname(verylongvariablename) -> verylongvariablename2 { + verylongvariablename2 := add(verylongvariablename, verylongvariablename) + } + // same long name + let verylongvariablename2 := 3 + mstore(0, verylongfunctionname(verylongvariablename2)) + mstore(1, verylongvariablename2) +} +// ---- +// fullInliner +// { +// { +// let verylongvariablename2_1 := 3 +// let verylongfu_verylongvariablename := verylongvariablename2_1 +// let verylongfu_verylongvariablename2 +// verylongfu_verylongvariablename2 := add(verylongfu_verylongvariablename, verylongfu_verylongvariablename) +// mstore(0, verylongfu_verylongvariablename2) +// mstore(1, verylongvariablename2_1) +// } +// function verylongfunctionname(verylongvariablename) -> verylongvariablename2 +// { +// verylongvariablename2 := add(verylongvariablename, verylongvariablename) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul new file mode 100644 index 000000000..f3d0b286b --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul @@ -0,0 +1,29 @@ +{ + function f(a, b, c) -> x { + x := add(a, b) + x := mul(x, c) + } + let y := add(mload(1), add(f(mload(2), mload(3), mload(4)), mload(5))) +} +// ---- +// fullInliner +// { +// { +// let _2 := mload(5) +// let _4 := mload(4) +// let _6 := mload(3) +// let f_a := mload(2) +// let f_b := _6 +// let f_c := _4 +// let f_x +// f_x := add(f_a, f_b) +// f_x := mul(f_x, f_c) +// let _10 := add(f_x, _2) +// let y := add(mload(1), _10) +// } +// function f(a, b, c) -> x +// { +// x := add(a, b) +// x := mul(x, c) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul new file mode 100644 index 000000000..8bc6ec58b --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul @@ -0,0 +1,31 @@ +{ + function f(a) -> x { x := add(a, a) } + function g(b, c) -> y { y := mul(mload(c), f(b)) } + let y := g(f(3), 7) +} +// ---- +// fullInliner +// { +// { +// let _1 := 7 +// let f_a := 3 +// let f_x +// f_x := add(f_a, f_a) +// let g_b := f_x +// let g_c := _1 +// let g_y +// g_y := mul(mload(g_c), f(g_b)) +// let y_1 := g_y +// } +// function f(a) -> x +// { +// x := add(a, a) +// } +// function g(b, c) -> y +// { +// let f_a_6 := b +// let f_x_7 +// f_x_7 := add(f_a_6, f_a_6) +// y := mul(mload(c), f_x_7) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul new file mode 100644 index 000000000..19ac945e5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul @@ -0,0 +1,63 @@ +{ + // This is a test for an older version where + // inlining was performed on a function + // just being called. This is a problem + // because the statemenst of the original + // function might be in an invalid state. + + function f(x) { + mstore(0, x) + mstore(7, h()) + g(10) + mstore(1, x) + } + function g(x) { + f(1) + } + function h() -> t { + t := 2 + + } + { + f(100) + } +} +// ---- +// fullInliner +// { +// { +// { +// let f_x := 100 +// mstore(0, f_x) +// mstore(7, h()) +// g(10) +// mstore(1, f_x) +// } +// } +// function f(x) +// { +// mstore(0, x) +// let h_t +// h_t := 2 +// mstore(7, h_t) +// let g_x_1 := 10 +// let g_f_x_8 := 1 +// mstore(0, g_f_x_8) +// mstore(7, h()) +// g(10) +// mstore(1, g_f_x_8) +// mstore(1, x) +// } +// function g(x_1) +// { +// let f_x_8 := 1 +// mstore(0, f_x_8) +// mstore(7, h()) +// g(10) +// mstore(1, f_x_8) +// } +// function h() -> t +// { +// t := 2 +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul new file mode 100644 index 000000000..eebdec384 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul @@ -0,0 +1,26 @@ +{ + function f(a) -> x, y { + x := mul(a, a) + y := add(a, x) + } + let r, s := f(mload(0)) + mstore(r, s) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(0) +// let f_x +// let f_y +// f_x := mul(f_a, f_a) +// f_y := add(f_a, f_x) +// let r := f_x +// mstore(r, f_y) +// } +// function f(a) -> x, y +// { +// x := mul(a, a) +// y := add(a, x) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_return.yul b/test/libyul/yulOptimizerTests/fullInliner/no_return.yul new file mode 100644 index 000000000..3708c5574 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/no_return.yul @@ -0,0 +1,18 @@ +{ + function f(a) { + sstore(a, a) + } + f(mload(0)) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(0) +// sstore(f_a, f_a) +// } +// function f(a) +// { +// sstore(a, a) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul new file mode 100644 index 000000000..9644e6c16 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul @@ -0,0 +1,43 @@ +{ + for { let x := f(0) } f(x) { x := f(x) } + { + let t := f(x) + } + function f(a) -> r { + sstore(a, 0) + r := a + } +} +// ---- +// fullInliner +// { +// { +// for { +// let f_a := 0 +// let f_r +// sstore(f_a, 0) +// f_r := f_a +// let x := f_r +// } +// f(x) +// { +// let f_a_3 := x +// let f_r_4 +// sstore(f_a_3, 0) +// f_r_4 := f_a_3 +// x := f_r_4 +// } +// { +// let f_a_6 := x +// let f_r_7 +// sstore(f_a_6, 0) +// f_r_7 := f_a_6 +// let t := f_r_7 +// } +// } +// function f(a) -> r +// { +// sstore(a, 0) +// r := a +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul new file mode 100644 index 000000000..cd9e27467 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul @@ -0,0 +1,27 @@ +// An earlier version of the inliner produced +// pop(...) statements and explicitly removed them. +// This used to test that they are removed. +{ + function f(a) -> x { + let r := mul(a, a) + x := add(r, r) + } + pop(add(f(7), 2)) +} +// ---- +// fullInliner +// { +// { +// let _1 := 2 +// let f_a := 7 +// let f_x +// let f_r := mul(f_a, f_a) +// f_x := add(f_r, f_r) +// pop(add(f_x, _1)) +// } +// function f(a) -> x +// { +// let r := mul(a, a) +// x := add(r, r) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/recursion.yul b/test/libyul/yulOptimizerTests/fullInliner/recursion.yul new file mode 100644 index 000000000..3e9a8021d --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/recursion.yul @@ -0,0 +1,18 @@ +{ + function f(a) { + f(1) + } + f(mload(0)) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(0) +// f(1) +// } +// function f(a) +// { +// f(1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/simple.yul b/test/libyul/yulOptimizerTests/fullInliner/simple.yul new file mode 100644 index 000000000..fcdf453b5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/simple.yul @@ -0,0 +1,24 @@ +{ + function f(a) -> x { + let r := mul(a, a) + x := add(r, r) + } + let y := add(f(sload(mload(2))), mload(7)) +} +// ---- +// fullInliner +// { +// { +// let _2 := mload(7) +// let f_a := sload(mload(2)) +// let f_x +// let f_r := mul(f_a, f_a) +// f_x := add(f_r, f_r) +// let y := add(f_x, _2) +// } +// function f(a) -> x +// { +// let r := mul(a, a) +// x := add(r, r) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul new file mode 100644 index 000000000..90a3e16d9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul @@ -0,0 +1,10 @@ +{ + let a := add(7, sub(mload(0), 7)) + mstore(a, 0) +} +// ---- +// fullSimplify +// { +// let _2 := 0 +// mstore(mload(_2), _2) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/constants.yul b/test/libyul/yulOptimizerTests/fullSimplify/constants.yul new file mode 100644 index 000000000..b9c7c1fcd --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/constants.yul @@ -0,0 +1,9 @@ +{ + let a := add(1, mul(3, 4)) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// mstore(0, 13) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul new file mode 100644 index 000000000..4b17d7ea1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul @@ -0,0 +1,9 @@ +{ + let a := sub(calldataload(0), calldataload(0)) + mstore(a, 0) +} +// ---- +// fullSimplify +// { +// mstore(0, 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul new file mode 100644 index 000000000..a1737efac --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul @@ -0,0 +1,10 @@ +{ + let a := sub(calldataload(1), calldataload(0)) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// mstore(_1, sub(calldataload(1), calldataload(_1))) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul new file mode 100644 index 000000000..22a358fd5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul @@ -0,0 +1,11 @@ +{ + let a := mload(0) + mstore(0, sub(a, a)) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// pop(mload(_1)) +// mstore(_1, 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul new file mode 100644 index 000000000..fa3ff07c3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul @@ -0,0 +1,13 @@ +{ + function f() -> a {} + let b := add(7, sub(f(), 7)) + mstore(b, 0) +} +// ---- +// fullSimplify +// { +// function f() -> a +// { +// } +// mstore(f(), 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul new file mode 100644 index 000000000..f1b403019 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul @@ -0,0 +1,17 @@ +{ + let x := calldataload(3) + for { let a := 10 } iszero(eq(a, sub(x, calldataload(3)))) { a := add(a, 1) } {} +} +// ---- +// fullSimplify +// { +// for { +// let a := 10 +// } +// iszero(iszero(a)) +// { +// a := add(a, 1) +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul new file mode 100644 index 000000000..a8eedef12 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul @@ -0,0 +1,17 @@ +{ + let a := calldataload(sub(7, 7)) + let b := sub(a, 0) + // Below, `b` is not eliminated, because + // we run CSE and then Simplify. + // Elimination of `b` would require another + // run of CSE afterwards. + mstore(b, eq(calldataload(0), a)) +} +// ---- +// fullSimplify +// { +// let a := calldataload(0) +// let _4 := 0 +// let b := a +// mstore(b, eq(calldataload(_4), a)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul new file mode 100644 index 000000000..bba16a944 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul @@ -0,0 +1,9 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 8))) +} +// ---- +// fullSimplify +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 255)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul new file mode 100644 index 000000000..4a6eaa526 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul @@ -0,0 +1,9 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 255))) +} +// ---- +// fullSimplify +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul new file mode 100644 index 000000000..0c5e3ed91 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul @@ -0,0 +1,14 @@ +{ + function f(a) -> b { } + mstore(0, sub(f(0), f(1))) +} +// ---- +// fullSimplify +// { +// function f(a) -> b +// { +// } +// let _2 := f(1) +// let _3 := 0 +// mstore(_3, sub(f(_3), _2)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul new file mode 100644 index 000000000..90e89fe1f --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul @@ -0,0 +1,17 @@ +{ + function f1() -> a { } + function f2() -> b { } + let c := sub(f1(), f2()) + mstore(0, c) +} +// ---- +// fullSimplify +// { +// function f1() -> a +// { +// } +// function f2() -> b +// { +// } +// mstore(0, sub(f1(), f2())) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul new file mode 100644 index 000000000..92e50ebe6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul @@ -0,0 +1,14 @@ +// Even if the functions pass the equality check, they are not movable. +{ + function f() -> a { } + let b := sub(f(), f()) + mstore(0, b) +} +// ---- +// fullSimplify +// { +// function f() -> a +// { +// } +// mstore(0, sub(f(), f())) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul new file mode 100644 index 000000000..7dcdc280e --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul @@ -0,0 +1,12 @@ +// div is eliminated, but keccak256 has side-effects. +{ + let a := div(keccak256(0, 0), 0) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// pop(keccak256(_1, _1)) +// mstore(_1, 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/operations.yul b/test/libyul/yulOptimizerTests/fullSimplify/operations.yul new file mode 100644 index 000000000..25467b629 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/operations.yul @@ -0,0 +1,44 @@ +{ + let x := mload(0) + mstore(1, mul(x, 0)) + mstore(2, div(x, 0)) + mstore(3, div(0, x)) + mstore(4, sdiv(x, 0)) + mstore(5, sdiv(0, x)) + mstore(6, and(0, x)) + mstore(7, and(x, 0)) + mstore(8, mod(0, x)) + mstore(9, mod(x, 0)) + mstore(10, lt(x, x)) + mstore(11, gt(x, x)) + mstore(12, slt(x, x)) + mstore(13, sgt(x, x)) + mstore(14, mod(x, x)) + mstore(15, and(x, not(x))) + mstore(16, and(not(x), x)) + mstore(17, or(x, not(x))) + mstore(18, or(not(x), x)) +} +// ---- +// fullSimplify +// { +// pop(mload(0)) +// mstore(1, 0) +// mstore(2, 0) +// mstore(3, 0) +// mstore(4, 0) +// mstore(5, 0) +// mstore(6, 0) +// mstore(7, 0) +// mstore(8, 0) +// mstore(9, 0) +// mstore(10, 0) +// mstore(11, 0) +// mstore(12, 0) +// mstore(13, 0) +// mstore(14, 0) +// mstore(15, 0) +// mstore(16, 0) +// mstore(17, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// mstore(18, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul b/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul new file mode 100644 index 000000000..fb916e6ae --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul @@ -0,0 +1,10 @@ +{ + let a := add(0, mload(0)) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// mstore(_1, mload(_1)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul b/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul new file mode 100644 index 000000000..714eb8602 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul @@ -0,0 +1,12 @@ +{ + let x := 7 + mstore(0, signextend(50, x)) + let y := 255 + mstore(1, signextend(0, y)) +} +// ---- +// fullSimplify +// { +// mstore(0, 7) +// mstore(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul b/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul new file mode 100644 index 000000000..a4fbb8990 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// fullSimplify +// { +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul new file mode 100644 index 000000000..a34da1980 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul @@ -0,0 +1,654 @@ +{ + let x := abi_encode_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr_to_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr(mload(0), 0x20) + let a, b, c, d := abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(mload(0x20), mload(0x40)) + sstore(a, b) + sstore(c, d) + sstore(0, x) + + function abi_decode_t_address(offset, end) -> value + { + value := cleanup_revert_t_address(calldataload(offset)) + } + function abi_decode_t_array$_t_address_$dyn_memory(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_address(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x40)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_array$_t_uint256_$2_memory(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x40) + } + } + function abi_decode_t_array$_t_uint256_$2_memory(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := 0x2 + array := allocateMemory(array_allocation_size_t_array$_t_uint256_$2_memory(length)) + let dst := array + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_uint256(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_array$_t_uint256_$dyn_memory(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_uint256(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_array$_t_uint256_$dyn_memory_ptr(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_uint256(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_contract$_C_$55(offset, end) -> value + { + value := cleanup_revert_t_contract$_C_$55(calldataload(offset)) + } + function abi_decode_t_struct$_S_$11_memory_ptr(headStart, end) -> value + { + if slt(sub(end, headStart), 0x60) + { + revert(0, 0) + } + value := allocateMemory(0x60) + { + let offset := 0 + mstore(add(value, 0x0), abi_decode_t_uint256(add(headStart, offset), end)) + } + { + let offset := calldataload(add(headStart, 32)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + mstore(add(value, 0x20), abi_decode_t_array$_t_uint256_$dyn_memory(add(headStart, offset), end)) + } + { + let offset := calldataload(add(headStart, 64)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + mstore(add(value, 0x40), abi_decode_t_array$_t_address_$dyn_memory(add(headStart, offset), end)) + } + } + function abi_decode_t_uint256(offset, end) -> value + { + value := cleanup_revert_t_uint256(calldataload(offset)) + } + function abi_decode_t_uint8(offset, end) -> value + { + value := cleanup_revert_t_uint8(calldataload(offset)) + } + function abi_decode_tuple_t_contract$_C_$55t_uint8(headStart, dataEnd) -> value0, value1 + { + if slt(sub(dataEnd, headStart), 64) + { + revert(0, 0) + } + { + let offset := 0 + value0 := abi_decode_t_contract$_C_$55(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value1 := abi_decode_t_uint8(add(headStart, offset), dataEnd) + } + } + function abi_decode_tuple_t_struct$_S_$11_memory_ptrt_uint256(headStart, dataEnd) -> value0, value1 + { + if slt(sub(dataEnd, headStart), 64) + { + revert(0, 0) + } + { + let offset := calldataload(add(headStart, 0)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + value0 := abi_decode_t_struct$_S_$11_memory_ptr(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value1 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + } + function abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(headStart, dataEnd) -> value0, value1, value2, value3 + { + if slt(sub(dataEnd, headStart), 128) + { + revert(0, 0) + } + { + let offset := 0 + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value1 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + { + let offset := calldataload(add(headStart, 64)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + value2 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(headStart, offset), dataEnd) + } + { + let offset := calldataload(add(headStart, 96)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(headStart, offset), dataEnd) + } + } + function abi_encode_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr_to_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr(value, pos) -> end + { + let length := array_length_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(value) + mstore(pos, length) + pos := add(pos, 0x20) + let srcPtr := array_dataslot_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(value) + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + abi_encode_t_array$_t_contract$_C_$55_$3_memory_to_t_array$_t_address_$3_memory_ptr(mload(srcPtr), pos) + srcPtr := array_nextElement_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(srcPtr) + pos := add(pos, 0x60) + } + end := pos + } + function abi_encode_t_array$_t_contract$_C_$55_$3_memory_to_t_array$_t_address_$3_memory_ptr(value, pos) + { + let length := array_length_t_array$_t_contract$_C_$55_$3_memory(value) + let srcPtr := array_dataslot_t_array$_t_contract$_C_$55_$3_memory(value) + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + abi_encode_t_contract$_C_$55_to_t_address(mload(srcPtr), pos) + srcPtr := array_nextElement_t_array$_t_contract$_C_$55_$3_memory(srcPtr) + pos := add(pos, 0x20) + } + } + function abi_encode_t_bool_to_t_bool(value, pos) + { + mstore(pos, cleanup_assert_t_bool(value)) + } + function abi_encode_t_contract$_C_$55_to_t_address(value, pos) + { + mstore(pos, convert_t_contract$_C_$55_to_t_address(value)) + } + function abi_encode_t_uint16_to_t_uint16(value, pos) + { + mstore(pos, cleanup_assert_t_uint16(value)) + } + function abi_encode_t_uint24_to_t_uint24(value, pos) + { + mstore(pos, cleanup_assert_t_uint24(value)) + } + function abi_encode_tuple_t_bool__to_t_bool_(headStart, value0) -> tail + { + tail := add(headStart, 32) + abi_encode_t_bool_to_t_bool(value0, add(headStart, 0)) + } + function abi_encode_tuple_t_uint16_t_uint24_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr__to_t_uint16_t_uint24_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr_(headStart, value2, value1, value0) -> tail + { + tail := add(headStart, 96) + abi_encode_t_uint16_to_t_uint16(value0, add(headStart, 0)) + abi_encode_t_uint24_to_t_uint24(value1, add(headStart, 32)) + mstore(add(headStart, 64), sub(tail, headStart)) + tail := abi_encode_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr_to_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr(value2, tail) + } + function allocateMemory(size) -> memPtr + { + memPtr := mload(64) + let newFreePtr := add(memPtr, size) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) + { + revert(0, 0) + } + mstore(64, newFreePtr) + } + function array_allocation_size_t_array$_t_address_$dyn_memory(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_allocation_size_t_array$_t_uint256_$2_memory(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + } + function array_allocation_size_t_array$_t_uint256_$dyn_memory(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_dataslot_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(memPtr) -> dataPtr + { + dataPtr := add(memPtr, 0x20) + } + function array_dataslot_t_array$_t_contract$_C_$55_$3_memory(memPtr) -> dataPtr + { + dataPtr := memPtr + } + function array_length_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(value) -> length + { + length := mload(value) + } + function array_length_t_array$_t_contract$_C_$55_$3_memory(value) -> length + { + length := 0x3 + } + function array_nextElement_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(memPtr) -> nextPtr + { + nextPtr := add(memPtr, 0x20) + } + function array_nextElement_t_array$_t_contract$_C_$55_$3_memory(memPtr) -> nextPtr + { + nextPtr := add(memPtr, 0x20) + } + function cleanup_assert_t_address(value) -> cleaned + { + cleaned := cleanup_assert_t_uint160(value) + } + function cleanup_assert_t_bool(value) -> cleaned + { + cleaned := iszero(iszero(value)) + } + function cleanup_assert_t_uint16(value) -> cleaned + { + cleaned := and(value, 0xFFFF) + } + function cleanup_assert_t_uint160(value) -> cleaned + { + cleaned := and(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + } + function cleanup_assert_t_uint24(value) -> cleaned + { + cleaned := and(value, 0xFFFFFF) + } + function cleanup_revert_t_address(value) -> cleaned + { + cleaned := cleanup_assert_t_uint160(value) + } + function cleanup_revert_t_contract$_C_$55(value) -> cleaned + { + cleaned := cleanup_assert_t_address(value) + } + function cleanup_revert_t_uint256(value) -> cleaned + { + cleaned := value + } + function cleanup_revert_t_uint8(value) -> cleaned + { + cleaned := and(value, 0xFF) + } + function convert_t_contract$_C_$55_to_t_address(value) -> converted + { + converted := convert_t_contract$_C_$55_to_t_uint160(value) + } + function convert_t_contract$_C_$55_to_t_uint160(value) -> converted + { + converted := cleanup_assert_t_uint160(value) + } +} +// ---- +// fullSuite +// { +// { +// let _1 := 0x20 +// let _2 := 0 +// let _485 := mload(_2) +// let abi_encode_pos := _1 +// let abi_encode_length_68 := mload(_485) +// mstore(_1, abi_encode_length_68) +// let abi_encode_pos_590 := 64 +// abi_encode_pos := abi_encode_pos_590 +// let abi_encode_srcPtr := add(_485, _1) +// for { +// let abi_encode_i_69 := _2 +// } +// lt(abi_encode_i_69, abi_encode_length_68) +// { +// abi_encode_i_69 := add(abi_encode_i_69, 1) +// } +// { +// let _931 := mload(abi_encode_srcPtr) +// let abi_encode_pos_71_1037 := abi_encode_pos +// let abi_encode_length_72_1038 := 0x3 +// let abi_encode_srcPtr_73_1039 := _931 +// for { +// let abi_encode_i_74_1040 := _2 +// } +// lt(abi_encode_i_74_1040, abi_encode_length_72_1038) +// { +// abi_encode_i_74_1040 := add(abi_encode_i_74_1040, 1) +// } +// { +// mstore(abi_encode_pos_71_1037, and(mload(abi_encode_srcPtr_73_1039), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) +// abi_encode_srcPtr_73_1039 := add(abi_encode_srcPtr_73_1039, _1) +// abi_encode_pos_71_1037 := add(abi_encode_pos_71_1037, _1) +// } +// abi_encode_srcPtr := add(abi_encode_srcPtr, _1) +// abi_encode_pos := add(abi_encode_pos, 0x60) +// } +// let _933 := 0x40 +// let _487 := mload(_933) +// let _488 := mload(_1) +// let abi_decode_value0_60_618 +// let abi_decode_value0_60 := abi_decode_value0_60_618 +// let abi_decode_value1_61_619 +// let abi_decode_value1_61 := abi_decode_value1_61_619 +// let abi_decode_value2_620 +// let abi_decode_value2 := abi_decode_value2_620 +// let abi_decode_value3_621 +// let abi_decode_value3 := abi_decode_value3_621 +// if slt(sub(_487, _488), 128) +// { +// revert(_2, _2) +// } +// { +// abi_decode_value0_60 := calldataload(_488) +// } +// { +// abi_decode_value1_61 := calldataload(add(_488, 32)) +// } +// { +// let abi_decode_offset_64 := calldataload(add(_488, abi_encode_pos_590)) +// let _940 := 0xffffffffffffffff +// if gt(abi_decode_offset_64, _940) +// { +// revert(_2, _2) +// } +// let _942 := add(_488, abi_decode_offset_64) +// if iszero(slt(add(_942, 0x1f), _487)) +// { +// revert(_2, _2) +// } +// let abi_decode_length_30_1046 := calldataload(_942) +// if gt(abi_decode_length_30_1046, _940) +// { +// revert(_2, _2) +// } +// let abi_decode_array_allo__561 := mul(abi_decode_length_30_1046, _1) +// let abi_decode_array_29_279_1047 := allocateMemory(add(abi_decode_array_allo__561, _1)) +// let abi_decode_dst_31_1048 := abi_decode_array_29_279_1047 +// mstore(abi_decode_array_29_279_1047, abi_decode_length_30_1046) +// let abi_decode_offset_27_281_1049 := add(_942, _1) +// abi_decode_dst_31_1048 := add(abi_decode_array_29_279_1047, _1) +// let abi_decode_src_32_1050 := abi_decode_offset_27_281_1049 +// if gt(add(add(_942, abi_decode_array_allo__561), _1), _487) +// { +// revert(_2, _2) +// } +// for { +// let abi_decode_i_33_1052 := _2 +// } +// lt(abi_decode_i_33_1052, abi_decode_length_30_1046) +// { +// abi_decode_i_33_1052 := add(abi_decode_i_33_1052, 1) +// } +// { +// mstore(abi_decode_dst_31_1048, calldataload(abi_decode_src_32_1050)) +// abi_decode_dst_31_1048 := add(abi_decode_dst_31_1048, _1) +// abi_decode_src_32_1050 := add(abi_decode_src_32_1050, _1) +// } +// abi_decode_value2 := abi_decode_array_29_279_1047 +// } +// { +// let abi_decode_offset_65 := calldataload(add(_488, 96)) +// let _945 := 0xffffffffffffffff +// if gt(abi_decode_offset_65, _945) +// { +// revert(_2, _2) +// } +// let _947 := add(_488, abi_decode_offset_65) +// let abi_decode__489_1056 := 0x1f +// if iszero(slt(add(_947, abi_decode__489_1056), _487)) +// { +// revert(_2, _2) +// } +// let abi_decode_length_6_1058 := calldataload(_947) +// if gt(abi_decode_length_6_1058, _945) +// { +// revert(_2, _2) +// } +// let abi_decode_array_5_254_1061 := allocateMemory(add(mul(abi_decode_length_6_1058, _1), _1)) +// let abi_decode_dst_7_1062 := abi_decode_array_5_254_1061 +// mstore(abi_decode_array_5_254_1061, abi_decode_length_6_1058) +// let abi_decode_offset_3_256_1063 := add(_947, _1) +// abi_decode_dst_7_1062 := add(abi_decode_array_5_254_1061, _1) +// let abi_decode_src_8_1064 := abi_decode_offset_3_256_1063 +// if gt(add(add(_947, mul(abi_decode_length_6_1058, _933)), _1), _487) +// { +// revert(_2, _2) +// } +// for { +// let abi_decode_i_9_1068 := _2 +// } +// lt(abi_decode_i_9_1068, abi_decode_length_6_1058) +// { +// abi_decode_i_9_1068 := add(abi_decode_i_9_1068, 1) +// } +// { +// if iszero(slt(add(abi_decode_src_8_1064, abi_decode__489_1056), _487)) +// { +// revert(_2, _2) +// } +// let abi_decode_abi_decode_length_14_1069 := 0x2 +// if _2 +// { +// revert(_2, _2) +// } +// let allocateMe_memPtr_315 := mload(abi_encode_pos_590) +// let allocateMe_newFreePtr := add(allocateMe_memPtr_315, abi_encode_pos_590) +// if or(gt(allocateMe_newFreePtr, _945), lt(allocateMe_newFreePtr, allocateMe_memPtr_315)) +// { +// revert(_2, _2) +// } +// mstore(abi_encode_pos_590, allocateMe_newFreePtr) +// let abi_decode_abi_decode_dst_15_1071 := allocateMe_memPtr_315 +// let abi_decode_abi_decode_src_16_1072 := abi_decode_src_8_1064 +// if gt(add(abi_decode_src_8_1064, abi_encode_pos_590), _487) +// { +// revert(_2, _2) +// } +// for { +// let abi_decode_abi_decode_i_17_1073 := _2 +// } +// lt(abi_decode_abi_decode_i_17_1073, abi_decode_abi_decode_length_14_1069) +// { +// abi_decode_abi_decode_i_17_1073 := add(abi_decode_abi_decode_i_17_1073, 1) +// } +// { +// mstore(abi_decode_abi_decode_dst_15_1071, calldataload(abi_decode_abi_decode_src_16_1072)) +// abi_decode_abi_decode_dst_15_1071 := add(abi_decode_abi_decode_dst_15_1071, _1) +// abi_decode_abi_decode_src_16_1072 := add(abi_decode_abi_decode_src_16_1072, _1) +// } +// mstore(abi_decode_dst_7_1062, allocateMe_memPtr_315) +// abi_decode_dst_7_1062 := add(abi_decode_dst_7_1062, _1) +// abi_decode_src_8_1064 := add(abi_decode_src_8_1064, _933) +// } +// abi_decode_value3 := abi_decode_array_5_254_1061 +// } +// sstore(abi_decode_value0_60, abi_decode_value1_61) +// sstore(abi_decode_value2, abi_decode_value3) +// sstore(_2, abi_encode_pos) +// } +// function allocateMemory(size) -> memPtr +// { +// let _199 := 64 +// let memPtr_315 := mload(_199) +// memPtr := memPtr_315 +// let newFreePtr := add(memPtr_315, size) +// if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr_315)) +// { +// let _204 := 0 +// revert(_204, _204) +// } +// mstore(_199, newFreePtr) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul new file mode 100644 index 000000000..deb020688 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul @@ -0,0 +1,24 @@ +{ + function allocate(size) -> p { + p := mload(0x40) + mstore(0x40, add(p, size)) + } + function array_index_access(array, index) -> p { + p := add(array, mul(index, 0x20)) + } + pop(allocate(0x20)) + let x := allocate(0x40) + mstore(array_index_access(x, 3), 2) +} +// ---- +// fullSuite +// { +// { +// let _18 := 0x20 +// let allocate__7 := 0x40 +// mstore(allocate__7, add(mload(allocate__7), _18)) +// let allocate_p_12_31 := mload(allocate__7) +// mstore(allocate__7, add(allocate_p_12_31, allocate__7)) +// mstore(add(allocate_p_12_31, 96), 2) +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul new file mode 100644 index 000000000..f0d49d7b3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul @@ -0,0 +1,24 @@ +// yul +{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } } +// ---- +// functionGrouper +// { +// { +// let a:u256 +// { +// } +// } +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// { +// } +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul new file mode 100644 index 000000000..c830d5da7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul @@ -0,0 +1,24 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 function g() { let d:u256 } + let e:u256 +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// let c:u256 +// let e:u256 +// } +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul new file mode 100644 index 000000000..4a8be86a4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul @@ -0,0 +1,27 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { + let c:u256 + } + let d:u256 + } +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// } +// function f() +// { +// let b:u256 +// function g() +// { +// let c:u256 +// } +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul new file mode 100644 index 000000000..149a44eb8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul @@ -0,0 +1,14 @@ +// yul +{ + let a:u256 function f() {} +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// } +// function f() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/smoke.yul b/test/libyul/yulOptimizerTests/functionGrouper/smoke.yul new file mode 100644 index 000000000..650a163e7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/smoke.yul @@ -0,0 +1,7 @@ +{ } +// ---- +// functionGrouper +// { +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul new file mode 100644 index 000000000..6ea9f59d3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + { } + function f() -> x:bool { + let b:u256 := 4:u256 + { } + for {} f() {} {} + } +} +// ---- +// functionHoister +// { +// let a:u256 +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul new file mode 100644 index 000000000..1e3bc5a1a --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul @@ -0,0 +1,23 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 + function g() { let d:u256 } + let e:u256 +} +// ---- +// functionHoister +// { +// let a:u256 +// let c:u256 +// let e:u256 +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/nested.yul b/test/libyul/yulOptimizerTests/functionHoister/nested.yul new file mode 100644 index 000000000..20f094f18 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/nested.yul @@ -0,0 +1,23 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { let c:u256 } + let d:u256 + } +} +// ---- +// functionHoister +// { +// let a:u256 +// function g() +// { +// let c:u256 +// } +// function f() +// { +// let b:u256 +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/single.yul b/test/libyul/yulOptimizerTests/functionHoister/single.yul new file mode 100644 index 000000000..ba922612e --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/single.yul @@ -0,0 +1,13 @@ +// yul +{ + let a:u256 + function f() {} +} +// ---- +// functionHoister +// { +// let a:u256 +// function f() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/smoke.yul b/test/libyul/yulOptimizerTests/functionHoister/smoke.yul new file mode 100644 index 000000000..35c1ce5fb --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/smoke.yul @@ -0,0 +1,6 @@ +{ +} +// ---- +// functionHoister +// { +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/empty_block.yul b/test/libyul/yulOptimizerTests/mainFunction/empty_block.yul new file mode 100644 index 000000000..bae6bd48d --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/empty_block.yul @@ -0,0 +1,33 @@ +// yul +{ + let a:u256 + { } + function f() -> x:bool { + let b:u256 := 4:u256 + {} + for {} f() {} {} + } +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// { +// } +// } +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// { +// } +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/multi_fun_mixed.yul b/test/libyul/yulOptimizerTests/mainFunction/multi_fun_mixed.yul new file mode 100644 index 000000000..dd5caaec4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/multi_fun_mixed.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 + function g() { let d:u256 } + let e:u256 +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// let c:u256 +// let e:u256 +// } +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/nested_fun.yul b/test/libyul/yulOptimizerTests/mainFunction/nested_fun.yul new file mode 100644 index 000000000..309b97ccf --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/nested_fun.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { let c:u256} + let d:u256 + } +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// } +// function f() +// { +// let b:u256 +// function g() +// { +// let c:u256 +// } +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/sigle_fun.yul b/test/libyul/yulOptimizerTests/mainFunction/sigle_fun.yul new file mode 100644 index 000000000..fa9a8f415 --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/sigle_fun.yul @@ -0,0 +1,16 @@ +// yul +{ + let a:u256 + function f() {} +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// } +// function f() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/smoke.yul b/test/libyul/yulOptimizerTests/mainFunction/smoke.yul new file mode 100644 index 000000000..7be147467 --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/smoke.yul @@ -0,0 +1,9 @@ +// yul +{} +// ---- +// mainFunction +// { +// function main() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul new file mode 100644 index 000000000..d9bbd86d3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul @@ -0,0 +1,26 @@ +{ + for { + let a := 2 + // Should not be removed, even though you might think + // it goes out of scope + a := 3 + } a { a := add(a, 1) } + { + a := 7 + } +} +// ---- +// redundantAssignEliminator +// { +// for { +// let a := 2 +// a := 3 +// } +// a +// { +// a := add(a, 1) +// } +// { +// a := 7 +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul new file mode 100644 index 000000000..7f5e97ce8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul @@ -0,0 +1,31 @@ +{ + let x + let y + // Cannot be removed, because we might skip the loop + x := 1 + for { } calldataload(0) { } + { + // Cannot be removed + x := 2 + // Can be removed + y := 3 + } + y := 8 + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// let y +// x := 1 +// for { +// } +// calldataload(0) +// { +// } +// { +// x := 2 +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul new file mode 100644 index 000000000..65eb2838a --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul @@ -0,0 +1,27 @@ +{ + let x + // Cannot be removed, because we might run the loop only once + x := 1 + for { } calldataload(0) { } + { + mstore(x, 2) + // Cannot be removed because of the line above + x := 2 + } + x := 3 +} +// ---- +// redundantAssignEliminator +// { +// let x +// x := 1 +// for { +// } +// calldataload(0) +// { +// } +// { +// mstore(x, 2) +// x := 2 +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul new file mode 100644 index 000000000..5bb920ec3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul @@ -0,0 +1,23 @@ +{ + let r + r := 1 + function f(x, y) -> a, b { + // Can be removed, is param + x := 1 + y := 2 + // Cannot be removed, is return param + a := 3 + b := 4 + } + r := 2 +} +// ---- +// redundantAssignEliminator +// { +// let r +// function f(x, y) -> a, b +// { +// a := 3 +// b := 4 +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul new file mode 100644 index 000000000..958bfc661 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul @@ -0,0 +1,24 @@ +{ + let c + let d + c := calldataload(0) + d := 1 + if c { + d := 2 + } + // This enforces that none of the assignments above can be removed. + mstore(0, d) +} +// ---- +// redundantAssignEliminator +// { +// let c +// let d +// c := calldataload(0) +// d := 1 +// if c +// { +// d := 2 +// } +// mstore(0, d) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul new file mode 100644 index 000000000..e47c31d1c --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul @@ -0,0 +1,24 @@ +{ + let c + let d + c := calldataload(0) + // This assignment will be overwritten in all branches and thus can be removed. + d := 1 + if c { + d := 2 + } + d := 3 + mstore(0, d) +} +// ---- +// redundantAssignEliminator +// { +// let c +// let d +// c := calldataload(0) +// if c +// { +// } +// d := 3 +// mstore(0, d) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul new file mode 100644 index 000000000..00065ed25 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul @@ -0,0 +1,25 @@ +{ + let c + let d + c := calldataload(0) + d := 1 + if c { + // Uses the assignment above + d := d + } + d := 3 + mstore(0, d) +} +// ---- +// redundantAssignEliminator +// { +// let c +// let d +// c := calldataload(0) +// d := 1 +// if c +// { +// } +// d := 3 +// mstore(0, d) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul new file mode 100644 index 000000000..26bcfc725 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul @@ -0,0 +1,19 @@ +{ + function f() -> a, b {} + let x, y + x := 1 + x := 2 + // Will not be used, but is a multi-assign, so not removed. + x, y := f() + x := 3 + y := 4 +} +// ---- +// redundantAssignEliminator +// { +// function f() -> a, b +// { +// } +// let x, y +// x, y := f() +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul new file mode 100644 index 000000000..cf6461268 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul @@ -0,0 +1,15 @@ +{ + let a := 2 + a := 7 + let b := 8 + b := a + a := b +} +// ---- +// redundantAssignEliminator +// { +// let a := 2 +// a := 7 +// let b := 8 +// b := a +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul new file mode 100644 index 000000000..ae3e5226d --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul @@ -0,0 +1,11 @@ +{ + let a + a := 0 + a := mload(0) +} +// ---- +// redundantAssignEliminator +// { +// let a +// a := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul new file mode 100644 index 000000000..702f854df --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul @@ -0,0 +1,16 @@ +{ + let a + { + let b + b := 2 + a := 2 + } +} +// ---- +// redundantAssignEliminator +// { +// let a +// { +// let b +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul new file mode 100644 index 000000000..913a76941 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul @@ -0,0 +1,10 @@ +{ + let a + a := 1 + a := 2 +} +// ---- +// redundantAssignEliminator +// { +// let a +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul new file mode 100644 index 000000000..962655764 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul @@ -0,0 +1,22 @@ +{ + let x + // Will be overwritten in all branches + x := 1 + switch calldataload(0) + case 0 { x := 2 } + default { x := 3 } + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// switch calldataload(0) +// case 0 { +// x := 2 +// } +// default { +// x := 3 +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul new file mode 100644 index 000000000..cbe859ed6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul @@ -0,0 +1,19 @@ +{ + let x + // Will NOT be overwritten in all branches + x := 1 + switch calldataload(0) + case 0 { x := 2 } + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// x := 1 +// switch calldataload(0) +// case 0 { +// x := 2 +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul new file mode 100644 index 000000000..1a3b26ebd --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul @@ -0,0 +1,23 @@ +{ + let x + // Will be used in some and overwritten in others + x := 1 + switch calldataload(0) + case 0 { x := 2 } + default { mstore(x, 1) } + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// x := 1 +// switch calldataload(0) +// case 0 { +// x := 2 +// } +// default { +// mstore(x, 1) +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul new file mode 100644 index 000000000..cc78b74d3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul @@ -0,0 +1,16 @@ +{ + let x + // Not referenced anywhere. + x := 1 + switch calldataload(0) + case 0 { mstore(0, 1) } +} +// ---- +// redundantAssignEliminator +// { +// let x +// switch calldataload(0) +// case 0 { +// mstore(0, 1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul new file mode 100644 index 000000000..dbd1ee636 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul @@ -0,0 +1,21 @@ +{ + let a := 1 + for { pop(a) } a { pop(a) } { + pop(a) + } +} +// ---- +// rematerialiser +// { +// let a := 1 +// for { +// pop(1) +// } +// 1 +// { +// pop(1) +// } +// { +// pop(1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul new file mode 100644 index 000000000..6a52e0455 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul @@ -0,0 +1,25 @@ +{ + let a := 1 + for { pop(a) } a { pop(a) } { + a := 7 + let c := a + } + let x := a +} +// ---- +// rematerialiser +// { +// let a := 1 +// for { +// pop(1) +// } +// a +// { +// pop(7) +// } +// { +// a := 7 +// let c := 7 +// } +// let x := a +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul new file mode 100644 index 000000000..fc8164195 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul @@ -0,0 +1,23 @@ +{ + let b := 0 + for { let a := 1 pop(a) } a { pop(a) } { + b := 1 pop(a) + } +} +// ---- +// rematerialiser +// { +// let b := 0 +// for { +// let a := 1 +// pop(1) +// } +// 1 +// { +// pop(1) +// } +// { +// b := 1 +// pop(1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul new file mode 100644 index 000000000..3d916890e --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul @@ -0,0 +1,24 @@ +{ + let b := 0 + for { let a := 1 pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { + b := 1 pop(a) + } +} +// ---- +// rematerialiser +// { +// let b := 0 +// for { +// let a := 1 +// pop(1) +// } +// lt(a, 0) +// { +// pop(a) +// a := add(a, 3) +// } +// { +// b := 1 +// pop(a) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_if.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_if.yul new file mode 100644 index 000000000..c148c2f2b --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_if.yul @@ -0,0 +1,18 @@ +{ + let a := 1 + let b := 2 + if b { pop(b) b := a } + let c := b +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 2 +// if 2 +// { +// pop(2) +// b := 1 +// } +// let c := b +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_switch.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_switch.yul new file mode 100644 index 000000000..8f70a79d9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_switch.yul @@ -0,0 +1,24 @@ +{ + let a := 1 + let b := 2 + switch number() + case 1 { b := a } + default { let x := a let y := b b := a } + pop(add(a, b)) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 2 +// switch number() +// case 1 { +// b := 1 +// } +// default { +// let x := 1 +// let y := b +// b := 1 +// } +// pop(add(1, b)) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul b/test/libyul/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul new file mode 100644 index 000000000..891a5043b --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul @@ -0,0 +1,19 @@ +// Cannot replace `let b := x` by `let b := a` since a is out of scope. +{ + let x + { + let a := sload(0) + x := a + } + let b := x +} +// ---- +// rematerialiser +// { +// let x +// { +// let a := sload(0) +// x := a +// } +// let b := x +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul new file mode 100644 index 000000000..016fa0d7d --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul @@ -0,0 +1,10 @@ +{ + let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) + let b := x +} +// ---- +// rematerialiser +// { +// let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) +// let b := x +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul new file mode 100644 index 000000000..d95dc1fc5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul @@ -0,0 +1,10 @@ +{ + let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) + let b := x +} +// ---- +// rematerialiser +// { +// let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) +// let b := add(mul(calldataload(2), calldataload(4)), calldatasize()) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/expression.yul b/test/libyul/yulOptimizerTests/rematerialiser/expression.yul new file mode 100644 index 000000000..a801677d9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/expression.yul @@ -0,0 +1,10 @@ +{ + let a := add(mul(calldatasize(), 2), number()) + let b := add(a, a) +} +// ---- +// rematerialiser +// { +// let a := add(mul(calldatasize(), 2), number()) +// let b := add(add(mul(calldatasize(), 2), number()), add(mul(calldatasize(), 2), number())) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul new file mode 100644 index 000000000..9a041dfc0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul @@ -0,0 +1,18 @@ +{ + function f(x) -> y {} + let a := 1 + let b := f(a) + let c := a + mstore(add(a, b), c) +} +// ---- +// rematerialiser +// { +// function f(x) -> y +// { +// } +// let a := 1 +// let b := f(1) +// let c := 1 +// mstore(add(1, b), 1) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/non_movable_instruction.yul b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_instruction.yul new file mode 100644 index 000000000..8767abc95 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_instruction.yul @@ -0,0 +1,14 @@ +{ + let a := 1 + let b := mload(a) + let c := a + mstore(add(a, b), c) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := mload(1) +// let c := 1 +// mstore(add(1, b), 1) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul new file mode 100644 index 000000000..471246587 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul @@ -0,0 +1,21 @@ +{ + let a := extcodesize(0) + let b := a + let c := b + a := 2 + let d := add(b, c) + pop(a) pop(b) pop(c) pop(d) +} +// ---- +// rematerialiser +// { +// let a := extcodesize(0) +// let b := a +// let c := a +// a := 2 +// let d := add(b, c) +// pop(2) +// pop(b) +// pop(c) +// pop(add(b, c)) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/reassignment.yul b/test/libyul/yulOptimizerTests/rematerialiser/reassignment.yul new file mode 100644 index 000000000..13238780f --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/reassignment.yul @@ -0,0 +1,19 @@ +{ + let a := 1 + pop(a) + if a { a := 2 } + let b := mload(a) + pop(b) +} +// ---- +// rematerialiser +// { +// let a := 1 +// pop(1) +// if 1 +// { +// a := 2 +// } +// let b := mload(a) +// pop(b) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/smoke.yul b/test/libyul/yulOptimizerTests/rematerialiser/smoke.yul new file mode 100644 index 000000000..2423db327 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/smoke.yul @@ -0,0 +1,5 @@ +{} +// ---- +// rematerialiser +// { +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/trivial.yul b/test/libyul/yulOptimizerTests/rematerialiser/trivial.yul new file mode 100644 index 000000000..d29ea98ad --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/trivial.yul @@ -0,0 +1,12 @@ +{ + let a := 1 + let b := a + mstore(0, b) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 1 +// mstore(0, 1) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul new file mode 100644 index 000000000..7d35fee04 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul @@ -0,0 +1,13 @@ +// We cannot substitute `a` in `let b := a` +{ + let a := extcodesize(0) + a := mul(a, 2) + let b := a +} +// ---- +// rematerialiser +// { +// let a := extcodesize(0) +// a := mul(a, 2) +// let b := a +// } diff --git a/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul b/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul new file mode 100644 index 000000000..ad609c74b --- /dev/null +++ b/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul @@ -0,0 +1,26 @@ +{ + if mul(add(calldataload(0), 2), 3) { + for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { + let b := mul(add(a, 2), 4) + sstore(b, mul(b, 2)) + } + } +} +// ---- +// splitJoin +// { +// if mul(add(calldataload(0), 2), 3) +// { +// for { +// let a := 2 +// } +// lt(a, mload(a)) +// { +// a := add(a, mul(a, 2)) +// } +// { +// let b := mul(add(a, 2), 4) +// sstore(b, mul(b, 2)) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/splitJoin/functions.yul b/test/libyul/yulOptimizerTests/splitJoin/functions.yul new file mode 100644 index 000000000..549fc5503 --- /dev/null +++ b/test/libyul/yulOptimizerTests/splitJoin/functions.yul @@ -0,0 +1,30 @@ +{ + let x := f(0) + function f(y) -> r { + r := mload(mul(6, add(y, 0x20))) + } + for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { + let b := mul(add(a, f(a)), 4) + sstore(b, mul(b, 2)) + } +} +// ---- +// splitJoin +// { +// let x := f(0) +// function f(y) -> r +// { +// r := mload(mul(6, add(y, 0x20))) +// } +// for { +// let a := 2 +// } +// lt(a, mload(a)) +// { +// a := add(a, mul(a, 2)) +// } +// { +// let b := mul(add(a, f(a)), 4) +// sstore(b, mul(b, 2)) +// } +// } diff --git a/test/libyul/yulOptimizerTests/splitJoin/smoke.yul b/test/libyul/yulOptimizerTests/splitJoin/smoke.yul new file mode 100644 index 000000000..4b1330293 --- /dev/null +++ b/test/libyul/yulOptimizerTests/splitJoin/smoke.yul @@ -0,0 +1,5 @@ +{} +// ---- +// splitJoin +// { +// } diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul new file mode 100644 index 000000000..d2408343b --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul @@ -0,0 +1,35 @@ +{ + function copy(from, to) -> length { + length := mload(from) + mstore(to, length) + from := add(from, 0x20) + to := add(to, 0x20) + for { let x := 1 } lt(x, length) { x := add(x, 0x20) } { + mstore(add(to, x), mload(add(from, x))) + } + } +} +// ---- +// ssaPlusCleanup +// { +// function copy(from, to) -> length +// { +// let length_1 := mload(from) +// length := length_1 +// mstore(to, length_1) +// let from_2 := add(from, 0x20) +// let to_3 := add(to, 0x20) +// for { +// let x_4 := 1 +// let x := x_4 +// } +// lt(x, length_1) +// { +// let x_5 := add(x, 0x20) +// x := x_5 +// } +// { +// mstore(add(to_3, x), mload(add(from_2, x))) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign.yul new file mode 100644 index 000000000..ddb33aa01 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign.yul @@ -0,0 +1,17 @@ +{ + let a := 1 + a := 2 + a := 3 + a := 4 + mstore(0, a) +} +// ---- +// ssaPlusCleanup +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := 2 +// let a_3 := 3 +// let a_4 := 4 +// mstore(0, a_4) +// } diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign_with_use.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign_with_use.yul new file mode 100644 index 000000000..67a6c5d3e --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign_with_use.yul @@ -0,0 +1,17 @@ +{ + let a := 1 + a := add(a, 2) + a := add(a, 3) + a := mload(add(a, 4)) + mstore(0, a) +} +// ---- +// ssaPlusCleanup +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := add(a_1, 2) +// let a_3 := add(a_2, 3) +// let a_4 := mload(add(a_3, 4)) +// mstore(0, a_4) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/branches.yul b/test/libyul/yulOptimizerTests/ssaTransform/branches.yul new file mode 100644 index 000000000..c089fe708 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/branches.yul @@ -0,0 +1,25 @@ +{ + let a := 1 + a := add(a, 1) + if a { + a := add(a, 1) + } + a := add(a, 1) + mstore(a, 1) +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := add(a_1, 1) +// a := a_2 +// if a_2 +// { +// let a_3 := add(a_2, 1) +// a := a_3 +// } +// let a_4 := add(a, 1) +// a := a_4 +// mstore(a_4, 1) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_body.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_body.yul new file mode 100644 index 000000000..416403465 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_body.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + for { mstore(0, a) } a { mstore(0, a) } + { + a := add(a, 3) + } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// for { +// mstore(0, a_1) +// } +// a +// { +// mstore(0, a) +// } +// { +// let a_2 := add(a, 3) +// a := a_2 +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_init.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_init.yul new file mode 100644 index 000000000..821a5b2a6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_init.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + for { a := add(a, 3) } a { mstore(0, a) } + { + mstore(0, a) + } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// for { +// let a_2 := add(a_1, 3) +// a := a_2 +// } +// a +// { +// mstore(0, a) +// } +// { +// mstore(0, a) +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_post.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_post.yul new file mode 100644 index 000000000..1fc075bc1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_post.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + for { mstore(0, a) } a { a := add(a, 3) } + { + mstore(0, a) + } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// for { +// mstore(0, a_1) +// } +// a +// { +// let a_2 := add(a, 3) +// a := a_2 +// } +// { +// mstore(0, a) +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_simple.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_simple.yul new file mode 100644 index 000000000..273d3811a --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_simple.yul @@ -0,0 +1,47 @@ +{ + let a := mload(0) + a := add(a, 1) + if a { + a := add(a, 2) + } + { + a := add(a, 4) + } + for { a := add(a, 3) } a { a := add(a, 6) } + { + a := add(a, 12) + } + a := add(a, 8) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// let a_2 := add(a_1, 1) +// a := a_2 +// if a_2 +// { +// let a_3 := add(a_2, 2) +// a := a_3 +// } +// { +// let a_4 := add(a, 4) +// a := a_4 +// } +// for { +// let a_5 := add(a, 3) +// a := a_5 +// } +// a +// { +// let a_7 := add(a, 6) +// a := a_7 +// } +// { +// let a_6 := add(a, 12) +// a := a_6 +// } +// let a_8 := add(a, 8) +// a := a_8 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/function.yul b/test/libyul/yulOptimizerTests/ssaTransform/function.yul new file mode 100644 index 000000000..995d16cc7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/function.yul @@ -0,0 +1,23 @@ +{ + function f(a, b) -> c, d { + b := add(b, a) + c := add(c, b) + d := add(d, c) + a := add(a, d) + } +} +// ---- +// ssaTransform +// { +// function f(a, b) -> c, d +// { +// let b_1 := add(b, a) +// b := b_1 +// let c_2 := add(c, b_1) +// c := c_2 +// let d_3 := add(d, c_2) +// d := d_3 +// let a_4 := add(a, d_3) +// a := a_4 +// } +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/nested.yul b/test/libyul/yulOptimizerTests/ssaTransform/nested.yul new file mode 100644 index 000000000..49a769537 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/nested.yul @@ -0,0 +1,32 @@ +{ + let a := 1 + a := 2 + let b := 3 + b := 4 + { + // b is not reassigned here + a := 3 + a := 4 + } + a := add(b, a) +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := 2 +// a := a_2 +// let b_3 := 3 +// let b := b_3 +// let b_4 := 4 +// b := b_4 +// { +// let a_5 := 3 +// a := a_5 +// let a_6 := 4 +// a := a_6 +// } +// let a_7 := add(b_4, a) +// a := a_7 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/notransform.yul b/test/libyul/yulOptimizerTests/ssaTransform/notransform.yul new file mode 100644 index 000000000..297905c60 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/notransform.yul @@ -0,0 +1,19 @@ +{ + let a := 1 + // this should not be transformed + let b := add(a, 2) + let c + mstore(c, 0) + c := add(a, b) +} +// ---- +// ssaTransform +// { +// let a := 1 +// let b := add(a, 2) +// let c_1 +// let c := c_1 +// mstore(c_1, 0) +// let c_2 := add(a, b) +// c := c_2 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/simple.yul b/test/libyul/yulOptimizerTests/ssaTransform/simple.yul new file mode 100644 index 000000000..6dbce7292 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/simple.yul @@ -0,0 +1,18 @@ +{ + let a := 1 + a := 2 + a := 3 + a := 4 +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := 2 +// a := a_2 +// let a_3 := 3 +// a := a_3 +// let a_4 := 4 +// a := a_4 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/switch.yul b/test/libyul/yulOptimizerTests/ssaTransform/switch.yul new file mode 100644 index 000000000..bc9b55bbb --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/switch.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + // This could be more efficient: + // all cases could use the value of the variable from just before + // the switch and not just the first + switch a + case 0 { a := add(a, 4) } + default { a := add(a, 8) } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// switch a_1 +// case 0 { +// let a_2 := add(a_1, 4) +// a := a_2 +// } +// default { +// let a_3 := add(a, 8) +// a := a_3 +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/used.yul b/test/libyul/yulOptimizerTests/ssaTransform/used.yul new file mode 100644 index 000000000..ad686ca11 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/used.yul @@ -0,0 +1,39 @@ +{ + let a := 1 + mstore(a, 0) + a := 2 + mstore(a, 0) + { + mstore(a, 0) + a := 3 + mstore(a, 0) + a := 4 + mstore(a, 0) + } + mstore(a, 0) + a := 4 + mstore(a, 0) +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// mstore(a_1, 0) +// let a_2 := 2 +// a := a_2 +// mstore(a_2, 0) +// { +// mstore(a_2, 0) +// let a_3 := 3 +// a := a_3 +// mstore(a_3, 0) +// let a_4 := 4 +// a := a_4 +// mstore(a_4, 0) +// } +// mstore(a, 0) +// let a_5 := 4 +// a := a_5 +// mstore(a_5, 0) +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/functions.yul b/test/libyul/yulOptimizerTests/unusedPruner/functions.yul new file mode 100644 index 000000000..ec9cdda83 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/functions.yul @@ -0,0 +1,8 @@ +{ + function f() { let a := 1 } + function g() { f() } +} +// ---- +// unusedPruner +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul new file mode 100644 index 000000000..4ed6dd2c5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul @@ -0,0 +1,11 @@ +{ + let a := 1 + a := 4 + let b := 1 +} +// ---- +// unusedPruner +// { +// let a := 1 +// a := 4 +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul new file mode 100644 index 000000000..94d101e9b --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul @@ -0,0 +1,16 @@ +{ + let a, b + function f() -> x { } + a := f() + b := 1 +} +// ---- +// unusedPruner +// { +// let a, b +// function f() -> x +// { +// } +// a := f() +// b := 1 +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul new file mode 100644 index 000000000..a14dc28ce --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul @@ -0,0 +1,16 @@ +{ + let a + let b + function f() -> x, y { } + a, b := f() +} +// ---- +// unusedPruner +// { +// let a +// let b +// function f() -> x, y +// { +// } +// a, b := f() +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul new file mode 100644 index 000000000..fe94edb8f --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul @@ -0,0 +1,12 @@ +{ + let x, y + x := 1 + y := 2 +} +// ---- +// unusedPruner +// { +// let x, y +// x := 1 +// y := 2 +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul new file mode 100644 index 000000000..3cf35007b --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul @@ -0,0 +1,7 @@ +{ + let x, y +} +// ---- +// unusedPruner +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul new file mode 100644 index 000000000..adabac87b --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul @@ -0,0 +1,12 @@ +{ + function f() -> x, y { } + let a, b := f() +} +// ---- +// unusedPruner +// { +// function f() -> x, y +// { +// } +// let a, b := f() +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul new file mode 100644 index 000000000..5db0ade9a --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul @@ -0,0 +1,10 @@ +{ + let x, y + x := 1 +} +// ---- +// unusedPruner +// { +// let x, y +// x := 1 +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/pop.yul b/test/libyul/yulOptimizerTests/unusedPruner/pop.yul new file mode 100644 index 000000000..542070f9f --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/pop.yul @@ -0,0 +1,8 @@ +{ + let a := 1 + pop(a) +} +// ---- +// unusedPruner +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul b/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul new file mode 100644 index 000000000..ca2ed9422 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// unusedPruner +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul b/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul new file mode 100644 index 000000000..9b4cf9fdb --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul @@ -0,0 +1,10 @@ +{ + let a := 1 + let b := 1 + mstore(0, 1) +} +// ---- +// unusedPruner +// { +// mstore(0, 1) +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul new file mode 100644 index 000000000..54fea2fbe --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul @@ -0,0 +1,17 @@ +{ + let a := 4 + let x + if a { + x := 2 + } +} +// ---- +// varDeclPropagator +// { +// let a := 4 +// let x +// if a +// { +// x := 2 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul new file mode 100644 index 000000000..ed8d33b46 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul @@ -0,0 +1,13 @@ +{ + function f() -> a, b, c {} + let x, y, z + z, x, y := f() +} +// ---- +// varDeclPropagator +// { +// function f() -> a, b, c +// { +// } +// let z, x, y := f() +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul new file mode 100644 index 000000000..ca9215000 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul @@ -0,0 +1,11 @@ +{ + let a + a := 4 + a := 5 +} +// ---- +// varDeclPropagator +// { +// let a := 4 +// a := 5 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul new file mode 100644 index 000000000..3affcac69 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul @@ -0,0 +1,10 @@ +{ + let a, b + a := mload(0) +} +// ---- +// varDeclPropagator +// { +// let b +// let a := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul new file mode 100644 index 000000000..d89590406 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul @@ -0,0 +1,9 @@ +{ + let f + f := mload(0) +} +// ---- +// varDeclPropagator +// { +// let f := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul new file mode 100644 index 000000000..e8c91e109 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul @@ -0,0 +1,11 @@ +{ + let a, b + a := mload(0) + b := mload(1) +} +// ---- +// varDeclPropagator +// { +// let a := mload(0) +// let b := mload(1) +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul new file mode 100644 index 000000000..5312112a4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul @@ -0,0 +1,12 @@ +{ + let b + let a := b + b := 1 +} +// ---- +// varDeclPropagator +// { +// let b +// let a := b +// b := 1 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul new file mode 100644 index 000000000..e27785dd5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul @@ -0,0 +1,16 @@ +{ + function f(x) {} + let a + f(a) + a := 4 +} +// ---- +// varDeclPropagator +// { +// function f(x) +// { +// } +// let a +// f(a) +// a := 4 +// } diff --git a/test/solcjsTests.sh b/test/solcjsTests.sh index 27797cb45..e0bbc5dfc 100755 --- a/test/solcjsTests.sh +++ b/test/solcjsTests.sh @@ -53,6 +53,11 @@ DIR=$(mktemp -d) rm -f soljson.js cp "$SOLJSON" soljson.js + # ensure to use always 0.5.0 sources + # FIXME: should be removed once the version bump in this repo is done + rm -rf test/DAO040 + cp -R test/DAO test/DAO040 + # Update version (needed for some tests) echo "Updating package.json to version $VERSION" npm version --no-git-tag-version $VERSION diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 11714017f..19a1d9581 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -1,5 +1,10 @@ add_executable(solfuzzer fuzzer.cpp) target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_SYSTEM_LIBRARIES}) -add_executable(isoltest isoltest.cpp ../Options.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/AnalysisFramework.cpp) +add_executable(yulopti yulopti.cpp) +target_link_libraries(yulopti PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_SYSTEM_LIBRARIES}) + +add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../libsolidity/TestCase.cpp ../libsolidity/SyntaxTest.cpp + ../libsolidity/AnalysisFramework.cpp ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp + ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libyul/YulOptimizerTest.cpp) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/tools/fuzzer.cpp b/test/tools/fuzzer.cpp index 71f38b673..8633454c5 100644 --- a/test/tools/fuzzer.cpp +++ b/test/tools/fuzzer.cpp @@ -28,6 +28,7 @@ #include #include +#include #include using namespace std; @@ -48,15 +49,17 @@ string contains(string const& _haystack, vector const& _needles) return ""; } -void testConstantOptimizer() +void testConstantOptimizer(string const& input) { if (!quiet) cout << "Testing constant optimizer" << endl; vector numbers; - while (!cin.eof()) + stringstream sin(input); + + while (!sin.eof()) { h256 data; - cin.read(reinterpret_cast(data.data()), 32); + sin.read(reinterpret_cast(data.data()), 32); numbers.push_back(u256(data)); } if (!quiet) @@ -84,13 +87,9 @@ void testConstantOptimizer() } } -void testStandardCompiler() +void runCompiler(string input) { - if (!quiet) - cout << "Testing compiler via JSON interface." << endl; - string input = readStandardInput(); - - string outputString(compileStandard(input.c_str(), NULL)); + string outputString(solidity_compile(input.c_str(), nullptr)); Json::Value output; if (!jsonParseStrict(outputString, output)) { @@ -112,48 +111,35 @@ void testStandardCompiler() } } -void testCompiler(bool optimize) +void testStandardCompiler(string const& input) +{ + if (!quiet) + cout << "Testing compiler via JSON interface." << endl; + + runCompiler(input); +} + +void testCompiler(string const& input, bool optimize) { if (!quiet) cout << "Testing compiler " << (optimize ? "with" : "without") << " optimizer." << endl; - string input = readStandardInput(); - string outputString(compileJSON(input.c_str(), optimize)); - Json::Value outputJson; - if (!jsonParseStrict(outputString, outputJson)) - { - cout << "Compiler produced invalid JSON output." << endl; - abort(); - } - if (outputJson.isMember("errors")) - { - if (!outputJson["errors"].isArray()) - { - cout << "Output JSON has \"errors\" but it is not an array." << endl; - abort(); - } - for (Json::Value const& error: outputJson["errors"]) - { - string invalid = contains(error.asString(), vector{ - "Internal compiler error", - "Exception during compilation", - "Unknown exception during compilation", - "Unknown exception while generating contract data output", - "Unknown exception while generating source name output", - "Unknown error while generating JSON" - }); - if (!invalid.empty()) - { - cout << "Invalid error: \"" << error.asString() << "\"" << endl; - abort(); - } - } - } - else if (!outputJson.isMember("contracts")) - { - cout << "Output JSON has neither \"errors\" nor \"contracts\"." << endl; - abort(); - } + Json::Value config = Json::objectValue; + config["language"] = "Solidity"; + config["sources"] = Json::objectValue; + config["sources"][""] = Json::objectValue; + config["sources"][""]["content"] = input; + config["settings"] = Json::objectValue; + config["settings"]["optimizer"] = Json::objectValue; + config["settings"]["optimizer"]["enabled"] = optimize; + config["settings"]["optimizer"]["runs"] = 200; + + // Enable all SourceUnit-level outputs. + config["settings"]["outputSelection"]["*"][""][0] = "*"; + // Enable all Contract-level outputs. + config["settings"]["outputSelection"]["*"]["*"][0] = "*"; + + runCompiler(jsonCompactPrint(config)); } } @@ -182,16 +168,25 @@ Allowed options)", "Run the constant optimizer instead of compiling. " "Expects a binary string of up to 32 bytes on stdin." ) + ( + "input-file", + po::value(), + "input file" + ) ( "without-optimizer", "Run without optimizations. Cannot be used together with standard-json." ); + // All positional options should be interpreted as input files + po::positional_options_description filesPositions; + filesPositions.add("input-file", 1); + po::variables_map arguments; try { po::command_line_parser cmdLineParser(argc, argv); - cmdLineParser.options(options); + cmdLineParser.options(options).positional(filesPositions); po::store(cmdLineParser.run(), arguments); } catch (po::error const& _exception) @@ -200,17 +195,23 @@ Allowed options)", return 1; } + string input; + if (arguments.count("input-file")) + input = readFileAsString(arguments["input-file"].as()); + else + input = readStandardInput(); + if (arguments.count("quiet")) quiet = true; if (arguments.count("help")) cout << options; else if (arguments.count("const-opt")) - testConstantOptimizer(); + testConstantOptimizer(input); else if (arguments.count("standard-json")) - testStandardCompiler(); + testStandardCompiler(input); else - testCompiler(!arguments.count("without-optimizer")); + testCompiler(input, !arguments.count("without-optimizer")); return 0; } diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 7a147bd02..1b6fd54a8 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -16,8 +16,12 @@ */ #include + +#include #include #include +#include +#include #include #include @@ -29,6 +33,10 @@ #include #include +#if defined(_WIN32) +#include +#endif + using namespace dev; using namespace dev::solidity; using namespace dev::solidity::test; @@ -37,18 +45,28 @@ using namespace std; namespace po = boost::program_options; namespace fs = boost::filesystem; -struct SyntaxTestStats +struct TestStats { int successCount; - int runCount; - operator bool() const { return successCount == runCount; } + int testCount; + operator bool() const { return successCount == testCount; } + TestStats& operator+=(TestStats const& _other) noexcept + { + successCount += _other.successCount; + testCount += _other.testCount; + return *this; + } }; -class SyntaxTestTool +class TestTool { public: - SyntaxTestTool(string const& _name, fs::path const& _path, bool _formatted): - m_formatted(_formatted), m_name(_name), m_path(_path) + TestTool( + TestCase::TestCaseCreator _testCaseCreator, + string const& _name, + fs::path const& _path, + bool _formatted + ): m_testCaseCreator(_testCaseCreator), m_formatted(_formatted), m_name(_name), m_path(_path) {} enum class Result @@ -60,7 +78,8 @@ public: Result process(); - static SyntaxTestStats processPath( + static TestStats processPath( + TestCase::TestCaseCreator _testCaseCreator, fs::path const& _basepath, fs::path const& _path, bool const _formatted @@ -77,68 +96,18 @@ private: Request handleResponse(bool const _exception); - void printContract() const; - - bool const m_formatted; + TestCase::TestCaseCreator m_testCaseCreator; + bool const m_formatted = false; string const m_name; fs::path const m_path; - unique_ptr m_test; + unique_ptr m_test; + static bool m_exitRequested; }; -string SyntaxTestTool::editor; +string TestTool::editor; +bool TestTool::m_exitRequested = false; -void SyntaxTestTool::printContract() const -{ - if (m_formatted) - { - string const& source = m_test->source(); - if (source.empty()) - return; - - std::vector sourceFormatting(source.length(), formatting::RESET); - for (auto const& error: m_test->errorList()) - if (error.locationStart >= 0 && error.locationEnd >= 0) - { - assert(static_cast(error.locationStart) < source.length()); - assert(static_cast(error.locationEnd) < source.length()); - bool isWarning = error.type == "Warning"; - for (int i = error.locationStart; i < error.locationEnd; i++) - if (isWarning) - { - if (sourceFormatting[i] == formatting::RESET) - sourceFormatting[i] = formatting::ORANGE_BACKGROUND; - } - else - sourceFormatting[i] = formatting::RED_BACKGROUND; - } - - cout << " " << sourceFormatting.front() << source.front(); - for (size_t i = 1; i < source.length(); i++) - { - if (sourceFormatting[i] != sourceFormatting[i - 1]) - cout << sourceFormatting[i]; - if (source[i] != '\n') - cout << source[i]; - else - { - cout << formatting::RESET << endl; - if (i + 1 < source.length()) - cout << " " << sourceFormatting[i]; - } - } - cout << formatting::RESET << endl; - } - else - { - stringstream stream(m_test->source()); - string line; - while (getline(stream, line)) - cout << " " << line << endl; - cout << endl; - } -} - -SyntaxTestTool::Result SyntaxTestTool::process() +TestTool::Result TestTool::process() { bool success; std::stringstream outputMessages; @@ -147,42 +116,25 @@ SyntaxTestTool::Result SyntaxTestTool::process() try { - m_test = unique_ptr(new SyntaxTest(m_path.string())); + m_test = m_testCaseCreator(m_path.string()); success = m_test->run(outputMessages, " ", m_formatted); } - catch(CompilerError const& _e) + catch(boost::exception const& _e) { FormattedScope(cout, m_formatted, {BOLD, RED}) << - "Exception: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(InternalCompilerError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "InternalCompilerError: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(FatalError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "FatalError: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(UnimplementedFeatureError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "UnimplementedFeatureError: " << SyntaxTest::errorMessage(_e) << endl; + "Exception during syntax test: " << boost::diagnostic_information(_e) << endl; return Result::Exception; } catch (std::exception const& _e) { - FormattedScope(cout, m_formatted, {BOLD, RED}) << "Exception: " << _e.what() << endl; + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "Exception during syntax test: " << _e.what() << endl; return Result::Exception; } - catch(...) + catch (...) { FormattedScope(cout, m_formatted, {BOLD, RED}) << - "Unknown Exception" << endl; + "Unknown exception during syntax test." << endl; return Result::Exception; } @@ -196,14 +148,14 @@ SyntaxTestTool::Result SyntaxTestTool::process() FormattedScope(cout, m_formatted, {BOLD, RED}) << "FAIL" << endl; FormattedScope(cout, m_formatted, {BOLD, CYAN}) << " Contract:" << endl; - printContract(); + m_test->printSource(cout, " ", m_formatted); - cout << outputMessages.str() << endl; + cout << endl << outputMessages.str() << endl; return Result::Failure; } } -SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _exception) +TestTool::Request TestTool::handleResponse(bool const _exception) { if (_exception) cout << "(e)dit/(s)kip/(q)uit? "; @@ -225,15 +177,14 @@ SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _exception) { cout << endl; ofstream file(m_path.string(), ios::trunc); - file << m_test->source(); + m_test->printSource(file); file << "// ----" << endl; - if (!m_test->errorList().empty()) - m_test->printErrorList(file, m_test->errorList(), "// ", false); + m_test->printUpdatedExpectations(file, "// "); return Request::Rerun; } case 'e': cout << endl << endl; - if (system((editor + " \"" + m_path.string() + "\"").c_str())) + if (system((TestTool::editor + " \"" + m_path.string() + "\"").c_str())) cerr << "Error running editor command." << endl << endl; return Request::Rerun; case 'q': @@ -245,8 +196,8 @@ SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _exception) } } - -SyntaxTestStats SyntaxTestTool::processPath( +TestStats TestTool::processPath( + TestCase::TestCaseCreator _testCaseCreator, fs::path const& _basepath, fs::path const& _path, bool const _formatted @@ -255,7 +206,7 @@ SyntaxTestStats SyntaxTestTool::processPath( std::queue paths; paths.push(_path); int successCount = 0; - int runCount = 0; + int testCount = 0; while (!paths.empty()) { @@ -269,13 +220,18 @@ SyntaxTestStats SyntaxTestTool::processPath( fs::directory_iterator(fullpath), fs::directory_iterator() )) - if (fs::is_directory(entry.path()) || SyntaxTest::isTestFilename(entry.path().filename())) + if (fs::is_directory(entry.path()) || TestCase::isTestFilename(entry.path().filename())) paths.push(currentPath / entry.path().filename()); } + else if (m_exitRequested) + { + ++testCount; + paths.pop(); + } else { - SyntaxTestTool testTool(currentPath.string(), fullpath, _formatted); - ++runCount; + ++testCount; + TestTool testTool(_testCaseCreator, currentPath.string(), fullpath, _formatted); auto result = testTool.process(); switch(result) @@ -285,10 +241,12 @@ SyntaxTestStats SyntaxTestTool::processPath( switch(testTool.handleResponse(result == Result::Exception)) { case Request::Quit: - return { successCount, runCount }; + paths.pop(); + m_exitRequested = true; + break; case Request::Rerun: cout << "Re-running test case..." << endl; - --runCount; + --testCount; break; case Request::Skip: paths.pop(); @@ -303,18 +261,74 @@ SyntaxTestStats SyntaxTestTool::processPath( } } - return { successCount, runCount }; + return { successCount, testCount }; + +} + +namespace +{ + +void setupTerminal() +{ +#if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) + // Set output mode to handle virtual terminal (ANSI escape sequences) + // ignore any error, as this is just a "nice-to-have" + // only windows needs to be taken care of, as other platforms (Linux/OSX) support them natively. + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut == INVALID_HANDLE_VALUE) + return; + + DWORD dwMode = 0; + if (!GetConsoleMode(hOut, &dwMode)) + return; + + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(hOut, dwMode)) + return; +#endif +} + +boost::optional runTestSuite( + string const& _name, + fs::path const& _basePath, + fs::path const& _subdirectory, + TestCase::TestCaseCreator _testCaseCreator, + bool _formatted +) +{ + fs::path testPath = _basePath / _subdirectory; + + if (!fs::exists(testPath) || !fs::is_directory(testPath)) + { + cerr << _name << " tests not found. Use the --testpath argument." << endl; + return {}; + } + + TestStats stats = TestTool::processPath(_testCaseCreator, _basePath, _subdirectory, _formatted); + + cout << endl << _name << " Test Summary: "; + FormattedScope(cout, _formatted, {BOLD, stats ? GREEN : RED}) << + stats.successCount << + "/" << + stats.testCount; + cout << " tests successful." << endl << endl; + + return stats; +} } int main(int argc, char *argv[]) { + setupTerminal(); + if (getenv("EDITOR")) - SyntaxTestTool::editor = getenv("EDITOR"); + TestTool::editor = getenv("EDITOR"); else if (fs::exists("/usr/bin/editor")) - SyntaxTestTool::editor = "/usr/bin/editor"; + TestTool::editor = "/usr/bin/editor"; fs::path testPath; + bool disableSMT = false; bool formatted = true; po::options_description options( R"(isoltest, tool for interactively managing test contracts. @@ -327,8 +341,9 @@ Allowed options)", options.add_options() ("help", "Show this help screen.") ("testpath", po::value(&testPath), "path to test files") + ("no-smt", "disable SMT checker") ("no-color", "don't use colors") - ("editor", po::value(&SyntaxTestTool::editor), "editor for opening contracts"); + ("editor", po::value(&TestTool::editor), "editor for opening contracts"); po::variables_map arguments; try @@ -347,50 +362,62 @@ Allowed options)", formatted = false; po::notify(arguments); + + if (arguments.count("no-smt")) + disableSMT = true; } - catch (po::error const& _exception) + catch (std::exception const& _exception) { cerr << _exception.what() << endl; return 1; } if (testPath.empty()) - { - auto const searchPath = - { - fs::current_path() / ".." / ".." / ".." / "test", - fs::current_path() / ".." / ".." / "test", - fs::current_path() / ".." / "test", - fs::current_path() / "test", - fs::current_path() - }; - for (auto const& basePath : searchPath) - { - fs::path syntaxTestPath = basePath / "libsolidity" / "syntaxTests"; - if (fs::exists(syntaxTestPath) && fs::is_directory(syntaxTestPath)) - { - testPath = basePath; - break; - } - } - } + testPath = dev::test::discoverTestPath(); - fs::path syntaxTestPath = testPath / "libsolidity" / "syntaxTests"; + TestStats global_stats{0, 0}; - if (fs::exists(syntaxTestPath) && fs::is_directory(syntaxTestPath)) - { - auto stats = SyntaxTestTool::processPath(testPath / "libsolidity", "syntaxTests", formatted); - - cout << endl << "Summary: "; - FormattedScope(cout, formatted, {BOLD, stats ? GREEN : RED}) << - stats.successCount << "/" << stats.runCount; - cout << " tests successful." << endl; - - return stats ? 0 : 1; - } + // Actually run the tests. + // If you add new tests here, you also have to add them in boostTest.cpp + if (auto stats = runTestSuite("Syntax", testPath / "libsolidity", "syntaxTests", SyntaxTest::create, formatted)) + global_stats += *stats; else - { - cerr << "Test path not found. Use the --testpath argument." << endl; return 1; + + if (auto stats = runTestSuite("JSON AST", testPath / "libsolidity", "ASTJSON", ASTJSONTest::create, formatted)) + global_stats += *stats; + else + return 1; + + if (auto stats = runTestSuite( + "Yul Optimizer", + testPath / "libyul", + "yulOptimizerTests", + yul::test::YulOptimizerTest::create, + formatted + )) + global_stats += *stats; + else + return 1; + + if (!disableSMT) + { + if (auto stats = runTestSuite( + "SMT Checker", + testPath / "libsolidity", + "smtCheckerTests", + SyntaxTest::create, + formatted + )) + global_stats += *stats; + else + return 1; } + + cout << endl << "Summary: "; + FormattedScope(cout, formatted, {BOLD, global_stats ? GREEN : RED}) << + global_stats.successCount << "/" << global_stats.testCount; + cout << " tests successful." << endl; + + return global_stats ? 0 : 1; } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp new file mode 100644 index 000000000..348c5f4a1 --- /dev/null +++ b/test/tools/yulopti.cpp @@ -0,0 +1,233 @@ +/* + 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 . +*/ +/** + * Interactive yul optimizer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; +using namespace dev::solidity::assembly; +using namespace dev::yul; + +namespace po = boost::program_options; + +class YulOpti +{ +public: + void printErrors(Scanner const& _scanner) + { + SourceReferenceFormatter formatter(cout, [&](string const&) -> Scanner const& { return _scanner; }); + + for (auto const& error: m_errors) + formatter.printExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error" + ); + } + + bool parse(string const& _input) + { + ErrorReporter errorReporter(m_errors); + shared_ptr scanner = make_shared(CharStream(_input), ""); + m_ast = assembly::Parser(errorReporter, assembly::AsmFlavour::Strict).parse(scanner, false); + if (!m_ast || !errorReporter.errors().empty()) + { + cout << "Error parsing source." << endl; + printErrors(*scanner); + return false; + } + m_analysisInfo = make_shared(); + AsmAnalyzer analyzer( + *m_analysisInfo, + errorReporter, + EVMVersion::byzantium(), + boost::none, + AsmFlavour::Strict + ); + if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) + { + cout << "Error analyzing source." << endl; + printErrors(*scanner); + return false; + } + return true; + } + + void runInteractive(string source) + { + bool disambiguated = false; + while (true) + { + cout << "----------------------" << endl; + cout << source << endl; + if (!parse(source)) + return; + if (!disambiguated) + { + *m_ast = boost::get(Disambiguator(*m_analysisInfo)(*m_ast)); + m_analysisInfo.reset(); + m_nameDispenser = make_shared(*m_ast); + disambiguated = true; + } + cout << "(q)quit/(f)flatten/(c)se/propagate var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl; + cout << " (e)xpr inline/(i)nline/(s)implify/(u)nusedprune/ss(a) transform/" << endl; + cout << " (r)edundant assign elim./re(m)aterializer? "; + cout.flush(); + int option = readStandardInputChar(); + cout << ' ' << char(option) << endl; + switch (option) + { + case 'q': + return; + case 'f': + BlockFlattener{}(*m_ast); + break; + case 'c': + (CommonSubexpressionEliminator{})(*m_ast); + break; + case 'd': + (VarDeclPropagator{})(*m_ast); + break; + case 'x': + ExpressionSplitter{*m_nameDispenser}(*m_ast); + break; + case 'j': + ExpressionJoiner::run(*m_ast); + break; + case 'g': + (FunctionGrouper{})(*m_ast); + break; + case 'h': + (FunctionHoister{})(*m_ast); + break; + case 'e': + ExpressionInliner{*m_ast}.run(); + break; + case 'i': + FullInliner(*m_ast, *m_nameDispenser).run(); + break; + case 's': + ExpressionSimplifier::run(*m_ast); + break; + case 'u': + UnusedPruner::runUntilStabilised(*m_ast); + break; + case 'a': + SSATransform::run(*m_ast, *m_nameDispenser); + break; + case 'r': + RedundantAssignEliminator::run(*m_ast); + break; + case 'm': + Rematerialiser{}(*m_ast); + break; + default: + cout << "Unknown option." << endl; + } + source = AsmPrinter{}(*m_ast); + } + } + +private: + ErrorList m_errors; + shared_ptr m_ast; + shared_ptr m_analysisInfo; + shared_ptr m_nameDispenser; +}; + +int main(int argc, char** argv) +{ + po::options_description options( + R"(yulopti, yul optimizer exploration tool. +Usage: yulopti [Options] +Reads as yul code and applies optimizer steps to it, +interactively read from stdin. + +Allowed options)", + po::options_description::m_default_line_length, + po::options_description::m_default_line_length - 23); + options.add_options() + ( + "input-file", + po::value(), + "input file" + ) + ("help", "Show this help screen."); + + // All positional options should be interpreted as input files + po::positional_options_description filesPositions; + filesPositions.add("input-file", 1); + + po::variables_map arguments; + try + { + po::command_line_parser cmdLineParser(argc, argv); + cmdLineParser.options(options).positional(filesPositions); + po::store(cmdLineParser.run(), arguments); + } + catch (po::error const& _exception) + { + cerr << _exception.what() << endl; + return 1; + } + + string input; + if (arguments.count("input-file")) + YulOpti{}.runInteractive(readFileAsString(arguments["input-file"].as())); + else + cout << options; + + return 0; +}