diff options
author | chriseth <chris@ethereum.org> | 2017-10-18 20:53:45 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-18 20:53:45 +0800 |
commit | 9cf6e910bd2b90d0c9415d9c257f85fe0c518de8 (patch) | |
tree | 6423baec5e26bbe174005c1a89d978cae15015d8 | |
parent | bdeb9e52a2211510644fb53df93fb98258b40a65 (diff) | |
parent | c85c41880ad1c996517b0ae14f98678b1e6c5613 (diff) | |
download | dexon-solidity-9cf6e910bd2b90d0c9415d9c257f85fe0c518de8.tar dexon-solidity-9cf6e910bd2b90d0c9415d9c257f85fe0c518de8.tar.gz dexon-solidity-9cf6e910bd2b90d0c9415d9c257f85fe0c518de8.tar.bz2 dexon-solidity-9cf6e910bd2b90d0c9415d9c257f85fe0c518de8.tar.lz dexon-solidity-9cf6e910bd2b90d0c9415d9c257f85fe0c518de8.tar.xz dexon-solidity-9cf6e910bd2b90d0c9415d9c257f85fe0c518de8.tar.zst dexon-solidity-9cf6e910bd2b90d0c9415d9c257f85fe0c518de8.zip |
Merge pull request #3099 from ethereum/develop
Merge develop into release for 0.4.18.
99 files changed, 3258 insertions, 1432 deletions
diff --git a/.travis.yml b/.travis.yml index c30e3e0f..708d3620 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,13 +49,6 @@ env: matrix: include: - # Ubuntu 14.04 LTS "Trusty Tahr" - # https://en.wikipedia.org/wiki/List_of_Ubuntu_releases#Ubuntu_14.04_LTS_.28Trusty_Tahr.29 - # - # TravisCI doesn't directly support any new Ubuntu releases. These is - # some Docker support, which we should probably investigate, at least for - # Ubuntu 16.04 LTS "Xenial Xerus" - # See https://en.wikipedia.org/wiki/List_of_Ubuntu_releases#Ubuntu_16.04_LTS_.28Xenial_Xerus.29. - os: linux dist: trusty sudo: required diff --git a/CMakeLists.txt b/CMakeLists.txt index 139d4fd5..537a9521 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.17") +set(PROJECT_VERSION "0.4.18") project(solidity VERSION ${PROJECT_VERSION}) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) @@ -35,7 +35,7 @@ string(REGEX MATCHALL ".." LICENSE_TEXT "${LICENSE_TEXT}") string(REGEX REPLACE ";" ",\n\t0x" LICENSE_TEXT "${LICENSE_TEXT}") set(LICENSE_TEXT "0x${LICENSE_TEXT}") -configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/license.h.in" "license.h") +configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/license.h.in" include/license.h) include(EthOptions) configure_project(TESTS) diff --git a/Changelog.md b/Changelog.md index bdd6ac46..a8a61363 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,31 @@ +### 0.4.18 (2017-10-18) + +Features: + * Code Generator: Always use all available gas for calls as experimental 0.5.0 feature + (previously, some amount was retained in order to work in pre-Tangerine-Whistle + EVM versions) + * Parser: Better error message for unexpected trailing comma in parameter lists. + * Standard JSON: Support the ``outputSelection`` field for selective compilation of supplied sources. + * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. + * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. + * Type Checker: Do not add members of ``address`` to contracts as experimental 0.5.0 feature. + * Type Checker: Force interface functions to be external as experimental 0.5.0 feature. + * Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature. + +Bugfixes: + * Code Generator: Allocate one byte per memory byte array element instead of 32. + * Code Generator: Do not accept data with less than four bytes (truncated function + signature) for regular function calls - fallback function is invoked instead. + * Optimizer: Remove unused stack computation results. + * Parser: Fix source location of VariableDeclarationStatement. + * Type Checker: Allow ``gas`` in view functions. + * Type Checker: Do not mark event parameters as shadowing state variables. + * Type Checker: Prevent duplicate event declarations. + * Type Checker: Properly check array length and don't rely on an assertion in code generation. + * Type Checker: Properly support overwriting members inherited from ``address`` in a contract + (such as ``balance``, ``transfer``, etc.) + * Type Checker: Validate each number literal in tuple expressions even if they are not assigned from. + ### 0.4.17 (2017-09-21) Features: diff --git a/appveyor.yml b/appveyor.yml index 3d4d65bb..c63414b3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,10 +47,12 @@ environment: #init: # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) install: - - ps: $fileContent = "-----BEGIN RSA PRIVATE KEY-----`n" - - ps: $fileContent += $env:priv_key.Replace(' ', "`n") - - ps: $fileContent += "`n-----END RSA PRIVATE KEY-----`n" - - ps: Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent + - ps: if ($env:priv_key) { + $fileContent = "-----BEGIN RSA PRIVATE KEY-----`n"; + $fileContent += $env:priv_key.Replace(' ', "`n"); + $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" @@ -66,12 +68,15 @@ build_script: - cd %APPVEYOR_BUILD_FOLDER% - scripts\release.bat %CONFIGURATION% - ps: $bytecodedir = git show -s --format="%cd-%H" --date=short - - ps: scripts\bytecodecompare\storebytecode.bat $Env:CONFIGURATION $bytecodedir +# Skip bytecode compare if private key is not available + - ps: if ($env:priv_key) { + scripts\bytecodecompare\storebytecode.bat $Env:CONFIGURATION $bytecodedir + } test_script: - cd %APPVEYOR_BUILD_FOLDER% - cd %APPVEYOR_BUILD_FOLDER%\build\test\%CONFIGURATION% - - soltest.exe --show-progress -- --no-ipc + - soltest.exe --show-progress -- --no-ipc --no-smt artifacts: - path: solidity-windows.zip diff --git a/cmake/EthBuildInfo.cmake b/cmake/EthBuildInfo.cmake index 1f70d371..cae3e5ce 100644 --- a/cmake/EthBuildInfo.cmake +++ b/cmake/EthBuildInfo.cmake @@ -39,5 +39,5 @@ function(create_build_info NAME) -DPROJECT_VERSION="${PROJECT_VERSION}" -P "${ETH_SCRIPTS_DIR}/buildinfo.cmake" ) - include_directories(BEFORE ${PROJECT_BINARY_DIR}) + include_directories("${PROJECT_BINARY_DIR}/include") endfunction() diff --git a/cmake/EthCheckCXXCompilerFlag.cmake b/cmake/EthCheckCXXCompilerFlag.cmake new file mode 100644 index 00000000..c6ed35b4 --- /dev/null +++ b/cmake/EthCheckCXXCompilerFlag.cmake @@ -0,0 +1,23 @@ +include(CheckCXXCompilerFlag) + +# Adds CXX compiler flag if the flag is supported by the compiler. +# +# This is effectively a combination of CMake's check_cxx_compiler_flag() +# and add_compile_options(): +# +# if(check_cxx_compiler_flag(flag)) +# add_compile_options(flag) +# +function(eth_add_cxx_compiler_flag_if_supported FLAG) + # Remove leading - or / from the flag name. + string(REGEX REPLACE "^-|/" "" name ${FLAG}) + check_cxx_compiler_flag(${FLAG} ${name}) + if(${name}) + add_compile_options(${FLAG}) + endif() + + # If the optional argument passed, store the result there. + if(ARGV1) + set(${ARGV1} ${name} PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 1a00ae70..6d4dadeb 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -4,7 +4,7 @@ # CMake file for cpp-ethereum project which specifies our compiler settings # for each supported platform and build configuration. # -# See http://www.ethdocs.org/en/latest/ethereum-clients/cpp-ethereum/. +# The documentation for cpp-ethereum is hosted at http://cpp-ethereum.org # # Copyright (c) 2014-2016 cpp-ethereum contributors. #------------------------------------------------------------------------------ @@ -14,18 +14,15 @@ # # These settings then end up spanning all POSIX platforms (Linux, OS X, BSD, etc) -include(CheckCXXCompilerFlag) +include(EthCheckCXXCompilerFlag) -check_cxx_compiler_flag(-fstack-protector-strong have_stack_protector_strong) -if (have_stack_protector_strong) - add_compile_options(-fstack-protector-strong) -else() - check_cxx_compiler_flag(-fstack-protector have_stack_protector) - if(have_stack_protector) - add_compile_options(-fstack-protector) - endif() +eth_add_cxx_compiler_flag_if_supported(-fstack-protector-strong have_stack_protector_strong_support) +if(NOT have_stack_protector_strong_support) + eth_add_cxx_compiler_flag_if_supported(-fstack-protector) endif() +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. @@ -83,12 +80,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") endif () - # Until https://github.com/ethereum/solidity/issues/2479 is handled - # disable all implicit fallthrough warnings in the codebase for GCC > 7.0 - if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0) - add_compile_options(-Wno-implicit-fallthrough) - endif() - # Additional Clang-specific compiler settings. elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 1204f186..233ac22a 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -48,10 +48,3 @@ option(Boost_USE_STATIC_LIBS "Link Boost statically" ON) find_package(Boost 1.54.0 QUIET REQUIRED COMPONENTS regex filesystem unit_test_framework program_options system) eth_show_dependency(Boost boost) - -if (APPLE) - link_directories(/usr/local/lib) - include_directories(/usr/local/include) -endif() - -include_directories(BEFORE "${PROJECT_BINARY_DIR}/include") diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 29d98645..43757d24 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -279,7 +279,7 @@ Events Events are an abstraction of the Ethereum logging/event-watching protocol. Log entries provide the contract's address, a series of up to four topics and some arbitrary length binary data. Events leverage the existing function ABI in order to interpret this (together with an interface spec) as a properly typed structure. -Given an event name and series of event parameters, we split them into two sub-series: those which are indexed and those which are not. Those which are indexed, which may number up to 3, are used alongside the Keccak hash of the event signature to form the topics of the log entry. Those which as not indexed form the byte array of the event. +Given an event name and series of event parameters, we split them into two sub-series: those which are indexed and those which are not. Those which are indexed, which may number up to 3, are used alongside the Keccak hash of the event signature to form the topics of the log entry. Those which are not indexed form the byte array of the event. In effect, a log entry using this ABI is described as: @@ -442,3 +442,22 @@ would result in the JSON: "outputs": [] } ] + +.. _abi_packed_mode: + +Non-standard Packed Mode +======================== + +Solidity supports a non-standard packed mode where: + +- no :ref:`function selector <abi_function_selector>` is encoded, +- short types are not zero padded and +- dynamic types are encoded in-place and without the length. + +As an example encoding ``uint1, bytes1, uint8, string`` with values ``1, 0x42, 0x2424, "Hello, world!"`` results in :: + + 0x0142242448656c6c6f2c20776f726c6421 + ^^ uint1(1) + ^^ bytes1(0x42) + ^^^^ uint8(0x2424) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field diff --git a/docs/bugs.json b/docs/bugs.json index ac322a48..c642793a 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,5 +1,12 @@ [ { + "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.", + "description": "If a function has a selector consisting only of zeros, is payable and part of a contract that does not have a fallback function and at most five external functions in total, this function is called instead of the fallback function if Ether is sent to the contract without data.", + "fixed": "0.4.18", + "severity": "very low" + }, + { "name": "DelegateCallReturnValue", "summary": "The low-level .delegatecall() does not return the execution outcome, but converts the value returned by the functioned called to a boolean instead.", "description": "The return value of the low-level .delegatecall() function is taken from a position in memory, where the call data or the return data resides. This value is interpreted as a boolean and put onto the stack. This means if the called function returns at least 32 zero bytes, .delegatecall() returns false even if the call was successuful.", diff --git a/docs/bugs.rst b/docs/bugs.rst index 55771a35..7629830d 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -48,7 +48,7 @@ fixed publish The date at which the bug became known publicly, optional severity - Severity of the bug: low, medium, high. Takes into account + Severity of the bug: very low, low, medium, high. Takes into account discoverability in contract tests, likelihood of occurrence and potential damage by exploits. conditions diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index c3686ebf..cca45428 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,6 +1,7 @@ { "0.1.0": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -17,6 +18,7 @@ }, "0.1.1": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -33,6 +35,7 @@ }, "0.1.2": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -49,6 +52,7 @@ }, "0.1.3": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -65,6 +69,7 @@ }, "0.1.4": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -81,6 +86,7 @@ }, "0.1.5": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -97,6 +103,7 @@ }, "0.1.6": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -114,6 +121,7 @@ }, "0.1.7": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -131,6 +139,7 @@ }, "0.2.0": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -148,6 +157,7 @@ }, "0.2.1": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -165,6 +175,7 @@ }, "0.2.2": { "bugs": [ + "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", @@ -182,6 +193,7 @@ }, "0.3.0": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -199,6 +211,7 @@ }, "0.3.1": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -215,6 +228,7 @@ }, "0.3.2": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -231,6 +245,7 @@ }, "0.3.3": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -246,6 +261,7 @@ }, "0.3.4": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -261,6 +277,7 @@ }, "0.3.5": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -276,6 +293,7 @@ }, "0.3.6": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -289,6 +307,7 @@ }, "0.4.0": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -302,6 +321,7 @@ }, "0.4.1": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -315,6 +335,7 @@ }, "0.4.10": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -324,6 +345,7 @@ }, "0.4.11": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral" @@ -332,6 +354,7 @@ }, "0.4.12": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" ], @@ -339,6 +362,7 @@ }, "0.4.13": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" ], @@ -346,24 +370,36 @@ }, "0.4.14": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue" ], "released": "2017-07-31" }, "0.4.15": { - "bugs": [], + "bugs": [ + "ZeroFunctionSelector" + ], "released": "2017-08-08" }, "0.4.16": { - "bugs": [], + "bugs": [ + "ZeroFunctionSelector" + ], "released": "2017-08-24" }, "0.4.17": { - "bugs": [], + "bugs": [ + "ZeroFunctionSelector" + ], "released": "2017-09-21" }, + "0.4.18": { + "bugs": [], + "released": "2017-10-18" + }, "0.4.2": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -376,6 +412,7 @@ }, "0.4.3": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -387,6 +424,7 @@ }, "0.4.4": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -397,6 +435,7 @@ }, "0.4.5": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -408,6 +447,7 @@ }, "0.4.6": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -418,6 +458,7 @@ }, "0.4.7": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -427,6 +468,7 @@ }, "0.4.8": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -436,6 +478,7 @@ }, "0.4.9": { "bugs": [ + "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index acef13b7..52319be0 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -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 -conssuming more than the 2300 gas stipend). That way, +consuming more than the 2300 gas stipend). 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. @@ -121,7 +121,7 @@ unless you declare make your state variables ``public``. Furthermore, you can restrict who can make modifications to your contract's state or call your contract's -functions and this is what this page is about. +functions and this is what this section is about. .. index:: function;modifier diff --git a/docs/contracts.rst b/docs/contracts.rst index 69600fc1..cdc92315 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -20,7 +20,7 @@ Contracts can be created "from outside" via Ethereum transactions or from within IDEs, such as `Remix <https://remix.ethereum.org/>`_, make the creation process seamless using UI elements. -Creating contracts programatically on Ethereum is best done via using the JavaScript API `web3.js <https://github.com/etherem/web3.js>`_. +Creating contracts programatically on Ethereum is best done via using the JavaScript API `web3.js <https://github.com/ethereum/web3.js>`_. As of today it has a method called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_ to facilitate contract creation. diff --git a/docs/contributing.rst b/docs/contributing.rst index 01caa5b1..0f7c3e72 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -64,9 +64,11 @@ 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. +called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode, +some others require ``libz3`` to be installed. -To run a subset of the tests that do not require ``cpp-ethereum``, use ``./build/test/soltest -- --no-ipc``. +To disable the z3 tests, use ``./build/test/soltest -- --no-smt`` and +to run a subset of the tests that do not require ``cpp-ethereum``, use ``./build/test/soltest -- --no-ipc``. For all other tests, you need to install `cpp-ethereum <https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth>`_ and run it in testing mode: ``eth --test -d /tmp/testeth``. diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index f59d86e7..5c427c69 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -304,8 +304,9 @@ There are defaults for the storage location depending on which type of variable it concerns: * state variables are always in storage -* function arguments are always in memory -* local variables always reference 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:: @@ -431,12 +432,12 @@ What happens to a ``struct``'s mapping when copying over a ``struct``? This is a very interesting question. Suppose that we have a contract field set up like such:: struct user { - mapping(string => address) usedContracts; + mapping(string => string) comments; } function somefunction { user user1; - user1.usedContracts["Hello"] = "World"; + user1.comments["Hello"] = "World"; user user2 = user1; } diff --git a/docs/grammar.txt b/docs/grammar.txt index 041728c5..72364b7c 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -145,7 +145,7 @@ Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | Fixed = 'fixed' | ( 'fixed' DecimalNumber 'x' DecimalNumber ) -Uixed = 'ufixed' | ( 'ufixed' DecimalNumber 'x' DecimalNumber ) +Ufixed = 'ufixed' | ( 'ufixed' DecimalNumber 'x' DecimalNumber ) InlineAssemblyBlock = '{' AssemblyItem* '}' diff --git a/docs/index.rst b/docs/index.rst index cb093bd6..351f8ad7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -61,6 +61,9 @@ Available Solidity Integrations * `Solium <https://github.com/duaraghav8/Solium/>`_ A commandline linter for Solidity which strictly follows the rules prescribed by the `Solidity Style Guide <http://solidity.readthedocs.io/en/latest/style-guide.html>`_. + +* `Solhint <https://github.com/protofire/solhint>`_ + Solidity linter that provides security, style guide and best practice rules for smart contract validation. * `Visual Studio Code extension <http://juan.blanco.ws/solidity-contracts-in-visual-studio-code/>`_ Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 6d6c25ac..1c4f918c 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -322,17 +322,17 @@ Global Variables - ``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) - ``revert()``: abort execution and revert state changes -- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments +- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` - ``sha3(...) returns (bytes32)``: an alias to ``keccak256`` -- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the (tightly packed) arguments -- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the (tightly packed) arguments +- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` +- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` - ``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`` - ``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`` - ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` - ``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 recipieint)``: an alias to ``selfdestruct`` +- ``suicide(address recipient)``: an alias to ``selfdestruct`` - ``<address>.balance`` (``uint256``): balance of the :ref:`address` in Wei - ``<address>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure - ``<address>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure diff --git a/docs/types.rst b/docs/types.rst index 5c291f35..774c1d04 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -107,6 +107,9 @@ Operators: * ``<=``, ``<``, ``==``, ``!=``, ``>=`` and ``>`` +.. note:: + Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address. + .. _members-of-addresses: Members of Addresses @@ -240,6 +243,9 @@ 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. +.. note:: + The mixed-case address checksum format is defined in `EIP-55 <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md>`_. + .. index:: literal, literal;rational .. _rational_literals: diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 887535da..7af97376 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -116,13 +116,13 @@ Mathematical and Cryptographic Functions ``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``. ``keccak256(...) returns (bytes32)``: - compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments + compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` ``sha256(...) returns (bytes32)``: - compute the SHA-256 hash of the (tightly packed) arguments + compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` ``sha3(...) returns (bytes32)``: alias to ``keccak256`` ``ripemd160(...) returns (bytes20)``: - compute RIPEMD-160 hash of the (tightly packed) arguments + compute RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` ``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 <https://ethereum.stackexchange.com/q/1777/222>`_) diff --git a/libdevcore/Exceptions.cpp b/libdevcore/Exceptions.cpp index f422d926..f204dbc2 100644 --- a/libdevcore/Exceptions.cpp +++ b/libdevcore/Exceptions.cpp @@ -24,10 +24,14 @@ using namespace dev; char const* Exception::what() const noexcept { + // Return the comment if available. if (string const* cmt = comment()) - return cmt->c_str(); - else - return nullptr; + return cmt->data(); + + // Fallback to base what(). + // Boost accepts nullptr, but the C++ standard doesn't + // and crashes on some platforms. + return std::exception::what(); } string Exception::lineInfo() const diff --git a/libdevcore/Whiskers.cpp b/libdevcore/Whiskers.cpp index b0a4c755..a6db35c8 100644 --- a/libdevcore/Whiskers.cpp +++ b/libdevcore/Whiskers.cpp @@ -90,7 +90,13 @@ string Whiskers::replace( string tagName(_match[1]); if (!tagName.empty()) { - assertThrow(_parameters.count(tagName), WhiskersError, "Value for tag " + tagName + " not provided."); + assertThrow( + _parameters.count(tagName), + WhiskersError, + "Value for tag " + tagName + " not provided.\n" + + "Template:\n" + + _template + ); return _parameters.at(tagName); } else diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index df691e7d..5fab24e1 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -408,7 +408,10 @@ map<u256, u256> Assembly::optimiseInternal( { PeepholeOptimiser peepOpt(m_items); while (peepOpt.optimise()) + { count++; + assertThrow(count < 64000, OptimizerException, "Peephole optimizer seems to be stuck."); + } } // This only modifies PushTags, we have to run again to actually remove code. diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index cfe91be0..64963021 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -17,8 +17,6 @@ #include <libevmasm/AssemblyItem.h> -#include <libevmasm/SemanticInformation.h> - #include <libdevcore/CommonData.h> #include <libdevcore/FixedHash.h> @@ -112,7 +110,7 @@ bool AssemblyItem::canBeFunctional() const switch (m_type) { case Operation: - return !SemanticInformation::isDupInstruction(*this) && !SemanticInformation::isSwapInstruction(*this); + return !isDupInstruction(instruction()) && !isSwapInstruction(instruction()); case Push: case PushString: case PushTag: diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 5c945c7d..cfd59dff 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -2,4 +2,4 @@ file(GLOB sources "*.cpp") file(GLOB headers "*.h") add_library(evmasm ${sources} ${headers}) -target_link_libraries(evmasm PUBLIC devcore jsoncpp) +target_link_libraries(evmasm PUBLIC jsoncpp devcore) diff --git a/libevmasm/EVMSchedule.h b/libevmasm/EVMSchedule.h deleted file mode 100644 index 1695a59c..00000000 --- a/libevmasm/EVMSchedule.h +++ /dev/null @@ -1,62 +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 <http://www.gnu.org/licenses/>. -*/ -/** @file EVMSchedule.h - * @author Gav <i@gavwood.com> - * @author Christian <c@ethdev.com> - * @date 2015 - */ - -#pragma once - -namespace dev -{ -namespace solidity -{ - -struct EVMSchedule -{ - unsigned stackLimit = 1024; - unsigned expGas = 10; - unsigned expByteGas = 10; - unsigned keccak256Gas = 30; - unsigned keccak256WordGas = 6; - unsigned sloadGas = 200; - unsigned sstoreSetGas = 20000; - unsigned sstoreResetGas = 5000; - unsigned sstoreRefundGas = 15000; - unsigned jumpdestGas = 1; - unsigned logGas = 375; - unsigned logDataGas = 8; - unsigned logTopicGas = 375; - unsigned createGas = 32000; - unsigned callGas = 40; - unsigned callStipend = 2300; - unsigned callValueTransferGas = 9000; - unsigned callNewAccountGas = 25000; - unsigned selfdestructRefundGas = 24000; - unsigned memoryGas = 3; - unsigned quadCoeffDiv = 512; - unsigned createDataGas = 200; - unsigned txGas = 21000; - unsigned txCreateGas = 53000; - unsigned txDataZeroGas = 4; - unsigned txDataNonZeroGas = 68; - unsigned copyGas = 3; -}; - -} -} diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index afbef71d..d9c53900 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -197,6 +197,24 @@ enum class Instruction: uint8_t SELFDESTRUCT = 0xff ///< halt execution and register account for later deletion }; +/// @returns true if the instruction is a PUSH +inline bool isPushInstruction(Instruction _inst) +{ + return Instruction::PUSH1 <= _inst && _inst <= Instruction::PUSH32; +} + +/// @returns true if the instruction is a DUP +inline bool isDupInstruction(Instruction _inst) +{ + return Instruction::DUP1 <= _inst && _inst <= Instruction::DUP16; +} + +/// @returns true if the instruction is a SWAP +inline bool isSwapInstruction(Instruction _inst) +{ + return Instruction::SWAP1 <= _inst && _inst <= Instruction::SWAP16; +} + /// @returns the number of PUSH Instruction _inst inline unsigned getPushNumber(Instruction _inst) { diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 31fdd317..168d1109 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -249,6 +249,11 @@ void applyMethods(OptimiserState& _state, Method, OtherMethods... _other) applyMethods(_state, _other...); } +size_t numberOfPops(AssemblyItems const& _items) +{ + return std::count(_items.begin(), _items.end(), Instruction::POP); +} + } bool PeepholeOptimiser::optimise() @@ -257,8 +262,10 @@ bool PeepholeOptimiser::optimise() while (state.i < m_items.size()) applyMethods(state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); if (m_optimisedItems.size() < m_items.size() || ( - m_optimisedItems.size() == m_items.size() && - eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) + m_optimisedItems.size() == m_items.size() && ( + eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) || + numberOfPops(m_optimisedItems) > numberOfPops(m_items) + ) )) { m_items = std::move(m_optimisedItems); diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index ceb3fbdd..61a6ccda 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -90,14 +90,14 @@ bool SemanticInformation::isDupInstruction(AssemblyItem const& _item) { if (_item.type() != Operation) return false; - return Instruction::DUP1 <= _item.instruction() && _item.instruction() <= Instruction::DUP16; + return solidity::isDupInstruction(_item.instruction()); } bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item) { if (_item.type() != Operation) return false; - return Instruction::SWAP1 <= _item.instruction() && _item.instruction() <= Instruction::SWAP16; + return solidity::isSwapInstruction(_item.instruction()); } bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item) @@ -198,6 +198,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) case Instruction::ORIGIN: case Instruction::CALLER: case Instruction::CALLVALUE: + case Instruction::GAS: case Instruction::GASPRICE: case Instruction::EXTCODESIZE: case Instruction::EXTCODECOPY: @@ -223,7 +224,6 @@ bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) case Instruction::SSTORE: case Instruction::JUMP: case Instruction::JUMPI: - case Instruction::GAS: case Instruction::LOG0: case Instruction::LOG1: case Instruction::LOG2: diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 254f436f..5c68194b 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -47,7 +47,34 @@ void CodeFragment::finalise(CompilerState const& _cs) } } -CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM) +namespace +{ +/// Returns true iff the instruction is valid in "inline assembly". +bool validAssemblyInstruction(string us) +{ + auto it = c_instructions.find(us); + return !( + it == c_instructions.end() || + solidity::isPushInstruction(it->second) + ); +} + +/// Returns true iff the instruction is valid as a function. +bool validFunctionalInstruction(string us) +{ + auto it = c_instructions.find(us); + return !( + it == c_instructions.end() || + solidity::isPushInstruction(it->second) || + solidity::isDupInstruction(it->second) || + solidity::isSwapInstruction(it->second) || + it->second == solidity::Instruction::JUMPDEST + ); +} +} + +CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM): + m_readFile(_readFile) { /* std::cout << "CodeFragment. Locals:"; @@ -79,7 +106,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS auto sr = _t.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>(); string s(sr.begin(), sr.end()); string us = boost::algorithm::to_upper_copy(s); - if (_allowASM && c_instructions.count(us)) + if (_allowASM && c_instructions.count(us) && validAssemblyInstruction(us)) m_asm.append(c_instructions.at(us)); else if (_s.defs.count(s)) m_asm.append(_s.defs.at(s).m_asm); @@ -103,7 +130,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS { bigint i = *_t.get<bigint*>(); if (i < 0 || i > bigint(u256(0) - 1)) - error<IntegerOutOfRange>(); + error<IntegerOutOfRange>(toString(i)); m_asm.append((u256)i); break; } @@ -157,7 +184,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { auto i = *++_t.begin(); if (i.tag()) - error<InvalidName>(); + error<InvalidName>(toString(i)); if (i.which() == sp::utree_type::string_type) { auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::string_type>>(); @@ -198,7 +225,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) int c = 0; for (auto const& i: _t) if (c++) - m_asm.append(CodeFragment(i, _s, true).m_asm); + m_asm.append(CodeFragment(i, _s, m_readFile, true).m_asm); } else if (us == "INCLUDE") { @@ -207,10 +234,12 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) string fileName = firstAsString(); if (fileName.empty()) error<InvalidName>("Empty file name provided"); - string contents = contentsString(fileName); + if (!m_readFile) + error<InvalidName>("Import callback not present"); + string contents = m_readFile(fileName); if (contents.empty()) error<InvalidName>(std::string("File not found (or empty): ") + fileName); - m_asm.append(CodeFragment::compile(contents, _s).m_asm); + m_asm.append(CodeFragment::compile(contents, _s, m_readFile).m_asm); } else if (us == "SET") { @@ -219,7 +248,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) int c = 0; for (auto const& i: _t) if (c++ == 2) - m_asm.append(CodeFragment(i, _s, false).m_asm); + m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm); m_asm.append((u256)varAddress(firstAsString(), true)); m_asm.append(Instruction::MSTORE); } @@ -244,7 +273,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (ii == 1) { if (i.tag()) - error<InvalidName>(); + error<InvalidName>(toString(i)); if (i.which() == sp::utree_type::string_type) { auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::string_type>>(); @@ -260,7 +289,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (_t.size() == 3) { /// NOTE: some compilers could do the assignment first if this is done in a single line - CodeFragment code = CodeFragment(i, _s); + CodeFragment code = CodeFragment(i, _s, m_readFile); _s.defs[n] = code; } else @@ -301,13 +330,13 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } else if (ii == 1) { - pos = CodeFragment(i, _s); + pos = CodeFragment(i, _s, m_readFile); if (pos.m_asm.deposit() != 1) - error<InvalidDeposit>(us); + error<InvalidDeposit>(toString(i)); } else if (i.tag() != 0) { - error<InvalidLiteral>(); + error<InvalidLiteral>(toString(i)); } else if (i.which() == sp::utree_type::string_type) { @@ -318,7 +347,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { bigint bi = *i.get<bigint*>(); if (bi < 0) - error<IntegerOutOfRange>(); + error<IntegerOutOfRange>(toString(i)); else { bytes tmp = toCompactBigEndian(bi); @@ -327,7 +356,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } else { - error<InvalidLiteral>(); + error<InvalidLiteral>(toString(i)); } ii++; @@ -380,9 +409,9 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (c++) { if (us == "LLL" && c == 1) - code.push_back(CodeFragment(i, ns)); + code.push_back(CodeFragment(i, ns, m_readFile)); else - code.push_back(CodeFragment(i, _s)); + code.push_back(CodeFragment(i, _s, m_readFile)); } auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(us); }; auto requireMinSize = [&](unsigned s) { if (code.size() < s) error<IncorrectParameterCount>(us); }; @@ -403,13 +432,13 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) //requireDeposit(i, 1); cs.args[m.args[i]] = code[i]; } - m_asm.append(CodeFragment(m.code, cs).m_asm); + m_asm.append(CodeFragment(m.code, cs, m_readFile).m_asm); for (auto const& i: cs.defs) _s.defs[i.first] = i.second; for (auto const& i: cs.macros) _s.macros.insert(i); } - else if (c_instructions.count(us)) + else if (c_instructions.count(us) && validFunctionalInstruction(us)) { auto it = c_instructions.find(us); requireSize(instructionInfo(it->second).args); @@ -514,6 +543,44 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) m_asm.appendJump(begin); m_asm << end.tag(); } + else if (us == "SWITCH") + { + requireMinSize(1); + + bool hasDefault = (code.size() % 2 == 1); + int startDeposit = m_asm.deposit(); + int targetDeposit = hasDefault ? code[code.size() - 1].m_asm.deposit() : 0; + + // The conditions + AssemblyItems jumpTags; + for (unsigned i = 0; i < code.size() - 1; i += 2) + { + requireDeposit(i, 1); + m_asm.append(code[i].m_asm); + jumpTags.push_back(m_asm.appendJumpI()); + } + + // The default, if present + if (hasDefault) + m_asm.append(code[code.size() - 1].m_asm); + + // The targets - appending in reverse makes the top case the most efficient. + if (code.size() > 1) + { + auto end = m_asm.appendJump(); + for (int i = 2 * (code.size() / 2 - 1); i >= 0; i -= 2) + { + m_asm << jumpTags[i / 2].tag(); + requireDeposit(i + 1, targetDeposit); + m_asm.append(code[i + 1].m_asm); + if (i != 0) + m_asm.appendJump(end); + } + m_asm << end.tag(); + } + + m_asm.setDeposit(startDeposit + targetDeposit); + } else if (us == "ALLOC") { requireSize(1); @@ -622,13 +689,13 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } } -CodeFragment CodeFragment::compile(string const& _src, CompilerState& _s) +CodeFragment CodeFragment::compile(string const& _src, CompilerState& _s, ReadCallback const& _readFile) { CodeFragment ret; sp::utree o; parseTreeLLL(_src, o); if (!o.empty()) - ret = CodeFragment(o, _s); + ret = CodeFragment(o, _s, _readFile); _s.treesToKill.push_back(o); return ret; } diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h index 95d21563..e5cac34e 100644 --- a/liblll/CodeFragment.h +++ b/liblll/CodeFragment.h @@ -39,10 +39,12 @@ struct CompilerState; class CodeFragment { public: + using ReadCallback = std::function<std::string(std::string const&)>; + CodeFragment() {} - CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM = false); + CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM = false); - static CodeFragment compile(std::string const& _src, CompilerState& _s); + static CodeFragment compile(std::string const& _src, CompilerState& _s, ReadCallback const& _readFile); /// Consolidates data and compiles code. Assembly& assembly(CompilerState const& _cs) { finalise(_cs); return m_asm; } @@ -60,6 +62,7 @@ private: bool m_finalised = false; Assembly m_asm; + ReadCallback m_readFile; }; static const CodeFragment NullCodeFragment; diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp index b69675aa..1638f69e 100644 --- a/liblll/Compiler.cpp +++ b/liblll/Compiler.cpp @@ -28,13 +28,14 @@ using namespace std; using namespace dev; using namespace dev::eth; -bytes dev::eth::compileLLL(string const& _src, bool _opt, vector<string>* _errors) + +bytes dev::eth::compileLLL(string const& _src, bool _opt, vector<string>* _errors, ReadCallback const& _readFile) { try { CompilerState cs; cs.populateStandard(); - auto assembly = CodeFragment::compile(_src, cs).assembly(cs); + auto assembly = CodeFragment::compile(_src, cs, _readFile).assembly(cs); if (_opt) assembly = assembly.optimise(true); bytes ret = assembly.assemble().bytecode; @@ -66,13 +67,13 @@ bytes dev::eth::compileLLL(string const& _src, bool _opt, vector<string>* _error return bytes(); } -std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::vector<std::string>* _errors) +std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::vector<std::string>* _errors, ReadCallback const& _readFile) { try { CompilerState cs; cs.populateStandard(); - auto assembly = CodeFragment::compile(_src, cs).assembly(cs); + auto assembly = CodeFragment::compile(_src, cs, _readFile).assembly(cs); if (_opt) assembly = assembly.optimise(true); string ret = assembly.assemblyString(); diff --git a/liblll/Compiler.h b/liblll/Compiler.h index 04aa1e26..c3395b66 100644 --- a/liblll/Compiler.h +++ b/liblll/Compiler.h @@ -30,9 +30,11 @@ namespace dev namespace eth { +using ReadCallback = std::function<std::string(std::string const&)>; + std::string parseLLL(std::string const& _src); -std::string compileLLLToAsm(std::string const& _src, bool _opt = true, std::vector<std::string>* _errors = nullptr); -bytes compileLLL(std::string const& _src, bool _opt = true, std::vector<std::string>* _errors = nullptr); +std::string compileLLLToAsm(std::string const& _src, bool _opt = true, std::vector<std::string>* _errors = nullptr, ReadCallback const& _readFile = ReadCallback()); +bytes compileLLL(std::string const& _src, bool _opt = true, std::vector<std::string>* _errors = nullptr, ReadCallback const& _readFile = ReadCallback()); } } diff --git a/liblll/CompilerState.cpp b/liblll/CompilerState.cpp index d53dec7e..c0e344b2 100644 --- a/liblll/CompilerState.cpp +++ b/liblll/CompilerState.cpp @@ -82,5 +82,5 @@ void CompilerState::populateStandard() "(def 'shl (val shift) (mul val (exp 2 shift)))" "(def 'shr (val shift) (div val (exp 2 shift)))" "}"; - CodeFragment::compile(s, *this); + CodeFragment::compile(s, *this, CodeFragment::ReadCallback()); } diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index f7c1a390..99612c40 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -6,9 +6,9 @@ find_package(Z3 QUIET) if (${Z3_FOUND}) include_directories(${Z3_INCLUDE_DIR}) add_definitions(-DHAVE_Z3) - message("Z3 SMT solver FOUND.") + message("Z3 SMT solver found. This enables optional SMT checking.") else() - message("Z3 SMT solver NOT found.") + message("Z3 SMT solver NOT found. Optional SMT checking will not be available. Please install Z3 if it is desired.") list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp") endif() diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 7057eab7..6636ad97 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -22,17 +22,17 @@ #include <libsolidity/analysis/ConstantEvaluator.h> #include <libsolidity/ast/AST.h> +#include <libsolidity/interface/ErrorReporter.h> using namespace std; using namespace dev; using namespace dev::solidity; - void ConstantEvaluator::endVisit(UnaryOperation const& _operation) { TypePointer const& subType = _operation.subExpression().annotation().type; if (!dynamic_cast<RationalNumberType const*>(subType.get())) - BOOST_THROW_EXCEPTION(_operation.subExpression().createTypeError("Invalid constant expression.")); + m_errorReporter.fatalTypeError(_operation.subExpression().location(), "Invalid constant expression."); TypePointer t = subType->unaryOperatorResult(_operation.getOperator()); _operation.annotation().type = t; } @@ -42,9 +42,9 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation) TypePointer const& leftType = _operation.leftExpression().annotation().type; TypePointer const& rightType = _operation.rightExpression().annotation().type; if (!dynamic_cast<RationalNumberType const*>(leftType.get())) - BOOST_THROW_EXCEPTION(_operation.leftExpression().createTypeError("Invalid constant expression.")); + m_errorReporter.fatalTypeError(_operation.leftExpression().location(), "Invalid constant expression."); if (!dynamic_cast<RationalNumberType const*>(rightType.get())) - BOOST_THROW_EXCEPTION(_operation.rightExpression().createTypeError("Invalid constant expression.")); + m_errorReporter.fatalTypeError(_operation.rightExpression().location(), "Invalid constant expression."); TypePointer commonType = leftType->binaryOperatorResult(_operation.getOperator(), rightType); if (Token::isCompareOp(_operation.getOperator())) commonType = make_shared<BoolType>(); @@ -55,5 +55,5 @@ void ConstantEvaluator::endVisit(Literal const& _literal) { _literal.annotation().type = Type::forLiteral(_literal); if (!_literal.annotation().type) - BOOST_THROW_EXCEPTION(_literal.createTypeError("Invalid literal value.")); + m_errorReporter.fatalTypeError(_literal.location(), "Invalid literal value."); } diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 9ec04ebe..90bceb5d 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -29,6 +29,7 @@ namespace dev namespace solidity { +class ErrorReporter; class TypeChecker; /** @@ -37,13 +38,18 @@ class TypeChecker; class ConstantEvaluator: private ASTConstVisitor { public: - ConstantEvaluator(Expression const& _expr) { _expr.accept(*this); } + ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter): + m_errorReporter(_errorReporter) + { + _expr.accept(*this); + } private: virtual void endVisit(BinaryOperation const& _operation); virtual void endVisit(UnaryOperation const& _operation); virtual void endVisit(Literal const& _literal); + ErrorReporter& m_errorReporter; }; } diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 62dbd394..fd39d860 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -34,44 +34,29 @@ namespace solidity { GlobalContext::GlobalContext(): -m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::Block)), - make_shared<MagicVariableDeclaration>("msg", make_shared<MagicType>(MagicType::Kind::Message)), - make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::Transaction)), - make_shared<MagicVariableDeclaration>("now", make_shared<IntegerType>(256)), - make_shared<MagicVariableDeclaration>("suicide", - make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), - make_shared<MagicVariableDeclaration>("selfdestruct", - make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), - make_shared<MagicVariableDeclaration>("addmod", - make_shared<FunctionType>(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("mulmod", - make_shared<FunctionType>(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("sha3", - make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("keccak256", - make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("log0", - make_shared<FunctionType>(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), - make_shared<MagicVariableDeclaration>("log1", - make_shared<FunctionType>(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), - make_shared<MagicVariableDeclaration>("log2", - make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), - make_shared<MagicVariableDeclaration>("log3", - make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log3)), - make_shared<MagicVariableDeclaration>("log4", - make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log4)), - make_shared<MagicVariableDeclaration>("sha256", - make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("ecrecover", - make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("ripemd160", - make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("assert", - make_shared<FunctionType>(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("require", - make_shared<FunctionType>(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("revert", - make_shared<FunctionType>(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure))}) +m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{ + make_shared<MagicVariableDeclaration>("addmod", make_shared<FunctionType>(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("assert", make_shared<FunctionType>(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::Block)), + make_shared<MagicVariableDeclaration>("ecrecover", make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("log0", make_shared<FunctionType>(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), + make_shared<MagicVariableDeclaration>("log1", make_shared<FunctionType>(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), + make_shared<MagicVariableDeclaration>("log2", make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), + make_shared<MagicVariableDeclaration>("log3", make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log3)), + make_shared<MagicVariableDeclaration>("log4", make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log4)), + make_shared<MagicVariableDeclaration>("msg", make_shared<MagicType>(MagicType::Kind::Message)), + make_shared<MagicVariableDeclaration>("mulmod", make_shared<FunctionType>(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("now", make_shared<IntegerType>(256)), + make_shared<MagicVariableDeclaration>("require", make_shared<FunctionType>(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("revert", make_shared<FunctionType>(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("selfdestruct", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), + make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("suicide", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), + make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::Transaction)) +}) { } @@ -92,8 +77,7 @@ vector<Declaration const*> GlobalContext::declarations() const MagicVariableDeclaration const* GlobalContext::currentThis() const { if (!m_thisPointer[m_currentContract]) - m_thisPointer[m_currentContract] = make_shared<MagicVariableDeclaration>( - "this", make_shared<ContractType>(*m_currentContract)); + m_thisPointer[m_currentContract] = make_shared<MagicVariableDeclaration>("this", make_shared<ContractType>(*m_currentContract)); return m_thisPointer[m_currentContract].get(); } @@ -101,8 +85,7 @@ MagicVariableDeclaration const* GlobalContext::currentThis() const MagicVariableDeclaration const* GlobalContext::currentSuper() const { if (!m_superPointer[m_currentContract]) - m_superPointer[m_currentContract] = make_shared<MagicVariableDeclaration>( - "super", make_shared<ContractType>(*m_currentContract, true)); + m_superPointer[m_currentContract] = make_shared<MagicVariableDeclaration>("super", make_shared<ContractType>(*m_currentContract, true)); return m_superPointer[m_currentContract].get(); } diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 523e7176..5d010693 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -647,10 +647,12 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio bool warnAboutShadowing = true; // Do not warn about shadowing for structs and enums because their members are - // not accessible without prefixes. + // not accessible without prefixes. Also do not warn about event parameters + // because they don't participate in any proper scope. if ( dynamic_cast<StructDefinition const*>(m_currentScope) || - dynamic_cast<EnumDefinition const*>(m_currentScope) + dynamic_cast<EnumDefinition const*>(m_currentScope) || + dynamic_cast<EventDefinition const*>(m_currentScope) ) warnAboutShadowing = false; // Do not warn about the constructor shadowing the contract. diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 8f07d43a..f22c95cc 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -147,10 +147,12 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName) if (Expression const* length = _typeName.length()) { if (!length->annotation().type) - ConstantEvaluator e(*length); + ConstantEvaluator e(*length, m_errorReporter); auto const* lengthType = dynamic_cast<RationalNumberType const*>(length->annotation().type.get()); - if (!lengthType || lengthType->isFractional()) + if (!lengthType || !lengthType->mobileType()) fatalTypeError(length->location(), "Invalid array length, expected integer literal."); + else if (lengthType->isFractional()) + fatalTypeError(length->location(), "Array with fractional length specified."); else if (lengthType->isNegative()) fatalTypeError(length->location(), "Array with negative length specified."); else @@ -296,11 +298,19 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) { typeLoc = DataLocation::Storage; if (_variable.isLocalVariable()) - m_errorReporter.warning( - _variable.location(), - "Variable is declared as a storage pointer. " - "Use an explicit \"storage\" keyword to silence this warning." - ); + { + if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + typeError( + _variable.location(), + "Storage location must be specified as either \"memory\" or \"storage\"." + ); + else + m_errorReporter.warning( + _variable.location(), + "Variable is declared as a storage pointer. " + "Use an explicit \"storage\" keyword to silence this warning." + ); + } } } else @@ -347,4 +357,3 @@ void ReferencesResolver::fatalDeclarationError(SourceLocation const& _location, m_errorOccurred = true; m_errorReporter.fatalDeclarationError(_location, _description); } - diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 187eb26f..0ca4b86c 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -182,8 +182,15 @@ bool SyntaxChecker::visit(Throw const& _throwStatement) bool SyntaxChecker::visit(UnaryOperation const& _operation) { + bool const v050 = m_sourceUnit->annotation().experimentalFeatures.count(ExperimentalFeature::V050); + if (_operation.getOperator() == Token::Add) - m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated."); + { + if (v050) + m_errorReporter.syntaxError(_operation.location(), "Use of unary + is deprecated."); + else + m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated."); + } return true; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4b2ec8d6..746e762e 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -75,6 +75,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.baseContracts(), *this); checkContractDuplicateFunctions(_contract); + checkContractDuplicateEvents(_contract); checkContractIllegalOverrides(_contract); checkContractAbstractFunctions(_contract); checkContractAbstractConstructors(_contract); @@ -183,9 +184,27 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con msg ); } - for (auto const& it: functions) + + findDuplicateDefinitions(functions, "Function with same name and arguments defined twice."); +} + +void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contract) +{ + /// Checks that two events with the same name defined in this contract have different + /// argument types + map<string, vector<EventDefinition const*>> events; + for (EventDefinition const* event: _contract.events()) + events[event->name()].push_back(event); + + findDuplicateDefinitions(events, "Event with same name and arguments defined twice."); +} + +template <class T> +void TypeChecker::findDuplicateDefinitions(map<string, vector<T>> const& _definitions, string _message) +{ + for (auto const& it: _definitions) { - vector<FunctionDefinition const*> const& overloads = it.second; + vector<T> const& overloads = it.second; set<size_t> reported; for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i) { @@ -200,18 +219,17 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con if (ssl.infos.size() > 0) { - string msg = "Function with same name and arguments defined twice."; size_t occurrences = ssl.infos.size(); if (occurrences > 32) { ssl.infos.resize(32); - msg += " Truncated from " + boost::lexical_cast<string>(occurrences) + " to the first 32 occurrences."; + _message += " Truncated from " + boost::lexical_cast<string>(occurrences) + " to the first 32 occurrences."; } m_errorReporter.declarationError( overloads[i]->location(), ssl, - msg + _message ); } } @@ -577,8 +595,16 @@ bool TypeChecker::visit(FunctionDefinition const& _function) { if (_function.isImplemented()) m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot have an implementation."); - if (_function.visibility() < FunctionDefinition::Visibility::Public) - m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot be internal or private."); + if (_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + { + if (_function.visibility() != FunctionDefinition::Visibility::External) + m_errorReporter.typeError(_function.location(), "Functions in interfaces must be declared external."); + } + else + { + if (_function.visibility() < FunctionDefinition::Visibility::Public) + m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot be internal or private."); + } if (_function.isConstructor()) m_errorReporter.typeError(_function.location(), "Constructor cannot be defined in interfaces."); } @@ -627,14 +653,23 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) if (!allowed) m_errorReporter.typeError(_variable.location(), "Constants of non-value type not yet implemented."); } + if (!_variable.value()) m_errorReporter.typeError(_variable.location(), "Uninitialized \"constant\" variable."); else if (!_variable.value()->annotation().isPure) - m_errorReporter.warning( - _variable.value()->location(), - "Initial value for constant variable has to be compile-time constant. " - "This will fail to compile with the next breaking version change." - ); + { + if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + m_errorReporter.typeError( + _variable.value()->location(), + "Initial value for constant variable has to be compile-time constant." + ); + else + m_errorReporter.warning( + _variable.value()->location(), + "Initial value for constant variable has to be compile-time constant. " + "This will fail to compile with the next breaking version change." + ); + } } if (!_variable.isStateVariable()) { @@ -1258,6 +1293,12 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { components[i]->accept(*this); types.push_back(type(*components[i])); + + // Note: code generation will visit each of the expression even if they are not assigned from. + if (types[i]->category() == Type::Category::RationalNumber && components.size() > 1) + if (!dynamic_cast<RationalNumberType const&>(*types[i]).mobileType()) + m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number."); + if (_tuple.isInlineArray()) solAssert(!!types[i], "Inline array cannot have empty components"); if (_tuple.isInlineArray()) @@ -1497,7 +1538,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) /* If no mobile type is available an error will be raised elsewhere. */ if (literal->mobileType()) m_errorReporter.warning( - _functionCall.location(), + arguments[i]->location(), "The type of \"" + argType->toString() + "\" was inferred as " + @@ -1954,7 +1995,7 @@ void TypeChecker::endVisit(Literal const& _literal) if (_literal.looksLikeAddress()) { if (_literal.passesAddressChecksum()) - _literal.annotation().type = make_shared<IntegerType>(0, IntegerType::Modifier::Address); + _literal.annotation().type = make_shared<IntegerType>(160, IntegerType::Modifier::Address); else m_errorReporter.warning( _literal.location(), diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 0c6f54d3..abe6dac1 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -61,6 +61,7 @@ private: /// Checks that two functions defined in this contract with the same name have different /// arguments and that there is at most one constructor. void checkContractDuplicateFunctions(ContractDefinition const& _contract); + void checkContractDuplicateEvents(ContractDefinition const& _contract); void checkContractIllegalOverrides(ContractDefinition const& _contract); /// Reports a type error with an appropiate message if overriden function signature differs. /// Also stores the direct super function in the AST annotations. @@ -108,6 +109,9 @@ private: virtual void endVisit(ElementaryTypeNameExpression const& _expr) override; virtual void endVisit(Literal const& _literal) override; + template <class T> + void findDuplicateDefinitions(std::map<std::string, std::vector<T>> const& _definitions, std::string _message); + bool contractDependenciesAreCyclic( ContractDefinition const& _contract, std::set<ContractDefinition const*> const& _seenContracts = std::set<ContractDefinition const*>() diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index a805322b..1048b610 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -22,7 +22,6 @@ #include <libsolidity/ast/AST.h> #include <libsolidity/ast/ASTVisitor.h> -#include <libsolidity/interface/Exceptions.h> #include <libsolidity/ast/AST_accept.h> #include <libdevcore/SHA3.h> @@ -73,11 +72,6 @@ ASTAnnotation& ASTNode::annotation() const return *m_annotation; } -Error ASTNode::createTypeError(string const& _description) const -{ - return Error(Error::Type::TypeError) << errinfo_sourceLocation(location()) << errinfo_comment(_description); -} - SourceUnitAnnotation& SourceUnit::annotation() const { if (!m_annotation) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 75b8e946..733e7c78 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -26,7 +26,6 @@ #include <libsolidity/ast/ASTForward.h> #include <libsolidity/parsing/Token.h> #include <libsolidity/ast/Types.h> -#include <libsolidity/interface/Exceptions.h> #include <libsolidity/ast/ASTAnnotations.h> #include <libsolidity/ast/ASTEnums.h> @@ -89,10 +88,6 @@ public: /// Returns the source code location of this node. SourceLocation const& location() const { return m_location; } - /// Creates a @ref TypeError exception and decorates it with the location of the node and - /// the given description - Error createTypeError(std::string const& _description) const; - ///@todo make this const-safe by providing a different way to access the annotation virtual ASTAnnotation& annotation() const; diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index 15735368..46675e51 100644 --- a/libsolidity/ast/ASTForward.h +++ b/libsolidity/ast/ASTForward.h @@ -57,6 +57,7 @@ class UserDefinedTypeName; class FunctionTypeName; class Mapping; class ArrayTypeName; +class InlineAssembly; class Statement; class Block; class PlaceholderStatement; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 83a5b465..ee5f462b 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -89,7 +89,7 @@ pair<u256, unsigned> const* StorageOffsets::offset(size_t _index) const MemberList& MemberList::operator=(MemberList&& _other) { - assert(&_other != this); + solAssert(&_other != this, ""); m_memberTypes = move(_other.m_memberTypes); m_storageOffsets = move(_other.m_storageOffsets); @@ -203,7 +203,7 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type) case Token::Byte: return make_shared<FixedBytesType>(1); case Token::Address: - return make_shared<IntegerType>(0, IntegerType::Modifier::Address); + return make_shared<IntegerType>(160, IntegerType::Modifier::Address); case Token::Bool: return make_shared<BoolType>(); case Token::Bytes: @@ -327,11 +327,11 @@ IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): m_bits(_bits), m_modifier(_modifier) { if (isAddress()) - m_bits = 160; + solAssert(m_bits == 160, ""); solAssert( m_bits > 0 && m_bits <= 256 && m_bits % 8 == 0, "Invalid bit number for integer type: " + dev::toString(_bits) - ); + ); } string IntegerType::identifier() const @@ -1616,10 +1616,10 @@ string ContractType::canonicalName() const return m_contract.annotation().canonicalName; } -MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) const +MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _contract) const { - // All address members and all interface functions - MemberList::MemberMap members(IntegerType(120, IntegerType::Modifier::Address).nativeMembers(nullptr)); + MemberList::MemberMap members; + solAssert(_contract, ""); if (m_super) { // add the most derived of all functions which are visible in derived contracts @@ -1661,9 +1661,47 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) con &it.second->declaration() )); } + // In 0.5.0 address members are not populated into the contract. + if (!_contract->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) + addNonConflictingAddressMembers(members); return members; } +void ContractType::addNonConflictingAddressMembers(MemberList::MemberMap& _members) +{ + MemberList::MemberMap addressMembers = IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr); + for (auto const& addressMember: addressMembers) + { + bool clash = false; + for (auto const& member: _members) + { + if ( + member.name == addressMember.name && + ( + // Members with different types are not allowed + member.type->category() != addressMember.type->category() || + // Members must overload functions without clash + ( + member.type->category() == Type::Category::Function && + dynamic_cast<FunctionType const&>(*member.type).hasEqualArgumentTypes(dynamic_cast<FunctionType const&>(*addressMember.type)) + ) + ) + ) + { + clash = true; + break; + } + } + + if (!clash) + _members.push_back(MemberList::Member( + addressMember.name, + addressMember.type, + addressMember.declaration + )); + } +} + shared_ptr<FunctionType const> const& ContractType::newExpressionType() const { if (!m_constructorType) @@ -1987,7 +2025,7 @@ unsigned EnumType::memberValue(ASTString const& _member) const return index; ++index; } - BOOST_THROW_EXCEPTION(m_enum.createTypeError("Requested unknown enum value ." + _member)); + solAssert(false, "Requested unknown enum value " + _member); } bool TupleType::isImplicitlyConvertibleTo(Type const& _other) const @@ -2968,7 +3006,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const { case Kind::Block: return MemberList::MemberMap({ - {"coinbase", make_shared<IntegerType>(0, IntegerType::Modifier::Address)}, + {"coinbase", make_shared<IntegerType>(160, IntegerType::Modifier::Address)}, {"timestamp", make_shared<IntegerType>(256)}, {"blockhash", make_shared<FunctionType>(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)}, {"difficulty", make_shared<IntegerType>(256)}, @@ -2977,7 +3015,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const }); case Kind::Message: return MemberList::MemberMap({ - {"sender", make_shared<IntegerType>(0, IntegerType::Modifier::Address)}, + {"sender", make_shared<IntegerType>(160, IntegerType::Modifier::Address)}, {"gas", make_shared<IntegerType>(256)}, {"value", make_shared<IntegerType>(256)}, {"data", make_shared<ArrayType>(DataLocation::CallData)}, @@ -2985,7 +3023,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const }); case Kind::Transaction: return MemberList::MemberMap({ - {"origin", make_shared<IntegerType>(0, IntegerType::Modifier::Address)}, + {"origin", make_shared<IntegerType>(160, IntegerType::Modifier::Address)}, {"gasprice", make_shared<IntegerType>(256)} }); default: diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 8ba55521..ce29975e 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -716,6 +716,8 @@ public: std::vector<std::tuple<VariableDeclaration const*, u256, unsigned>> stateVariables() const; private: + static void addNonConflictingAddressMembers(MemberList::MemberMap& _members); + ContractDefinition const& m_contract; /// If true, it is the "super" type of the current contract, i.e. it contains only inherited /// members. diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 9f6c55ba..080be359 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -87,7 +87,7 @@ string ABIFunctions::tupleEncoder( ); elementTempl("values", valueNames); elementTempl("pos", to_string(headPos)); - elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, false)); + elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, true)); encodeElements += elementTempl.render(); headPos += dynamic ? 0x20 : _targetTypes[i]->calldataEncodedSize(); } @@ -162,7 +162,7 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) break; } case Type::Category::Contract: - templ("body", "cleaned := " + cleanupFunction(IntegerType(0, IntegerType::Modifier::Address)) + "(value)"); + templ("body", "cleaned := " + cleanupFunction(IntegerType(160, IntegerType::Modifier::Address)) + "(value)"); break; case Type::Category::Enum: { @@ -243,7 +243,7 @@ string ABIFunctions::conversionFunction(Type const& _from, Type const& _to) toCategory == Type::Category::Integer || toCategory == Type::Category::Contract, ""); - IntegerType const addressType(0, IntegerType::Modifier::Address); + IntegerType const addressType(160, IntegerType::Modifier::Address); IntegerType const& to = toCategory == Type::Category::Integer ? dynamic_cast<IntegerType const&>(_to) : @@ -371,7 +371,7 @@ string ABIFunctions::abiEncodingFunction( Type const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solUnimplementedAssert( @@ -415,7 +415,7 @@ string ABIFunctions::abiEncodingFunction( dynamic_cast<FunctionType const&>(_from), to, _encodeAsLibraryTypes, - _compacted + _fromStack ); solAssert(_from.sizeOnStack() == 1, ""); @@ -487,6 +487,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArray( // TODO if this is not a byte array, we might just copy byte-by-byte anyway, // because the encoding is position-independent, but we have to check that. Whiskers templ(R"( + // <readableTypeNameFrom> -> <readableTypeNameTo> function <functionName>(start, length, pos) -> end { <storeLength> // might update pos <copyFun>(start, pos, length) @@ -495,6 +496,8 @@ string ABIFunctions::abiEncodingFunctionCalldataArray( )"); templ("storeLength", _to.isDynamicallySized() ? "mstore(pos, length) pos := add(pos, 0x20)" : ""); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("copyFun", copyToMemoryFunction(true)); templ("roundUpFun", roundUpFunction()); return templ.render(); @@ -527,6 +530,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( Whiskers templ( dynamicBase ? R"( + // <readableTypeNameFrom> -> <readableTypeNameTo> function <functionName>(value, pos) <return> { let length := <lengthFun>(value) <storeLength> // might update pos @@ -538,13 +542,14 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( mstore(pos, sub(tail, headStart)) tail := <encodeToMemoryFun>(<arrayElementAccess>, tail) srcPtr := <nextArrayElement>(srcPtr) - pos := add(pos, <elementEncodedSize>) + pos := add(pos, 0x20) } pos := tail <assignEnd> } )" : R"( + // <readableTypeNameFrom> -> <readableTypeNameTo> function <functionName>(value, pos) <return> { let length := <lengthFun>(value) <storeLength> // might update pos @@ -560,6 +565,8 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( )" ); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("return", dynamic ? " -> end " : ""); templ("assignEnd", dynamic ? "end := pos" : ""); templ("lengthFun", arrayLengthFunction(_from)); @@ -573,7 +580,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false )); templ("arrayElementAccess", inMemory ? "mload(srcPtr)" : _from.baseType()->isValueType() ? "sload(srcPtr)" : "srcPtr" ); templ("nextArrayElement", nextArrayElementFunction(_from)); @@ -639,6 +646,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( { solAssert(_to.isByteArray(), ""); Whiskers templ(R"( + // <readableTypeNameFrom> -> <readableTypeNameTo> function <functionName>(value, pos) -> ret { let slotValue := sload(value) switch and(slotValue, 1) @@ -665,6 +673,8 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( } )"); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("arrayDataSlot", arrayDataAreaFunction(_from)); return templ.render(); } @@ -681,6 +691,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( // more than desired, i.e. it writes beyond the end of memory. Whiskers templ( R"( + // <readableTypeNameFrom> -> <readableTypeNameTo> function <functionName>(value, pos) <return> { let length := <lengthFun>(value) <storeLength> // might update pos @@ -701,6 +712,8 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( )" ); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("return", dynamic ? " -> end " : ""); templ("assignEnd", dynamic ? "end := pos" : ""); templ("lengthFun", arrayLengthFunction(_from)); @@ -716,7 +729,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false ); templ("encodeToMemoryFun", encodeToMemoryFun); std::vector<std::map<std::string, std::string>> items(itemsPerSlot); @@ -748,6 +761,7 @@ string ABIFunctions::abiEncodingFunctionStruct( bool fromStorage = _from.location() == DataLocation::Storage; bool dynamic = _to.isDynamicallyEncoded(); Whiskers templ(R"( + // <readableTypeNameFrom> -> <readableTypeNameTo> function <functionName>(value, pos) <return> { let tail := add(pos, <headSize>) <init> @@ -761,6 +775,8 @@ string ABIFunctions::abiEncodingFunctionStruct( } )"); templ("functionName", functionName); + templ("readableTypeNameFrom", _from.toString(true)); + templ("readableTypeNameTo", _to.toString(true)); templ("return", dynamic ? " -> end " : ""); templ("assignEnd", dynamic ? "end := tail" : ""); // to avoid multiple loads from the same slot for subsequent members @@ -909,7 +925,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType( FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solAssert(_from.kind() == FunctionType::Kind::External, ""); @@ -920,35 +936,31 @@ string ABIFunctions::abiEncodingFunctionFunctionType( _from.identifier() + "_to_" + _to.identifier() + - (_compacted ? "_compacted" : "") + + (_fromStack ? "_fromStack" : "") + (_encodeAsLibraryTypes ? "_library" : ""); - if (_compacted) - { + if (_fromStack) return createFunction(functionName, [&]() { return Whiskers(R"( - function <functionName>(addr_and_function_id, pos) { - mstore(pos, <cleanExtFun>(addr_and_function_id)) + function <functionName>(addr, function_id, pos) { + mstore(pos, <combineExtFun>(addr, function_id)) } )") ("functionName", functionName) - ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) + ("combineExtFun", combineExternalFunctionIdFunction()) .render(); }); - } else - { return createFunction(functionName, [&]() { return Whiskers(R"( - function <functionName>(addr, function_id, pos) { - mstore(pos, <combineExtFun>(addr, function_id)) + function <functionName>(addr_and_function_id, pos) { + mstore(pos, <cleanExtFun>(addr_and_function_id)) } )") ("functionName", functionName) - ("combineExtFun", combineExternalFunctionIdFunction()) + ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) .render(); }); - } } string ABIFunctions::copyToMemoryFunction(bool _fromCalldata) @@ -995,9 +1007,11 @@ string ABIFunctions::shiftLeftFunction(size_t _numBits) return createFunction(functionName, [&]() { solAssert(_numBits < 256, ""); return - Whiskers(R"(function <functionName>(value) -> newValue { + Whiskers(R"( + function <functionName>(value) -> newValue { newValue := mul(value, <multiplier>) - })") + } + )") ("functionName", functionName) ("multiplier", toCompactHexWithPrefix(u256(1) << _numBits)) .render(); @@ -1010,9 +1024,11 @@ string ABIFunctions::shiftRightFunction(size_t _numBits, bool _signed) return createFunction(functionName, [&]() { solAssert(_numBits < 256, ""); return - Whiskers(R"(function <functionName>(value) -> newValue { + Whiskers(R"( + function <functionName>(value) -> newValue { newValue := <div>(value, <multiplier>) - })") + } + )") ("functionName", functionName) ("div", _signed ? "sdiv" : "div") ("multiplier", toCompactHexWithPrefix(u256(1) << _numBits)) @@ -1025,9 +1041,11 @@ string ABIFunctions::roundUpFunction() string functionName = "round_up_to_mul_of_32"; return createFunction(functionName, [&]() { return - Whiskers(R"(function <functionName>(value) -> result { + Whiskers(R"( + function <functionName>(value) -> result { result := and(add(value, 31), not(31)) - })") + } + )") ("functionName", functionName) .render(); }); @@ -1190,10 +1208,7 @@ size_t ABIFunctions::headSize(TypePointers const& _targetTypes) if (t->isDynamicallyEncoded()) headSize += 0x20; else - { - solAssert(t->calldataEncodedSize() > 0, ""); headSize += t->calldataEncodedSize(); - } } return headSize; diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index de2a140a..e61f68bc 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -89,13 +89,13 @@ private: /// @returns the name of the ABI encoding function with the given type /// and queues the generation of the function to the requested functions. - /// @param _compacted if true, the input value was just loaded from storage + /// @param _fromStack if false, the input value was just loaded from storage /// or memory and thus might be compacted into a single slot (depending on the type). std::string abiEncodingFunction( Type const& _givenType, Type const& _targetType, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// Part of @a abiEncodingFunction for array target type and given calldata array. std::string abiEncodingFunctionCalldataArray( @@ -143,7 +143,7 @@ private: FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// @returns a function that copies raw bytes of dynamic length from calldata diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index e17188c2..ce8cbb5f 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -291,8 +291,11 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord CompilerUtils utils(m_context); unsigned baseSize = 1; if (!_sourceType.isByteArray()) + { // We always pad the elements, regardless of _padToWordBoundaries. baseSize = _sourceType.baseType()->calldataEncodedSize(); + solAssert(baseSize >= 0x20, ""); + } if (_sourceType.location() == DataLocation::CallData) { diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 5a77162e..ce9c3b7f 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -26,6 +26,7 @@ #include <libsolidity/codegen/Compiler.h> #include <libsolidity/interface/Version.h> #include <libsolidity/interface/ErrorReporter.h> +#include <libsolidity/interface/SourceReferenceFormatter.h> #include <libsolidity/parsing/Scanner.h> #include <libsolidity/inlineasm/AsmParser.h> #include <libsolidity/inlineasm/AsmCodeGen.h> @@ -37,6 +38,13 @@ #include <utility> #include <numeric> +// Change to "define" to output all intermediate code +#undef SOL_OUTPUT_ASM +#ifdef SOL_OUTPUT_ASM +#include <libsolidity/inlineasm/AsmPrinter.h> +#endif + + using namespace std; namespace dev @@ -312,12 +320,31 @@ void CompilerContext::appendInlineAssembly( ErrorReporter errorReporter(errors); auto scanner = make_shared<Scanner>(CharStream(_assembly), "--CODEGEN--"); auto parserResult = assembly::Parser(errorReporter).parse(scanner); - solAssert(parserResult, "Failed to parse inline assembly block."); - solAssert(errorReporter.errors().empty(), "Failed to parse inline assembly block."); - +#ifdef SOL_OUTPUT_ASM + cout << assembly::AsmPrinter()(*parserResult) << endl; +#endif assembly::AsmAnalysisInfo analysisInfo; - assembly::AsmAnalyzer analyzer(analysisInfo, errorReporter, false, identifierAccess.resolve); - solAssert(analyzer.analyze(*parserResult), "Failed to analyze inline assembly block."); + bool analyzerResult = false; + if (parserResult) + analyzerResult = assembly::AsmAnalyzer(analysisInfo, errorReporter, false, identifierAccess.resolve).analyze(*parserResult); + if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) + { + string message = + "Error parsing/analyzing inline assembly block:\n" + "------------------ Input: -----------------\n" + + _assembly + "\n" + "------------------ Errors: ----------------\n"; + for (auto const& error: errorReporter.errors()) + message += SourceReferenceFormatter::formatExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error", + [&](string const&) -> Scanner const& { return *scanner; } + ); + message += "-------------------------------------------\n"; + + solAssert(false, message); + } + solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); assembly::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system); } diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 37aa1aea..f9b181ae 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -191,7 +191,7 @@ void CompilerUtils::encodeToMemory( { // Use the new JULIA-based encoding function auto stackHeightBefore = m_context.stackHeight(); - abiEncode(_givenTypes, targetTypes, _encodeAsLibraryTypes); + abiEncodeV2(_givenTypes, targetTypes, _encodeAsLibraryTypes); solAssert(stackHeightBefore - m_context.stackHeight() == sizeOnStack(_givenTypes), ""); return; } @@ -302,7 +302,7 @@ void CompilerUtils::encodeToMemory( popStackSlots(argSize + dynPointers + 1); } -void CompilerUtils::abiEncode( +void CompilerUtils::abiEncodeV2( TypePointers const& _givenTypes, TypePointers const& _targetTypes, bool _encodeAsLibraryTypes @@ -541,7 +541,7 @@ void CompilerUtils::convertType( else { solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); - IntegerType addressType(0, IntegerType::Modifier::Address); + IntegerType addressType(160, IntegerType::Modifier::Address); IntegerType const& targetType = targetTypeCategory == Type::Category::Integer ? dynamic_cast<IntegerType const&>(_targetType) : addressType; if (stackTypeCategory == Type::Category::RationalNumber) @@ -596,7 +596,6 @@ void CompilerUtils::convertType( storeInMemoryDynamic(IntegerType(256)); // stack: mempos datapos storeStringData(data); - break; } else solAssert( @@ -810,9 +809,8 @@ void CompilerUtils::convertType( if (_cleanupNeeded) m_context << Instruction::ISZERO << Instruction::ISZERO; break; - case Type::Category::Function: - { - if (targetTypeCategory == Type::Category::Integer) + default: + if (stackTypeCategory == Type::Category::Function && targetTypeCategory == Type::Category::Integer) { IntegerType const& targetType = dynamic_cast<IntegerType const&>(_targetType); solAssert(targetType.isAddress(), "Function type can only be converted to address."); @@ -821,17 +819,16 @@ void CompilerUtils::convertType( // stack: <address> <function_id> m_context << Instruction::POP; - break; } - } - // fall-through - default: - // All other types should not be convertible to non-equal types. - solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); - if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32) + else + { + // All other types should not be convertible to non-equal types. + solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); + if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32) m_context << ((u256(1) << (8 * _targetType.storageBytes())) - 1) << Instruction::AND; + } break; } diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 5e45699b..ad3989ad 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -102,13 +102,26 @@ public: /// @note the locations of target reference types are ignored, because it will always be /// memory. void encodeToMemory( - TypePointers const& _givenTypes = {}, - TypePointers const& _targetTypes = {}, - bool _padToWords = true, - bool _copyDynamicDataInPlace = false, + TypePointers const& _givenTypes, + TypePointers const& _targetTypes, + bool _padToWords, + bool _copyDynamicDataInPlace, bool _encodeAsLibraryTypes = false ); + /// Special case of @a encodeToMemory which assumes tight packing, e.g. no zero padding + /// and dynamic data is encoded in-place. + /// Stack pre: <value0> <value1> ... <valueN-1> <head_start> + /// Stack post: <mem_ptr> + void packedEncode( + TypePointers const& _givenTypes, + TypePointers const& _targetTypes, + bool _encodeAsLibraryTypes = false + ) + { + encodeToMemory(_givenTypes, _targetTypes, false, true, _encodeAsLibraryTypes); + } + /// Special case of @a encodeToMemory which assumes that everything is padded to words /// and dynamic data is not copied in place (i.e. a proper ABI encoding). /// Stack pre: <value0> <value1> ... <valueN-1> <head_start> @@ -117,6 +130,20 @@ public: TypePointers const& _givenTypes, TypePointers const& _targetTypes, bool _encodeAsLibraryTypes = false + ) + { + encodeToMemory(_givenTypes, _targetTypes, true, false, _encodeAsLibraryTypes); + } + + /// Special case of @a encodeToMemory which assumes that everything is padded to words + /// and dynamic data is not copied in place (i.e. a proper ABI encoding). + /// Uses a new, less tested encoder implementation. + /// Stack pre: <value0> <value1> ... <valueN-1> <head_start> + /// Stack post: <mem_ptr> + void abiEncodeV2( + TypePointers const& _givenTypes, + TypePointers const& _targetTypes, + bool _encodeAsLibraryTypes = false ); /// Zero-initialises (the data part of) an already allocated memory array. diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 92782b8d..74565ae4 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -251,13 +251,10 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac FunctionDefinition const* fallback = _contract.fallbackFunction(); eth::AssemblyItem notFound = m_context.newTag(); - // shortcut messages without data if we have many functions in order to be able to receive - // ether with constant gas - if (interfaceFunctions.size() > 5 || fallback) - { - m_context << Instruction::CALLDATASIZE << Instruction::ISZERO; - m_context.appendConditionalJumpTo(notFound); - } + // directly jump to fallback if the data is too short to contain a function selector + // also guards against short data + m_context << u256(4) << Instruction::CALLDATASIZE << Instruction::LT; + m_context.appendConditionalJumpTo(notFound); // retrieve the function signature hash from the calldata if (!interfaceFunctions.empty()) @@ -421,7 +418,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete utils.fetchFreeMemoryPointer(); //@todo optimization: if we return a single memory array, there should be enough space before // its data to add the needed parts and we avoid a memory copy. - utils.encodeToMemory(_typeParameters, _typeParameters, true, false, _isLibrary); + utils.abiEncode(_typeParameters, _typeParameters, _isLibrary); utils.toSizeAfterFreeMemoryPointer(); m_context << Instruction::RETURN; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c94baa10..bb8c4a94 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -581,7 +581,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) _context << Instruction::ADD; } ); - utils().encodeToMemory(argumentTypes, function.parameterTypes()); + utils().abiEncode(argumentTypes, function.parameterTypes()); // now on stack: memory_end_ptr // need: size, offset, endowment utils().toSizeAfterFreeMemoryPointer(); @@ -675,7 +675,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) argumentTypes.push_back(arg->annotation().type); } utils().fetchFreeMemoryPointer(); - utils().encodeToMemory(argumentTypes, TypePointers(), function.padArguments(), true); + solAssert(!function.padArguments(), ""); + utils().packedEncode(argumentTypes, TypePointers()); utils().toSizeAfterFreeMemoryPointer(); m_context << Instruction::KECCAK256; break; @@ -694,11 +695,10 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } arguments.front()->accept(*this); utils().fetchFreeMemoryPointer(); - utils().encodeToMemory( + utils().packedEncode( {arguments.front()->annotation().type}, - {function.parameterTypes().front()}, - false, - true); + {function.parameterTypes().front()} + ); utils().toSizeAfterFreeMemoryPointer(); m_context << logInstruction(logNumber); break; @@ -717,11 +717,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) if (auto const& arrayType = dynamic_pointer_cast<ArrayType const>(function.parameterTypes()[arg - 1])) { utils().fetchFreeMemoryPointer(); - utils().encodeToMemory( + utils().packedEncode( {arguments[arg - 1]->annotation().type}, - {arrayType}, - false, - true + {arrayType} ); utils().toSizeAfterFreeMemoryPointer(); m_context << Instruction::KECCAK256; @@ -751,7 +749,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) nonIndexedParamTypes.push_back(function.parameterTypes()[arg]); } utils().fetchFreeMemoryPointer(); - utils().encodeToMemory(nonIndexedArgTypes, nonIndexedParamTypes); + utils().abiEncode(nonIndexedArgTypes, nonIndexedParamTypes); // need: topic1 ... topicn memsize memstart utils().toSizeAfterFreeMemoryPointer(); m_context << logInstruction(numIndexed); @@ -860,8 +858,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE; // Stack: memptr requested_length // update free memory pointer - m_context << Instruction::DUP1 << arrayType.baseType()->memoryHeadSize(); - m_context << Instruction::MUL << u256(32) << Instruction::ADD; + m_context << Instruction::DUP1; + // Stack: memptr requested_length requested_length + if (arrayType.isByteArray()) + // Round up to multiple of 32 + m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND; + else + m_context << arrayType.baseType()->memoryHeadSize() << Instruction::MUL; + // stacK: memptr requested_length data_size + m_context << u256(32) << Instruction::ADD; m_context << Instruction::DUP3 << Instruction::ADD; utils().storeFreeMemoryPointer(); // Stack: memptr requested_length @@ -1014,59 +1019,65 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) switch (_memberAccess.expression().annotation().type->category()) { case Type::Category::Contract: + case Type::Category::Integer: { bool alsoSearchInteger = false; - ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type); - if (type.isSuper()) + if (_memberAccess.expression().annotation().type->category() == Type::Category::Contract) { - solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); - utils().pushCombinedFunctionEntryLabel(m_context.superFunction( - dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration), - type.contractDefinition() - )); + ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type); + if (type.isSuper()) + { + solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); + utils().pushCombinedFunctionEntryLabel(m_context.superFunction( + dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration), + type.contractDefinition() + )); + } + else + { + // ordinary contract type + if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration) + { + u256 identifier; + if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration)) + identifier = FunctionType(*variable).externalIdentifier(); + else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration)) + identifier = FunctionType(*function).externalIdentifier(); + else + solAssert(false, "Contract member is neither variable nor function."); + utils().convertType(type, IntegerType(160, IntegerType::Modifier::Address), true); + m_context << identifier; + } + else + // not found in contract, search in members inherited from address + alsoSearchInteger = true; + } } else + alsoSearchInteger = true; + + if (alsoSearchInteger) { - // ordinary contract type - if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration) + if (member == "balance") { - u256 identifier; - if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration)) - identifier = FunctionType(*variable).externalIdentifier(); - else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration)) - identifier = FunctionType(*function).externalIdentifier(); - else - solAssert(false, "Contract member is neither variable nor function."); - utils().convertType(type, IntegerType(0, IntegerType::Modifier::Address), true); - m_context << identifier; + utils().convertType( + *_memberAccess.expression().annotation().type, + IntegerType(160, IntegerType::Modifier::Address), + true + ); + m_context << Instruction::BALANCE; } + else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) + utils().convertType( + *_memberAccess.expression().annotation().type, + IntegerType(160, IntegerType::Modifier::Address), + true + ); else - // not found in contract, search in members inherited from address - alsoSearchInteger = true; - } - if (!alsoSearchInteger) - break; - } - // fall-through - case Type::Category::Integer: - if (member == "balance") - { - utils().convertType( - *_memberAccess.expression().annotation().type, - IntegerType(0, IntegerType::Modifier::Address), - true - ); - m_context << Instruction::BALANCE; + solAssert(false, "Invalid member access to integer"); } - else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) - utils().convertType( - *_memberAccess.expression().annotation().type, - IntegerType(0, IntegerType::Modifier::Address), - true - ); - else - solAssert(false, "Invalid member access to integer"); break; + } case Type::Category::Function: if (member == "selector") { @@ -1206,11 +1217,9 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) utils().fetchFreeMemoryPointer(); // stack: base index mem // note: the following operations must not allocate memory! - utils().encodeToMemory( + utils().packedEncode( TypePointers{_indexAccess.indexExpression()->annotation().type}, - TypePointers{keyType}, - false, - true + TypePointers{keyType} ); m_context << Instruction::SWAP1; utils().storeInMemoryDynamic(IntegerType(256)); @@ -1712,6 +1721,9 @@ void ExpressionCompiler::appendExternalFunctionCall( if (_functionType.gasSet()) m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); + else if (m_context.experimentalFeatureActive(ExperimentalFeature::V050)) + // Send all gas (requires tangerine whistle EVM) + m_context << Instruction::GAS; else { // send all gas except the amount needed to execute "SUB" and "CALL" diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index fd78e578..2d2f05ec 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -234,6 +234,16 @@ void SMTChecker::endVisit(BinaryOperation const& _op) void SMTChecker::endVisit(FunctionCall const& _funCall) { + solAssert(_funCall.annotation().kind != FunctionCallKind::Unset, ""); + if (_funCall.annotation().kind != FunctionCallKind::FunctionCall) + { + m_errorReporter.warning( + _funCall.location(), + "Assertion checker does not yet implement this expression." + ); + return; + } + FunctionType const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type); std::vector<ASTPointer<Expression const>> const args = _funCall.arguments(); @@ -484,10 +494,10 @@ void SMTChecker::createVariable(VariableDeclaration const& _varDecl, bool _setTo { solAssert(m_currentSequenceCounter.count(&_varDecl) == 0, ""); solAssert(m_nextFreeSequenceCounter.count(&_varDecl) == 0, ""); - solAssert(m_Variables.count(&_varDecl) == 0, ""); + solAssert(m_variables.count(&_varDecl) == 0, ""); m_currentSequenceCounter[&_varDecl] = 0; m_nextFreeSequenceCounter[&_varDecl] = 1; - m_Variables.emplace(&_varDecl, m_interface->newFunction(uniqueSymbol(_varDecl), smt::Sort::Int, smt::Sort::Int)); + m_variables.emplace(&_varDecl, m_interface->newFunction(uniqueSymbol(_varDecl), smt::Sort::Int, smt::Sort::Int)); setValue(_varDecl, _setToZero); } else @@ -556,7 +566,7 @@ smt::Expression SMTChecker::maxValue(IntegerType const& _t) smt::Expression SMTChecker::expr(Expression const& _e) { - if (!m_Expressions.count(&_e)) + if (!m_expressions.count(&_e)) { solAssert(_e.annotation().type, ""); switch (_e.annotation().type->category()) @@ -565,24 +575,24 @@ smt::Expression SMTChecker::expr(Expression const& _e) { if (RationalNumberType const* rational = dynamic_cast<RationalNumberType const*>(_e.annotation().type.get())) solAssert(!rational->isFractional(), ""); - m_Expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); + m_expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); break; } case Type::Category::Integer: - m_Expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); + m_expressions.emplace(&_e, m_interface->newInteger(uniqueSymbol(_e))); break; case Type::Category::Bool: - m_Expressions.emplace(&_e, m_interface->newBool(uniqueSymbol(_e))); + m_expressions.emplace(&_e, m_interface->newBool(uniqueSymbol(_e))); break; default: solAssert(false, "Type not implemented."); } } - return m_Expressions.at(&_e); + return m_expressions.at(&_e); } smt::Expression SMTChecker::var(Declaration const& _decl) { - solAssert(m_Variables.count(&_decl), ""); - return m_Variables.at(&_decl); + solAssert(m_variables.count(&_decl), ""); + return m_variables.at(&_decl); } diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index d23fd201..faaac639 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -103,8 +103,8 @@ private: std::shared_ptr<smt::SolverInterface> m_interface; std::map<Declaration const*, int> m_currentSequenceCounter; std::map<Declaration const*, int> m_nextFreeSequenceCounter; - std::map<Expression const*, smt::Expression> m_Expressions; - std::map<Declaration const*, smt::Expression> m_Variables; + std::map<Expression const*, smt::Expression> m_expressions; + std::map<Declaration const*, smt::Expression> m_variables; ErrorReporter& m_errorReporter; FunctionDefinition const* m_currentFunction = nullptr; diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 522928f0..ab28baa3 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -72,36 +72,38 @@ void Z3Interface::addAssertion(Expression const& _expr) pair<CheckResult, vector<string>> Z3Interface::check(vector<Expression> const& _expressionsToEvaluate) { -// cout << "---------------------------------" << endl; -// cout << m_solver << endl; CheckResult result; - switch (m_solver.check()) + vector<string> values; + try { - case z3::check_result::sat: - result = CheckResult::SATISFIABLE; - cout << "sat" << endl; - break; - case z3::check_result::unsat: - result = CheckResult::UNSATISFIABLE; - cout << "unsat" << endl; - break; - case z3::check_result::unknown: - result = CheckResult::UNKNOWN; - cout << "unknown" << endl; - break; - default: - solAssert(false, ""); + switch (m_solver.check()) + { + case z3::check_result::sat: + result = CheckResult::SATISFIABLE; + break; + case z3::check_result::unsat: + result = CheckResult::UNSATISFIABLE; + break; + case z3::check_result::unknown: + result = CheckResult::UNKNOWN; + break; + default: + solAssert(false, ""); + } + + if (result != CheckResult::UNSATISFIABLE) + { + z3::model m = m_solver.get_model(); + for (Expression const& e: _expressionsToEvaluate) + values.push_back(toString(m.eval(toZ3Expr(e)))); + } } -// cout << "---------------------------------" << endl; - - - vector<string> values; - if (result != CheckResult::UNSATISFIABLE) + catch (z3::exception const& _e) { - z3::model m = m_solver.get_model(); - for (Expression const& e: _expressionsToEvaluate) - values.push_back(toString(m.eval(toZ3Expr(e)))); + result = CheckResult::ERROR; + values.clear(); } + return make_pair(result, values); } @@ -125,8 +127,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) {">=", 2}, {"+", 2}, {"-", 2}, - {"*", 2}, - {">=", 2} + {"*", 2} }; string const& n = _expr.name; if (m_functions.count(n)) @@ -142,7 +143,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) return m_context.int_val(n.c_str()); } - assert(arity.count(n) && arity.at(n) == arguments.size()); + solAssert(arity.count(n) && arity.at(n) == arguments.size(), ""); if (n == "ite") return z3::ite(arguments[0], arguments[1], arguments[2]); else if (n == "not") diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 3087ad86..1f4df75b 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -256,7 +256,7 @@ std::map<string, dev::solidity::Instruction> const& Parser::instructions() { if ( instruction.second == solidity::Instruction::JUMPDEST || - (solidity::Instruction::PUSH1 <= instruction.second && instruction.second <= solidity::Instruction::PUSH32) + solidity::isPushInstruction(instruction.second) ) continue; string name = instruction.first; @@ -443,9 +443,9 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction) ret.location = ret.instruction.location; solidity::Instruction instr = ret.instruction.instruction; InstructionInfo instrInfo = instructionInfo(instr); - if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16) + if (solidity::isDupInstruction(instr)) fatalParserError("DUPi instructions not allowed for functional notation"); - if (solidity::Instruction::SWAP1 <= instr && instr <= solidity::Instruction::SWAP16) + if (solidity::isSwapInstruction(instr)) fatalParserError("SWAPi instructions not allowed for functional notation"); expectToken(Token::LParen); unsigned args = unsigned(instrInfo.args); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 51544f8a..b99fe4ee 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -252,6 +252,14 @@ bool CompilerStack::parseAndAnalyze() return parse() && analyze(); } +bool CompilerStack::isRequestedContract(ContractDefinition const& _contract) const +{ + return + m_requestedContractNames.empty() || + m_requestedContractNames.count(_contract.fullyQualifiedName()) || + m_requestedContractNames.count(_contract.name()); +} + bool CompilerStack::compile() { if (m_stackState < AnalysisSuccessful) @@ -262,7 +270,8 @@ bool CompilerStack::compile() for (Source const* source: m_sourceOrder) for (ASTPointer<ASTNode> const& node: source->ast->nodes()) if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) - compileContract(*contract, compiledContracts); + if (isRequestedContract(*contract)) + compileContract(*contract, compiledContracts); this->link(); m_stackState = CompilationSuccessful; return true; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index f1bbae47..c567ac2c 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -116,6 +116,13 @@ public: m_optimizeRuns = _runs; } + /// Sets the list of requested contract names. If empty, no filtering is performed and every contract + /// found in the supplied sources is compiled. Names are cleared iff @a _contractNames is missing. + void setRequestedContractNames(std::set<std::string> const& _contractNames = std::set<std::string>{}) + { + m_requestedContractNames = _contractNames; + } + /// @arg _metadataLiteralSources When true, store sources as literals in the contract metadata. void useMetadataLiteralSources(bool _metadataLiteralSources) { m_metadataLiteralSources = _metadataLiteralSources; } @@ -259,6 +266,9 @@ private: /// Helper function to return path converted strings. std::string sanitizePath(std::string const& _path) const { return boost::filesystem::path(_path).generic_string(); } + /// @returns true if the contract is requested to be compiled. + bool isRequestedContract(ContractDefinition const& _contract) const; + /// Compile a single contract and put the result in @a _compiledContracts. void compileContract( ContractDefinition const& _contract, @@ -297,6 +307,7 @@ private: ReadCallback::Callback m_smtQuery; bool m_optimize = false; unsigned m_optimizeRuns = 200; + std::set<std::string> m_requestedContractNames; std::map<std::string, h160> m_libraries; /// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum /// "context:prefix=target" diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index 852b392c..22cc0266 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -48,7 +48,7 @@ GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimatio ControlFlowGraph cfg(_items); for (BasicBlock const& block: cfg.optimisedBlocks()) { - assertThrow(!!block.startState, OptimizerException, ""); + solAssert(!!block.startState, ""); GasMeter meter(block.startState->copy()); auto const end = _items.begin() + block.end; for (auto iter = _items.begin() + block.begin; iter != end; ++iter) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index b4fbbef9..430739ac 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -92,6 +92,22 @@ Json::Value formatErrorWithException( return formatError(_warning, _type, _component, message, formattedMessage, location); } +set<string> requestedContractNames(Json::Value const& _outputSelection) +{ + set<string> names; + for (auto const& sourceName: _outputSelection.getMemberNames()) + { + for (auto const& contractName: _outputSelection[sourceName].getMemberNames()) + { + /// Consider the "all sources" shortcuts as requesting everything. + if (contractName == "*" || contractName == "") + return set<string>(); + names.insert((sourceName == "*" ? "" : sourceName) + ":" + contractName); + } + } + return names; +} + /// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content. bool hashMatchesContent(string const& _hash, string const& _content) { @@ -265,6 +281,9 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) Json::Value metadataSettings = settings.get("metadata", Json::Value()); m_compilerStack.useMetadataLiteralSources(metadataSettings.get("useLiteralContent", Json::Value(false)).asBool()); + Json::Value outputSelection = settings.get("outputSelection", Json::Value()); + m_compilerStack.setRequestedContractNames(requestedContractNames(outputSelection)); + auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compilerStack.scanner(_sourceName); }; try diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index ce8a9f01..821e81d2 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -828,6 +828,8 @@ ASTPointer<ParameterList> Parser::parseParameterList( parameters.push_back(parseVariableDeclaration(options)); while (m_scanner->currentToken() != Token::RParen) { + if (m_scanner->currentToken() == Token::Comma && m_scanner->peekNextToken() == Token::RParen) + fatalParserError("Unexpected trailing comma in parameter list."); expectToken(Token::Comma); parameters.push_back(parseVariableDeclaration(options)); } @@ -1131,6 +1133,7 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme options.allowVar = true; options.allowLocationSpecifier = true; variables.push_back(parseVariableDeclaration(options, _lookAheadArrayType)); + nodeFactory.setEndPositionFromNode(variables.back()); } if (m_scanner->currentToken() == Token::Assign) { diff --git a/lllc/main.cpp b/lllc/main.cpp index 06a0fc81..912ce16a 100644 --- a/lllc/main.cpp +++ b/lllc/main.cpp @@ -138,7 +138,7 @@ int main(int argc, char** argv) } else if (mode == Binary || mode == Hex) { - auto bs = compileLLL(src, optimise ? true : false, &errors); + auto bs = compileLLL(src, optimise ? true : false, &errors, contentsString); if (mode == Hex) cout << toHex(bs) << endl; else if (mode == Binary) @@ -147,7 +147,7 @@ int main(int argc, char** argv) else if (mode == ParseTree) cout << parseLLL(src) << endl; else if (mode == Assembly) - cout << compileLLLToAsm(src, optimise ? true : false, &errors) << endl; + cout << compileLLLToAsm(src, optimise ? true : false, &errors, contentsString) << endl; for (auto const& i: errors) cerr << i << endl; if ( errors.size() ) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 3a1abe10..49f864a0 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -231,6 +231,7 @@ case $(uname -s) in autoconf \ automake \ boost-devel \ + boost-static \ cmake \ gcc \ gcc-c++ \ @@ -256,15 +257,6 @@ case $(uname -s) in #------------------------------------------------------------------------------ # Ubuntu # -# TODO - I wonder whether all of the Ubuntu-variants need some special -# treatment? -# -# TODO - We should also test this code on Ubuntu Server, Ubuntu Snappy Core -# and Ubuntu Phone. -# -# TODO - Our Ubuntu build is only working for amd64 and i386 processors. -# It would be good to add armel, armhf and arm64. -# See https://github.com/ethereum/webthree-umbrella/issues/228. #------------------------------------------------------------------------------ Ubuntu) @@ -320,6 +312,14 @@ case $(uname -s) in libboost-all-dev \ "$install_z3" if [ "$CI" = true ]; then + # install Z3 from PPA if the distribution does not provide it + if ! dpkg -l libz3-dev > /dev/null 2>&1 + then + sudo apt-add-repository -y ppa:hvr/z3 + sudo apt-get -y update + sudo apt-get -y install libz3-dev + fi + # Install 'eth', for use in the Solidity Tests-over-IPC. # We will not use this 'eth', but its dependencies sudo add-apt-repository -y ppa:ethereum/ethereum diff --git a/scripts/test_emscripten.sh b/scripts/test_emscripten.sh index b01b33bb..4996e957 100755 --- a/scripts/test_emscripten.sh +++ b/scripts/test_emscripten.sh @@ -36,6 +36,10 @@ DIR=$(mktemp -d) echo "Preparing solc-js..." git clone --depth 1 https://github.com/ethereum/solc-js "$DIR" cd "$DIR" + # disable "prepublish" script which downloads the latest version + # (we will replace it anyway and it is often incorrectly cached + # on travis) + npm config set script.prepublish '' npm install # Replace soljson with current build diff --git a/scripts/tests.sh b/scripts/tests.sh index 5d7eb0e1..2b47c254 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -42,8 +42,9 @@ elif [ -z $CI ]; then ETH_PATH="eth" else mkdir -p /tmp/test - wget -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth - test "$(shasum /tmp/test/eth)" = "c132e8989229e4840831a4fb1a1d058b732a11d5 /tmp/test/eth" + # Update hash below if binary is changed. + wget -q -O /tmp/test/eth https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth_byzantium2 + test "$(shasum /tmp/test/eth)" = "4dc3f208475f622be7c8e53bee720e14cd254c6f /tmp/test/eth" sync chmod +x /tmp/test/eth sync # Otherwise we might get a "text file busy" error diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 271511d4..1686dc2e 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -716,8 +716,17 @@ bool CommandLineInterface::processInput() if (m_args.count(g_argAllowPaths)) { vector<string> paths; - for (string const& path: boost::split(paths, m_args[g_argAllowPaths].as<string>(), boost::is_any_of(","))) - m_allowedDirectories.push_back(boost::filesystem::path(path)); + for (string const& path: boost::split(paths, m_args[g_argAllowPaths].as<string>(), boost::is_any_of(","))) { + auto filesystem_path = boost::filesystem::path(path); + // If the given path had a trailing slash, the Boost filesystem + // path will have it's last component set to '.'. This breaks + // path comparison in later parts of the code, so we need to strip + // it. + if (filesystem_path.filename() == ".") { + filesystem_path.remove_filename(); + } + m_allowedDirectories.push_back(filesystem_path); + } } if (m_args.count(g_argStandardJSON)) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index b2de814a..85b5bd3b 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -25,6 +25,8 @@ #include <libdevcore/CommonIO.h> #include <test/ExecutionFramework.h> +#include <boost/algorithm/string/replace.hpp> + using namespace std; using namespace dev; using namespace dev::test; @@ -54,6 +56,32 @@ ExecutionFramework::ExecutionFramework() : m_rpc.test_rewindToBlock(0); } +std::pair<bool, string> ExecutionFramework::compareAndCreateMessage( + bytes const& _result, + bytes const& _expectation +) +{ + if (_result == _expectation) + return std::make_pair(true, std::string{}); + std::string message = + "Invalid encoded data\n" + " Result Expectation\n"; + auto resultHex = boost::replace_all_copy(toHex(_result), "0", "."); + auto expectedHex = boost::replace_all_copy(toHex(_expectation), "0", "."); + for (size_t i = 0; i < std::max(resultHex.size(), expectedHex.size()); i += 0x40) + { + std::string result{i >= resultHex.size() ? string{} : resultHex.substr(i, 0x40)}; + std::string expected{i > expectedHex.size() ? string{} : expectedHex.substr(i, 0x40)}; + message += + (result == expected ? " " : " X ") + + result + + std::string(0x41 - result.size(), ' ') + + expected + + "\n"; + } + return make_pair(false, message); +} + void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) { if (m_showMessages) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index e8d8d111..cc25bea7 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -131,6 +131,8 @@ public: } } + static std::pair<bool, std::string> compareAndCreateMessage(bytes const& _result, bytes const& _expectation); + static bytes encode(bool _value) { return encode(byte(_value)); } static bytes encode(int _value) { return encode(u256(_value)); } static bytes encode(size_t _value) { return encode(u256(_value)); } @@ -293,6 +295,12 @@ protected: u256 m_gasUsed; }; +#define ABI_CHECK(result, expectation) do { \ + auto abiCheckResult = ExecutionFramework::compareAndCreateMessage((result), (expectation)); \ + BOOST_CHECK_MESSAGE(abiCheckResult.first, abiCheckResult.second); \ +} while (0) + + } } // end namespaces diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index c4fbfefb..72b26453 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -217,11 +217,11 @@ void RPCSession::test_setChainParams(vector<string> const& _accounts) { "sealEngine": "NoProof", "params": { - "accountStartNonce": "0x", + "accountStartNonce": "0x00", "maximumExtraDataSize": "0x1000000", "blockReward": "0x", - "allowFutureBlocks": "1", - "homsteadForkBlock": "0x00", + "allowFutureBlocks": true, + "homesteadForkBlock": "0x00", "EIP150ForkBlock": "0x00", "EIP158ForkBlock": "0x00" }, @@ -236,7 +236,10 @@ void RPCSession::test_setChainParams(vector<string> const& _accounts) "0000000000000000000000000000000000000001": { "wei": "1", "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, "0000000000000000000000000000000000000002": { "wei": "1", "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, "0000000000000000000000000000000000000003": { "wei": "1", "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000006": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_add", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000007": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_mul", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000008": { "wei": "1", "precompiled": { "name": "alt_bn128_pairing_product", "linear": { "base": 15, "word": 3 } } } } } )"; diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 094b59c6..c8747a06 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -45,6 +45,8 @@ Options::Options() showMessages = true; else if (string(suite.argv[i]) == "--no-ipc") disableIPC = true; + else if (string(suite.argv[i]) == "--no-smt") + disableSMT = true; if (!disableIPC && ipcPath.empty()) if (auto path = getenv("ETH_TEST_IPC")) diff --git a/test/TestHelper.h b/test/TestHelper.h index 3e74b54c..d25c5cd8 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -15,8 +15,6 @@ along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** @file TestHelper.h - * @author Marko Simovic <markobarko@gmail.com> - * @date 2014 */ #pragma once @@ -31,84 +29,13 @@ namespace dev namespace test { -#if (BOOST_VERSION >= 105900) -#define ETH_BOOST_CHECK_IMPL(_message, _requireOrCheck) BOOST_TEST_TOOL_DIRECT_IMPL( \ - false, \ - _requireOrCheck, \ - _message \ - ) -#else -#define ETH_BOOST_CHECK_IMPL(_message, _requireOrCheck) BOOST_CHECK_IMPL( \ - false, \ - _message, \ - _requireOrCheck, \ - CHECK_MSG \ - ) -#endif - -/// Make sure that no Exception is thrown during testing. If one is thrown show its info and fail the test. -/// Our version of BOOST_REQUIRE_NO_THROW() -/// @param _statement The statement for which to make sure no exceptions are thrown -/// @param _message A message to act as a prefix to the expression's error information -#define ETH_TEST_REQUIRE_NO_THROW(_statement, _message) \ - do \ - { \ - try \ - { \ - BOOST_TEST_PASSPOINT(); \ - _statement; \ - } \ - catch (boost::exception const& _e) \ - { \ - auto msg = std::string(_message " due to an exception thrown by " \ - BOOST_STRINGIZE(_statement) "\n") + boost::diagnostic_information(_e); \ - ETH_BOOST_CHECK_IMPL(msg, REQUIRE); \ - } \ - catch (...) \ - { \ - ETH_BOOST_CHECK_IMPL( \ - "Unknown exception thrown by " BOOST_STRINGIZE(_statement), \ - REQUIRE \ - ); \ - } \ - } \ - while (0) - -/// Check if an Exception is thrown during testing. If one is thrown show its info and continue the test -/// Our version of BOOST_CHECK_NO_THROW() -/// @param _statement The statement for which to make sure no exceptions are thrown -/// @param _message A message to act as a prefix to the expression's error information -#define ETH_TEST_CHECK_NO_THROW(_statement, _message) \ - do \ - { \ - try \ - { \ - BOOST_TEST_PASSPOINT(); \ - _statement; \ - } \ - catch (boost::exception const& _e) \ - { \ - auto msg = std::string(_message " due to an exception thrown by " \ - BOOST_STRINGIZE(_statement) "\n") + boost::diagnostic_information(_e); \ - ETH_BOOST_CHECK_IMPL(msg, CHECK); \ - } \ - catch (...) \ - { \ - ETH_BOOST_CHECK_IMPL( \ - "Unknown exception thrown by " BOOST_STRINGIZE(_statement), \ - CHECK \ - ); \ - } \ - } \ - while (0) - - struct Options: boost::noncopyable { std::string ipcPath; bool showMessages = false; bool optimize = false; bool disableIPC = false; + bool disableSMT = false; static Options const& get(); diff --git a/test/boostTest.cpp b/test/boostTest.cpp index d8c5b678..7b452e06 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -39,6 +39,17 @@ using namespace boost::unit_test; +namespace +{ +void removeTestSuite(std::string const& _name) +{ + master_test_suite_t& master = framework::master_test_suite(); + auto id = master.get(_name); + assert(id != INV_TEST_UNIT_ID); + master.remove(id); +} +} + test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) { master_test_suite_t& master = framework::master_test_suite(); @@ -57,12 +68,10 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "SolidityEndToEndTest", "SolidityOptimizer" }) - { - auto id = master.get(suite); - assert(id != INV_TEST_UNIT_ID); - master.remove(id); - } + removeTestSuite(suite); } + if (dev::test::Options::get().disableSMT) + removeTestSuite("SMTChecker"); return 0; } diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index d56edc56..73a5d1ed 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -223,7 +223,7 @@ protected: m_compiler.reset(false); m_compiler.addSource("", registrarCode); m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); s_compiledRegistrar.reset(new bytes(m_compiler.object("GlobalRegistrar").bytecode)); } sendMessage(*s_compiledRegistrar, true); diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index 967d60b6..8327999d 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -136,7 +136,7 @@ protected: m_compiler.reset(false); m_compiler.addSource("", registrarCode); m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); s_compiledRegistrar.reset(new bytes(m_compiler.object("FixedFeeRegistrar").bytecode)); } sendMessage(*s_compiledRegistrar, true); diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index d12b7493..bbe603d4 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -451,7 +451,7 @@ protected: m_compiler.reset(false); m_compiler.addSource("", walletCode); m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); s_compiledWallet.reset(new bytes(m_compiler.object("Wallet").bytecode)); } bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 9dc49581..0ab95b08 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -841,6 +841,20 @@ BOOST_AUTO_TEST_CASE(peephole_double_push) ); } +BOOST_AUTO_TEST_CASE(peephole_pop_calldatasize) +{ + AssemblyItems items{ + u256(4), + Instruction::CALLDATASIZE, + Instruction::LT, + Instruction::POP + }; + PeepholeOptimiser peepOpt(items); + for (size_t i = 0; i < 3; i++) + BOOST_CHECK(peepOpt.optimise()); + BOOST_CHECK(items.empty()); +} + BOOST_AUTO_TEST_CASE(jumpdest_removal) { AssemblyItems items{ diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp new file mode 100644 index 00000000..77d263b8 --- /dev/null +++ b/test/liblll/Compiler.cpp @@ -0,0 +1,145 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @author Alex Beregszaszi + * @date 2017 + * Unit tests for the LLL compiler. + */ + +#include <string> +#include <memory> +#include <boost/test/unit_test.hpp> +#include <liblll/Compiler.h> + +using namespace std; + +namespace dev +{ +namespace lll +{ +namespace test +{ + +namespace +{ + +bool successCompile(std::string const& _sourceCode) +{ + std::vector<std::string> errors; + bytes bytecode = eth::compileLLL(_sourceCode, false, &errors); + if (!errors.empty()) + return false; + if (bytecode.empty()) + return false; + return true; +} + +} + +BOOST_AUTO_TEST_SUITE(LLLCompiler) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + char const* sourceCode = "1"; + BOOST_CHECK(successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_valid) +{ + char const* sourceCode = R"( + (switch (origin)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (panic) + 2 (panic)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (panic) + 2 (panic) + (panic)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + (origin)) + )"; + BOOST_CHECK(successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_invalid_arg_count) +{ + char const* sourceCode = R"( + (switch) + )"; + BOOST_CHECK(!successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) +{ + // cannot return stack items if the default case is not present + char const* sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + )"; + BOOST_CHECK(!successCompile(sourceCode)); + // return count mismatch + sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + (panic)) + )"; + BOOST_CHECK(!successCompile(sourceCode)); + // return count mismatch + sourceCode = R"( + (switch + 1 (panic) + 2 (panic) + (origin)) + )"; + BOOST_CHECK(!successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(disallowed_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(asm PUSH" + boost::lexical_cast<string>(i) + ")")); +} + +BOOST_AUTO_TEST_CASE(disallowed_functional_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(PUSH" + boost::lexical_cast<string>(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(DUP" + boost::lexical_cast<string>(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(SWAP" + boost::lexical_cast<string>(i) + ")")); + BOOST_CHECK(!successCompile("(JUMPDEST)")); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 9292d963..1a5bb490 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -215,6 +215,92 @@ BOOST_AUTO_TEST_CASE(conditional_nested_then) BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); } +BOOST_AUTO_TEST_CASE(conditional_switch) +{ + char const* sourceCode = R"( + (returnlll + (seq + (def 'input (calldataload 0x04)) + ;; Calculates width in bytes of utf-8 characters. + (return + (switch + (< input 0x80) 1 + (< input 0xE0) 2 + (< input 0xF0) 3 + (< input 0xF8) 4 + (< input 0xFC) 5 + 6)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2))); + BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3))); + BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4))); + BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5))); + BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_with_deposit) +{ + char const* sourceCode = R"( + (returnlll + (return + (switch 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_no_deposit) +{ + char const* sourceCode = R"( + (returnlll + (seq + (switch [0]:42) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_two_args) +{ + char const* sourceCode = R"( + (returnlll + (seq + (switch (= (calldataload 0x04) 1) [0]:42) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_three_args_with_deposit) +{ + char const* sourceCode = R"( + (returnlll + (return + (switch (= (calldataload 0x04) 1) 41 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_three_args_no_deposit) +{ + char const* sourceCode = R"( + (returnlll + (switch + (= (calldataload 0x04) 1) (return 41) + (return 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); +} + BOOST_AUTO_TEST_CASE(exp_operator_const) { char const* sourceCode = R"( diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 05158601..af51edcc 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -462,6 +462,87 @@ 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"( + contract C { + 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) { + a = 7; + b = 8; + s1[0].c = this; + s1[0].t = new T[](1); + s1[0].t[0].x = 0x11; + s1[0].t[0].e = E.B; + s1[0].t[0].y = 0x12; + s2 = new S[](2); + s2[1].c = C(0x1234); + s2[1].t = new T[](3); + s2[1].t[1].x = 0x21; + s2[1].t[1].e = E.C; + s2[1].t[1].y = 0x22; + } + } + )"; + + NEW_ENCODER( + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 7, 0x80, 0x1e0, 8, + // S[2] s1 + 0x40, + 0x100, + // S s1[0] + u256(u160(m_contractAddress)), + 0x40, + // T s1[0].t + 1, // length + // s1[0].t[0] + 0x11, 1, 0x12, + // S s1[1] + 0, 0x40, + // T s1[1].t + 0, + // S[] s2 (0x1e0) + 2, // length + 0x40, 0xa0, + // S s2[0] + 0, 0x40, 0, + // S s2[1] + 0x1234, 0x40, + // s2[1].t + 3, // length + 0, 0, 0, + 0x21, 2, 0x22, + 0, 0, 0 + )); + ) +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 5f5f6411..3bdc40a0 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -25,6 +25,8 @@ #include <libsolidity/ast/AST.h> +#include <libsolidity/parsing/Scanner.h> + #include <libdevcore/SHA3.h> #include <boost/test/unit_test.hpp> @@ -46,8 +48,7 @@ AnalysisFramework::parseAnalyseAndReturnError( m_compiler.addSource("", _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source); if (!m_compiler.parse()) { - printErrors(); - BOOST_ERROR("Parsing contract failed in analysis test suite."); + BOOST_ERROR("Parsing contract failed in analysis test suite:" + formatErrors()); } m_compiler.analyze(); @@ -56,15 +57,24 @@ AnalysisFramework::parseAnalyseAndReturnError( for (auto const& currentError: m_compiler.errors()) { solAssert(currentError->comment(), ""); - if (currentError->comment()->find("This is a pre-release compiler version") == 0) - continue; + if (currentError->type() == Error::Type::Warning) + { + bool ignoreWarning = false; + for (auto const& filter: m_warningsToFilter) + if (currentError->comment()->find(filter) == 0) + { + ignoreWarning = true; + break; + } + if (ignoreWarning) + continue; + } if (_reportWarnings || (currentError->type() != Error::Type::Warning)) { if (firstError && !_allowMultipleErrors) { - printErrors(); - BOOST_FAIL("Multiple errors found."); + BOOST_FAIL("Multiple errors found: " + formatErrors()); } if (!firstError) firstError = currentError; @@ -78,7 +88,10 @@ SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source) { auto sourceAndError = parseAnalyseAndReturnError(_source); BOOST_REQUIRE(!!sourceAndError.first); - BOOST_REQUIRE(!sourceAndError.second); + string message; + if (sourceAndError.second) + message = "Unexpected error: " + formatError(*sourceAndError.second); + BOOST_REQUIRE_MESSAGE(!sourceAndError.second, message); return sourceAndError.first; } @@ -91,17 +104,23 @@ Error AnalysisFramework::expectError(std::string const& _source, bool _warning, { auto sourceAndError = parseAnalyseAndReturnError(_source, _warning, true, _allowMultiple); BOOST_REQUIRE(!!sourceAndError.second); - BOOST_REQUIRE(!!sourceAndError.first); + BOOST_REQUIRE_MESSAGE(!!sourceAndError.first, "Expected error, but no error happened."); return *sourceAndError.second; } -void AnalysisFramework::printErrors() +string AnalysisFramework::formatErrors() { + string message; for (auto const& error: m_compiler.errors()) - SourceReferenceFormatter::printExceptionInformation( - std::cerr, - *error, - (error->type() == Error::Type::Warning) ? "Warning" : "Error", + message += formatError(*error); + return message; +} + +string AnalysisFramework::formatError(Error const& _error) +{ + return SourceReferenceFormatter::formatExceptionInformation( + _error, + (_error.type() == Error::Type::Warning) ? "Warning" : "Error", [&](std::string const& _sourceName) -> solidity::Scanner const& { return m_compiler.scanner(_sourceName); } ); } diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index 172ae01b..a566ba1d 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -45,7 +45,7 @@ class AnalysisFramework { protected: - std::pair<SourceUnit const*, std::shared_ptr<Error const>> + virtual std::pair<SourceUnit const*, std::shared_ptr<Error const>> parseAnalyseAndReturnError( std::string const& _source, bool _reportWarnings = false, @@ -57,7 +57,8 @@ protected: bool success(std::string const& _source); Error expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false); - void printErrors(); + std::string formatErrors(); + std::string formatError(Error const& _error); static ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name); static FunctionTypePointer retrieveFunctionBySignature( @@ -65,6 +66,7 @@ protected: std::string const& _signature ); + std::vector<std::string> m_warningsToFilter = {"This is a pre-release compiler version"}; dev::solidity::CompilerStack m_compiler; }; @@ -104,7 +106,10 @@ CHECK_ERROR_OR_WARNING(text, Warning, substring, true, true) do \ { \ auto sourceAndError = parseAnalyseAndReturnError((text), true); \ - BOOST_CHECK(sourceAndError.second == nullptr); \ + std::string message; \ + if (sourceAndError.second) \ + message = formatError(*sourceAndError.second); \ + BOOST_CHECK_MESSAGE(!sourceAndError.second, message); \ } \ while(0) diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 56ac8cf5..358d3c72 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr<string const> n = make_shared<string>(""); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(18, SourceLocation(2, 75, n)) + + vector<SourceLocation>(24, SourceLocation(2, 75, n)) + vector<SourceLocation>(32, SourceLocation(20, 72, n)) + vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector<SourceLocation>(2, SourceLocation(58, 67, n)) + diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index df9afaae..c2886f5b 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -21,7 +21,6 @@ */ #include <test/libsolidity/SolidityExecutionFramework.h> -#include <libevmasm/EVMSchedule.h> #include <libevmasm/GasMeter.h> #include <libevmasm/KnownState.h> #include <libevmasm/PathGasMeter.h> @@ -50,7 +49,7 @@ public: m_compiler.reset(false); m_compiler.addSource("", "pragma solidity >=0.0;\n" + _sourceCode); m_compiler.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); AssemblyItems const* items = m_compiler.runtimeAssemblyItems(""); ASTNode const& sourceUnit = m_compiler.ast(); @@ -63,15 +62,13 @@ public: void testCreationTimeGas(string const& _sourceCode) { - EVMSchedule schedule; - compileAndRun(_sourceCode); auto state = make_shared<KnownState>(); PathGasMeter meter(*m_compiler.assemblyItems()); GasMeter::GasConsumption gas = meter.estimateMax(0, state); u256 bytecodeSize(m_compiler.runtimeObject().bytecode.size()); // costs for deployment - gas += bytecodeSize * schedule.createDataGas; + gas += bytecodeSize * GasCosts::createDataGas; // costs for transaction gas += gasForTransaction(m_compiler.object().bytecode, true); @@ -103,10 +100,9 @@ public: static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation) { - EVMSchedule schedule; - GasMeter::GasConsumption gas = _isCreation ? schedule.txCreateGas : schedule.txGas; + GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas; for (auto i: _data) - gas += i != 0 ? schedule.txDataNonZeroGas : schedule.txDataZeroGas; + gas += i != 0 ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas; return gas; } diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index c46e3160..efe8faff 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) CompilerStack compilerStack; compilerStack.addSource("", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; std::string const& metadata = compilerStack.metadata("test"); BOOST_CHECK(dev::test::isValidMetadata(metadata)); @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) CompilerStack compilerStack; compilerStack.addSource("", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; std::string const& metadata = compilerStack.metadata("test"); BOOST_CHECK(dev::test::isValidMetadata(metadata)); @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources) )"; compilerStack.addSource("B", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("A"); BOOST_CHECK(dev::test::isValidMetadata(serialisedMetadata)); @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) )"; compilerStack.addSource("C", std::string(sourceCode)); compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("C"); BOOST_CHECK(dev::test::isValidMetadata(serialisedMetadata)); diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp new file mode 100644 index 00000000..8d712a80 --- /dev/null +++ b/test/libsolidity/SMTChecker.cpp @@ -0,0 +1,112 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Unit tests for the SMT checker. + */ + +#include <test/libsolidity/AnalysisFramework.h> + +#include <boost/test/unit_test.hpp> + +#include <string> + +using namespace std; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class SMTCheckerFramework: public AnalysisFramework +{ +public: + SMTCheckerFramework() + { + m_warningsToFilter.push_back("Experimental features are turned on."); + } + +protected: + virtual std::pair<SourceUnit const*, std::shared_ptr<Error const>> + parseAnalyseAndReturnError( + std::string const& _source, + bool _reportWarnings = false, + bool _insertVersionPragma = true, + bool _allowMultipleErrors = false + ) + { + return AnalysisFramework::parseAnalyseAndReturnError( + "pragma experimental SMTChecker;\n" + _source, + _reportWarnings, + _insertVersionPragma, + _allowMultipleErrors + ); + } +}; + +BOOST_FIXTURE_TEST_SUITE(SMTChecker, SMTCheckerFramework) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + string text = R"( + contract C { } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(simple_overflow) +{ + string text = R"( + contract C { + function f(uint a, uint b) public pure returns (uint) { return a + b; } + } + )"; + CHECK_WARNING(text, "Overflow (resulting value larger than"); +} + +BOOST_AUTO_TEST_CASE(warn_on_typecast) +{ + string text = R"( + contract C { + function f() public pure returns (uint) { + return uint8(1); + } + } + )"; + CHECK_WARNING(text, "Assertion checker does not yet implement this expression."); +} + +BOOST_AUTO_TEST_CASE(warn_on_struct) +{ + string text = R"( + contract C { + struct A { uint a; uint b; } + function f() public pure returns (A) { + return A({ a: 1, b: 2 }); + } + } + )"; + /// Multiple warnings, should check for: Assertion checker does not yet implement this expression. + CHECK_WARNING_ALLOW_MULTI(text, ""); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index e5d9e99c..42f7525f 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -44,7 +44,7 @@ public: { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); - ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); + BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); Json::Value generatedInterface = m_compilerStack.contractABI(""); Json::Value expectedInterface; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 458b64f4..9a837113 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_const) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(8))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(8))); } BOOST_AUTO_TEST_CASE(exp_operator_const_signed) @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(-8))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(-8))); } BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) @@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(5))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(5))); } BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(10))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(10))); } BOOST_AUTO_TEST_CASE(conditional_expression_multiple) @@ -134,10 +134,10 @@ BOOST_AUTO_TEST_CASE(conditional_expression_multiple) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1001)) == toBigEndian(u256(1000))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(500)) == toBigEndian(u256(100))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(80)) == toBigEndian(u256(50))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(40)) == toBigEndian(u256(10))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1001)), toBigEndian(u256(1000))); + ABI_CHECK(callContractFunction("f(uint256)", u256(500)), toBigEndian(u256(100))); + ABI_CHECK(callContractFunction("f(uint256)", u256(80)), toBigEndian(u256(50))); + ABI_CHECK(callContractFunction("f(uint256)", u256(40)), toBigEndian(u256(10))); } BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) @@ -149,8 +149,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)) == encodeArgs(u256(20), u256(0))); - BOOST_CHECK(callContractFunction("f(bool,uint256)", false, u256(20)) == encodeArgs(u256(0), u256(20))); + 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))); } BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) @@ -182,8 +182,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) @@ -216,8 +216,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(conditional_expression_different_types) @@ -232,8 +232,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_different_types) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(0xcd))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(0xabab))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(0xcd))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(0xabab))); } /* let's add this back when I figure out the correct type conversion. @@ -247,8 +247,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_string_literal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(string("true", 4))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(string("false", 5))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(string("true", 4))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(string("false", 5))); } */ @@ -262,8 +262,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_tuples) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1), u256(2))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(3), u256(4))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(3), u256(4))); } BOOST_AUTO_TEST_CASE(conditional_expression_functions) @@ -280,8 +280,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(recursive_calls) @@ -317,11 +317,11 @@ BOOST_AUTO_TEST_CASE(multiple_functions) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("a()", bytes()) == toBigEndian(u256(0))); - BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(1))); - BOOST_CHECK(callContractFunction("c()", bytes()) == toBigEndian(u256(2))); - BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(3))); - BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()) == bytes()); + ABI_CHECK(callContractFunction("a()", bytes()), toBigEndian(u256(0))); + ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(1))); + ABI_CHECK(callContractFunction("c()", bytes()), toBigEndian(u256(2))); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(3))); + ABI_CHECK(callContractFunction("i_am_not_there()", bytes()), bytes()); } BOOST_AUTO_TEST_CASE(named_args) @@ -333,7 +333,7 @@ BOOST_AUTO_TEST_CASE(named_args) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); + ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(disorder_named_args) @@ -345,7 +345,7 @@ BOOST_AUTO_TEST_CASE(disorder_named_args) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); + ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(while_loop) @@ -665,8 +665,10 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0")) - == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); + ABI_CHECK( + callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0")), + fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f") + ); } BOOST_AUTO_TEST_CASE(packing_signed_types) @@ -680,8 +682,10 @@ BOOST_AUTO_TEST_CASE(packing_signed_types) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run()") - == fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa")); + ABI_CHECK( + callContractFunction("run()"), + fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa") + ); } BOOST_AUTO_TEST_CASE(multiple_return_values) @@ -694,7 +698,7 @@ BOOST_AUTO_TEST_CASE(multiple_return_values) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd) == encodeArgs(0xcd, true, 0)); + ABI_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd), encodeArgs(0xcd, true, 0)); } BOOST_AUTO_TEST_CASE(short_circuiting) @@ -816,8 +820,8 @@ BOOST_AUTO_TEST_CASE(strings) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("fixedBytes()") == encodeArgs(string("abc\0\xff__", 7))); - BOOST_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true)); + ABI_CHECK(callContractFunction("fixedBytes()"), encodeArgs(string("abc\0\xff__", 7))); + ABI_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true), encodeArgs(string("\0\x2", 2), true)); } BOOST_AUTO_TEST_CASE(inc_dec_operators) @@ -838,7 +842,7 @@ BOOST_AUTO_TEST_CASE(inc_dec_operators) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(0x53866)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x53866)); } BOOST_AUTO_TEST_CASE(bytes_comparison) @@ -854,7 +858,7 @@ BOOST_AUTO_TEST_CASE(bytes_comparison) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(state_smoke_test) @@ -874,14 +878,14 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x1234) == encodeArgs()); - BOOST_CHECK(callContractFunction("set(uint8,uint256)", byte(0x01), 0x8765) == encodeArgs()); - BOOST_CHECK(callContractFunction("get(uint8)", byte( 0x00)) == encodeArgs(0x1234)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(0x8765)); - BOOST_CHECK(callContractFunction("set(uint8,uint256)", byte(0x00), 0x3) == encodeArgs()); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(0x3)); + 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)); } BOOST_AUTO_TEST_CASE(compound_assign) @@ -936,21 +940,21 @@ BOOST_AUTO_TEST_CASE(simple_mapping) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x00))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + 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)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(byte(0x00))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0xa1))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + 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)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(byte(0xef))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0xa1))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + 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)); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(byte(0xef))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x05))); - BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); + 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))); } BOOST_AUTO_TEST_CASE(mapping_state) @@ -1126,9 +1130,9 @@ BOOST_AUTO_TEST_CASE(structs) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("set()") == bytes()); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("check()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("set()"), bytes()); + ABI_CHECK(callContractFunction("check()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(struct_reference) @@ -1156,9 +1160,9 @@ BOOST_AUTO_TEST_CASE(struct_reference) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("set()") == bytes()); - BOOST_CHECK(callContractFunction("check()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("check()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("set()"), bytes()); + ABI_CHECK(callContractFunction("check()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(deleteStruct) @@ -1209,14 +1213,14 @@ BOOST_AUTO_TEST_CASE(deleteStruct) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("getNestedValue()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("getToDelete()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("getTopValue()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("getNestedValue()"), encodeArgs(0)); // mapping values should be the same - BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 0) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 1) == encodeArgs(2)); - BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 0) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 1) == encodeArgs(false)); + ABI_CHECK(callContractFunction("getTopMapping(uint256)", 0), encodeArgs(1)); + ABI_CHECK(callContractFunction("getTopMapping(uint256)", 1), encodeArgs(2)); + ABI_CHECK(callContractFunction("getNestedMapping(uint256)", 0), encodeArgs(true)); + ABI_CHECK(callContractFunction("getNestedMapping(uint256)", 1), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(deleteLocal) @@ -1231,7 +1235,7 @@ BOOST_AUTO_TEST_CASE(deleteLocal) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("delLocal()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(deleteLocals) @@ -1249,7 +1253,7 @@ BOOST_AUTO_TEST_CASE(deleteLocals) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6, 7)); + ABI_CHECK(callContractFunction("delLocal()"), encodeArgs(6, 7)); } BOOST_AUTO_TEST_CASE(constructor) @@ -1287,7 +1291,7 @@ BOOST_AUTO_TEST_CASE(simple_accessor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); + ABI_CHECK(callContractFunction("data()"), encodeArgs(8)); } BOOST_AUTO_TEST_CASE(array_accessor) @@ -1314,14 +1318,14 @@ BOOST_AUTO_TEST_CASE(array_accessor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data(uint256)", 0) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("data(uint256)", 8) == encodeArgs()); - BOOST_CHECK(callContractFunction("dynamicData(uint256)", 2) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("dynamicData(uint256)", 8) == encodeArgs()); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 1) == encodeArgs(22)); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 127) == encodeArgs(2)); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 128) == encodeArgs()); - BOOST_CHECK(callContractFunction("multiple_map(uint256,uint256,uint256)", 2, 1, 2) == encodeArgs(3)); + ABI_CHECK(callContractFunction("data(uint256)", 0), encodeArgs(8)); + ABI_CHECK(callContractFunction("data(uint256)", 8), encodeArgs()); + ABI_CHECK(callContractFunction("dynamicData(uint256)", 2), encodeArgs(8)); + ABI_CHECK(callContractFunction("dynamicData(uint256)", 8), encodeArgs()); + ABI_CHECK(callContractFunction("smallTypeData(uint256)", 1), encodeArgs(22)); + ABI_CHECK(callContractFunction("smallTypeData(uint256)", 127), encodeArgs(2)); + ABI_CHECK(callContractFunction("smallTypeData(uint256)", 128), encodeArgs()); + ABI_CHECK(callContractFunction("multiple_map(uint256,uint256,uint256)", 2, 1, 2), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) @@ -1338,10 +1342,10 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", 2, 2) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("data(uint256, 256)", 2, 8) == encodeArgs()); - BOOST_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 2) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 8) == encodeArgs()); + ABI_CHECK(callContractFunction("data(uint256,uint256)", 2, 2), encodeArgs(8)); + ABI_CHECK(callContractFunction("data(uint256, 256)", 2, 8), encodeArgs()); + ABI_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 2), encodeArgs(8)); + ABI_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 8), encodeArgs()); } BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) @@ -1363,11 +1367,11 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); - BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::keccak256(bytes(1, 0x7b)))); - BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337)))); - BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); + ABI_CHECK(callContractFunction("data()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("name()"), encodeArgs("Celina")); + ABI_CHECK(callContractFunction("a_hash()"), encodeArgs(dev::keccak256(bytes(1, 0x7b)))); + ABI_CHECK(callContractFunction("an_address()"), encodeArgs(toBigEndian(u160(0x1337)))); + ABI_CHECK(callContractFunction("super_secret_data()"), bytes()); } BOOST_AUTO_TEST_CASE(complex_accessors) @@ -1387,10 +1391,10 @@ BOOST_AUTO_TEST_CASE(complex_accessors) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("to_string_map(uint256)", 42) == encodeArgs("24")); - BOOST_CHECK(callContractFunction("to_bool_map(uint256)", 42) == encodeArgs(false)); - BOOST_CHECK(callContractFunction("to_uint_map(uint256)", 42) == encodeArgs(12)); - BOOST_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23) == encodeArgs(31)); + ABI_CHECK(callContractFunction("to_string_map(uint256)", 42), encodeArgs("24")); + ABI_CHECK(callContractFunction("to_bool_map(uint256)", 42), encodeArgs(false)); + ABI_CHECK(callContractFunction("to_uint_map(uint256)", 42), encodeArgs(12)); + ABI_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23), encodeArgs(31)); } BOOST_AUTO_TEST_CASE(struct_accessor) @@ -1408,7 +1412,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data(uint256)", 7) == encodeArgs(1, 2, true)); + ABI_CHECK(callContractFunction("data(uint256)", 7), encodeArgs(1, 2, true)); } BOOST_AUTO_TEST_CASE(balance) @@ -1422,7 +1426,7 @@ BOOST_AUTO_TEST_CASE(balance) } )"; compileAndRun(sourceCode, 23); - BOOST_CHECK(callContractFunction("getBalance()") == encodeArgs(23)); + ABI_CHECK(callContractFunction("getBalance()"), encodeArgs(23)); } BOOST_AUTO_TEST_CASE(blockchain) @@ -1440,7 +1444,7 @@ BOOST_AUTO_TEST_CASE(blockchain) BOOST_CHECK(m_rpc.rpcCall("miner_setEtherbase", {"\"0x1212121212121212121212121212121212121212\""}).asBool() == true); m_rpc.test_mineBlocks(5); compileAndRun(sourceCode, 27); - BOOST_CHECK(callContractFunctionWithValue("someInfo()", 28) == encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7)); + ABI_CHECK(callContractFunctionWithValue("someInfo()", 28), encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7)); } BOOST_AUTO_TEST_CASE(msg_sig) @@ -1453,7 +1457,7 @@ BOOST_AUTO_TEST_CASE(msg_sig) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256)") == encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)", 0), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) @@ -1469,7 +1473,7 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256)") == encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)", 0), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(now) @@ -1490,7 +1494,7 @@ BOOST_AUTO_TEST_CASE(now) size_t endTime = blockTimestamp(endBlock); BOOST_CHECK(startBlock != endBlock); BOOST_CHECK(startTime != endTime); - BOOST_CHECK(ret == encodeArgs(true, endTime)); + ABI_CHECK(ret, encodeArgs(true, endTime)); } BOOST_AUTO_TEST_CASE(type_conversions_cleanup) @@ -1518,7 +1522,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_smaller_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("ab")); + ABI_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd"), encodeArgs("ab")); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size) @@ -1531,7 +1535,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToBytes(bytes2)", "ab") == encodeArgs("ab")); + ABI_CHECK(callContractFunction("bytesToBytes(bytes2)", "ab"), encodeArgs("ab")); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size) @@ -1544,7 +1548,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("abcd")); + ABI_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd"), encodeArgs("abcd")); } // fixed bytes to uint conversion tests @@ -1558,8 +1562,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes32)", string("abc2")) == - encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes32)", string("abc2")), + encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000")) + ); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size) @@ -1572,8 +1578,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes1)", string("a")) == - encodeArgs(u256("0x61"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes1)", string("a")), + encodeArgs(u256("0x61")) + ); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) @@ -1586,8 +1594,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == - encodeArgs(u256("0x6364"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes4)", string("abcd")), + encodeArgs(u256("0x6364")) + ); } BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) @@ -1600,8 +1610,10 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == - encodeArgs(u256("0x61626364"))); + ABI_CHECK( + callContractFunction("bytesToUint(bytes4)", string("abcd")), + encodeArgs(u256("0x61626364")) + ); } // uint fixed bytes conversion tests @@ -1616,7 +1628,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_size) )"; compileAndRun(sourceCode); u256 a("0x6162630000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK(callContractFunction("uintToBytes(uint256)", a) == encodeArgs(a)); + ABI_CHECK(callContractFunction("uintToBytes(uint256)", a), encodeArgs(a)); } BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size) @@ -1629,8 +1641,10 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("UintToBytes(uint8)", u256("0x61")) == - encodeArgs(string("a"))); + ABI_CHECK( + callContractFunction("UintToBytes(uint8)", u256("0x61")), + encodeArgs(string("a")) + ); } BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) @@ -1643,8 +1657,10 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("uintToBytes(uint32)", - u160("0x61626364")) == encodeArgs(string("cd"))); + ABI_CHECK( + callContractFunction("uintToBytes(uint32)", u160("0x61626364")), + encodeArgs(string("cd")) + ); } BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) @@ -1657,8 +1673,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) } )"; compileAndRun(sourceCode); - BOOST_CHECK( - callContractFunction("UintToBytes(uint16)", u256("0x6162")) == + ABI_CHECK( + callContractFunction("UintToBytes(uint16)", u256("0x6162")), encodeArgs(string("\0\0\0\0\0\0ab", 8)) ); } @@ -1677,7 +1693,7 @@ BOOST_AUTO_TEST_CASE(send_ether) u256 amount(130); compileAndRun(sourceCode, amount + 1); u160 address(23); - BOOST_CHECK(callContractFunction("a(address,uint256)", address, amount) == encodeArgs(1)); + ABI_CHECK(callContractFunction("a(address,uint256)", address, amount), encodeArgs(1)); BOOST_CHECK_EQUAL(balanceAt(address), amount); } @@ -1710,11 +1726,11 @@ BOOST_AUTO_TEST_CASE(transfer_ether) u160 const oogRecipient = m_contractAddress; compileAndRun(sourceCode, 20, "A"); u160 payableRecipient(23); - BOOST_CHECK(callContractFunction("a(address,uint256)", payableRecipient, 10) == encodeArgs(10)); + ABI_CHECK(callContractFunction("a(address,uint256)", payableRecipient, 10), encodeArgs(10)); BOOST_CHECK_EQUAL(balanceAt(payableRecipient), 10); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); - BOOST_CHECK(callContractFunction("b(address,uint256)", nonPayableRecipient, 10) == encodeArgs()); - BOOST_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10) == encodeArgs()); + ABI_CHECK(callContractFunction("b(address,uint256)", nonPayableRecipient, 10), encodeArgs()); + ABI_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10), encodeArgs()); } BOOST_AUTO_TEST_CASE(log0) @@ -1840,7 +1856,7 @@ BOOST_AUTO_TEST_CASE(suicide) u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); - BOOST_CHECK(callContractFunction("a(address)", address) == bytes()); + ABI_CHECK(callContractFunction("a(address)", address), bytes()); BOOST_CHECK(!addressHasCode(m_contractAddress)); BOOST_CHECK_EQUAL(balanceAt(address), amount); } @@ -1859,7 +1875,7 @@ BOOST_AUTO_TEST_CASE(selfdestruct) u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); - BOOST_CHECK(callContractFunction("a(address)", address) == bytes()); + ABI_CHECK(callContractFunction("a(address)", address), bytes()); BOOST_CHECK(!addressHasCode(m_contractAddress)); BOOST_CHECK_EQUAL(balanceAt(address), amount); } @@ -2046,7 +2062,7 @@ BOOST_AUTO_TEST_CASE(ecrecover) u256 r("0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"); u256 s("0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"); u160 addr("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); - BOOST_CHECK(callContractFunction("a(bytes32,uint8,bytes32,bytes32)", h, v, r, s) == encodeArgs(addr)); + ABI_CHECK(callContractFunction("a(bytes32,uint8,bytes32,bytes32)", h, v, r, s), encodeArgs(addr)); } BOOST_AUTO_TEST_CASE(inter_contract_calls) @@ -2231,7 +2247,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_in_calls) compileAndRun(sourceCode, 0, "Main"); BOOST_REQUIRE(callContractFunction("setHelper(address)", c_helperAddress) == bytes()); BOOST_REQUIRE(callContractFunction("getHelper()", c_helperAddress) == encodeArgs(c_helperAddress)); - BOOST_CHECK(callContractFunction("callHelper(bytes2,bool)", string("\0a", 2), true) == encodeArgs(string("\0a\0\0\0", 5))); + ABI_CHECK(callContractFunction("callHelper(bytes2,bool)", string("\0a", 2), true), encodeArgs(string("\0a\0\0\0", 5))); } BOOST_AUTO_TEST_CASE(constructor_arguments_internal) @@ -2257,8 +2273,8 @@ BOOST_AUTO_TEST_CASE(constructor_arguments_internal) function getName() returns (bytes3 ret) { return h.getName(); } })"; compileAndRun(sourceCode, 0, "Main"); - BOOST_CHECK(callContractFunction("getFlag()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getName()") == encodeArgs("abc")); + ABI_CHECK(callContractFunction("getFlag()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("getName()"), encodeArgs("abc")); } BOOST_AUTO_TEST_CASE(constructor_arguments_external) @@ -2277,8 +2293,8 @@ BOOST_AUTO_TEST_CASE(constructor_arguments_external) } )"; compileAndRun(sourceCode, 0, "Main", encodeArgs("abc", true)); - BOOST_CHECK(callContractFunction("getFlag()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getName()") == encodeArgs("abc")); + ABI_CHECK(callContractFunction("getFlag()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("getName()"), encodeArgs("abc")); } BOOST_AUTO_TEST_CASE(constructor_with_long_arguments) @@ -2305,8 +2321,8 @@ BOOST_AUTO_TEST_CASE(constructor_with_long_arguments) u256(b.length()), b )); - BOOST_CHECK(callContractFunction("a()") == encodeDyn(a)); - BOOST_CHECK(callContractFunction("b()") == encodeDyn(b)); + ABI_CHECK(callContractFunction("a()"), encodeDyn(a)); + ABI_CHECK(callContractFunction("b()"), encodeDyn(b)); } BOOST_AUTO_TEST_CASE(constructor_static_array_argument) @@ -2323,10 +2339,10 @@ BOOST_AUTO_TEST_CASE(constructor_static_array_argument) } )"; compileAndRun(sourceCode, 0, "C", encodeArgs(u256(1), u256(2), u256(3), u256(4))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("b(uint256)", u256(0)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("b(uint256)", u256(1)) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("b(uint256)", u256(2)) == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("b(uint256)", u256(0)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("b(uint256)", u256(1)), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("b(uint256)", u256(2)), encodeArgs(u256(4))); } BOOST_AUTO_TEST_CASE(functions_called_by_constructor) @@ -2485,8 +2501,8 @@ BOOST_AUTO_TEST_CASE(virtual_function_calls) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(2)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(access_base_storage) @@ -2510,9 +2526,9 @@ BOOST_AUTO_TEST_CASE(access_base_storage) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("setData(uint256,uint256)", 1, 2) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getViaBase()") == encodeArgs(1)); - BOOST_CHECK(callContractFunction("getViaDerived()") == encodeArgs(1, 2)); + ABI_CHECK(callContractFunction("setData(uint256,uint256)", 1, 2), encodeArgs(true)); + ABI_CHECK(callContractFunction("getViaBase()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("getViaDerived()"), encodeArgs(1, 2)); } BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) @@ -2528,9 +2544,9 @@ BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance) contract Derived is Base, B, A { } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("setViaA(uint256)", 23) == encodeArgs()); - BOOST_CHECK(callContractFunction("getViaB()") == encodeArgs(23)); + ABI_CHECK(callContractFunction("getViaB()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("setViaA(uint256)", 23), encodeArgs()); + ABI_CHECK(callContractFunction("getViaB()"), encodeArgs(23)); } BOOST_AUTO_TEST_CASE(explicit_base_class) @@ -2544,8 +2560,8 @@ BOOST_AUTO_TEST_CASE(explicit_base_class) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(3)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(base_constructor_arguments) @@ -2567,7 +2583,7 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(7 * 7)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(7 * 7)); } BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments) @@ -2587,7 +2603,7 @@ BOOST_AUTO_TEST_CASE(function_usage_in_constructor_arguments) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments) @@ -2609,7 +2625,7 @@ BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(constructor_argument_overriding) @@ -2627,7 +2643,7 @@ BOOST_AUTO_TEST_CASE(constructor_argument_overriding) } )"; compileAndRun(sourceCode, 0, "Derived"); - BOOST_CHECK(callContractFunction("getA()") == encodeArgs(3)); + ABI_CHECK(callContractFunction("getA()"), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(internal_constructor) @@ -2649,8 +2665,8 @@ BOOST_AUTO_TEST_CASE(function_modifier) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getOne()") == encodeArgs(0)); - BOOST_CHECK(callContractFunctionWithValue("getOne()", 1) == encodeArgs(1)); + ABI_CHECK(callContractFunction("getOne()"), encodeArgs(0)); + ABI_CHECK(callContractFunctionWithValue("getOne()", 1), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(function_modifier_local_variables) @@ -2663,8 +2679,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_local_variables) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(3)); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(0)); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(function_modifier_loop) @@ -2676,7 +2692,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_loop) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(10)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(function_modifier_multi_invocation) @@ -2688,8 +2704,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_invocation) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(2)); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(function_modifier_multi_with_return) @@ -2703,8 +2719,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multi_with_return) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bool)", false) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", true) == encodeArgs(2)); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(function_modifier_overriding) @@ -2719,7 +2735,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_overriding) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context) @@ -2742,7 +2758,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0x4300)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(0x4300)); } BOOST_AUTO_TEST_CASE(function_modifier_for_constructor) @@ -2759,7 +2775,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_for_constructor) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(4 | 2)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(4 | 2)); } BOOST_AUTO_TEST_CASE(function_modifier_multiple_times) @@ -2772,8 +2788,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(2 + 5 + 3)); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(2 + 5 + 3)); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(2 + 5 + 3)); + ABI_CHECK(callContractFunction("a()"), encodeArgs(2 + 5 + 3)); } BOOST_AUTO_TEST_CASE(function_modifier_multiple_times_local_vars) @@ -2786,8 +2802,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times_local_vars) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(2 + 5 + 3)); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(2 + 5 + 3)); + ABI_CHECK(callContractFunction("a()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) @@ -2803,7 +2819,7 @@ BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(-7))); } BOOST_AUTO_TEST_CASE(super) @@ -2815,7 +2831,7 @@ BOOST_AUTO_TEST_CASE(super) contract D is B, C { function f() returns (uint r) { return super.f() | 8; } } )"; compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 | 2 | 4 | 8)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8)); } BOOST_AUTO_TEST_CASE(super_in_constructor) @@ -2827,7 +2843,7 @@ BOOST_AUTO_TEST_CASE(super_in_constructor) contract D is B, C { uint data; function D() { data = super.f() | 8; } function f() returns (uint r) { return data; } } )"; compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 | 2 | 4 | 8)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8)); } BOOST_AUTO_TEST_CASE(super_alone) @@ -2836,7 +2852,7 @@ BOOST_AUTO_TEST_CASE(super_alone) contract A { function f() { super; } } )"; compileAndRun(sourceCode, 0, "A"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(fallback_function) @@ -2849,9 +2865,9 @@ BOOST_AUTO_TEST_CASE(fallback_function) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("") == encodeArgs()); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(0)); + ABI_CHECK(callContractFunction(""), encodeArgs()); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(inherited_fallback_function) @@ -2865,9 +2881,9 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function) contract B is A {} )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("") == encodeArgs()); - BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(0)); + ABI_CHECK(callContractFunction(""), encodeArgs()); + ABI_CHECK(callContractFunction("getData()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(default_fallback_throws) @@ -2880,7 +2896,26 @@ BOOST_AUTO_TEST_CASE(default_fallback_throws) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); +} + +BOOST_AUTO_TEST_CASE(short_data_calls_fallback) +{ + char const* sourceCode = R"( + contract A { + uint public x; + // Signature is d88e0b00 + function fow() { x = 3; } + function () { x = 2; } + } + )"; + compileAndRun(sourceCode); + // should call fallback + sendMessage(asBytes("\xd8\x8e\x0b"), false, 0); + ABI_CHECK(callContractFunction("x()"), encodeArgs(2)); + // should call function + sendMessage(asBytes(string("\xd8\x8e\x0b") + string(1, 0)), false, 0); + ABI_CHECK(callContractFunction("x()"), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(event) @@ -2980,21 +3015,21 @@ BOOST_AUTO_TEST_CASE(events_with_same_name) u160 const c_loggedAddress = m_contractAddress; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("deposit()") == encodeArgs(u256(1))); + 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()"))); - BOOST_CHECK(callContractFunction("deposit(address)", c_loggedAddress) == encodeArgs(u256(1))); + 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)"))); - BOOST_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)) == encodeArgs(u256(1))); + 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)); @@ -3032,21 +3067,21 @@ BOOST_AUTO_TEST_CASE(events_with_same_name_inherited) u160 const c_loggedAddress = m_contractAddress; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("deposit()") == encodeArgs(u256(1))); + 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()"))); - BOOST_CHECK(callContractFunction("deposit(address)", c_loggedAddress) == encodeArgs(u256(1))); + 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)"))); - BOOST_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)) == encodeArgs(u256(1))); + 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)); @@ -3074,7 +3109,7 @@ 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, bool _manually) payable { + function deposit(bytes32 _id) payable { Deposit(msg.sender, _id, msg.value, 2, "abc"); } } @@ -3082,7 +3117,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics) compileAndRun(sourceCode); u256 value(18); u256 id(0x1234); - callContractFunctionWithValue("deposit(bytes32,bool)", value, id); + callContractFunctionWithValue("deposit(bytes32)", value, id); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs("abc")); @@ -3230,7 +3265,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8)); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8)); + ABI_CHECK(callContractFunction("f(uint256,uint256)", 5, 9), encodeArgs(9, 8)); } BOOST_AUTO_TEST_CASE(empty_name_return_parameter) @@ -3243,7 +3278,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9)); + ABI_CHECK(callContractFunction("f(uint256)", 9), encodeArgs(9)); } BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments) @@ -3258,11 +3293,13 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - toBigEndian(u256(12)) + - toBigEndian(u256(13))))); + 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(keccak256_multiple_arguments_with_numeric_literals) @@ -3277,11 +3314,13 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_numeric_literals) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - bytes{0x0, 0xc} + - bytes(1, 0x91)))); + ABI_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12), encodeArgs( + dev::keccak256( + toBigEndian(u256(10)) + + bytes{0x0, 0xc} + + bytes(1, 0x91) + ) + )); } BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_string_literals) @@ -3300,14 +3339,16 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_string_literals) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::keccak256("foo"))); + ABI_CHECK(callContractFunction("foo()"), encodeArgs(dev::keccak256("foo"))); - BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - bytes{0x0, 0xc} + - bytes(1, 0x91) + - bytes{0x66, 0x6f, 0x6f}))); + ABI_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12), encodeArgs( + dev::keccak256( + toBigEndian(u256(10)) + + bytes{0x0, 0xc} + + bytes(1, 0x91) + + bytes{0x66, 0x6f, 0x6f} + ) + )); } BOOST_AUTO_TEST_CASE(keccak256_with_bytes) @@ -3326,7 +3367,7 @@ BOOST_AUTO_TEST_CASE(keccak256_with_bytes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("foo()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) @@ -3345,7 +3386,7 @@ BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo()") == encodeArgs( + ABI_CHECK(callContractFunction("foo()"), encodeArgs( u256(dev::keccak256(bytes{'b'} + dev::keccak256("xyz").asBytes() + bytes{'a'})) )); } @@ -3361,7 +3402,7 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( + ABI_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13), encodeArgs( dev::keccak256( toBigEndian(u256(10)) + toBigEndian(u256(12)) + @@ -3416,10 +3457,10 @@ BOOST_AUTO_TEST_CASE(generic_callcode) u160 const c_receiverAddress = m_contractAddress; compileAndRun(sourceCode, 50, "Sender"); u160 const c_senderAddress = m_contractAddress; - BOOST_CHECK(callContractFunction("doSend(address)", c_receiverAddress) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("received()") == encodeArgs(23)); + ABI_CHECK(callContractFunction("doSend(address)", c_receiverAddress), encodeArgs(0)); + ABI_CHECK(callContractFunction("received()"), encodeArgs(23)); m_contractAddress = c_receiverAddress; - BOOST_CHECK(callContractFunction("received()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("received()"), encodeArgs(0)); BOOST_CHECK(storageEmpty(c_receiverAddress)); BOOST_CHECK(!storageEmpty(c_senderAddress)); BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); @@ -3453,14 +3494,14 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall) compileAndRun(sourceCode, 50, "Sender"); u160 const c_senderAddress = m_contractAddress; BOOST_CHECK(m_sender != c_senderAddress); // just for sanity - BOOST_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress) == encodeArgs()); - BOOST_CHECK(callContractFunction("received()") == encodeArgs(u256(23))); - BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u160(m_sender))); - BOOST_CHECK(callContractFunction("value()") == encodeArgs(u256(11))); + ABI_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress), encodeArgs()); + ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(23))); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender))); + ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(11))); m_contractAddress = c_receiverAddress; - BOOST_CHECK(callContractFunction("received()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("value()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("received()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("value()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(c_receiverAddress)); BOOST_CHECK(!storageEmpty(c_senderAddress)); BOOST_CHECK_EQUAL(balanceAt(c_receiverAddress), 0); @@ -3480,8 +3521,8 @@ BOOST_AUTO_TEST_CASE(library_call_in_homestead) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u160(m_sender))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("sender()"), encodeArgs(u160(m_sender))); } BOOST_AUTO_TEST_CASE(store_bytes) @@ -3499,8 +3540,8 @@ BOOST_AUTO_TEST_CASE(store_bytes) )"; compileAndRun(sourceCode); // empty copy loop - BOOST_CHECK(callContractFunction("save()") == encodeArgs(24)); - BOOST_CHECK(callContractFunction("save()", "abcdefg") == encodeArgs(24)); + ABI_CHECK(callContractFunction("save()"), encodeArgs(24)); + ABI_CHECK(callContractFunction("save()", "abcdefg"), encodeArgs(24)); } BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) @@ -3537,14 +3578,14 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes) } )"; compileAndRun(sourceCode, 0, "sender"); - BOOST_CHECK(callContractFunction("receive(uint256)", 7) == bytes()); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("forward()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("clear()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("forward()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0x80)); + ABI_CHECK(callContractFunction("receive(uint256)", 7), bytes()); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("forward()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("clear()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("forward()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80)); } BOOST_AUTO_TEST_CASE(copying_bytes_multiassign) @@ -3570,14 +3611,14 @@ BOOST_AUTO_TEST_CASE(copying_bytes_multiassign) } )"; compileAndRun(sourceCode, 0, "sender"); - BOOST_CHECK(callContractFunction("receive(uint256)", 7) == bytes()); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("forward(bool)", true) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(8)); - BOOST_CHECK(callContractFunction("forward(bool)", false) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(16)); - BOOST_CHECK(callContractFunction("forward(bool)", true) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("val()") == encodeArgs(0x80)); + ABI_CHECK(callContractFunction("receive(uint256)", 7), bytes()); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("forward(bool)", true), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("forward(bool)", false), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(16)); + ABI_CHECK(callContractFunction("forward(bool)", true), encodeArgs(true)); + ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80)); } BOOST_AUTO_TEST_CASE(delete_removes_bytes_data) @@ -3590,9 +3631,9 @@ BOOST_AUTO_TEST_CASE(delete_removes_bytes_data) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("---", 7) == bytes()); + ABI_CHECK(callContractFunction("---", 7), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("del()", 7) == encodeArgs(true)); + ABI_CHECK(callContractFunction("del()", 7), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3606,7 +3647,7 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); sendMessage(bytes(), false); BOOST_CHECK(m_output == bytes()); @@ -3624,9 +3665,9 @@ BOOST_AUTO_TEST_CASE(copy_removes_bytes_data) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("reset()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("reset()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3641,16 +3682,16 @@ BOOST_AUTO_TEST_CASE(bytes_inside_mappings) )"; compileAndRun(sourceCode); // store a short byte array at 1 and a longer one at 2 - BOOST_CHECK(callContractFunction("set(uint256)", 1, 2) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("set(uint256)", 2, 2, 3, 4, 5) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256)", 1, 2), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256)", 2, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); // copy shorter to longer - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 1, 2) == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 1, 2), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); // copy empty to both - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 99, 1) == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 1), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 99, 2) == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 2), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3664,9 +3705,9 @@ BOOST_AUTO_TEST_CASE(bytes_length_member) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getLength()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("set()", 1, 2) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("getLength()") == encodeArgs(4+32+32)); + ABI_CHECK(callContractFunction("getLength()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("set()", 1, 2), encodeArgs(true)); + ABI_CHECK(callContractFunction("getLength()"), encodeArgs(4+32+32)); } BOOST_AUTO_TEST_CASE(struct_copy) @@ -3697,16 +3738,16 @@ BOOST_AUTO_TEST_CASE(struct_copy) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set(uint256)", 7) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 7) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 7) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 8) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 0, 7) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 7) == encodeArgs(0, 0, 0, 0)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 8) == encodeArgs(1, 3, 4, 2)); - BOOST_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("retrieve(uint256)", 8) == encodeArgs(0, 0, 0, 0)); + ABI_CHECK(callContractFunction("set(uint256)", 7), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 7), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 7), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 8), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 0, 7), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 7), encodeArgs(0, 0, 0, 0)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 8), encodeArgs(1, 3, 4, 2)); + ABI_CHECK(callContractFunction("copy(uint256,uint256)", 7, 8), encodeArgs(true)); + ABI_CHECK(callContractFunction("retrieve(uint256)", 8), encodeArgs(0, 0, 0, 0)); } BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) @@ -3735,13 +3776,13 @@ BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) compileAndRun(sourceCode); string data = "123456789012345678901234567890123"; BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("copy()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("copy()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("del()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("del()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -3762,7 +3803,7 @@ BOOST_AUTO_TEST_CASE(struct_copy_via_local) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(using_enums) @@ -3782,7 +3823,7 @@ BOOST_AUTO_TEST_CASE(using_enums) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getChoice()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("getChoice()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(enum_explicit_overflow) @@ -3813,12 +3854,12 @@ BOOST_AUTO_TEST_CASE(enum_explicit_overflow) )"; compileAndRun(sourceCode); // These should throw - BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 3) == encodeArgs()); - BOOST_CHECK(callContractFunction("getChoiceFromSigned(int256)", -1) == encodeArgs()); - BOOST_CHECK(callContractFunction("getChoiceFromNegativeLiteral()") == encodeArgs()); + ABI_CHECK(callContractFunction("getChoiceExp(uint256)", 3), encodeArgs()); + ABI_CHECK(callContractFunction("getChoiceFromSigned(int256)", -1), encodeArgs()); + ABI_CHECK(callContractFunction("getChoiceFromNegativeLiteral()"), encodeArgs()); // These should work - BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 2) == encodeArgs(2)); - BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 0) == encodeArgs(0)); + ABI_CHECK(callContractFunction("getChoiceExp(uint256)", 2), encodeArgs(2)); + ABI_CHECK(callContractFunction("getChoiceExp(uint256)", 0), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(storing_invalid_boolean) @@ -3853,10 +3894,10 @@ BOOST_AUTO_TEST_CASE(storing_invalid_boolean) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("set()") == encodeArgs(1)); - BOOST_CHECK(callContractFunction("perm()") == encodeArgs(1)); - BOOST_CHECK(callContractFunction("ret()") == encodeArgs(1)); - BOOST_CHECK(callContractFunction("ev()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("set()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("perm()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("ret()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("ev()"), encodeArgs(1)); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs(1)); @@ -3877,7 +3918,7 @@ BOOST_AUTO_TEST_CASE(using_contract_enums_with_explicit_contract_name) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("answer()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("answer()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(using_inherited_enum) @@ -3895,7 +3936,7 @@ BOOST_AUTO_TEST_CASE(using_inherited_enum) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("answer()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("answer()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(using_inherited_enum_excplicitly) @@ -3913,7 +3954,7 @@ BOOST_AUTO_TEST_CASE(using_inherited_enum_excplicitly) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("answer()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("answer()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) @@ -3928,7 +3969,7 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(inline_member_init) @@ -3949,7 +3990,7 @@ BOOST_AUTO_TEST_CASE(inline_member_init) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(5, 6, 8)); + ABI_CHECK(callContractFunction("get()"), encodeArgs(5, 6, 8)); } BOOST_AUTO_TEST_CASE(inline_member_init_inheritence) @@ -3966,8 +4007,8 @@ BOOST_AUTO_TEST_CASE(inline_member_init_inheritence) function getDMember() returns (uint i) { return m_derived; } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getBMember()") == encodeArgs(5)); - BOOST_CHECK(callContractFunction("getDMember()") == encodeArgs(6)); + ABI_CHECK(callContractFunction("getBMember()"), encodeArgs(5)); + ABI_CHECK(callContractFunction("getDMember()"), encodeArgs(6)); } BOOST_AUTO_TEST_CASE(inline_member_init_inheritence_without_constructor) @@ -3982,8 +4023,8 @@ BOOST_AUTO_TEST_CASE(inline_member_init_inheritence_without_constructor) function getDMember() returns (uint i) { return m_derived; } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getBMember()") == encodeArgs(5)); - BOOST_CHECK(callContractFunction("getDMember()") == encodeArgs(6)); + ABI_CHECK(callContractFunction("getBMember()"), encodeArgs(5)); + ABI_CHECK(callContractFunction("getDMember()"), encodeArgs(6)); } BOOST_AUTO_TEST_CASE(external_function) @@ -3998,7 +4039,7 @@ BOOST_AUTO_TEST_CASE(external_function) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", 2, 3) == encodeArgs(2+7, 3)); + ABI_CHECK(callContractFunction("test(uint256,uint256)", 2, 3), encodeArgs(2+7, 3)); } BOOST_AUTO_TEST_CASE(bytes_in_arguments) @@ -4026,8 +4067,10 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) 12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, u256(innercalldata1.length()), innercalldata1, u256(innercalldata2.length()), innercalldata2); - BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata) - == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); + ABI_CHECK( + callContractFunction("test(uint256,bytes,bytes,uint256)", calldata), + encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length())) + ); } BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) @@ -4046,15 +4089,15 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); - BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); - BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); - BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); - BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(u256(1) << 10, (u256(1) << 10) + 3)); + ABI_CHECK(callContractFunction("setIDStatic(uint256)", 11), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 2), encodeArgs(11)); + ABI_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 7), encodeArgs(8)); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9), bytes()); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11), bytes()); + ABI_CHECK(callContractFunction("getData(uint256)", 7), encodeArgs(8, 9)); + ABI_CHECK(callContractFunction("getData(uint256)", 8), encodeArgs(10, 11)); + ABI_CHECK(callContractFunction("getLengths()"), encodeArgs(u256(1) << 10, (u256(1) << 10) + 3)); } BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) @@ -4074,17 +4117,17 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(0, 0)); - BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes()); - BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49)); - BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); - BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); - BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); - BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); - BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); - BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); + ABI_CHECK(callContractFunction("getLengths()"), encodeArgs(0, 0)); + ABI_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49), bytes()); + ABI_CHECK(callContractFunction("getLengths()"), encodeArgs(48, 49)); + ABI_CHECK(callContractFunction("setIDStatic(uint256)", 11), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 2), encodeArgs(11)); + ABI_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8), bytes()); + ABI_CHECK(callContractFunction("getID(uint256)", 7), encodeArgs(8)); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9), bytes()); + ABI_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11), bytes()); + ABI_CHECK(callContractFunction("getData(uint256)", 7), encodeArgs(8, 9)); + ABI_CHECK(callContractFunction("getData(uint256)", 8), encodeArgs(10, 11)); } BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access) @@ -4098,14 +4141,14 @@ BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 5) == bytes()); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 400, 5) == bytes()); - BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); - BOOST_CHECK(callContractFunction("get(uint256)", 4) == bytes()); - BOOST_CHECK(callContractFunction("get(uint256)", 400) == bytes()); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 3, 4), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 4, 5), bytes()); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 400, 5), bytes()); + ABI_CHECK(callContractFunction("get(uint256)", 3), encodeArgs(4)); + ABI_CHECK(callContractFunction("get(uint256)", 4), bytes()); + ABI_CHECK(callContractFunction("get(uint256)", 400), bytes()); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access) @@ -4120,15 +4163,15 @@ BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(0)); - BOOST_CHECK(callContractFunction("get(uint256)", 3) == bytes()); - BOOST_CHECK(callContractFunction("enlarge(uint256)", 4) == encodeArgs(4)); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); - BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 8) == bytes()); - BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(0)); + ABI_CHECK(callContractFunction("get(uint256)", 3), bytes()); + ABI_CHECK(callContractFunction("enlarge(uint256)", 4), encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 3, 4), encodeArgs(true)); + ABI_CHECK(callContractFunction("get(uint256)", 3), encodeArgs(4)); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("set(uint256,uint256)", 4, 8), bytes()); + ABI_CHECK(callContractFunction("length()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(fixed_array_cleanup) @@ -4146,9 +4189,9 @@ BOOST_AUTO_TEST_CASE(fixed_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == bytes()); + ABI_CHECK(callContractFunction("fill()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == bytes()); + ABI_CHECK(callContractFunction("clear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4167,9 +4210,9 @@ BOOST_AUTO_TEST_CASE(short_fixed_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == bytes()); + ABI_CHECK(callContractFunction("fill()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == bytes()); + ABI_CHECK(callContractFunction("clear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4189,11 +4232,11 @@ BOOST_AUTO_TEST_CASE(dynamic_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == bytes()); + ABI_CHECK(callContractFunction("fill()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("halfClear()") == bytes()); + ABI_CHECK(callContractFunction("halfClear()"), bytes()); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fullClear()") == bytes()); + ABI_CHECK(callContractFunction("fullClear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4215,9 +4258,9 @@ BOOST_AUTO_TEST_CASE(dynamic_multi_array_cleanup) )"; compileAndRun(sourceCode); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("fill()") == encodeArgs(8)); + ABI_CHECK(callContractFunction("fill()"), encodeArgs(8)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == bytes()); + ABI_CHECK(callContractFunction("clear()"), bytes()); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4237,12 +4280,12 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_dyn_dyn) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 10, 5, 4) == bytes()); - BOOST_CHECK(callContractFunction("copyStorageStorage()") == bytes()); - BOOST_CHECK(callContractFunction("getData2(uint256)", 5) == encodeArgs(10, 4)); - BOOST_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 0, 0, 0) == bytes()); - BOOST_CHECK(callContractFunction("copyStorageStorage()") == bytes()); - BOOST_CHECK(callContractFunction("getData2(uint256)", 0) == encodeArgs(0, 0)); + ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 10, 5, 4), bytes()); + ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes()); + ABI_CHECK(callContractFunction("getData2(uint256)", 5), encodeArgs(10, 4)); + ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 0, 0, 0), bytes()); + ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes()); + ABI_CHECK(callContractFunction("getData2(uint256)", 0), encodeArgs(0, 0)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4264,7 +4307,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_static) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(8, 0)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(8, 0)); } BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_dynamic) @@ -4282,7 +4325,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_dynamic) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(9, 4)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(9, 4)); } BOOST_AUTO_TEST_CASE(array_copy_different_packing) @@ -4305,7 +4348,7 @@ BOOST_AUTO_TEST_CASE(array_copy_different_packing) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( asString(fromHex("0000000000000001")), asString(fromHex("0000000000000002")), asString(fromHex("0000000000000003")), @@ -4334,7 +4377,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_simple) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( asString(fromHex("0000000000000001")), asString(fromHex("0000000000000002")), asString(fromHex("0000000000000003")), @@ -4366,7 +4409,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( u256("0xffffffff"), asString(fromHex("0000000000000000""000000000a000900""0800070006000500""0400030002000100")), asString(fromHex("0000000000000000""0000000000000000""0000000000000000""0000000000000000")) @@ -4396,7 +4439,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover2) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs( + ABI_CHECK(callContractFunction("test()"), encodeArgs( asString(fromHex("0000000000000004")), asString(fromHex("0000000000000000")), asString(fromHex("0000000000000000")) @@ -4423,7 +4466,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(4, 5)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(4, 5)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4466,10 +4509,10 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) bytes valueSequence; for (size_t i = 0; i < 101; ++i) valueSequence += toBigEndian(u256(i)); - BOOST_CHECK(callContractFunction("test1()") == encodeArgs(0x20, 101) + valueSequence); - BOOST_CHECK(callContractFunction("test2()") == encodeArgs(0x20, 101) + valueSequence); - BOOST_CHECK(callContractFunction("test3()") == encodeArgs(0x20, 101) + valueSequence); - BOOST_CHECK(callContractFunction("test4()") == + ABI_CHECK(callContractFunction("test1()"), encodeArgs(0x20, 101) + valueSequence); + ABI_CHECK(callContractFunction("test2()"), encodeArgs(0x20, 101) + valueSequence); + ABI_CHECK(callContractFunction("test3()"), encodeArgs(0x20, 101) + valueSequence); + ABI_CHECK(callContractFunction("test4()"), encodeArgs(0x20, 5, 0xa0, 0xa0 + 102 * 32 * 1, 0xa0 + 102 * 32 * 2, 0xa0 + 102 * 32 * 3, 0xa0 + 102 * 32 * 4) + encodeArgs(101) + valueSequence + encodeArgs(101) + valueSequence + @@ -4501,7 +4544,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi_signed) )"; compileAndRun(sourceCode); bytes valueSequence; - BOOST_CHECK(callContractFunction("test()") == encodeArgs(0x20, 8, + ABI_CHECK(callContractFunction("test()"), encodeArgs(0x20, 8, u256(-1), u256(-1), u256(8), @@ -4529,7 +4572,7 @@ BOOST_AUTO_TEST_CASE(array_push) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(5, 4, 3, 3)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(5, 4, 3, 3)); } BOOST_AUTO_TEST_CASE(byte_array_push) @@ -4549,7 +4592,7 @@ BOOST_AUTO_TEST_CASE(byte_array_push) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(external_array_args) @@ -4573,7 +4616,7 @@ BOOST_AUTO_TEST_CASE(external_array_args) 3, // b.length 11, 12, 13 // b ); - BOOST_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params) == encodeArgs(1, 12, 23)); + ABI_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params), encodeArgs(1, 12, 23)); } BOOST_AUTO_TEST_CASE(bytes_index_access) @@ -4607,9 +4650,9 @@ BOOST_AUTO_TEST_CASE(bytes_index_access) 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33}; - BOOST_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33)); - BOOST_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33)); - BOOST_CHECK(callContractFunction("storageWrite()") == encodeArgs(0x193)); + ABI_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); + ABI_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); + ABI_CHECK(callContractFunction("storageWrite()"), encodeArgs(0x193)); } BOOST_AUTO_TEST_CASE(bytes_delete_element) @@ -4629,7 +4672,7 @@ BOOST_AUTO_TEST_CASE(bytes_delete_element) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test1()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test1()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) @@ -4657,7 +4700,7 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs( + ABI_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs( 21, 22, 23, 24, 25, 26, 27, 28, 29, // a u256(32 * (9 + 1)), 4, // size of b @@ -4665,8 +4708,8 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) 11, 12, 13, // b[1] 21, 22, 23, // b[2] 31, 32, 33 // b[3] - )) == encodeArgs(32)); - BOOST_CHECK(callContractFunction("retrieve()") == encodeArgs( + )), encodeArgs(32)); + ABI_CHECK(callContractFunction("retrieve()"), encodeArgs( 9, 28, 9, 28, 4, 3, 32)); } @@ -4687,12 +4730,12 @@ BOOST_AUTO_TEST_CASE(array_copy_nested_array) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test(uint256[2][])", encodeArgs( + ABI_CHECK(callContractFunction("test(uint256[2][])", encodeArgs( 32, 3, 7, 8, 9, 10, 11, 12 - )) == encodeArgs(10)); + )), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(array_copy_including_mapping) @@ -4725,10 +4768,10 @@ BOOST_AUTO_TEST_CASE(array_copy_including_mapping) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(0x02000200)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000200)); // storage is not empty because we cannot delete the mappings BOOST_CHECK(!storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("clear()") == encodeArgs(7)); + ABI_CHECK(callContractFunction("clear()"), encodeArgs(7)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -4754,14 +4797,14 @@ BOOST_AUTO_TEST_CASE(swap_in_storage_overwrite) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0), u256(0))); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(0), u256(0))); - BOOST_CHECK(callContractFunction("set()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1), u256(2))); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(3), u256(4))); - BOOST_CHECK(callContractFunction("swap()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1), u256(2))); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0), u256(0))); + ABI_CHECK(callContractFunction("y()"), encodeArgs(u256(0), u256(0))); + ABI_CHECK(callContractFunction("set()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("y()"), encodeArgs(u256(3), u256(4))); + ABI_CHECK(callContractFunction("swap()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1), u256(2))); + ABI_CHECK(callContractFunction("y()"), encodeArgs(u256(1), u256(2))); } BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base) @@ -4781,7 +4824,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base) contract Final is Derived(4) { })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base) @@ -4804,7 +4847,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base) contract Final is Derived(4) { })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap) @@ -4824,7 +4867,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap) contract Final is Derived(4) { })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("m_i()") == encodeArgs(4)); + ABI_CHECK(callContractFunction("m_i()"), encodeArgs(4)); } BOOST_AUTO_TEST_CASE(simple_constant_variables_test) @@ -4835,7 +4878,7 @@ BOOST_AUTO_TEST_CASE(simple_constant_variables_test) uint constant x = 56; })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getX()") == encodeArgs(56)); + ABI_CHECK(callContractFunction("getX()"), encodeArgs(56)); } BOOST_AUTO_TEST_CASE(constant_variables) @@ -4859,7 +4902,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_expression) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(0x123 + 0x456 + 1)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x123 + 0x456 + 1)); } BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) @@ -4871,7 +4914,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(dev::keccak256("abc"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(dev::keccak256("abc"))); } // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented @@ -4885,7 +4928,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) // } // )"; // compileAndRun(sourceCode); -// BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 + 2 + 3)); +// ABI_CHECK(callContractFunction("f()"), encodeArgs(1 + 2 + 3)); //} // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented @@ -4899,7 +4942,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak) // } // )"; // compileAndRun(sourceCode); -// BOOST_CHECK(callContractFunction("f()") == encodeArgs(5)); +// ABI_CHECK(callContractFunction("f()"), encodeArgs(5)); //} BOOST_AUTO_TEST_CASE(packed_storage_structs_uint) @@ -4929,7 +4972,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_uint) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(packed_storage_structs_enum) @@ -4961,7 +5004,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_enum) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(packed_storage_structs_bytes) @@ -4991,7 +5034,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_bytes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(packed_storage_structs_delete) @@ -5021,7 +5064,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_delete) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -5035,7 +5078,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_first) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(3)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_second) @@ -5048,7 +5091,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_second) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(10)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else) @@ -5066,8 +5109,8 @@ BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(3)); - BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs(10)); + ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(3)); + ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs(10)); } BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct) @@ -5080,7 +5123,7 @@ BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect) @@ -5094,8 +5137,8 @@ BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(10)); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(10)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(super_overload) @@ -5109,8 +5152,8 @@ BOOST_AUTO_TEST_CASE(super_overload) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(10)); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(10)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(bool_conversion) @@ -5129,16 +5172,16 @@ BOOST_AUTO_TEST_CASE(bool_conversion) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(bool)", 0) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("f(bool)", 1) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", 2) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", 3) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("f(bool)", 255) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 0) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("g(bool)", 1) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 2) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 3) == encodeArgs(1)); - BOOST_CHECK(callContractFunction("g(bool)", 255) == encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 0), encodeArgs(0)); + ABI_CHECK(callContractFunction("f(bool)", 1), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 2), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 3), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(bool)", 255), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 0), encodeArgs(0)); + ABI_CHECK(callContractFunction("g(bool)", 1), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 2), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 3), encodeArgs(1)); + ABI_CHECK(callContractFunction("g(bool)", 255), encodeArgs(1)); } BOOST_AUTO_TEST_CASE(packed_storage_signed) @@ -5161,7 +5204,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_signed) } )"; compileAndRun(sourceCode); - BOOST_CHECK( callContractFunction("test()") == encodeArgs(u256(-2), u256(4), u256(-112), u256(0))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(-2), u256(4), u256(-112), u256(0))); } BOOST_AUTO_TEST_CASE(external_types_in_calls) @@ -5179,8 +5222,8 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(9), u256(7))); - BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(9), u256(7))); + ABI_CHECK(callContractFunction("t2()"), encodeArgs(u256(9))); } BOOST_AUTO_TEST_CASE(invalid_enum_compared) @@ -5210,10 +5253,10 @@ BOOST_AUTO_TEST_CASE(invalid_enum_compared) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test_eq_ok()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("test_eq_ok()"), encodeArgs(u256(1))); // both should throw - BOOST_CHECK(callContractFunction("test_eq()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test_neq()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_eq()"), encodeArgs()); + ABI_CHECK(callContractFunction("test_neq()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_logged) @@ -5239,7 +5282,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test_log_ok()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("test_log_ok()"), encodeArgs(u256(1))); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); @@ -5247,7 +5290,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged) BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(0))); // should throw - BOOST_CHECK(callContractFunction("test_log()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_log()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_stored) @@ -5272,11 +5315,11 @@ BOOST_AUTO_TEST_CASE(invalid_enum_stored) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test_store_ok()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("test_store_ok()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); // should throw - BOOST_CHECK(callContractFunction("test_store()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_store()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_as_external_ret) @@ -5308,9 +5351,9 @@ BOOST_AUTO_TEST_CASE(invalid_enum_as_external_ret) )"; compileAndRun(sourceCode, 0, "C"); // both should throw - BOOST_CHECK(callContractFunction("test_return()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test_inline_assignment()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test_assignment()") == encodeArgs()); + ABI_CHECK(callContractFunction("test_return()"), encodeArgs()); + ABI_CHECK(callContractFunction("test_inline_assignment()"), encodeArgs()); + ABI_CHECK(callContractFunction("test_assignment()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(invalid_enum_as_external_arg) @@ -5336,7 +5379,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_as_external_arg) )"; compileAndRun(sourceCode, 0, "C"); // should throw - BOOST_CHECK(callContractFunction("test()") == encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); } @@ -5361,12 +5404,12 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) } )"; compileAndRun(sourceCode, 0, "init_fix"); - BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("isOk()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("ok()"), encodeArgs(true)); compileAndRun(sourceCode, 0, "fix_init"); - BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("ok()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("isOk()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("ok()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) @@ -5400,7 +5443,7 @@ BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("assign()") == encodeArgs(2, 2, 3, 3)); + ABI_CHECK(callContractFunction("assign()"), encodeArgs(2, 2, 3, 3)); } BOOST_AUTO_TEST_CASE(struct_delete_member) @@ -5426,7 +5469,7 @@ BOOST_AUTO_TEST_CASE(struct_delete_member) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("deleteMember()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("deleteMember()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(struct_delete_struct_in_mapping) @@ -5451,7 +5494,7 @@ BOOST_AUTO_TEST_CASE(struct_delete_struct_in_mapping) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("deleteIt()") == encodeArgs(0)); + ABI_CHECK(callContractFunction("deleteIt()"), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(evm_exceptions_out_of_band_access) @@ -5473,9 +5516,9 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_out_of_band_access) } )"; compileAndRun(sourceCode, 0, "A"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("testIt()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(false)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("testIt()"), encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs(false)); } BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_call_fail) @@ -5498,8 +5541,8 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_call_fail) )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("testIt()") == encodeArgs()); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("testIt()"), encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) @@ -5516,7 +5559,7 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) } } )"; - BOOST_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A").empty()); + ABI_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A"), encodeArgs()); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed) @@ -5529,9 +5572,9 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_signed) } )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(2)); - BOOST_CHECK(callContractFunction("y()") == encodeArgs(127)); - BOOST_CHECK(callContractFunction("q()") == encodeArgs(250)); + ABI_CHECK(callContractFunction("x()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("y()"), encodeArgs(127)); + ABI_CHECK(callContractFunction("q()"), encodeArgs(250)); } BOOST_AUTO_TEST_CASE(failing_send) @@ -5624,9 +5667,9 @@ BOOST_AUTO_TEST_CASE(return_string) string s("Julia"); bytes args = encodeArgs(u256(0x20), u256(s.length()), s); BOOST_REQUIRE(callContractFunction("set(string)", asString(args)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get1()") == args); - BOOST_CHECK(callContractFunction("get2()") == args); - BOOST_CHECK(callContractFunction("s()") == args); + ABI_CHECK(callContractFunction("get1()"), args); + ABI_CHECK(callContractFunction("get2()"), args); + ABI_CHECK(callContractFunction("s()"), args); } BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) @@ -5672,9 +5715,9 @@ BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) encodeArgs(u256(l1)) ); bytes result = encodeArgs(u256(0x40), u256(0x40 + dyn1.size())) + dyn1 + dyn2; - BOOST_CHECK(callContractFunction("get()") == result); - BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn1); - BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn2); + ABI_CHECK(callContractFunction("get()"), result); + ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn1); + ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn2); } } @@ -5740,16 +5783,16 @@ BOOST_AUTO_TEST_CASE(bytes_in_function_calls) callContractFunction("setIndirectFromMemory(string,uint256,string)", asString(args1)) == encodeArgs(u256(l1)) ); - BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn1); - BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn2); + ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn1); + ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn2); // swapped bytes args2 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn2.size())) + dyn2 + dyn1; BOOST_REQUIRE( callContractFunction("setIndirectFromCalldata(string,uint256,string)", asString(args2)) == encodeArgs(u256(l1)) ); - BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn2); - BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn1); + ABI_CHECK(callContractFunction("s1()"), encodeArgs(0x20) + dyn2); + ABI_CHECK(callContractFunction("s2()"), encodeArgs(0x20) + dyn1); } } @@ -5946,10 +5989,10 @@ BOOST_AUTO_TEST_CASE(arrays_from_and_to_storage) callContractFunction("set(uint24[])", u256(0x20), u256(data.size()), data) == encodeArgs(u256(data.size())) ); - BOOST_CHECK(callContractFunction("data(uint256)", u256(7)) == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("data(uint256)", u256(15)) == encodeArgs(u256(16))); - BOOST_CHECK(callContractFunction("data(uint256)", u256(18)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0x20), u256(data.size()), data)); + ABI_CHECK(callContractFunction("data(uint256)", u256(7)), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("data(uint256)", u256(15)), encodeArgs(u256(16))); + ABI_CHECK(callContractFunction("data(uint256)", u256(18)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0x20), u256(data.size()), data)); } BOOST_AUTO_TEST_CASE(arrays_complex_from_and_to_storage) @@ -5973,10 +6016,10 @@ BOOST_AUTO_TEST_CASE(arrays_complex_from_and_to_storage) callContractFunction("set(uint24[3][])", u256(0x20), u256(data.size() / 3), data) == encodeArgs(u256(data.size() / 3)) ); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", u256(2), u256(2)) == encodeArgs(u256(9))); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", u256(5), u256(1)) == encodeArgs(u256(17))); - BOOST_CHECK(callContractFunction("data(uint256,uint256)", u256(6), u256(0)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0x20), u256(data.size() / 3), data)); + ABI_CHECK(callContractFunction("data(uint256,uint256)", u256(2), u256(2)), encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("data(uint256,uint256)", u256(5), u256(1)), encodeArgs(u256(17))); + ABI_CHECK(callContractFunction("data(uint256,uint256)", u256(6), u256(0)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0x20), u256(data.size() / 3), data)); } BOOST_AUTO_TEST_CASE(arrays_complex_memory_index_access) @@ -6062,19 +6105,19 @@ BOOST_AUTO_TEST_CASE(storage_array_ref) BOOST_REQUIRE(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(-1))); BOOST_REQUIRE(callContractFunction("add(uint256)", u256(7)) == encodeArgs()); BOOST_REQUIRE(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("add(uint256)", u256(11)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(17)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(27)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(31)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(32)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(66)) == encodeArgs()); - BOOST_CHECK(callContractFunction("add(uint256)", u256(177)) == encodeArgs()); - BOOST_CHECK(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(27)) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(32)) == encodeArgs(u256(5))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(176)) == encodeArgs(u256(-1))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(0)) == encodeArgs(u256(-1))); - BOOST_CHECK(callContractFunction("find(uint256)", u256(400)) == encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("add(uint256)", u256(11)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(17)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(27)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(31)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(32)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(66)), encodeArgs()); + ABI_CHECK(callContractFunction("add(uint256)", u256(177)), encodeArgs()); + ABI_CHECK(callContractFunction("find(uint256)", u256(7)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("find(uint256)", u256(27)), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("find(uint256)", u256(32)), encodeArgs(u256(5))); + ABI_CHECK(callContractFunction("find(uint256)", u256(176)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("find(uint256)", u256(0)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("find(uint256)", u256(400)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(memory_types_initialisation) @@ -6093,10 +6136,10 @@ BOOST_AUTO_TEST_CASE(memory_types_initialisation) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("stat()") == encodeArgs(vector<u256>(5))); - BOOST_CHECK(callContractFunction("dyn()") == encodeArgs(u256(0x20), u256(0))); - BOOST_CHECK(callContractFunction("nested()") == encodeArgs(u256(0x20), u256(0))); - BOOST_CHECK(callContractFunction("nestedStat()") == encodeArgs(vector<u256>(3 * 7))); + ABI_CHECK(callContractFunction("stat()"), encodeArgs(vector<u256>(5))); + ABI_CHECK(callContractFunction("dyn()"), encodeArgs(u256(0x20), u256(0))); + ABI_CHECK(callContractFunction("nested()"), encodeArgs(u256(0x20), u256(0))); + ABI_CHECK(callContractFunction("nestedStat()"), encodeArgs(vector<u256>(3 * 7))); } BOOST_AUTO_TEST_CASE(memory_arrays_delete) @@ -6125,7 +6168,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_delete) v = i * 0x10 + j; data[i * 3 + j] = v; } - BOOST_CHECK(callContractFunction("del()") == encodeArgs(data)); + ABI_CHECK(callContractFunction("del()"), encodeArgs(data)); } BOOST_AUTO_TEST_CASE(memory_arrays_index_access_write) @@ -6148,7 +6191,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_index_access_write) vector<u256> data(3 * 4); data[3 * 2 + 2] = 1; data[3 * 3 + 2] = 7; - BOOST_CHECK(callContractFunction("f()") == encodeArgs(data)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(data)); } BOOST_AUTO_TEST_CASE(memory_arrays_dynamic_index_access_write) @@ -6172,7 +6215,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_dynamic_index_access_write) vector<u256> data(3 * 4); data[3 * 2 + 2] = 1; data[3 * 3 + 2] = 7; - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x20), u256(4), data)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x20), u256(4), data)); } BOOST_AUTO_TEST_CASE(memory_structs_read_write) @@ -6215,9 +6258,9 @@ BOOST_AUTO_TEST_CASE(memory_structs_read_write) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("testInit()") == encodeArgs(u256(0), u256(0), u256(0), u256(0), true)); - BOOST_CHECK(callContractFunction("testCopyRead()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); - BOOST_CHECK(callContractFunction("testAssign()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); + ABI_CHECK(callContractFunction("testInit()"), encodeArgs(u256(0), u256(0), u256(0), u256(0), true)); + ABI_CHECK(callContractFunction("testCopyRead()"), encodeArgs(u256(1), u256(2), u256(3), u256(4))); + ABI_CHECK(callContractFunction("testAssign()"), encodeArgs(u256(1), u256(2), u256(3), u256(4))); } BOOST_AUTO_TEST_CASE(memory_structs_as_function_args) @@ -6245,7 +6288,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_as_function_args) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(1), u256(2), u256(3))); } BOOST_AUTO_TEST_CASE(memory_structs_nested) @@ -6277,7 +6320,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested) )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(1), u256(2), u256(3), u256(4))); } BOOST_AUTO_TEST_CASE(memory_structs_nested_load) @@ -6323,8 +6366,8 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested_load) compileAndRun(sourceCode, 0, "Test"); auto out = encodeArgs(u256(1), u256(2), u256(3), u256(4), u256(5), u256(6)); - BOOST_CHECK(callContractFunction("load()") == out); - BOOST_CHECK(callContractFunction("store()") == out); + ABI_CHECK(callContractFunction("load()"), out); + ABI_CHECK(callContractFunction("store()"), out); } BOOST_AUTO_TEST_CASE(struct_constructor_nested) @@ -6351,7 +6394,7 @@ BOOST_AUTO_TEST_CASE(struct_constructor_nested) compileAndRun(sourceCode, 0, "C"); auto out = encodeArgs(u256(1), u256(0), u256(9), u256(0), u256(4), u256(5)); - BOOST_CHECK(callContractFunction("get()") == out); + ABI_CHECK(callContractFunction("get()"), out); } BOOST_AUTO_TEST_CASE(struct_named_constructor) @@ -6367,7 +6410,7 @@ BOOST_AUTO_TEST_CASE(struct_named_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("s()") == encodeArgs(u256(1), true)); + ABI_CHECK(callContractFunction("s()"), encodeArgs(u256(1), true)); } BOOST_AUTO_TEST_CASE(literal_strings) @@ -6393,11 +6436,11 @@ BOOST_AUTO_TEST_CASE(literal_strings) string shortStr = "123"; string hello = "Hello, World!"; - BOOST_CHECK(callContractFunction("f()") == encodeDyn(hello)); - BOOST_CHECK(callContractFunction("long()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("medium()") == encodeDyn(medium)); - BOOST_CHECK(callContractFunction("short()") == encodeDyn(shortStr)); - BOOST_CHECK(callContractFunction("empty()") == encodeDyn(string())); + ABI_CHECK(callContractFunction("f()"), encodeDyn(hello)); + ABI_CHECK(callContractFunction("long()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("medium()"), encodeDyn(medium)); + ABI_CHECK(callContractFunction("short()"), encodeDyn(shortStr)); + ABI_CHECK(callContractFunction("empty()"), encodeDyn(string())); } BOOST_AUTO_TEST_CASE(initialise_string_constant) @@ -6412,8 +6455,8 @@ BOOST_AUTO_TEST_CASE(initialise_string_constant) string longStr = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; string shortStr = "abcdef"; - BOOST_CHECK(callContractFunction("long()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("short()") == encodeDyn(shortStr)); + ABI_CHECK(callContractFunction("long()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("short()"), encodeDyn(shortStr)); } BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) @@ -6436,7 +6479,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(string_bytes_conversion) @@ -6454,14 +6497,14 @@ BOOST_AUTO_TEST_CASE(string_bytes_conversion) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "f(string,uint256)", u256(0x40), u256(2), u256(6), string("abcdef") - ) == encodeArgs("c")); - BOOST_CHECK(callContractFunction("l()") == encodeArgs(u256(6))); + ), encodeArgs("c")); + ABI_CHECK(callContractFunction("l()"), encodeArgs(u256(6))); } BOOST_AUTO_TEST_CASE(string_as_mapping_key) @@ -6481,31 +6524,32 @@ BOOST_AUTO_TEST_CASE(string_as_mapping_key) "1" }; for (unsigned i = 0; i < strings.size(); i++) - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "set(string,uint256)", u256(0x40), u256(7 + i), u256(strings[i].size()), strings[i] - ) == encodeArgs()); + ), encodeArgs()); for (unsigned i = 0; i < strings.size(); i++) - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "get(string)", u256(0x20), u256(strings[i].size()), strings[i] - ) == encodeArgs(u256(7 + i))); + ), encodeArgs(u256(7 + i))); } BOOST_AUTO_TEST_CASE(accessor_for_state_variable) { char const* sourceCode = R"( - contract Lotto{ + contract Lotto { uint public ticketPrice = 500; - })"; + } + )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("ticketPrice()") == encodeArgs(u256(500))); + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500))); } BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) @@ -6513,10 +6557,11 @@ BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) char const* sourceCode = R"( contract Lotto{ uint constant public ticketPrice = 555; - })"; + } + )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("ticketPrice()") == encodeArgs(u256(555))); + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(555))); } BOOST_AUTO_TEST_CASE(state_variable_under_contract_name) @@ -6531,7 +6576,7 @@ BOOST_AUTO_TEST_CASE(state_variable_under_contract_name) } )"; compileAndRun(text); - BOOST_CHECK(callContractFunction("getStateVar()") == encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("getStateVar()"), encodeArgs(u256(42))); } BOOST_AUTO_TEST_CASE(state_variable_local_variable_mixture) @@ -6547,7 +6592,7 @@ BOOST_AUTO_TEST_CASE(state_variable_local_variable_mixture) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(inherited_function) { @@ -6562,7 +6607,7 @@ BOOST_AUTO_TEST_CASE(inherited_function) { )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(inherited_function_from_a_library) { @@ -6577,7 +6622,7 @@ BOOST_AUTO_TEST_CASE(inherited_function_from_a_library) { )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(inherited_constant_state_var) @@ -6594,7 +6639,7 @@ BOOST_AUTO_TEST_CASE(inherited_constant_state_var) )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(multiple_inherited_state_vars) @@ -6625,12 +6670,12 @@ BOOST_AUTO_TEST_CASE(multiple_inherited_state_vars) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("b()") == encodeArgs(u256(9))); - BOOST_CHECK(callContractFunction("a_set(uint256)", u256(1)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("b_set(uint256)", u256(3)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("b()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("b()"), encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("a_set(uint256)", u256(1)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("b_set(uint256)", u256(3)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("b()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(constant_string_literal) @@ -6657,12 +6702,12 @@ BOOST_AUTO_TEST_CASE(constant_string_literal) compileAndRun(sourceCode); string longStr = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; string shortStr = "abcdefghijklmnopq"; - BOOST_CHECK(callContractFunction("b()") == encodeArgs(shortStr)); - BOOST_CHECK(callContractFunction("x()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("getB()") == encodeArgs(shortStr)); - BOOST_CHECK(callContractFunction("getX()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("getX2()") == encodeDyn(longStr)); - BOOST_CHECK(callContractFunction("unused()") == encodeArgs(2)); + ABI_CHECK(callContractFunction("b()"), encodeArgs(shortStr)); + ABI_CHECK(callContractFunction("x()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("getB()"), encodeArgs(shortStr)); + ABI_CHECK(callContractFunction("getX()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("getX2()"), encodeDyn(longStr)); + ABI_CHECK(callContractFunction("unused()"), encodeArgs(2)); } BOOST_AUTO_TEST_CASE(storage_string_as_mapping_key_without_variable) @@ -6677,7 +6722,7 @@ BOOST_AUTO_TEST_CASE(storage_string_as_mapping_key_without_variable) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(library_call) @@ -6692,7 +6737,7 @@ BOOST_AUTO_TEST_CASE(library_call) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(33) * 9)); + ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(33) * 9)); } BOOST_AUTO_TEST_CASE(library_stray_values) @@ -6709,7 +6754,7 @@ BOOST_AUTO_TEST_CASE(library_stray_values) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(42))); } BOOST_AUTO_TEST_CASE(cross_contract_types) @@ -6724,7 +6769,7 @@ BOOST_AUTO_TEST_CASE(cross_contract_types) } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(simple_throw) @@ -6741,8 +6786,8 @@ BOOST_AUTO_TEST_CASE(simple_throw) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(11)) == encodeArgs(u256(21))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs()); + ABI_CHECK(callContractFunction("f(uint256)", u256(11)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs()); } BOOST_AUTO_TEST_CASE(strings_in_struct) @@ -6781,10 +6826,10 @@ BOOST_AUTO_TEST_CASE(strings_in_struct) )"; compileAndRun(sourceCode); string s = "asdfghjkl"; - BOOST_CHECK(callContractFunction("getFirst()") == encodeArgs(u256(10))); - BOOST_CHECK(callContractFunction("getSecond()") == encodeArgs(u256(20))); - BOOST_CHECK(callContractFunction("getThird()") == encodeArgs(u256(30))); - BOOST_CHECK(callContractFunction("getLast()") == encodeDyn(s)); + ABI_CHECK(callContractFunction("getFirst()"), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("getSecond()"), encodeArgs(u256(20))); + ABI_CHECK(callContractFunction("getThird()"), encodeArgs(u256(30))); + ABI_CHECK(callContractFunction("getLast()"), encodeDyn(s)); } BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type) @@ -6810,7 +6855,7 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type) } )"; compileAndRun(sourceCode, 0, "B"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs( + ABI_CHECK(callContractFunction("f()"), encodeArgs( u256(2), u256(3), u256(4), u256(5), u256(6), // first return argument u256(1000), u256(1001), u256(1002), u256(1003), u256(1004)) // second return argument ); @@ -6842,7 +6887,7 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4), u256(17))); } BOOST_AUTO_TEST_CASE(using_library_structs) @@ -6869,7 +6914,7 @@ BOOST_AUTO_TEST_CASE(using_library_structs) )"; compileAndRun(sourceCode, 0, "Lib"); compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7), u256(8))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7), u256(8))); } BOOST_AUTO_TEST_CASE(library_struct_as_an_expression) @@ -6890,7 +6935,7 @@ BOOST_AUTO_TEST_CASE(library_struct_as_an_expression) } )"; compileAndRun(sourceCode, 0, "Tsra"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(library_enum_as_an_expression) @@ -6911,7 +6956,7 @@ BOOST_AUTO_TEST_CASE(library_enum_as_an_expression) } )"; compileAndRun(sourceCode, 0, "Tsra"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(short_strings) @@ -7015,12 +7060,12 @@ BOOST_AUTO_TEST_CASE(short_strings) } )"; compileAndRun(sourceCode, 0, "A"); - BOOST_CHECK(callContractFunction("data1()") == encodeDyn(string("123"))); - BOOST_CHECK(callContractFunction("lengthChange()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("data1()"), encodeDyn(string("123"))); + ABI_CHECK(callContractFunction("lengthChange()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("deleteElements()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("deleteElements()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(m_contractAddress)); - BOOST_CHECK(callContractFunction("copy()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("copy()"), encodeArgs(u256(0))); BOOST_CHECK(storageEmpty(m_contractAddress)); } @@ -7040,7 +7085,7 @@ BOOST_AUTO_TEST_CASE(calldata_offset) } )"; compileAndRun(sourceCode, 0, "CB", encodeArgs(u256(0x20))); - BOOST_CHECK(callContractFunction("last()", encodeArgs()) == encodeDyn(string("nd"))); + ABI_CHECK(callContractFunction("last()", encodeArgs()), encodeDyn(string("nd"))); } BOOST_AUTO_TEST_CASE(contract_binary_dependencies) @@ -7070,10 +7115,10 @@ BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library) compileAndRun(sourceCode, 10, "c"); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0); - BOOST_CHECK(callContractFunction("f(address)", encodeArgs(u160(libraryAddress))) == encodeArgs(false)); + ABI_CHECK(callContractFunction("f(address)", encodeArgs(u160(libraryAddress))), encodeArgs(false)); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0); - BOOST_CHECK(callContractFunction("f(address)", encodeArgs(u160(m_contractAddress))) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f(address)", encodeArgs(u160(m_contractAddress))), encodeArgs(true)); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 10); BOOST_CHECK_EQUAL(balanceAt(libraryAddress), 0); } @@ -7099,7 +7144,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()", encodeArgs()) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()", encodeArgs()), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(tuples) @@ -7130,7 +7175,7 @@ BOOST_AUTO_TEST_CASE(tuples) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(string_tuples) @@ -7149,8 +7194,8 @@ BOOST_AUTO_TEST_CASE(string_tuples) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(8), u256(3), string("abc"))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(0x40), u256(0x80), u256(3), string("abc"), u256(3), string("def"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x40), u256(8), u256(3), string("abc"))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0x40), u256(0x80), u256(3), string("abc"), u256(3), string("def"))); } BOOST_AUTO_TEST_CASE(decayed_tuple) @@ -7165,7 +7210,7 @@ BOOST_AUTO_TEST_CASE(decayed_tuple) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(inline_tuple_with_rational_numbers) @@ -7179,7 +7224,7 @@ BOOST_AUTO_TEST_CASE(inline_tuple_with_rational_numbers) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(destructuring_assignment) @@ -7218,7 +7263,7 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), string("abcde")) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), string("abcde")), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(destructuring_assignment_wildcard) @@ -7243,7 +7288,7 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment_wildcard) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(lone_struct_array_type) @@ -7258,7 +7303,7 @@ BOOST_AUTO_TEST_CASE(lone_struct_array_type) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(create_memory_array) @@ -7280,9 +7325,33 @@ BOOST_AUTO_TEST_CASE(create_memory_array) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(string("A"), u256(8), u256(4), string("B"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(string("A"), u256(8), u256(4), string("B"))); } +BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size) +{ + // Check allocation size of byte array. Should be 32 plus length rounded up to next + // multiple of 32 + char const* sourceCode = R"( + contract C { + function f() pure returns (uint d1, uint d2, uint d3) { + bytes memory b1 = new bytes(31); + bytes memory b2 = new bytes(32); + bytes memory b3 = new bytes(256); + bytes memory b4 = new bytes(31); + assembly { + d1 := sub(b2, b1) + d2 := sub(b3, b2) + d3 := sub(b4, b3) + } + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256)); +} + + BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) { // Computes binomial coefficients the chinese way @@ -7301,8 +7370,8 @@ BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(3), u256(1))) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(9), u256(5))) == encodeArgs(u256(70))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(3), u256(1))), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(9), u256(5))), encodeArgs(u256(70))); } BOOST_AUTO_TEST_CASE(memory_overwrite) @@ -7317,7 +7386,7 @@ BOOST_AUTO_TEST_CASE(memory_overwrite) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeDyn(string("b23a5"))); + ABI_CHECK(callContractFunction("f()"), encodeDyn(string("b23a5"))); } BOOST_AUTO_TEST_CASE(addmod_mulmod) @@ -7336,7 +7405,7 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(divisiod_by_zero) @@ -7352,12 +7421,12 @@ BOOST_AUTO_TEST_CASE(divisiod_by_zero) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 2) == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("div(uint256,uint256)", 7, 2), encodeArgs(u256(3))); // throws - BOOST_CHECK(callContractFunction("div(uint256,uint256)", 7, 0) == encodeArgs()); - BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 2) == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("div(uint256,uint256)", 7, 0), encodeArgs()); + ABI_CHECK(callContractFunction("mod(uint256,uint256)", 7, 2), encodeArgs(u256(1))); // throws - BOOST_CHECK(callContractFunction("mod(uint256,uint256)", 7, 0) == encodeArgs()); + ABI_CHECK(callContractFunction("mod(uint256,uint256)", 7, 0), encodeArgs()); } BOOST_AUTO_TEST_CASE(string_allocation_bug) @@ -7378,7 +7447,7 @@ BOOST_AUTO_TEST_CASE(string_allocation_bug) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("p(uint256)") == encodeArgs( + ABI_CHECK(callContractFunction("p(uint256)", 0), encodeArgs( u256(0xbbbb), u256(0xcccc), u256(0x80), @@ -7403,7 +7472,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_int) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(9)) == encodeArgs(u256(2 * 9))); + ABI_CHECK(callContractFunction("f(uint256)", u256(9)), encodeArgs(u256(2 * 9))); } BOOST_AUTO_TEST_CASE(using_for_function_on_struct) @@ -7421,8 +7490,8 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_struct) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(3 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(3 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(3 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(3 * 7))); } BOOST_AUTO_TEST_CASE(using_for_overload) @@ -7444,8 +7513,8 @@ BOOST_AUTO_TEST_CASE(using_for_overload) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); } BOOST_AUTO_TEST_CASE(using_for_by_name) @@ -7463,8 +7532,8 @@ BOOST_AUTO_TEST_CASE(using_for_by_name) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); } BOOST_AUTO_TEST_CASE(bound_function_in_var) @@ -7483,8 +7552,8 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); } BOOST_AUTO_TEST_CASE(bound_function_to_string) @@ -7506,8 +7575,8 @@ BOOST_AUTO_TEST_CASE(bound_function_to_string) )"; compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}}); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(3))); } BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) @@ -7523,7 +7592,7 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(0x80), u256(3), string("ray"), u256(2), string("mi"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x40), u256(0x80), u256(3), string("ray"), u256(2), string("mi"))); } BOOST_AUTO_TEST_CASE(inline_array_strings_from_document) @@ -7537,10 +7606,10 @@ BOOST_AUTO_TEST_CASE(inline_array_strings_from_document) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(0x20), u256(4), string("This"))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(0x20), u256(2), string("is"))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(0x20), u256(2), string("an"))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(0x20), u256(5), string("array"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(0x20), u256(4), string("This"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(0x20), u256(2), string("is"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(0x20), u256(2), string("an"))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(0x20), u256(5), string("array"))); } BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) @@ -7556,7 +7625,7 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(3, 6)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3, 6)); } BOOST_AUTO_TEST_CASE(inline_array_index_access_ints) @@ -7569,7 +7638,7 @@ BOOST_AUTO_TEST_CASE(inline_array_index_access_ints) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(3)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3)); } BOOST_AUTO_TEST_CASE(inline_array_index_access_strings) @@ -7586,8 +7655,8 @@ BOOST_AUTO_TEST_CASE(inline_array_index_access_strings) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs()); - BOOST_CHECK(callContractFunction("tester()") == encodeArgs(u256(0x20), u256(3), string("abc"))); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); + ABI_CHECK(callContractFunction("tester()"), encodeArgs(u256(0x20), u256(3), string("abc"))); } BOOST_AUTO_TEST_CASE(inline_array_return) @@ -7606,7 +7675,7 @@ BOOST_AUTO_TEST_CASE(inline_array_return) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(1, 2, 3, 4, 5)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1, 2, 3, 4, 5)); } BOOST_AUTO_TEST_CASE(inline_array_singleton) @@ -7620,7 +7689,7 @@ BOOST_AUTO_TEST_CASE(inline_array_singleton) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4))); } BOOST_AUTO_TEST_CASE(inline_long_string_return) @@ -7635,7 +7704,7 @@ BOOST_AUTO_TEST_CASE(inline_long_string_return) string strLong = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeDyn(strLong)); + ABI_CHECK(callContractFunction("f()"), encodeDyn(strLong)); } BOOST_AUTO_TEST_CASE(fixed_bytes_index_access) @@ -7654,9 +7723,9 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_index_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(bytes32)", "789") == encodeArgs("9")); - BOOST_CHECK(callContractFunction("g(bytes32)", "789") == encodeArgs(u256(int('5')))); - BOOST_CHECK(callContractFunction("data(uint256)", u256(1)) == encodeArgs("8")); + ABI_CHECK(callContractFunction("f(bytes32)", "789"), encodeArgs("9")); + ABI_CHECK(callContractFunction("g(bytes32)", "789"), encodeArgs(u256(int('5')))); + ABI_CHECK(callContractFunction("data(uint256)", u256(1)), encodeArgs("8")); } BOOST_AUTO_TEST_CASE(fixed_bytes_length_access) @@ -7670,7 +7739,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_length_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(bytes32)", "789") == encodeArgs(u256(32), u256(16), u256(8))); + ABI_CHECK(callContractFunction("f(bytes32)", "789"), encodeArgs(u256(32), u256(16), u256(8))); } BOOST_AUTO_TEST_CASE(inline_assembly_write_to_stack) @@ -7683,7 +7752,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_write_to_stack) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7), string("abcdef"))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7), string("abcdef"))); } BOOST_AUTO_TEST_CASE(inline_assembly_read_and_write_stack) @@ -7697,7 +7766,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_read_and_write_stack) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(45))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(45))); } BOOST_AUTO_TEST_CASE(inline_assembly_memory_access) @@ -7714,7 +7783,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_memory_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0x20), u256(5), string("12345"))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(0x20), u256(5), string("12345"))); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_access) @@ -7739,8 +7808,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("z()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("z()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_inside_function) @@ -7766,8 +7835,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_inside_function) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("z()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("z()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) @@ -7791,10 +7860,10 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("separator()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("separator2()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("separator()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("separator2()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(inline_assembly_jumps) @@ -7819,8 +7888,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_jumps) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()", u256(5)) == encodeArgs(u256(13))); - BOOST_CHECK(callContractFunction("f()", u256(7)) == encodeArgs(u256(34))); + 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) @@ -7839,8 +7908,8 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_access) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(5)) == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("f(uint256)", u256(5)), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(10))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_call) @@ -7864,7 +7933,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(2), u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_call_assignment) @@ -7889,7 +7958,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(2), u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_call2) @@ -7915,7 +7984,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call2) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7), u256(0x10))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(2), u256(7), u256(0x10))); } BOOST_AUTO_TEST_CASE(inline_assembly_embedded_function_call) @@ -7942,7 +8011,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_embedded_function_call) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(4), u256(7), u256(0x10))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(4), u256(7), u256(0x10))); } BOOST_AUTO_TEST_CASE(inline_assembly_switch) @@ -7960,10 +8029,10 @@ BOOST_AUTO_TEST_CASE(inline_assembly_switch) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(9))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(inline_assembly_recursion) @@ -7984,11 +8053,11 @@ BOOST_AUTO_TEST_CASE(inline_assembly_recursion) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(4)) == encodeArgs(u256(24))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("f(uint256)", u256(4)), encodeArgs(u256(24))); } BOOST_AUTO_TEST_CASE(inline_assembly_for) @@ -8009,11 +8078,11 @@ BOOST_AUTO_TEST_CASE(inline_assembly_for) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(4)) == encodeArgs(u256(24))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f(uint256)", u256(3)), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("f(uint256)", u256(4)), encodeArgs(u256(24))); } BOOST_AUTO_TEST_CASE(inline_assembly_for2) @@ -8035,9 +8104,9 @@ BOOST_AUTO_TEST_CASE(inline_assembly_for2) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(0), u256(2), u256(0))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1), u256(4), u256(3))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(0), u256(2), u256(0))); + ABI_CHECK(callContractFunction("f(uint256)", u256(0)), encodeArgs(u256(0), u256(2), u256(0))); + ABI_CHECK(callContractFunction("f(uint256)", u256(1)), encodeArgs(u256(1), u256(4), u256(3))); + ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(0), u256(2), u256(0))); } BOOST_AUTO_TEST_CASE(index_access_with_type_conversion) @@ -8075,7 +8144,7 @@ BOOST_AUTO_TEST_CASE(delete_on_array_of_structs) compileAndRun(sourceCode, 0, "C"); // This code interprets x as an array length and thus will go out of gas. // neither of the two should throw due to out-of-bounds access - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } @@ -8100,7 +8169,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(internal_library_function_calling_private) @@ -8128,7 +8197,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function_calling_private) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(internal_library_function_bound) @@ -8153,7 +8222,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function_bound) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(internal_library_function_return_var_size) @@ -8178,7 +8247,7 @@ BOOST_AUTO_TEST_CASE(internal_library_function_return_var_size) )"; // This has to work without linking, because everything will be inlined. compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(iszero_bnot_correct) @@ -8198,7 +8267,7 @@ BOOST_AUTO_TEST_CASE(iszero_bnot_correct) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(cleanup_bytes_types) @@ -8216,7 +8285,7 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types) )"; compileAndRun(sourceCode, 0, "C"); // We input longer data on purpose. - BOOST_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)) == encodeArgs(0)); + ABI_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)), encodeArgs(0)); } BOOST_AUTO_TEST_CASE(skip_dynamic_types) @@ -8235,7 +8304,7 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(7), u256(8))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(7), u256(8))); } BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs) @@ -8261,7 +8330,7 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2), u256(6))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(2), u256(6))); } BOOST_AUTO_TEST_CASE(failed_create) @@ -8285,11 +8354,11 @@ BOOST_AUTO_TEST_CASE(failed_create) )"; compileAndRun(sourceCode, 20, "C"); BOOST_CHECK(callContractFunction("f(uint256)", 20) != encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("f(uint256)", 20) == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("stack(uint256)", 1023) == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f(uint256)", 20), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("stack(uint256)", 1023), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length) @@ -8303,7 +8372,7 @@ BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier) @@ -8321,9 +8390,9 @@ BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(9))); } BOOST_AUTO_TEST_CASE(break_in_modifier) @@ -8343,9 +8412,9 @@ BOOST_AUTO_TEST_CASE(break_in_modifier) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) @@ -8365,9 +8434,9 @@ BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(mutex) @@ -8429,11 +8498,11 @@ BOOST_AUTO_TEST_CASE(mutex) auto fund = m_contractAddress; BOOST_CHECK_EQUAL(balanceAt(fund), 500); compileAndRun(sourceCode, 0, "Attacker", encodeArgs(u160(fund))); - BOOST_CHECK(callContractFunction("setProtected(bool)", true) == encodeArgs()); - BOOST_CHECK(callContractFunction("attack()") == encodeArgs()); + ABI_CHECK(callContractFunction("setProtected(bool)", true), encodeArgs()); + ABI_CHECK(callContractFunction("attack()"), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(fund), 500); - BOOST_CHECK(callContractFunction("setProtected(bool)", false) == encodeArgs()); - BOOST_CHECK(callContractFunction("attack()") == encodeArgs(u256(460))); + ABI_CHECK(callContractFunction("setProtected(bool)", false), encodeArgs()); + ABI_CHECK(callContractFunction("attack()"), encodeArgs(u256(460))); BOOST_CHECK_EQUAL(balanceAt(fund), 460); } @@ -8450,7 +8519,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper) @@ -8476,7 +8545,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) @@ -8497,7 +8566,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) @@ -8521,9 +8590,9 @@ BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("g()") == encodeArgs()); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(payable_constructor) @@ -8550,11 +8619,11 @@ BOOST_AUTO_TEST_CASE(payable_function) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(27))); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs(u256(27))); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27); - BOOST_CHECK(callContractFunctionWithValue("", 27) == encodeArgs()); + ABI_CHECK(callContractFunctionWithValue("", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(28))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(28))); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27); } @@ -8572,7 +8641,7 @@ BOOST_AUTO_TEST_CASE(payable_function_calls_library) )"; compileAndRun(sourceCode, 0, "L"); compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}}); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7))); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(non_payable_throw) @@ -8589,14 +8658,14 @@ BOOST_AUTO_TEST_CASE(non_payable_throw) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs()); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); - BOOST_CHECK(callContractFunction("") == encodeArgs()); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunctionWithValue("", 27) == encodeArgs()); + ABI_CHECK(callContractFunction(""), encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunctionWithValue("", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunctionWithValue("a()", 27) == encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunctionWithValue("a()", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); } @@ -8613,7 +8682,7 @@ BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier) } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs()); + ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs()); BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); } @@ -8635,7 +8704,7 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) compileAndRun(sourceCode, 0, "C"); u160 cAddr = m_contractAddress; compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f(address)", cAddr), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(calling_uninitialized_function) @@ -8657,8 +8726,8 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function) compileAndRun(sourceCode, 0, "C"); // This should throw exceptions - BOOST_CHECK(callContractFunction("intern()") == encodeArgs()); - BOOST_CHECK(callContractFunction("extern()") == encodeArgs()); + ABI_CHECK(callContractFunction("intern()"), encodeArgs()); + ABI_CHECK(callContractFunction("extern()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail) @@ -8679,7 +8748,7 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs()); + ABI_CHECK(callContractFunction("t()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(pass_function_types_internally) @@ -8697,7 +8766,7 @@ BOOST_AUTO_TEST_CASE(pass_function_types_internally) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f(uint256)", 7), encodeArgs(u256(8))); } BOOST_AUTO_TEST_CASE(pass_function_types_externally) @@ -8718,8 +8787,8 @@ BOOST_AUTO_TEST_CASE(pass_function_types_externally) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("f2(uint256)", 7) == encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f(uint256)", 7), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f2(uint256)", 7), encodeArgs(u256(8))); } BOOST_AUTO_TEST_CASE(receive_external_function_type) @@ -8734,10 +8803,10 @@ BOOST_AUTO_TEST_CASE(receive_external_function_type) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "f(function)", m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) - ) == encodeArgs(u256(7))); + ), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(return_external_function_type) @@ -8752,8 +8821,8 @@ BOOST_AUTO_TEST_CASE(return_external_function_type) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK( - callContractFunction("f()") == + ABI_CHECK( + callContractFunction("f()"), m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) ); } @@ -8782,7 +8851,7 @@ BOOST_AUTO_TEST_CASE(store_function) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(9))); + ABI_CHECK(callContractFunction("t()"), encodeArgs(u256(9))); } BOOST_AUTO_TEST_CASE(store_function_in_constructor) @@ -8805,8 +8874,8 @@ BOOST_AUTO_TEST_CASE(store_function_in_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("use(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("result_in_constructor()") == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("use(uint256)", encodeArgs(u256(3))), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("result_in_constructor()"), encodeArgs(u256(4))); } // TODO: store bound internal library functions @@ -8829,7 +8898,7 @@ BOOST_AUTO_TEST_CASE(store_internal_unused_function_in_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(store_internal_unused_library_function_in_constructor) @@ -8848,7 +8917,7 @@ BOOST_AUTO_TEST_CASE(store_internal_unused_library_function_in_constructor) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime) @@ -8869,8 +8938,8 @@ BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("runtime(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6))); - BOOST_CHECK(callContractFunction("initial()") == encodeArgs(u256(4))); + ABI_CHECK(callContractFunction("runtime(uint256)", encodeArgs(u256(3))), encodeArgs(u256(6))); + ABI_CHECK(callContractFunction("initial()"), encodeArgs(u256(4))); } BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime_equality_check) @@ -8891,7 +8960,7 @@ BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime_equality_check) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("test()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(function_type_library_internal) @@ -8916,7 +8985,7 @@ BOOST_AUTO_TEST_CASE(function_type_library_internal) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256[])", 0x20, 3, u256(1), u256(7), u256(3)) == encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("f(uint256[])", 0x20, 3, u256(1), u256(7), u256(3)), encodeArgs(u256(11))); } @@ -8946,7 +9015,7 @@ BOOST_AUTO_TEST_CASE(call_function_returning_function) )"; compileAndRun(sourceCode, 0, "test"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(mapping_of_functions) @@ -8981,12 +9050,12 @@ BOOST_AUTO_TEST_CASE(mapping_of_functions) )"; compileAndRun(sourceCode, 0, "Flow"); - BOOST_CHECK(callContractFunction("success()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("success()") == encodeArgs(false)); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("success()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("success()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("success()"), encodeArgs(false)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("success()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(packed_functions) @@ -9029,12 +9098,12 @@ BOOST_AUTO_TEST_CASE(packed_functions) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("set()") == encodeArgs()); - BOOST_CHECK(callContractFunction("t1()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("t3()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("t4()") == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("set()"), encodeArgs()); + ABI_CHECK(callContractFunction("t1()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t2()"), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("t3()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("t4()"), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(function_memory_array) @@ -9060,12 +9129,12 @@ BOOST_AUTO_TEST_CASE(function_memory_array) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(0)) == encodeArgs(u256(11))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(1)) == encodeArgs(u256(12))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(2)) == encodeArgs(u256(13))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(3)) == encodeArgs(u256(15))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(4)) == encodeArgs(u256(18))); - BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(5)) == encodeArgs()); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(0)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(1)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(2)), encodeArgs(u256(13))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(3)), encodeArgs(u256(15))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(4)), encodeArgs(u256(18))); + ABI_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(5)), encodeArgs()); } BOOST_AUTO_TEST_CASE(function_delete_storage) @@ -9089,10 +9158,10 @@ BOOST_AUTO_TEST_CASE(function_delete_storage) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("set()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("ca()") == encodeArgs(u256(7))); - BOOST_CHECK(callContractFunction("d()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("ca()") == encodeArgs()); + ABI_CHECK(callContractFunction("set()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("ca()"), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("d()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("ca()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(function_delete_stack) @@ -9109,7 +9178,7 @@ BOOST_AUTO_TEST_CASE(function_delete_stack) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs()); + ABI_CHECK(callContractFunction("test()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(copy_function_storage_array) @@ -9131,7 +9200,7 @@ BOOST_AUTO_TEST_CASE(copy_function_storage_array) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(function_array_cross_calls) @@ -9170,7 +9239,7 @@ BOOST_AUTO_TEST_CASE(function_array_cross_calls) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(5), u256(6), u256(7))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(5), u256(6), u256(7))); } BOOST_AUTO_TEST_CASE(external_function_to_address) @@ -9187,8 +9256,8 @@ BOOST_AUTO_TEST_CASE(external_function_to_address) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); - BOOST_CHECK(callContractFunction("g(function)", fromHex("00000000000000000000000000000000000004226121ff00000000000000000")) == encodeArgs(u160(0x42))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g(function)", fromHex("00000000000000000000000000000000000004226121ff00000000000000000")), encodeArgs(u160(0x42))); } @@ -9215,8 +9284,8 @@ BOOST_AUTO_TEST_CASE(copy_internal_function_array_to_storage) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("one()") == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("two()") == encodeArgs()); + ABI_CHECK(callContractFunction("one()"), encodeArgs(u256(3))); + ABI_CHECK(callContractFunction("two()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(shift_constant_left) @@ -9227,7 +9296,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0x4200))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(0x4200))); } BOOST_AUTO_TEST_CASE(shift_negative_constant_left) @@ -9238,7 +9307,7 @@ BOOST_AUTO_TEST_CASE(shift_negative_constant_left) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x4200))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(-0x4200))); } BOOST_AUTO_TEST_CASE(shift_constant_right) @@ -9249,7 +9318,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(0x42))); } BOOST_AUTO_TEST_CASE(shift_negative_constant_right) @@ -9260,7 +9329,7 @@ BOOST_AUTO_TEST_CASE(shift_negative_constant_right) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x42))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(-0x42))); } BOOST_AUTO_TEST_CASE(shift_left) @@ -9273,12 +9342,12 @@ BOOST_AUTO_TEST_CASE(shift_left) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)), fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_uint32) @@ -9291,11 +9360,11 @@ BOOST_AUTO_TEST_CASE(shift_left_uint32) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(32)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(32)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_uint8) @@ -9308,8 +9377,8 @@ BOOST_AUTO_TEST_CASE(shift_left_uint8) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)), encodeArgs(u256(0x66))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_larger_type) @@ -9325,7 +9394,7 @@ BOOST_AUTO_TEST_CASE(shift_left_larger_type) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_assignment) @@ -9339,12 +9408,12 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)), fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) @@ -9358,11 +9427,11 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(8)), encodeArgs(u256(0x426600))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(16)), encodeArgs(u256(0x42660000))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(17)), encodeArgs(u256(0x84cc0000))); + ABI_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(240)), fromHex("4266000000000000000000000000000000000000000000000000000000000000")); } BOOST_AUTO_TEST_CASE(shift_right) @@ -9375,10 +9444,10 @@ BOOST_AUTO_TEST_CASE(shift_right) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + 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))); } BOOST_AUTO_TEST_CASE(shift_right_garbled) @@ -9395,8 +9464,8 @@ BOOST_AUTO_TEST_CASE(shift_right_garbled) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(4)) == encodeArgs(u256(0xf))); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)) == encodeArgs(u256(0xf))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(4)), encodeArgs(u256(0xf))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(0xf))); } BOOST_AUTO_TEST_CASE(shift_right_uint32) @@ -9409,10 +9478,10 @@ BOOST_AUTO_TEST_CASE(shift_right_uint32) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)), encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)), encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_right_uint8) @@ -9425,8 +9494,8 @@ BOOST_AUTO_TEST_CASE(shift_right_uint8) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); - BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0x0))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)), encodeArgs(u256(0x66))); + ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)), encodeArgs(u256(0x0))); } BOOST_AUTO_TEST_CASE(shift_right_assignment) @@ -9440,10 +9509,10 @@ BOOST_AUTO_TEST_CASE(shift_right_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)), encodeArgs(u256(0x4266))); + 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))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) @@ -9456,10 +9525,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); + 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))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) @@ -9473,10 +9542,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); + 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))); } BOOST_AUTO_TEST_CASE(shift_negative_rvalue) @@ -9492,8 +9561,8 @@ BOOST_AUTO_TEST_CASE(shift_negative_rvalue) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); - BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)), encodeArgs()); + ABI_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)), encodeArgs()); } BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment) @@ -9511,8 +9580,8 @@ BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); - BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)), encodeArgs()); + ABI_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)), encodeArgs()); } BOOST_AUTO_TEST_CASE(shift_constant_left_assignment) @@ -9526,7 +9595,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x4200))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x4200))); } BOOST_AUTO_TEST_CASE(shift_constant_right_assignment) @@ -9540,7 +9609,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x42))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x42))); } BOOST_AUTO_TEST_CASE(shift_cleanup) @@ -9556,7 +9625,7 @@ BOOST_AUTO_TEST_CASE(shift_cleanup) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x0))); } BOOST_AUTO_TEST_CASE(shift_cleanup_garbled) @@ -9572,7 +9641,7 @@ BOOST_AUTO_TEST_CASE(shift_cleanup_garbled) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x0))); } BOOST_AUTO_TEST_CASE(shift_overflow) @@ -9588,13 +9657,13 @@ BOOST_AUTO_TEST_CASE(shift_overflow) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 8) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1) == encodeArgs(u256(254))); - BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0) == encodeArgs(u256(255))); + ABI_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 8), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1), encodeArgs(u256(254))); + ABI_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0), encodeArgs(u256(255))); // Result is -128 and output is sign-extended, not zero-padded. - BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 7) == encodeArgs(u256(0) - 128)); - BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64))); + ABI_CHECK(callContractFunction("leftS(int8,int8)", 1, 7), encodeArgs(u256(0) - 128)); + ABI_CHECK(callContractFunction("leftS(int8,int8)", 1, 6), encodeArgs(u256(64))); } BOOST_AUTO_TEST_CASE(shift_bytes) @@ -9610,8 +9679,8 @@ BOOST_AUTO_TEST_CASE(shift_bytes) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); - BOOST_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); + ABI_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8), encodeArgs("901234567890" + string(8, 0))); + ABI_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8), encodeArgs(string(8, 0) + "123456789012")); } BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) @@ -9631,8 +9700,8 @@ BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("left(uint8)", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); - BOOST_CHECK(callContractFunction("right(uint8)", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); + ABI_CHECK(callContractFunction("left(uint8)", 8 * 8), encodeArgs("901234567890" + string(8, 0))); + ABI_CHECK(callContractFunction("right(uint8)", 8 * 8), encodeArgs(string(8, 0) + "123456789012")); } BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) @@ -9650,7 +9719,7 @@ BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0xff), u256(0xff))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(0xff), u256(0xff))); } BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) @@ -9672,7 +9741,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(packed_storage_overflow) @@ -9692,7 +9761,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_overflow) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x1234), u256(0), u256(0), u256(0xfffe))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1234), u256(0), u256(0), u256(0xfffe))); } BOOST_AUTO_TEST_CASE(contracts_separated_with_comment) @@ -9756,7 +9825,7 @@ BOOST_AUTO_TEST_CASE(recursive_structs) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(invalid_instruction) @@ -9771,7 +9840,7 @@ BOOST_AUTO_TEST_CASE(invalid_instruction) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); } BOOST_AUTO_TEST_CASE(assert_require) @@ -9792,11 +9861,11 @@ BOOST_AUTO_TEST_CASE(assert_require) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs()); - BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(true)); - BOOST_CHECK(callContractFunction("h(bool)", false) == encodeArgs()); - BOOST_CHECK(callContractFunction("h(bool)", true) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs()); + ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(true)); + ABI_CHECK(callContractFunction("h(bool)", false), encodeArgs()); + ABI_CHECK(callContractFunction("h(bool)", true), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(revert) @@ -9817,10 +9886,10 @@ BOOST_AUTO_TEST_CASE(revert) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs()); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(42))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs()); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(42))); } BOOST_AUTO_TEST_CASE(negative_stack_height) @@ -9860,11 +9929,11 @@ BOOST_AUTO_TEST_CASE(literal_empty_string) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(2))); } BOOST_AUTO_TEST_CASE(scientific_notation) @@ -9892,12 +9961,12 @@ BOOST_AUTO_TEST_CASE(scientific_notation) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(20000000000))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(25))); - BOOST_CHECK(callContractFunction("i()") == encodeArgs(u256(-20000000000))); - BOOST_CHECK(callContractFunction("j()") == encodeArgs(u256(-2))); - BOOST_CHECK(callContractFunction("k()") == encodeArgs(u256(-25))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(20000000000))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(2))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(25))); + ABI_CHECK(callContractFunction("i()"), encodeArgs(u256(-20000000000))); + ABI_CHECK(callContractFunction("j()"), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("k()"), encodeArgs(u256(-25))); } BOOST_AUTO_TEST_CASE(interface_contract) @@ -9932,7 +10001,7 @@ BOOST_AUTO_TEST_CASE(interface_contract) compileAndRun(sourceCode, 0, "A"); u160 const recipient = m_contractAddress; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(address)", recipient) == encodeArgs(true)); + ABI_CHECK(callContractFunction("f(address)", recipient), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(keccak256_assembly) @@ -9968,10 +10037,10 @@ BOOST_AUTO_TEST_CASE(keccak256_assembly) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - BOOST_CHECK(callContractFunction("g()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - BOOST_CHECK(callContractFunction("h()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - BOOST_CHECK(callContractFunction("i()") == fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + 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) @@ -9995,10 +10064,10 @@ BOOST_AUTO_TEST_CASE(multi_modifiers) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f1()") == bytes()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(8))); - BOOST_CHECK(callContractFunction("f2()") == bytes()); - BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("f1()"), bytes()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(8))); + ABI_CHECK(callContractFunction("f2()"), bytes()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(12))); } BOOST_AUTO_TEST_CASE(inlineasm_empty_let) @@ -10016,7 +10085,7 @@ BOOST_AUTO_TEST_CASE(inlineasm_empty_let) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0), u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0), u256(0))); } BOOST_AUTO_TEST_CASE(bare_call_invalid_address) @@ -10036,9 +10105,9 @@ BOOST_AUTO_TEST_CASE(bare_call_invalid_address) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(1))); } BOOST_AUTO_TEST_CASE(delegatecall_return_value) @@ -10064,17 +10133,17 @@ BOOST_AUTO_TEST_CASE(delegatecall_return_value) } )DELIMITER"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("set(uint256)", u256(1)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("set(uint256)", u256(42)) == encodeArgs()); - BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(42))); - BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); + 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) @@ -10096,9 +10165,9 @@ BOOST_AUTO_TEST_CASE(function_types_sig) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); } BOOST_AUTO_TEST_CASE(constant_string) @@ -10120,9 +10189,335 @@ BOOST_AUTO_TEST_CASE(constant_string) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeDyn(string("\x03\x01\x02"))); - BOOST_CHECK(callContractFunction("g()") == encodeDyn(string("\x03\x01\x02"))); - BOOST_CHECK(callContractFunction("h()") == encodeDyn(string("hello"))); + ABI_CHECK(callContractFunction("f()"), encodeDyn(string("\x03\x01\x02"))); + ABI_CHECK(callContractFunction("g()"), encodeDyn(string("\x03\x01\x02"))); + ABI_CHECK(callContractFunction("h()"), encodeDyn(string("hello"))); +} + +BOOST_AUTO_TEST_CASE(address_overload_resolution) +{ + char const* sourceCode = R"( + contract C { + function balance() returns (uint) { + return 1; + } + function transfer(uint amount) returns (uint) { + return amount; + } + } + contract D { + function f() returns (uint) { + return (new C()).balance(); + } + function g() returns (uint) { + return (new C()).transfer(5); + } + } + )"; + compileAndRun(sourceCode, 0, "D"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(5))); +} + +BOOST_AUTO_TEST_CASE(snark) +{ + char const* sourceCode = R"( + library Pairing { + struct G1Point { + uint X; + uint Y; + } + // Encoding of field elements is: X[0] * z + X[1] + struct G2Point { + uint[2] X; + uint[2] Y; + } + + /// @return the generator of G1 + function P1() internal returns (G1Point) { + return G1Point(1, 2); + } + + /// @return the generator of G2 + function P2() internal returns (G2Point) { + return G2Point( + [11559732032986387107991004021392285783925812861821192530917403151452391805634, + 10857046999023057135944570762232829481370756359578518086990519993285655852781], + [4082367875863433681332203403145435568316851327593401208105741076214120093531, + 8495653923123431417604973247489272438418190587263600148770280649306958101930] + ); + } + + /// @return the negation of p, i.e. p.add(p.negate()) should be zero. + function negate(G1Point p) internal returns (G1Point) { + // The prime q in the base field F_q for G1 + uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + if (p.X == 0 && p.Y == 0) + return G1Point(0, 0); + return G1Point(p.X, q - (p.Y % q)); + } + + /// @return the sum of two points of G1 + function add(G1Point p1, G1Point p2) internal returns (G1Point r) { + uint[4] memory input; + input[0] = p1.X; + input[1] = p1.Y; + input[2] = p2.X; + input[3] = p2.Y; + bool success; + assembly { + success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + } + + /// @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) { + uint[3] memory input; + input[0] = p.X; + input[1] = p.Y; + input[2] = s; + bool success; + assembly { + success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + } + + /// @return the result of computing the pairing check + /// 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) { + require(p1.length == p2.length); + uint elements = p1.length; + uint inputSize = p1.length * 6; + uint[] memory input = new uint[](inputSize); + for (uint i = 0; i < elements; i++) + { + input[i * 6 + 0] = p1[i].X; + input[i * 6 + 1] = p1[i].Y; + input[i * 6 + 2] = p2[i].X[0]; + input[i * 6 + 3] = p2[i].X[1]; + input[i * 6 + 4] = p2[i].Y[0]; + input[i * 6 + 5] = p2[i].Y[1]; + } + uint[1] memory out; + bool success; + assembly { + success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + return out[0] != 0; + } + function pairingProd2(G1Point a1, G2Point a2, G1Point b1, G2Point b2) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](2); + G2Point[] memory p2 = new G2Point[](2); + p1[0] = a1; + p1[1] = b1; + p2[0] = a2; + p2[1] = b2; + return pairing(p1, p2); + } + function pairingProd3( + G1Point a1, G2Point a2, + G1Point b1, G2Point b2, + G1Point c1, G2Point c2 + ) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](3); + G2Point[] memory p2 = new G2Point[](3); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + return pairing(p1, p2); + } + function pairingProd4( + G1Point a1, G2Point a2, + G1Point b1, G2Point b2, + G1Point c1, G2Point c2, + G1Point d1, G2Point d2 + ) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](4); + G2Point[] memory p2 = new G2Point[](4); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p1[3] = d1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + p2[3] = d2; + return pairing(p1, p2); + } + } + + contract Test { + using Pairing for *; + struct VerifyingKey { + Pairing.G2Point A; + Pairing.G1Point B; + Pairing.G2Point C; + Pairing.G2Point gamma; + Pairing.G1Point gammaBeta1; + Pairing.G2Point gammaBeta2; + Pairing.G2Point Z; + Pairing.G1Point[] IC; + } + struct Proof { + Pairing.G1Point A; + Pairing.G1Point A_p; + Pairing.G2Point B; + Pairing.G1Point B_p; + Pairing.G1Point C; + Pairing.G1Point C_p; + Pairing.G1Point K; + Pairing.G1Point H; + } + function f() 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); + return (explict_sum.X == scalar_prod.X && + explict_sum.Y == scalar_prod.Y); + } + function g() 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) { + Pairing.G1Point memory p; + // @TODO The points here are reported to be not well-formed + p.X = 14125296762497065001182820090155008161146766663259912659363835465243039841726; + p.Y = 16229134936871442251132173501211935676986397196799085184804749187146857848057; + p = Pairing.mul(p, 13986731495506593864492662381614386532349950841221768152838255933892789078521); + return + p.X == 18256332256630856740336504687838346961237861778318632856900758565550522381207 && + p.Y == 6976682127058094634733239494758371323697222088503263230319702770853579280803; + } + function pair() returns (bool) { + Pairing.G2Point memory fiveTimesP2 = Pairing.G2Point( + [4540444681147253467785307942530223364530218361853237193970751657229138047649, 20954117799226682825035885491234530437475518021362091509513177301640194298072], + [11631839690097995216017572651900167465857396346217730511548857041925508482915, 21508930868448350162258892668132814424284302804699005394342512102884055673846] + ); + // The prime p in the base field F_p for G1 + uint p = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + Pairing.G1Point[] memory g1points = new Pairing.G1Point[](2); + Pairing.G2Point[] memory g2points = new Pairing.G2Point[](2); + // check e(5 P1, P2)e(-P1, 5 P2) == 1 + g1points[0] = Pairing.P1().mul(5); + g1points[1] = Pairing.P1().negate(); + g2points[0] = Pairing.P2(); + g2points[1] = fiveTimesP2; + if (!Pairing.pairing(g1points, g2points)) + return false; + // check e(P1, P2)e(-P1, P2) == 1 + g1points[0] = Pairing.P1(); + g1points[1] = Pairing.P1(); + g1points[1].Y = p - g1points[1].Y; + g2points[0] = Pairing.P2(); + g2points[1] = Pairing.P2(); + if (!Pairing.pairing(g1points, g2points)) + return false; + return true; + } + function verifyingKey() internal returns (VerifyingKey vk) { + vk.A = Pairing.G2Point([0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7, 0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678], [0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d, 0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550]); + vk.B = Pairing.G1Point(0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84); + vk.C = Pairing.G2Point([0x2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb, 0x01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3], [0x14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713, 0x178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590]); + vk.gamma = Pairing.G2Point([0x25f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb1, 0x22acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d], [0x065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf68, 0x06d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb]); + vk.gammaBeta1 = Pairing.G1Point(0x15794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f21, 0x14db745c6780e9df549864cec19c2daf4531f6ec0c89cc1c7436cc4d8d300c6d); + vk.gammaBeta2 = Pairing.G2Point([0x1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e, 0x283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39], [0x140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e, 0x0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd4]); + vk.Z = Pairing.G2Point([0x217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac29, 0x0a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c], [0x26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a9855, 0x2fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d7]); + vk.IC = new Pairing.G1Point[](10); + vk.IC[0] = Pairing.G1Point(0x0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a, 0x044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf); + vk.IC[1] = Pairing.G1Point(0x1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc, 0x2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb); + vk.IC[2] = Pairing.G1Point(0x1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f, 0x042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db); + vk.IC[3] = Pairing.G1Point(0x17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5, 0x02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1); + vk.IC[4] = Pairing.G1Point(0x0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d, 0x0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b); + vk.IC[5] = Pairing.G1Point(0x232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8, 0x2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7); + vk.IC[6] = Pairing.G1Point(0x09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe, 0x18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4); + vk.IC[7] = Pairing.G1Point(0x0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a, 0x18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e); + vk.IC[8] = Pairing.G1Point(0x0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a, 0x04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e); + vk.IC[9] = Pairing.G1Point(0x111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f, 0x1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30); + } + function verify(uint[] input, Proof proof) internal returns (uint) { + VerifyingKey memory vk = verifyingKey(); + require(input.length + 1 == vk.IC.length); + // Compute the linear combination vk_x + Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); + for (uint i = 0; i < input.length; i++) + vk_x = Pairing.add(vk_x, Pairing.mul(vk.IC[i + 1], input[i])); + vk_x = Pairing.add(vk_x, vk.IC[0]); + if (!Pairing.pairingProd2(proof.A, vk.A, Pairing.negate(proof.A_p), Pairing.P2())) return 1; + if (!Pairing.pairingProd2(vk.B, proof.B, Pairing.negate(proof.B_p), Pairing.P2())) return 2; + if (!Pairing.pairingProd2(proof.C, vk.C, Pairing.negate(proof.C_p), Pairing.P2())) return 3; + if (!Pairing.pairingProd3( + proof.K, vk.gamma, + Pairing.negate(Pairing.add(vk_x, Pairing.add(proof.A, proof.C))), vk.gammaBeta2, + Pairing.negate(vk.gammaBeta1), proof.B + )) return 4; + if (!Pairing.pairingProd3( + Pairing.add(vk_x, proof.A), proof.B, + Pairing.negate(proof.H), vk.Z, + Pairing.negate(proof.C), Pairing.P2() + )) return 5; + return 0; + } + event Verified(string); + function verifyTx() returns (bool) { + uint[] memory input = new uint[](9); + Proof memory proof; + proof.A = Pairing.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497); + proof.A_p = Pairing.G1Point(7742452358972543465462254569134860944739929848367563713587808717088650354556, 7324522103398787664095385319014038380128814213034709026832529060148225837366); + proof.B = Pairing.G2Point( + [8176651290984905087450403379100573157708110416512446269839297438960217797614, 15588556568726919713003060429893850972163943674590384915350025440408631945055], + [15347511022514187557142999444367533883366476794364262773195059233657571533367, 4265071979090628150845437155927259896060451682253086069461962693761322642015]); + proof.B_p = Pairing.G1Point(2979746655438963305714517285593753729335852012083057917022078236006592638393, 6470627481646078059765266161088786576504622012540639992486470834383274712950); + proof.C = Pairing.G1Point(6851077925310461602867742977619883934042581405263014789956638244065803308498, 10336382210592135525880811046708757754106524561907815205241508542912494488506); + proof.C_p = Pairing.G1Point(12491625890066296859584468664467427202390981822868257437245835716136010795448, 13818492518017455361318553880921248537817650587494176379915981090396574171686); + proof.H = Pairing.G1Point(12091046215835229523641173286701717671667447745509192321596954139357866668225, 14446807589950902476683545679847436767890904443411534435294953056557941441758); + proof.K = Pairing.G1Point(21341087976609916409401737322664290631992568431163400450267978471171152600502, 2942165230690572858696920423896381470344658299915828986338281196715687693170); + input[0] = 13986731495506593864492662381614386532349950841221768152838255933892789078521; + input[1] = 622860516154313070522697309645122400675542217310916019527100517240519630053; + input[2] = 11094488463398718754251685950409355128550342438297986977413505294941943071569; + input[3] = 6627643779954497813586310325594578844876646808666478625705401786271515864467; + input[4] = 2957286918163151606545409668133310005545945782087581890025685458369200827463; + input[5] = 1384290496819542862903939282897996566903332587607290986044945365745128311081; + input[6] = 5613571677741714971687805233468747950848449704454346829971683826953541367271; + input[7] = 9643208548031422463313148630985736896287522941726746581856185889848792022807; + input[8] = 18066496933330839731877828156604; + if (verify(input, proof) == 0) { + Verified("Transaction successfully verified."); + return true; + } else { + return false; + } + } + + } + )"; + compileAndRun(sourceCode, 0, "Pairing"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Pairing", m_contractAddress}}); + // Disabled because the point seems to be not well-formed, we need to find another example. + //BOOST_CHECK(callContractFunction("testMul()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("pair()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("verifyTx()") == encodeArgs(true)); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index a8e58c25..342d0875 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -24,7 +24,7 @@ #include <functional> -#include "../ExecutionFramework.h" +#include <test/ExecutionFramework.h> #include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/Exceptions.h> diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 58efa0a2..67747386 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -125,7 +125,7 @@ bytes compileFirstExpression( for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) { - ETH_TEST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract), "Resolving names failed"); + BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*contract), "Resolving names failed"); inheritanceHierarchy = vector<ContractDefinition const*>(1, contract); } for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 39c47f9c..9b0647bf 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1395,6 +1395,61 @@ BOOST_AUTO_TEST_CASE(events_with_same_name) BOOST_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"( @@ -2306,17 +2361,28 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); } -BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) +BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable_0_4_x) { char const* text = R"( contract C { address constant x = msg.sender; } )"; - // Change to TypeError for 0.5.0. 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"( @@ -2333,7 +2399,7 @@ BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment) CHECK_ERROR(text, TypeError, "Index access for string is not possible."); } -BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) +BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant_0_4_x) { char const* text = R"( contract C { @@ -2341,10 +2407,22 @@ BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) uint constant y = x(); } )"; - // Change to TypeError for 0.5.0. CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); } +BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + + contract C { + function () constant returns (uint) x; + uint constant y = x(); + } + )"; + CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant."); +} + BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion) { char const* text = R"( @@ -4135,6 +4213,8 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } )"; CHECK_SUCCESS_NO_WARNINGS(text); + + // Test deprecation warning under < 0.5.0 text = R"( contract test { function f() pure public { @@ -4154,6 +4234,29 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } )"; 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) @@ -4251,7 +4354,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Array with fractional length specified."); } BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type) @@ -4263,7 +4366,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type) @@ -4275,7 +4378,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion) @@ -5434,7 +5537,7 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid mobile type."); + CHECK_ERROR(text, TypeError, "Invalid rational number."); } BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function) @@ -5776,6 +5879,28 @@ BOOST_AUTO_TEST_CASE(interface_function_bodies) CHECK_ERROR(text, TypeError, "Functions in interfaces cannot have an implementation"); } +BOOST_AUTO_TEST_CASE(interface_function_external) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + interface I { + function f() external; + } + )"; + success(text); +} + +BOOST_AUTO_TEST_CASE(interface_function_public) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + interface I { + function f() public; + } + )"; + CHECK_ERROR(text, TypeError, "Functions in interfaces must be declared external."); +} + BOOST_AUTO_TEST_CASE(interface_function_internal) { char const* text = R"( @@ -6107,6 +6232,26 @@ BOOST_AUTO_TEST_CASE(warn_unused_return_parameter) 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 public 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"( @@ -6268,6 +6413,17 @@ BOOST_AUTO_TEST_CASE(function_override_is_not_shadowing) 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"( @@ -6409,7 +6565,19 @@ BOOST_AUTO_TEST_CASE(warn_unspecified_storage) } } )"; - CHECK_WARNING(text, "is declared as a storage pointer. Use an explicit \"storage\" keyword to silence this warning"); + 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(implicit_conversion_disallowed) @@ -6928,6 +7096,53 @@ BOOST_AUTO_TEST_CASE(non_external_fallback) 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(warn_about_sha3) { char const* text = R"( @@ -6953,6 +7168,135 @@ BOOST_AUTO_TEST_CASE(warn_about_suicide) CHECK_WARNING(text, "\"suicide\" has been deprecated in favour of \"selfdestruct\""); } +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_too_large) +{ + char const* text = R"( + contract C { + uint[8**90] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); +} + +BOOST_AUTO_TEST_CASE(array_length_not_convertible_to_integer) +{ + char const* text = R"( + contract C { + uint[true] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); +} + +BOOST_AUTO_TEST_CASE(array_length_invalid_expression) +{ + char const* text = R"( + contract C { + uint[-true] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid constant expression."); + text = R"( + contract C { + uint[true/1] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid constant expression."); + text = R"( + contract C { + uint[1/true] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid constant expression."); + text = R"( + contract C { + uint[1.111111E1111111111111] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid literal value."); +} + +BOOST_AUTO_TEST_CASE(no_address_members_on_contract) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + contract C { + function f() { + 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() { + 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() { + 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() { + 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() { + 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() { + this.delegatecall; + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"delegatecall\" not found or not visible after argument-dependent lookup in contract"); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 149221d5..d83773bc 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -47,7 +47,7 @@ public: { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); - ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); + BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); Json::Value generatedDocumentation; if (_userDocumentation) diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 60ca03c9..72473c3e 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -167,6 +167,90 @@ BOOST_AUTO_TEST_CASE(single_function_param) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(single_function_param_trailing_comma) +{ + char const* text = R"( + contract test { + function(uint a,) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(single_return_param_trailing_comma) +{ + char const* text = R"( + contract test { + function() returns (uint a,) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(single_modifier_arg_trailing_comma) +{ + char const* text = R"( + contract test { + modifier modTest(uint a,) { _; } + function(uint a) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(single_event_arg_trailing_comma) +{ + char const* text = R"( + contract test { + event Test(uint a,); + function(uint a) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +BOOST_AUTO_TEST_CASE(multiple_function_param_trailing_comma) +{ + char const* text = R"( + contract test { + function(uint a, uint b,) {} + } + )"; + CHECK_PARSE_ERROR(text, "Unexpected trailing comma in parameter list."); +} + +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(function_no_body) { char const* text = R"( @@ -250,7 +334,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) FunctionDefinition const* function = nullptr; auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "This is a test function"); } @@ -268,7 +352,7 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(function->documentation() == nullptr, "Should not have gotten a Natspecc comment for this function"); } @@ -294,17 +378,17 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) ASTPointer<ContractDefinition> contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "This is test function 1"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(1), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(1), "Failed to retrieve function"); checkFunctionNatspec(function, "This is test function 2"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(2), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(2), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(function->documentation() == nullptr, "Should not have gotten natspec comment for functionName3()"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(3), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(3), "Failed to retrieve function"); checkFunctionNatspec(function, "This is test function 4"); } @@ -323,7 +407,7 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "This is a test function\n" " and it has 2 lines"); } @@ -351,10 +435,10 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) ASTPointer<ContractDefinition> contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); checkFunctionNatspec(function, "fun1 description"); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(1), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(1), "Failed to retrieve function"); checkFunctionNatspec(function, "This is a test function\n" " and it has 2 lines"); } @@ -380,7 +464,7 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) ASTPointer<ContractDefinition> contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(!function->documentation(), "Shouldn't get natspec docstring for this function"); } @@ -406,7 +490,7 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) ASTPointer<ContractDefinition> contract = parseText(text, errors); auto functions = contract->definedFunctions(); - ETH_TEST_REQUIRE_NO_THROW(function = functions.at(0), "Failed to retrieve function"); + BOOST_REQUIRE_MESSAGE(function = functions.at(0), "Failed to retrieve function"); BOOST_CHECK_MESSAGE(!function->documentation(), "Shouldn't get natspec docstring for this function"); } diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 24f915c0..4504946b 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -226,6 +226,183 @@ BOOST_AUTO_TEST_CASE(basic_compilation) ); } +BOOST_AUTO_TEST_CASE(output_selection_explicit) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "fileA": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_all_contracts) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "fileA": { + "*": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_all_files_single_contract) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_all_files_all_contracts) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "*": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract A { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_dependent_contract) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "contract B { } contract A { function f() { new B(); } }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[{\"constant\":false,\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); +} + +BOOST_AUTO_TEST_CASE(output_selection_dependent_contract_with_import) +{ + char const* input = R"( + { + "language": "Solidity", + "settings": { + "outputSelection": { + "*": { + "A": [ + "abi" + ] + } + } + }, + "sources": { + "fileA": { + "content": "import \"fileB\"; contract A { function f() { new B(); } }" + }, + "fileB": { + "content": "contract B { }" + } + } + } + )"; + Json::Value result = compile(input); + BOOST_CHECK(containsAtMostWarnings(result)); + Json::Value contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.isObject()); + BOOST_CHECK(contract["abi"].isArray()); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[{\"constant\":false,\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 80241519..6353ae8a 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE(assembly) assembly { x := 7 } } function g() view public { - assembly { for {} 1 { pop(sload(0)) } { } } + assembly { for {} 1 { pop(sload(0)) } { } pop(gas) } } function h() view public { assembly { function g() { pop(blockhash(20)) } } @@ -357,6 +357,9 @@ BOOST_AUTO_TEST_CASE(assembly) 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); @@ -367,7 +370,7 @@ BOOST_AUTO_TEST_CASE(assembly_staticcall) string text = R"( contract C { function i() view public { - assembly { pop(staticcall(0, 1, 2, 3, 4, 5)) } + assembly { pop(staticcall(gas, 1, 2, 3, 4, 5)) } } } )"; |