aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md13
-rw-r--r--cmake/FindCLN.cmake3
-rw-r--r--cmake/FindCVC4.cmake20
-rw-r--r--docs/_static/css/custom.css (renamed from docs/docs-css/custom.css)6
-rw-r--r--docs/abi-spec.rst124
-rw-r--r--docs/assembly.rst18
-rw-r--r--docs/common-patterns.rst2
-rw-r--r--docs/conf.py2
-rw-r--r--docs/contracts.rst66
-rw-r--r--docs/control-structures.rst44
-rw-r--r--docs/frequently-asked-questions.rst13
-rw-r--r--docs/index.rst77
-rw-r--r--docs/installing-solidity.rst42
-rw-r--r--docs/layout-of-source-files.rst13
-rw-r--r--docs/solidity-by-example.rst10
-rw-r--r--docs/structure-of-a-contract.rst2
-rw-r--r--docs/style-guide.rst123
-rw-r--r--docs/types.rst119
-rw-r--r--docs/using-the-compiler.rst11
-rw-r--r--libdevcore/StringUtils.h2
-rw-r--r--libevmasm/Assembly.cpp8
-rw-r--r--libevmasm/ConstantOptimiser.cpp3
-rw-r--r--libevmasm/ConstantOptimiser.h2
-rw-r--r--libevmasm/Instruction.cpp2
-rw-r--r--libsolidity/CMakeLists.txt17
-rw-r--r--libsolidity/analysis/ControlFlowAnalyzer.cpp5
-rw-r--r--libsolidity/analysis/GlobalContext.cpp4
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp2
-rw-r--r--libsolidity/analysis/TypeChecker.cpp46
-rw-r--r--libsolidity/analysis/TypeChecker.h3
-rw-r--r--libsolidity/ast/Types.cpp163
-rw-r--r--libsolidity/ast/Types.h29
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp2
-rw-r--r--libsolidity/formal/CVC4Interface.h11
-rw-r--r--libsolidity/interface/CompilerStack.cpp37
-rw-r--r--libsolidity/interface/CompilerStack.h21
-rw-r--r--libsolidity/interface/StandardCompiler.cpp9
-rwxr-xr-xscripts/isolate_tests.py49
-rw-r--r--solc/CommandLineInterface.cpp15
-rw-r--r--solc/CommandLineInterface.h2
-rw-r--r--test/ExecutionFramework.cpp16
-rw-r--r--test/ExecutionFramework.h7
-rw-r--r--test/RPCSession.cpp5
-rw-r--r--test/RPCSession.h1
-rwxr-xr-xtest/cmdlineTests.sh77
-rw-r--r--test/compilationTests/stringutils/strings.sol10
-rw-r--r--test/libevmasm/Assembler.cpp152
-rw-r--r--test/libjulia/Simplifier.cpp28
-rw-r--r--test/libsolidity/ABIDecoderTests.cpp4
-rw-r--r--test/libsolidity/ABIEncoderTests.cpp2
-rw-r--r--test/libsolidity/GasMeter.cpp2
-rw-r--r--test/libsolidity/Imports.cpp14
-rw-r--r--test/libsolidity/LibSolc.cpp8
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp503
-rw-r--r--test/libsolidity/SolidityTypes.cpp8
-rw-r--r--test/libsolidity/StandardCompiler.cpp32
-rw-r--r--test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol5
-rw-r--r--test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol5
-rw-r--r--test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol5
-rw-r--r--test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol5
-rw-r--r--test/libsolidity/syntaxTests/conversion/conversion_to_bytes.sol5
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/161_warns_assigning_decimal_to_bytesxx.sol5
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/162_does_not_warn_assigning_hex_number_to_bytesxx.sol3
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/163_explicit_conversion_from_decimal_to_bytesxx.sol3
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol2
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol3
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol2
-rw-r--r--test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol9
-rw-r--r--test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol10
-rw-r--r--test/libsolidity/syntaxTests/types/bytesm.sol2
-rw-r--r--test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_explicit.sol23
-rw-r--r--test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_implicit.sol23
-rw-r--r--test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol42
-rw-r--r--test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol39
-rw-r--r--test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol51
-rw-r--r--test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol46
-rw-r--r--test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_explicit.sol31
-rw-r--r--test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_implicit.sol31
-rw-r--r--test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_explicit.sol13
-rw-r--r--test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_implicit.sol13
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/argument_external.sol7
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/argument_internal.sol5
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/argument_private.sol5
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/argument_public.sol7
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol5
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol5
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_return_external.sol10
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_return_private.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/library_return_public.sol10
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol16
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol5
-rw-r--r--test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_explicit.sol30
-rw-r--r--test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_implicit.sol30
-rw-r--r--test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol2
-rw-r--r--test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol8
113 files changed, 2055 insertions, 575 deletions
diff --git a/Changelog.md b/Changelog.md
index eec62736..ea4504ac 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -16,6 +16,8 @@ Breaking Changes:
* Commandline interface: Remove obsolete ``--formal`` option.
* Commandline interface: Rename the ``--julia`` option to ``--yul``.
* Commandline interface: Require ``-`` if standard input is used as source.
+ * Compiler interface: Disallow remappings with empty prefix.
+ * Control Flow Analyzer: Consider mappings as well when checking for uninitialized return values.
* Control Flow Analyzer: Turn warning about returning uninitialized storage pointers into an error.
* General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code.
* General: Disallow declaring empty structs.
@@ -57,7 +59,9 @@ Breaking Changes:
* Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Address members are not included in contract types anymore. An explicit conversion is now required before invoking an ``address`` member from a contract.
* Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore.
- * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/solidity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible.
+ * Type System: Disallow explicit and implicit conversions from decimal literals to ``bytesXX`` types.
+ * Type System: Disallow explicit and implicit conversions from hex literals to ``bytesXX`` types of different size.
+ * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible.
* References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode.
* Syntax Checker: Disallow functions without implementation to use modifiers. This was already the case in the experimental 0.5.0 mode.
* Syntax Checker: Named return values in function types are an error.
@@ -70,6 +74,8 @@ Language Features:
* General: Support ``pop()`` for storage arrays.
* General: Scoping rules now follow the C99-style.
* General: Allow ``enum``s in interfaces.
+ * General: Allow ``mapping`` storage pointers as arguments and return values in all internal functions.
+ * General: Allow ``struct``s in interfaces.
Compiler Features:
* C API (``libsolc``): Export the ``solidity_license``, ``solidity_version`` and ``solidity_compile`` methods.
@@ -80,19 +86,24 @@ Compiler Features:
* Removed ``pragma experimental "v0.5.0";``.
Bugfixes:
+ * Build System: Support versions of CVC4 linked against CLN instead of GMP. In case of compilation issues due to the experimental SMT solver support, the solvers can be disabled when configuring the project with CMake using ``-DUSE_CVC4=OFF`` or ``-DUSE_Z3=OFF``.
* Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum.
* Code Generator: Fix allocation of byte arrays (zeroed out too much memory).
* Code Generator: Properly handle negative number literals in ABIEncoderV2.
* Commandline Interface: Correctly handle paths with backslashes on windows.
* Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions.
+ * Optimizer: Correctly estimate gas costs of constants for special cases.
* References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own.
* References Resolver: Enforce ``storage`` as data location for mappings.
* References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``.
* References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter.
+ * Type Checker: Default data location for type conversions (e.g. from literals) is memory and not storage.
* Type Checker: Disallow assignments to mappings within tuple assignments as well.
+ * Type Checker: Disallow packed encoding of arrays of structs.
* Type Checker: Allow assignments to local variables of mapping types.
* Type Checker: Consider fixed size arrays when checking for recursive structs.
* Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined.
+ * Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``.
* Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values.
* Type System: Allow arbitrary exponents for literals with a mantissa of zero.
diff --git a/cmake/FindCLN.cmake b/cmake/FindCLN.cmake
new file mode 100644
index 00000000..f2234bb4
--- /dev/null
+++ b/cmake/FindCLN.cmake
@@ -0,0 +1,3 @@
+find_library(CLN_LIBRARY NAMES cln)
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(CLN DEFAULT_MSG CLN_LIBRARY)
diff --git a/cmake/FindCVC4.cmake b/cmake/FindCVC4.cmake
index 90b7ebd5..2649d7c7 100644
--- a/cmake/FindCVC4.cmake
+++ b/cmake/FindCVC4.cmake
@@ -1,8 +1,26 @@
if (USE_CVC4)
find_path(CVC4_INCLUDE_DIR cvc4/cvc4.h)
- find_library(CVC4_LIBRARY NAMES cvc4 )
+ find_library(CVC4_LIBRARY NAMES cvc4)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CVC4 DEFAULT_MSG CVC4_LIBRARY CVC4_INCLUDE_DIR)
+ if(CVC4_FOUND)
+ # CVC4 may depend on either CLN or GMP.
+ # We can assume that the one it requires is present on the system,
+ # so we quietly try to find both and link against them, if they are
+ # present.
+ find_package(CLN QUIET)
+ find_package(GMP QUIET)
+
+ set(CVC4_LIBRARIES ${CVC4_LIBRARY})
+
+ if (CLN_FOUND)
+ set(CVC4_LIBRARIES ${CVC4_LIBRARIES} ${CLN_LIBRARY})
+ endif ()
+
+ if (GMP_FOUND)
+ set(CVC4_LIBRARIES ${CVC4_LIBRARIES} ${GMP_LIBRARY})
+ endif ()
+ endif()
else()
set(CVC4_FOUND FALSE)
endif()
diff --git a/docs/docs-css/custom.css b/docs/_static/css/custom.css
index 970148ed..fd506203 100644
--- a/docs/docs-css/custom.css
+++ b/docs/_static/css/custom.css
@@ -7,8 +7,8 @@ pre {
}
.wy-table-responsive table td, .wy-table-responsive table th {
- white-space: pre-wrap;
+ white-space: normal;
}
-.wy-table-responsive table td, .wy-table-responsive table th {
- white-space: pre-wrap;
+.rst-content table.docutils td {
+ vertical-align: top;
}
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index ec84d123..92af8f0c 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -151,8 +151,8 @@ on the type of ``X`` being
- ``bytes``, of length ``k`` (which is assumed to be of type ``uint256``):
``enc(X) = enc(k) pad_right(X)``, i.e. the number of bytes is encoded as a
- ``uint256`` followed by the actual value of ``X`` as a byte sequence, followed by
- the minimum number of zero-bytes such that ``len(enc(X))`` is a multiple of 32.
+ ``uint256`` followed by the actual value of ``X`` as a byte sequence, followed by
+ the minimum number of zero-bytes such that ``len(enc(X))`` is a multiple of 32.
- ``string``:
@@ -205,7 +205,9 @@ Thus for our ``Foo`` example if we wanted to call ``baz`` with the parameters ``
- ``0x0000000000000000000000000000000000000000000000000000000000000045``: the first parameter, a uint32 value ``69`` padded to 32 bytes
- ``0x0000000000000000000000000000000000000000000000000000000000000001``: the second parameter - boolean ``true``, padded to 32 bytes
-In total::
+In total:
+
+.. code-block:: none
0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001
@@ -217,7 +219,9 @@ If we wanted to call ``bar`` with the argument ``["abc", "def"]``, we would pass
- ``0x6162630000000000000000000000000000000000000000000000000000000000``: the first part of the first parameter, a ``bytes3`` value ``"abc"`` (left-aligned).
- ``0x6465660000000000000000000000000000000000000000000000000000000000``: the second part of the first parameter, a ``bytes3`` value ``"def"`` (left-aligned).
-In total::
+In total:
+
+.. code-block:: none
0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000
@@ -234,7 +238,9 @@ If we wanted to call ``sam`` with the arguments ``"dave"``, ``true`` and ``[1,2,
- ``0x0000000000000000000000000000000000000000000000000000000000000002``: the second entry of the third parameter.
- ``0x0000000000000000000000000000000000000000000000000000000000000003``: the third entry of the third parameter.
-In total::
+In total:
+
+.. code-block:: none
0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003
@@ -264,7 +270,7 @@ Finally, we encode the data part of the second dynamic argument, ``"Hello, world
All together, the encoding is (newline after function selector and each 32-bytes for clarity):
-::
+.. code-block:: none
0x8be65246
0000000000000000000000000000000000000000000000000000000000000123
@@ -292,15 +298,15 @@ Then we encode the length and data of the second embedded dynamic array ``[3]``
Then we need to find the offsets ``a`` and ``b`` for their respective dynamic arrays ``[1, 2]`` and ``[3]``. To calculate the offsets we can take a look at the encoded data of the first root array ``[[1, 2], [3]]`` enumerating each line in the encoding:
-::
+.. code-block:: none
- 0 - a - offset of [1, 2]
- 1 - b - offset of [3]
- 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2]
- 3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1
- 4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2
- 5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3]
- 6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3
+ 0 - a - offset of [1, 2]
+ 1 - b - offset of [3]
+ 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2]
+ 3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1
+ 4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2
+ 5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3]
+ 6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3
Offset ``a`` points to the start of the content of the array ``[1, 2]`` which is line 2 (64 bytes); thus ``a = 0x0000000000000000000000000000000000000000000000000000000000000040``.
@@ -318,17 +324,17 @@ Then we encode the embedded strings of the second root array:
In parallel to the first root array, since strings are dynamic elements we need to find their offsets ``c``, ``d`` and ``e``:
-::
+.. code-block:: none
- 0 - c - offset for "one"
- 1 - d - offset for "two"
- 2 - e - offset for "three"
- 3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"
- 4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"
- 5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"
- 6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"
- 7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"
- 8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"
+ 0 - c - offset for "one"
+ 1 - d - offset for "two"
+ 2 - e - offset for "three"
+ 3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"
+ 4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"
+ 5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"
+ 6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"
+ 7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"
+ 8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"
Offset ``c`` points to the start of the content of the string ``"one"`` which is line 3 (96 bytes); thus ``c = 0x0000000000000000000000000000000000000000000000000000000000000060``.
@@ -349,29 +355,29 @@ Then we encode the length of the second root array:
Finally we find the offsets ``f`` and ``g`` for their respective root dynamic arrays ``[[1, 2], [3]]`` and ``["one", "two", "three"]``, and assemble parts in the correct order:
-::
-
- 0x2289b18c - function signature
- 0 - f - offset of [[1, 2], [3]]
- 1 - g - offset of ["one", "two", "three"]
- 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]]
- 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2]
- 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3]
- 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2]
- 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1
- 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2
- 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3]
- 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3
- 10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"]
- 11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one"
- 12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two"
- 13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three"
- 14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"
- 15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"
- 16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"
- 17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"
- 18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"
- 19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"
+.. code-block:: none
+
+ 0x2289b18c - function signature
+ 0 - f - offset of [[1, 2], [3]]
+ 1 - g - offset of ["one", "two", "three"]
+ 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]]
+ 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2]
+ 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3]
+ 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2]
+ 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1
+ 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2
+ 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3]
+ 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3
+ 10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"]
+ 11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one"
+ 12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two"
+ 13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three"
+ 14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"
+ 15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"
+ 16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"
+ 17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"
+ 18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"
+ 19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"
Offset ``f`` points to the start of the content of the array ``[[1, 2], [3]]`` which is line 2 (64 bytes); thus ``f = 0x0000000000000000000000000000000000000000000000000000000000000040``.
@@ -444,7 +450,7 @@ For example,
pragma solidity >0.4.24;
contract Test {
- constructor() public { b = 0x12345678901234567890123456789012; }
+ constructor() public { b = hex"12345678901234567890123456789012"; }
event Event(uint indexed a, bytes32 b);
event Event2(uint indexed a, bytes32 b);
function foo(uint a) public { emit Event(a, b); }
@@ -453,7 +459,7 @@ For example,
would result in the JSON:
-.. code:: json
+.. code-block:: json
[{
"type":"event",
@@ -494,13 +500,13 @@ As an example, the code
contract Test {
struct S { uint a; uint[] b; T[] c; }
struct T { uint x; uint y; }
- function f(S memory s, T memory t, uint a) public { }
- function g() public returns (S memory s, T memory t, uint a) {}
+ function f(S memory s, T memory t, uint a) public;
+ function g() public returns (S memory s, T memory t, uint a);
}
would result in the JSON:
-.. code:: json
+.. code-block:: json
[
{
@@ -565,14 +571,15 @@ Non-standard Packed Mode
Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode where:
-- no :ref:`function selector <abi_function_selector>` is encoded,
- types shorter than 32 bytes are neither zero padded nor sign extended and
- dynamic types are encoded in-place and without the length.
-As an example encoding ``int1, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in ::
+As an example encoding ``int8, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in:
+
+.. code-block:: none
0xff42242448656c6c6f2c20776f726c6421
- ^^ int1(-1)
+ ^^ int8(-1)
^^ bytes1(0x42)
^^^^ uint16(0x2424)
^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field
@@ -582,8 +589,7 @@ and dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded
their length field. This means that the encoding is ambiguous as soon as there are two
dynamically-sized elements.
-Note that constants will be packed using the minimum number of bytes required to store them.
-This means that, for example, ``abi.encodePacked(0) == abi.encodePacked(uint8(0)) == hex"00"`` and
-``abi.encodePacked(0x12345678) == abi.encodePacked(uint32(0x12345678)) == hex"12345678"``.
-
If padding is needed, explicit type conversions can be used: ``abi.encodePacked(uint16(0x12)) == hex"0012"``.
+
+Since packed encoding is not used when calling functions, there is no special support
+for prepending a function selector.
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 91ba076a..2cbad06f 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -82,7 +82,7 @@ you really know what you are doing.
library VectorSum {
// This function is less efficient because the optimizer currently fails to
// remove the bounds checks in array access.
- function sumSolidity(uint[] memory _data) public view returns (uint o_sum) {
+ function sumSolidity(uint[] memory _data) public pure returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i)
o_sum += _data[i];
}
@@ -90,7 +90,7 @@ you really know what you are doing.
// We know that we only access the array in bounds, so we can avoid the check.
// 0x20 needs to be added to an array because the first slot contains the
// array length.
- function sumAsm(uint[] memory _data) public view returns (uint o_sum) {
+ function sumAsm(uint[] memory _data) public pure returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i) {
assembly {
o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
@@ -99,7 +99,7 @@ you really know what you are doing.
}
// Same as above, but accomplish the entire code within inline assembly.
- function sumPureAsm(uint[] memory _data) public view returns (uint o_sum) {
+ function sumPureAsm(uint[] memory _data) public pure returns (uint o_sum) {
assembly {
// Load the length (first 32 bytes)
let len := mload(_data)
@@ -378,23 +378,13 @@ used ``x_slot`` and to retrieve the byte-offset you used ``x_offset``.
In assignments (see below), we can even use local Solidity variables to assign to.
-Functions external to inline assembly can also be accessed: The assembly will
-push their entry label (with virtual function resolution applied). The calling semantics
-in solidity are:
-
- - the caller pushes ``return label``, ``arg1``, ``arg2``, ..., ``argn``
- - the call returns with ``ret1``, ``ret2``, ..., ``retm``
-
-This feature is still a bit cumbersome to use, because the stack offset essentially
-changes during the call, and thus references to local variables will be wrong.
-
.. code::
pragma solidity ^0.4.11;
contract C {
uint b;
- function f(uint x) public returns (uint r) {
+ function f(uint x) public view returns (uint r) {
assembly {
r := mul(x, sload(b_slot)) // ignore the offset, we know it is zero
}
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst
index bc8286b2..6b061bf7 100644
--- a/docs/common-patterns.rst
+++ b/docs/common-patterns.rst
@@ -198,7 +198,7 @@ restrictions highly readable.
);
_;
if (msg.value > _amount)
- msg.sender.send(msg.value - _amount);
+ msg.sender.transfer(msg.value - _amount);
}
function forceOwnerChange(address _newOwner)
diff --git a/docs/conf.py b/docs/conf.py
index 55f4f1a8..233ff7b6 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -143,7 +143,7 @@ html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
+html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 561d2f97..ca15d814 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -110,12 +110,11 @@ This means that cyclic creation dependencies are impossible.
function isTokenTransferOK(address currentOwner, address newOwner)
public
- view
+ pure
returns (bool ok)
{
// Check some arbitrary condition.
- address tokenAddress = msg.sender;
- return (keccak256(abi.encodePacked(newOwner)) & 0xff) == (bytes20(tokenAddress) & 0xff);
+ return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f;
}
}
@@ -138,16 +137,16 @@ Functions have to be specified as being ``external``,
For state variables, ``external`` is not possible.
``external``:
- External functions are part of the contract
- interface, which means they can be called from other contracts and
+ External functions are part of the contract interface,
+ which means they can be called from other contracts and
via transactions. An external function ``f`` cannot be called
internally (i.e. ``f()`` does not work, but ``this.f()`` works).
External functions are sometimes more efficient when
they receive large arrays of data.
``public``:
- Public functions are part of the contract
- interface and can be either called internally or via
+ Public functions are part of the contract interface
+ and can be either called internally or via
messages. For public state variables, an automatic getter
function (see below) is generated.
@@ -188,8 +187,6 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
::
- // This will not compile
-
pragma solidity ^0.4.0;
contract C {
@@ -201,6 +198,7 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
function compute(uint a, uint b) internal pure returns (uint) { return a + b; }
}
+ // This will not compile
contract D {
function readData() public {
C c = new C();
@@ -228,8 +226,8 @@ The compiler automatically creates getter functions for
all **public** state variables. For the contract given below, the compiler will
generate a function called ``data`` that does not take any
arguments and returns a ``uint``, the value of the state
-variable ``data``. The initialization of state variables can
-be done at declaration.
+variable ``data``. State variables can be initialized
+when they are declared.
::
@@ -241,8 +239,8 @@ be done at declaration.
contract Caller {
C c = new C();
- function f() public {
- uint local = c.data();
+ function f() public view returns (uint) {
+ return c.data();
}
}
@@ -257,9 +255,9 @@ it is evaluated as a state variable. If it is accessed externally
contract C {
uint public data;
- function x() public {
+ function x() public returns (uint) {
data = 3; // internal access
- uint val = this.data(); // external access
+ return this.data(); // external access
}
}
@@ -616,14 +614,13 @@ Like any function, the fallback function can execute complex operations as long
}
contract Caller {
- function callTest(Test test) public {
- address(test).call(abi.encodeWithSignature("nonExistingFunction()"));
+ function callTest(Test test) public returns (bool) {
+ require(address(test).call(abi.encodeWithSignature("nonExistingFunction()")));
// results in test.x becoming == 1.
// If someone sends ether to that contract,
- // the transaction will fail and reject the
- // Ether.
- address(test).send(2 ether);
+ // the transfer will fail, i.e. this returns false here.
+ return address(test).send(2 ether);
}
}
@@ -634,9 +631,11 @@ Like any function, the fallback function can execute complex operations as long
Function Overloading
====================
-A Contract can have multiple functions of the same name but with different arguments.
-This also applies to inherited functions. The following example shows overloading of the
-``f`` function in the scope of contract ``A``.
+A contract can have multiple functions of the same name but with different parameter
+types.
+This process is called "overloading" and also applies to inherited functions.
+The following example shows overloading of the function
+``f`` in the scope of contract ``A``.
::
@@ -644,11 +643,12 @@ This also applies to inherited functions. The following example shows overloadin
contract A {
function f(uint _in) public pure returns (uint out) {
- out = 1;
+ out = _in;
}
- function f(uint _in, bytes32 _key) public pure returns (uint out) {
- out = 2;
+ function f(uint _in, bool _really) public pure returns (uint out) {
+ if (_really)
+ out = _in;
}
}
@@ -657,9 +657,9 @@ externally visible functions differ by their Solidity types but not by their ext
::
- // This will not compile
pragma solidity ^0.4.16;
+ // This will not compile
contract A {
function f(B _in) public pure returns (B out) {
out = _in;
@@ -811,12 +811,12 @@ as topics. The event call above can be performed in the same way as
contract C {
function f() public payable {
- bytes32 _id = 0x420042;
+ uint256 _id = 0x420042;
log3(
bytes32(msg.value),
bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
bytes32(uint256(msg.sender)),
- _id
+ bytes32(_id)
);
}
}
@@ -1038,10 +1038,12 @@ derived contracts need to specify all of them. This can be done in two ways::
constructor(uint _x) public { x = _x; }
}
+ // Either directly specify in the inheritance list...
contract Derived1 is Base(7) {
- constructor(uint _y) public {}
+ constructor() public {}
}
+ // or through a "modifier" of the derived constructor.
contract Derived2 is Base {
constructor(uint _y) Base(_y * _y) public {}
}
@@ -1080,12 +1082,11 @@ error "Linearization of inheritance graph impossible".
::
- // This will not compile
-
pragma solidity ^0.4.0;
contract X {}
contract A is X {}
+ // This will not compile
contract C is A, X {}
The reason for this is that ``C`` requests ``X`` to override ``A``
@@ -1343,6 +1344,7 @@ custom types without the overhead of external function calls:
BigInt.bigint memory x = BigInt.fromUint(7);
BigInt.bigint memory y = BigInt.fromUint(uint(-1));
BigInt.bigint memory z = x.add(y);
+ assert(z.limb(1) > 0);
}
}
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 9fd017db..def75132 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -23,8 +23,9 @@ something like::
pragma solidity ^0.4.16;
contract Simple {
- function taker(uint _a, uint _b) public pure {
- // do something with _a and _b.
+ uint sum;
+ function taker(uint _a, uint _b) public {
+ sum = _a + _b;
}
}
@@ -102,7 +103,7 @@ this nonsensical example::
pragma solidity ^0.4.16;
contract C {
- function g(uint a) public pure returns (uint ret) { return f(); }
+ function g(uint a) public pure returns (uint ret) { return a + f(); }
function f() internal pure returns (uint ret) { return g(7) + f(); }
}
@@ -158,8 +159,8 @@ throws an exception or goes out of gas.
.. warning::
Any interaction with another contract imposes a potential danger, especially
- if the source code of the contract is not known in advance. The current
- contract hands over control to the called contract and that may potentially
+ if the source code of the contract is not known in advance. The
+ current contract hands over control to the called contract and that may potentially
do just about anything. Even if the called contract inherits from a known parent contract,
the inheriting contract is only required to have a correct interface. The
implementation of the contract, however, can be completely arbitrary and thus,
@@ -184,14 +185,16 @@ parameters from the function declaration, but can be in arbitrary order.
pragma solidity ^0.4.0;
contract C {
- function f(uint key, uint value) public {
- // ...
+ mapping(uint => uint) data;
+
+ function f() public {
+ set({value: 2, key: 3});
}
- function g() public {
- // named arguments
- f({value: 2, key: 3});
+ function set(uint key, uint value) public {
+ data[key] = value;
}
+
}
Omitted Function Parameter Names
@@ -228,7 +231,7 @@ creation-dependencies are not possible.
pragma solidity >0.4.24;
contract D {
- uint x;
+ uint public x;
constructor(uint a) public payable {
x = a;
}
@@ -239,11 +242,13 @@ creation-dependencies are not possible.
function createD(uint arg) public {
D newD = new D(arg);
+ newD.x();
}
function createAndEndowD(uint arg, uint amount) public payable {
// Send ether along with the creation
D newD = (new D).value(amount)(arg);
+ newD.x();
}
}
@@ -287,12 +292,13 @@ These can then either be assigned to newly declared variables or to pre-existing
}
function g() public {
- // Variables declared with type and assigned from the returned tuple.
- (uint x, bool b, uint y) = f();
+ // Variables declared with type and assigned from the returned tuple,
+ // not all elements have to be specified (but the number must match).
+ (uint x, , uint y) = f();
// Common trick to swap values -- does not work for non-value storage types.
(x, y) = (y, x);
// Components can be left out (also for variable declarations).
- (data.length,,) = f(); // Sets the length to 7
+ (data.length, , ) = f(); // Sets the length to 7
}
}
@@ -338,11 +344,13 @@ the two variables have the same name but disjoint scopes.
contract C {
function minimalScoping() pure public {
{
- uint same2 = 0;
+ uint same;
+ same = 1;
}
{
- uint same2 = 0;
+ uint same;
+ same = 3;
}
}
}
@@ -354,6 +362,7 @@ In any case, you will get a warning about the outer variable being shadowed.
::
pragma solidity >0.4.24;
+ // This will report a warning
contract C {
function f() pure public returns (uint) {
uint x = 1;
@@ -372,9 +381,8 @@ In any case, you will get a warning about the outer variable being shadowed.
::
- // This will not compile
-
pragma solidity >0.4.24;
+ // This will not compile
contract C {
function f() pure public returns (uint) {
x = 2;
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index 786c3341..b26ff527 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -62,7 +62,8 @@ Example::
contract C {
function f() public pure returns (uint8[5] memory) {
string[4] memory adaArr = ["This", "is", "an", "array"];
- return ([1, 2, 3, 4, 5]);
+ adaArr[0] = "That";
+ return [1, 2, 3, 4, 5];
}
}
@@ -186,9 +187,10 @@ If you do not want to throw, you can return a pair::
function checkCounter(uint index) public view {
(uint counter, bool error) = getCounter(index);
if (error) {
- // ...
+ // Handle the error
} else {
- // ...
+ // Do something with counter.
+ require(counter > 7, "Invalid counter value");
}
}
}
@@ -372,15 +374,14 @@ contract level) with ``arrayname.length = <some new length>;``. If you get the
::
- // This will not compile
-
pragma solidity ^0.4.18;
+ // This will not compile
contract C {
int8[] dynamicStorageArray;
int8[5] fixedStorageArray;
- function f() {
+ function f() public {
int8[] memory memArr; // Case 1
memArr.length++; // illegal
diff --git a/docs/index.rst b/docs/index.rst
index af27d534..d59d476e 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -60,44 +60,55 @@ Useful links
Available Solidity Integrations
-------------------------------
-* `Remix <https://remix.ethereum.org/>`_
- Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components.
+* Generic:
-* `IntelliJ IDEA plugin <https://plugins.jetbrains.com/plugin/9475-intellij-solidity>`_
- Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs)
+ * `Remix <https://remix.ethereum.org/>`_
+ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components.
-* `Visual Studio Extension <https://visualstudiogallery.msdn.microsoft.com/96221853-33c4-4531-bdd5-d2ea5acc4799/>`_
- Solidity plugin for Microsoft Visual Studio that includes the Solidity compiler.
+ * `Solium <https://github.com/duaraghav8/Solium/>`_
+ Linter to identify and fix style and security issues in Solidity.
+
+ * `Solhint <https://github.com/protofire/solhint>`_
+ Solidity linter that provides security, style guide and best practice rules for smart contract validation.
+
+* Atom:
+
+ * `Etheratom <https://github.com/0mkara/etheratom>`_
+ Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible).
+
+ * `Atom Solidity Linter <https://atom.io/packages/linter-solidity>`_
+ Plugin for the Atom editor that provides Solidity linting.
-* `Package for SublimeText — Solidity language syntax <https://packagecontrol.io/packages/Ethereum/>`_
- Solidity syntax highlighting for SublimeText editor.
+ * `Atom Solium Linter <https://atom.io/packages/linter-solium>`_
+ Configurable Solidty linter for Atom using Solium as a base.
-* `Etheratom <https://github.com/0mkara/etheratom>`_
- Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible).
+* Emacs:
-* `Atom Solidity Linter <https://atom.io/packages/linter-solidity>`_
- Plugin for the Atom editor that provides Solidity linting.
+ * `Emacs Solidity <https://github.com/ethereum/emacs-solidity/>`_
+ Plugin for the Emacs editor providing syntax highlighting and compilation error reporting.
-* `Atom Solium Linter <https://atom.io/packages/linter-solium>`_
- Configurable Solidty linter for Atom using Solium as a base.
+* IntelliJ:
-* `Solium <https://github.com/duaraghav8/Solium/>`_
- Linter to identify and fix style and security issues in Solidity.
+ * `IntelliJ IDEA plugin <https://plugins.jetbrains.com/plugin/9475-intellij-solidity>`_
+ Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs)
-* `Solhint <https://github.com/protofire/solhint>`_
- Solidity linter that provides security, style guide and best practice rules for smart contract validation.
+* Sublime:
-* `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.
+ * `Package for SublimeText — Solidity language syntax <https://packagecontrol.io/packages/Ethereum/>`_
+ Solidity syntax highlighting for SublimeText editor.
-* `Emacs Solidity <https://github.com/ethereum/emacs-solidity/>`_
- Plugin for the Emacs editor providing syntax highlighting and compilation error reporting.
+* Vim:
-* `Vim Solidity <https://github.com/tomlion/vim-solidity/>`_
- Plugin for the Vim editor providing syntax highlighting.
+ * `Vim Solidity <https://github.com/tomlion/vim-solidity/>`_
+ Plugin for the Vim editor providing syntax highlighting.
-* `Vim Syntastic <https://github.com/scrooloose/syntastic>`_
- Plugin for the Vim editor providing compile checking.
+ * `Vim Syntastic <https://github.com/scrooloose/syntastic>`_
+ Plugin for the Vim editor providing compile checking.
+
+* Visual Studio Code:
+
+ * `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.
Discontinued:
@@ -107,10 +118,13 @@ Discontinued:
* `Ethereum Studio <https://live.ether.camp/>`_
Specialized web IDE that also provides shell access to a complete Ethereum environment.
+* `Visual Studio Extension <https://visualstudiogallery.msdn.microsoft.com/96221853-33c4-4531-bdd5-d2ea5acc4799/>`_
+ Solidity plugin for Microsoft Visual Studio that includes the Solidity compiler.
+
Solidity Tools
--------------
-* `Dapp <https://dapp.readthedocs.io>`_
+* `Dapp <https://dapp.tools/dapp/>`_
Build tool, package manager, and deployment assistant for Solidity.
* `Solidity REPL <https://github.com/raineorshine/solidity-repl>`_
@@ -127,6 +141,15 @@ Solidity Tools
* `ABI to solidity interface converter <https://gist.github.com/chriseth/8f533d133fa0c15b0d6eaf3ec502c82b>`_
A script for generating contract interfaces from the ABI of a smart contract.
+
+* `Securify <https://securify.ch/>`_
+ Fully automated online static analyzer for smart contracts, providing a security report based on vulnerability patterns.
+
+* `SÅ«rya <https://github.com/ConsenSys/surya/>`_
+ Utility tool for smart contract systems, offering a number of visual outputs and information about the contracts' structure. Also supports querying the function call graph.
+
+* `EVM Lab <https://github.com/ethereum/evmlab/>`_
+ Rich tool package to interact with the EVM. Includes a VM, Etherchain API, and a trace-viewer with gas cost display.
.. note::
Information like variable names, comments, and source code formatting is lost in the compilation process and it is not possible to completely recover the original source code. Decompiling smart contracts to view the original source code might not be possible, or the end result that useful.
diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst
index 41204bba..910f80cf 100644
--- a/docs/installing-solidity.rst
+++ b/docs/installing-solidity.rst
@@ -44,7 +44,7 @@ Note: The solc-js project is derived from the C++
`solc` by using Emscripten. `solc-js` can be used in JavaScript projects directly (such as Remix).
Please refer to the solc-js repository for instructions.
-.. code:: bash
+.. code-block:: bash
npm install -g solc
@@ -62,7 +62,7 @@ We provide up to date docker builds for the compiler. The ``stable``
repository contains released versions while the ``nightly``
repository contains potentially unstable changes in the develop branch.
-.. code:: bash
+.. code-block:: bash
docker run ethereum/solc:stable --version
@@ -78,7 +78,7 @@ Binary packages of Solidity are available at
We also have PPAs for Ubuntu. For the latest stable version.
-.. code:: bash
+.. code-block:: bash
sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
@@ -86,7 +86,7 @@ We also have PPAs for Ubuntu. For the latest stable version.
If you want to use the cutting edge developer version:
-.. code:: bash
+.. code-block:: bash
sudo add-apt-repository ppa:ethereum/ethereum
sudo add-apt-repository ppa:ethereum/ethereum-dev
@@ -95,19 +95,19 @@ If you want to use the cutting edge developer version:
We are also releasing a `snap package <https://snapcraft.io/>`_, which is installable in all the `supported Linux distros <https://snapcraft.io/docs/core/install>`_. To install the latest stable version of solc:
-.. code:: bash
+.. code-block:: bash
sudo snap install solc
Or if you want to help testing the unstable solc with the most recent changes from the development branch:
-.. code:: bash
+.. code-block:: bash
sudo snap install solc --edge
Arch Linux also has packages, albeit limited to the latest development version:
-.. code:: bash
+.. code-block:: bash
pacman -S solidity
@@ -116,7 +116,7 @@ following a Jenkins to TravisCI migration, but Homebrew
should still work just fine as a means to build-from-source.
We will re-add the pre-built bottles soon.
-.. code:: bash
+.. code-block:: bash
brew update
brew upgrade
@@ -134,7 +134,7 @@ specific commit of ``solidity.rb``.
Install it using ``brew``:
-.. code:: bash
+.. code-block:: bash
brew unlink solidity
# Install 0.4.8
@@ -142,7 +142,7 @@ Install it using ``brew``:
Gentoo Linux also provides a solidity package that can be installed using ``emerge``:
-.. code:: bash
+.. code-block:: bash
emerge dev-lang/solidity
@@ -156,7 +156,7 @@ Clone the Repository
To clone the source code, execute the following command:
-.. code:: bash
+.. code-block:: bash
git clone --recursive https://github.com/ethereum/solidity.git
cd solidity
@@ -164,14 +164,14 @@ To clone the source code, execute the following command:
If you want to help developing Solidity,
you should fork Solidity and add your personal fork as a second remote:
-.. code:: bash
+.. code-block:: bash
cd solidity
git remote add personal git@github.com:[username]/solidity.git
Solidity has git submodules. Ensure they are properly loaded:
-.. code:: bash
+.. code-block:: bash
git submodule update --init --recursive
@@ -187,7 +187,7 @@ If you are installing Xcode for the first time, or have just installed a new
version then you will need to agree to the license before you can do
command-line builds:
-.. code:: bash
+.. code-block:: bash
sudo xcodebuild -license accept
@@ -244,13 +244,13 @@ We now have a "one button" script which installs all required external dependenc
on macOS, Windows and on numerous Linux distros. This used to be a multi-step
manual process, but is now a one-liner:
-.. code:: bash
+.. code-block:: bash
./scripts/install_deps.sh
Or, on Windows:
-.. code:: bat
+.. code-block:: bat
scripts\install_deps.bat
@@ -263,7 +263,7 @@ Command-Line Build
Solidity project uses CMake to configure the build.
Building Solidity is quite similar on Linux, macOS and other Unices:
-.. code:: bash
+.. code-block:: bash
mkdir build
cd build
@@ -271,14 +271,14 @@ Building Solidity is quite similar on Linux, macOS and other Unices:
or even easier:
-.. code:: bash
+.. code-block:: bash
#note: this will install binaries solc and soltest at usr/local/bin
./scripts/build.sh
And even for Windows:
-.. code:: bash
+.. code-block:: bash
mkdir build
cd build
@@ -291,7 +291,7 @@ should result in Visual Studio firing up. We suggest building
Alternatively, you can build for Windows on the command-line, like so:
-.. code:: bash
+.. code-block:: bash
cmake --build . --config RelWithDebInfo
@@ -310,7 +310,7 @@ they are found in the system. Each solver can be disabled by a `cmake` option.
Inside the build folder you can disable them, since they are enabled by default:
-.. code:: bash
+.. code-block:: bash
# disables only Z3 SMT Solver.
cmake .. -DUSE_Z3=OFF
diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst
index 46ef3d57..5cbb6cff 100644
--- a/docs/layout-of-source-files.rst
+++ b/docs/layout-of-source-files.rst
@@ -100,11 +100,10 @@ When the compiler is invoked, it is not only possible to specify how to
discover the first element of a path, but it is possible to specify path prefix
remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to
``/usr/local/dapp-bin/library`` and the compiler will read the files from there.
-If multiple remappings can be applied, the one with the longest key is tried first. This
-allows for a "fallback-remapping" with e.g. ``""`` maps to
-``"/usr/local/include/solidity"``. Furthermore, these remappings can
-depend on the context, which allows you to configure packages to
-import e.g. different versions of a library of the same name.
+If multiple remappings can be applied, the one with the longest key is tried first.
+An empty prefix is not allowed. Furthermore, these remappings can depend on the context,
+which allows you to configure packages to import e.g. different versions of a library
+of the same name.
**solc**:
@@ -148,7 +147,7 @@ Note that solc only allows you to include files from certain directories:
They have to be in the directory (or subdirectory) of one of the explicitly
specified source files or in the directory (or subdirectory) of a remapping
target. If you want to allow direct absolute includes, just add the
-remapping ``=/``.
+remapping ``/=/``.
If there are multiple remappings that lead to a valid file, the remapping
with the longest common prefix is chosen.
@@ -205,7 +204,7 @@ for the two input parameters and two returned values.
* @return s The calculated surface.
* @return p The calculated perimeter.
*/
- function rectangle(uint w, uint h) public returns (uint s, uint p) {
+ function rectangle(uint w, uint h) public pure returns (uint s, uint p) {
s = w * h;
p = 2 * (w + h);
}
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 3f054297..7d325746 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -467,22 +467,22 @@ high or low invalid bids.
uint refund;
for (uint i = 0; i < length; i++) {
- Bid storage bid = bids[msg.sender][i];
+ Bid storage bidToCheck = bids[msg.sender][i];
(uint value, bool fake, bytes32 secret) =
(_values[i], _fake[i], _secret[i]);
- if (bid.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
+ if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
// Bid was not actually revealed.
// Do not refund deposit.
continue;
}
- refund += bid.deposit;
- if (!fake && bid.deposit >= value) {
+ refund += bidToCheck.deposit;
+ if (!fake && bidToCheck.deposit >= value) {
if (placeBid(msg.sender, value))
refund -= value;
}
// Make it impossible for the sender to re-claim
// the same deposit.
- bid.blindedBid = bytes32(0);
+ bidToCheck.blindedBid = bytes32(0);
}
msg.sender.transfer(refund);
}
diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst
index 7a6317eb..ae349055 100644
--- a/docs/structure-of-a-contract.rst
+++ b/docs/structure-of-a-contract.rst
@@ -75,7 +75,7 @@ Function modifiers can be used to amend the semantics of functions in a declarat
_;
}
- function abort() public onlySeller { // Modifier usage
+ function abort() public view onlySeller { // Modifier usage
// ...
}
}
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index 53e126b4..d2de5287 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -52,31 +52,35 @@ Surround top level declarations in solidity source with two blank lines.
Yes::
+ pragma solidity ^0.4.0;
+
contract A {
- ...
+ // ...
}
contract B {
- ...
+ // ...
}
contract C {
- ...
+ // ...
}
No::
+ pragma solidity ^0.4.0;
+
contract A {
- ...
+ // ...
}
contract B {
- ...
+ // ...
}
contract C {
- ...
+ // ...
}
Within a contract surround function declarations with a single blank line.
@@ -85,30 +89,34 @@ Blank lines may be omitted between groups of related one-liners (such as stub fu
Yes::
+ pragma solidity ^0.4.0;
+
contract A {
- function spam() public;
- function ham() public;
+ function spam() public pure;
+ function ham() public pure;
}
contract B is A {
- function spam() public {
- ...
+ function spam() public pure {
+ // ...
}
- function ham() public {
- ...
+ function ham() public pure {
+ // ...
}
}
No::
+ pragma solidity ^0.4.0;
+
contract A {
- function spam() public {
- ...
+ function spam() public pure {
+ // ...
}
- function ham() public {
- ...
+ function ham() public pure {
+ // ...
}
}
@@ -229,22 +237,24 @@ Import statements should always be placed at the top of the file.
Yes::
- import "./Owned.sol";
+ pragma solidity ^0.4.0;
+ import "./Owned.sol";
contract A {
- ...
+ // ...
}
-
contract B is Owned {
- ...
+ // ...
}
No::
+ pragma solidity ^0.4.0;
+
contract A {
- ...
+ // ...
}
@@ -252,7 +262,7 @@ No::
contract B is Owned {
- ...
+ // ...
}
Order of Functions
@@ -273,13 +283,15 @@ Within a grouping, place the ``view`` and ``pure`` functions last.
Yes::
+ pragma solidity ^0.4.0;
+
contract A {
constructor() public {
- ...
+ // ...
}
function() external {
- ...
+ // ...
}
// External functions
@@ -303,13 +315,15 @@ Yes::
No::
+ pragma solidity ^0.4.0;
+
contract A {
// External functions
// ...
function() external {
- ...
+ // ...
}
// Private functions
@@ -319,7 +333,7 @@ No::
// ...
constructor() public {
- ...
+ // ...
}
// Internal functions
@@ -397,6 +411,8 @@ should:
Yes::
+ pragma solidity ^0.4.0;
+
contract Coin {
struct Bank {
address owner;
@@ -406,6 +422,8 @@ Yes::
No::
+ pragma solidity ^0.4.0;
+
contract Coin
{
struct Bank {
@@ -705,7 +723,25 @@ manner as modifiers if the function declaration is long or hard to read.
Yes::
+ pragma solidity ^0.4.0;
+
+ // Base contracts just to make this compile
+ contract B {
+ constructor(uint) public {
+ }
+ }
+ contract C {
+ constructor(uint, uint) public {
+ }
+ }
+ contract D {
+ constructor(uint) public {
+ }
+ }
+
contract A is B, C, D {
+ uint x;
+
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
@@ -713,29 +749,50 @@ Yes::
public
{
// do something with param5
+ x = param5;
}
}
No::
+ pragma solidity ^0.4.0;
+
+ // Base contracts just to make this compile
+ contract B {
+ constructor(uint) public {
+ }
+ }
+ contract C {
+ constructor(uint, uint) public {
+ }
+ }
+ contract D {
+ constructor(uint) public {
+ }
+ }
+
contract A is B, C, D {
+ uint x;
+
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
D(param4)
public
{
- // do something with param5
+ x = param5;
}
}
- contract A is B, C, D {
+ contract X is B, C, D {
+ uint x;
+
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
D(param4)
public {
- // do something with param5
+ x = param5;
}
}
@@ -875,6 +932,8 @@ As shown in the example below, if the contract name is `Congress` and the librar
Yes::
+ pragma solidity ^0.4.0;
+
// Owned.sol
contract Owned {
address public owner;
@@ -897,11 +956,13 @@ Yes::
import "./Owned.sol";
contract Congress is Owned, TokenRecipient {
- ...
+ //...
}
No::
+ pragma solidity ^0.4.0;
+
// owned.sol
contract owned {
address public owner;
@@ -924,7 +985,7 @@ No::
import "./owned.sol";
contract Congress is owned, tokenRecipient {
- ...
+ //...
}
diff --git a/docs/types.rst b/docs/types.rst
index 5c4a30ca..18400dee 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -134,7 +134,7 @@ and to send Ether (in units of wei) to an address using the ``transfer`` functio
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
.. note::
- If ``x`` is a contract address, its code (more specifically: its fallback function, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception.
+ If ``x`` is a contract address, its code (more specifically: its :ref:`fallback-function`, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception.
* ``send``
@@ -200,25 +200,38 @@ The ``.gas()`` option is available on all three methods, while the ``.value()``
.. note::
The use of ``callcode`` is discouraged and will be removed in the future.
+.. index:: ! contract type, ! type; contract
+
+.. _contract_types:
+
Contract Types
--------------
-Every :ref:`contract<contracts>` defines its own type. Contracts can be implicitly converted
-to contracts they inherit from. They can be explicitly converted from and to ``address`` types.
+Every :ref:`contract<contracts>` defines its own type.
+You can implicitly convert contracts to contracts they inherit from,
+and explicitly convert them to and from the ``address`` type.
-The data representation of a contract is identical to that of the ``address`` type and
-this type is also used in the :ref:`ABI<ABI>`.
+.. note::
+ Starting with version 0.5.0 contracts do not derive from the address type,
+ but can still be explicitly converted to address.
-Contracts do not support any operators.
+If you declare a local variable of contract type (`MyContract c`), you can call
+functions on that contract. Take care to assign it from somewhere that is the
+same contract type.
-The members of contract types are the external functions of the contract including
-public state variables.
+You can also instantiate contracts (which means they are newly created). You
+can find more details in the :ref:`'Contracts via new'<creating-contracts>`
+section.
-.. note::
- Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address.
+The data representation of a contract is identical to that of the ``address``
+type and this type is also used in the :ref:`ABI<ABI>`.
-.. index:: byte array, bytes32
+Contracts do not support any operators.
+
+The members of contract types are the external functions of the contract
+including public state variables.
+.. index:: byte array, bytes32
Fixed-size byte arrays
----------------------
@@ -355,6 +368,10 @@ Enums are one way to create a user-defined type in Solidity. They are explicitly
to and from all integer types but implicit conversion is not allowed. The explicit conversions
check the value ranges at runtime and a failure causes an exception. Enums needs at least one member.
+The data representation is the same as for enums in C: The options are represented by
+subsequent unsigned integer values starting from ``0``.
+
+
::
pragma solidity ^0.4.16;
@@ -371,7 +388,7 @@ check the value ranges at runtime and a failure causes an exception. Enums need
// Since enum types are not part of the ABI, the signature of "getChoice"
// will automatically be changed to "getChoice() returns (uint8)"
// for all matters external to Solidity. The integer type used is just
- // large enough to hold all enum values, i.e. if you have more values,
+ // large enough to hold all enum values, i.e. if you have more than 256 values,
// `uint16` will be used and so on.
function getChoice() public view returns (ActionChoices) {
return choice;
@@ -413,8 +430,26 @@ function type should not return anything, the whole ``returns (<return types>)``
part has to be omitted.
By default, function types are internal, so the ``internal`` keyword can be
-omitted. In contrast, contract functions themselves are public by default,
-only when used as the name of a type, the default is internal.
+omitted. Note that this only applies to function types. Visibility has
+to be specified explicitly for functions defined in contracts, they
+do not have a default.
+
+A function type ``A`` is implicitly convertible to a function type ``B`` if and only if
+their parameter types are identical, their return types are identical,
+their internal/external property is identical and the state mutability of ``A``
+is not more restrictive than the state mutability of ``B``. In particular:
+
+ - ``pure`` functions can be converted to ``view`` and ``non-payable`` functions
+ - ``view`` functions can be converted to ``non-payable`` functions
+ - ``payable`` functions can be converted to ``non-payable`` functions
+
+No other conversions are possible.
+
+The rule about ``payable`` and ``non-payable`` might be a little
+confusing, but in essence, if a function is ``payable``, this means that it
+also accepts a payment of zero Ether, so it also is ``non-payable``.
+On the other hand, a ``non-payable`` function will reject Ether sent to it,
+so ``non-payable`` functions cannot be converted to ``payable`` functions.
If a function type variable is not initialized, calling it will result
in an exception. The same happens if you call a function after using ``delete``
@@ -434,7 +469,7 @@ which returns the :ref:`ABI function selector <abi_function_selector>`::
pragma solidity ^0.4.16;
contract Selector {
- function f() public view returns (bytes4) {
+ function f() public pure returns (bytes4) {
return this.f.selector;
}
}
@@ -497,15 +532,15 @@ Another example that uses external function types::
contract Oracle {
struct Request {
bytes data;
- function(bytes memory) external callback;
+ function(uint) external callback;
}
Request[] requests;
event NewRequest(uint);
- function query(bytes memory data, function(bytes memory) external callback) public {
+ function query(bytes memory data, function(uint) external callback) public {
requests.push(Request(data, callback));
emit NewRequest(requests.length - 1);
}
- function reply(uint requestID, bytes memory response) public {
+ function reply(uint requestID, uint response) public {
// Here goes the check that the reply comes from a trusted source
requests[requestID].callback(response);
}
@@ -513,15 +548,16 @@ Another example that uses external function types::
contract OracleUser {
Oracle constant oracle = Oracle(0x1234567); // known contract
+ uint exchangeRate;
function buySomething() public {
oracle.query("USD", this.oracleResponse);
}
- function oracleResponse(bytes memory response) public {
+ function oracleResponse(uint response) public {
require(
msg.sender == address(oracle),
"Only oracle can call this."
);
- // Use the data
+ exchangeRate = response;
}
}
@@ -588,8 +624,8 @@ memory-stored reference type do not create a copy.
h(x); // calls h and creates an independent, temporary copy in memory
}
- function g(uint[] storage storageArray) internal {}
- function h(uint[] memory memoryArray) public {}
+ function g(uint[] storage) internal pure {}
+ function h(uint[] memory) public pure {}
}
Summary
@@ -646,8 +682,9 @@ Allocating Memory Arrays
^^^^^^^^^^^^^^^^^^^^^^^^
Creating arrays with variable length in memory can be done using the ``new`` keyword.
-As opposed to storage arrays, it is **not** possible to resize memory arrays by assigning to
-the ``.length`` member.
+As opposed to storage arrays, it is **not** possible to resize memory arrays (e.g. by assigning to
+the ``.length`` member). You either have to calculate the required size in advance
+or create a new memory array and copy every element.
::
@@ -657,7 +694,8 @@ the ``.length`` member.
function f(uint len) public pure {
uint[] memory a = new uint[](7);
bytes memory b = new bytes(len);
- // Here we have a.length == 7 and b.length == len
+ assert(a.length == 7);
+ assert(b.length == len);
a[6] = 8;
}
}
@@ -678,7 +716,7 @@ assigned to a variable right away.
function f() public pure {
g([uint(1), 2, 3]);
}
- function g(uint[3] memory _data) public pure {
+ function g(uint[3] memory) public pure {
// ...
}
}
@@ -693,10 +731,9 @@ possible:
::
- // This will not compile.
-
pragma solidity ^0.4.0;
+ // This will not compile.
contract C {
function f() public {
// The next line creates a type error because uint[3] memory
@@ -725,14 +762,11 @@ Members
.. warning::
It is not yet possible to use arrays of arrays in external functions.
-.. warning::
- Due to limitations of the EVM, it is not possible to return
- dynamic content from external function calls. The function ``f`` in
- ``contract C { function f() returns (uint[]) { ... } }`` will return
- something if called from web3.js, but not if called from Solidity.
-
- The only workaround for now is to use large statically-sized arrays.
-
+.. note::
+ In EVM versions before Byzantium, it was not possible to access
+ dynamic arrays return from function calls. If you call functions
+ that return dynamic arrays, make sure to use an EVM that is set to
+ Byzantium mode.
::
@@ -742,9 +776,12 @@ Members
uint[2**20] m_aLotOfIntegers;
// Note that the following is not a pair of dynamic arrays but a
// dynamic array of pairs (i.e. of fixed size arrays of length two).
+ // Because of that, T[] is always a dynamic array of T, even if T
+ // itself is an array.
bool[2][] m_pairsOfFlags;
- // newPairs is stored in memory - the default for function arguments
+ // newPairs is stored in memory - the only possibility
+ // for public function arguments
function setAllFlagPairs(bool[2][] memory newPairs) public {
// assignment to a storage array replaces the complete array
m_pairsOfFlags = newPairs;
@@ -776,7 +813,7 @@ Members
// but can be treated identical to "uint8[]"
m_byteData = data;
m_byteData.length += 7;
- m_byteData[3] = byte(8);
+ m_byteData[3] = 0x08;
delete m_byteData[2];
}
@@ -787,6 +824,11 @@ Members
function createMemoryArray(uint size) public pure returns (bytes memory) {
// Dynamic memory arrays are created using `new`:
uint[2][] memory arrayOfPairs = new uint[2][](size);
+
+ // Inline arrays are always statically-sized and if you only
+ // use literals, you have to provide at least one type.
+ arrayOfPairs[0] = [uint(1), 2];
+
// Create a dynamic byte array:
bytes memory b = new bytes(200);
for (uint i = 0; i < b.length; i++)
@@ -958,6 +1000,7 @@ It is important to note that ``delete a`` really behaves like an assignment to `
// y is affected which is an alias to the storage object
// On the other hand: "delete y" is not valid, as assignments to local variables
// referencing storage objects can only be made from existing storage objects.
+ assert(y.length == 0);
}
}
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index 1d7cb97b..b286e1a3 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -23,14 +23,15 @@ it is also possible to provide path redirects using ``prefix=path`` in the follo
::
- solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol
+ solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ file.sol
This essentially instructs the compiler to search for anything starting with
-``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin`` and if it does not
-find the file there, it will look at ``/usr/local/lib/fallback`` (the empty prefix
-always matches). ``solc`` will not read files from the filesystem that lie outside of
+``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin``.
+``solc`` will not read files from the filesystem that lie outside of
the remapping targets and outside of the directories where explicitly specified source
-files reside, so things like ``import "/etc/passwd";`` only work if you add ``=/`` as a remapping.
+files reside, so things like ``import "/etc/passwd";`` only work if you add ``/=/`` as a remapping.
+
+An empty remapping prefix is not allowed.
If there are multiple matches due to remappings, the one with the longest common prefix is selected.
diff --git a/libdevcore/StringUtils.h b/libdevcore/StringUtils.h
index 4fb5a748..94c6e3c5 100644
--- a/libdevcore/StringUtils.h
+++ b/libdevcore/StringUtils.h
@@ -63,7 +63,7 @@ std::string joinHumanReadable
for (;it != itEnd; ++it)
{
- if ((next(it) == itEnd) && !_lastSeparator.empty())
+ if ((std::next(it) == itEnd) && !_lastSeparator.empty())
result += _lastSeparator; // last iteration
else
result += _separator;
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index b71bc80c..e49e675d 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -264,7 +264,7 @@ Json::Value Assembly::assemblyJSON(StringMap const& _sourceCodes) const
createJsonValue("PUSH [ErrorTag]", i.location().start, i.location().end, ""));
else
collection.append(
- createJsonValue("PUSH [tag]", i.location().start, i.location().end, string(i.data())));
+ createJsonValue("PUSH [tag]", i.location().start, i.location().end, dev::toString(i.data())));
break;
case PushSub:
collection.append(
@@ -290,7 +290,7 @@ Json::Value Assembly::assemblyJSON(StringMap const& _sourceCodes) const
break;
case Tag:
collection.append(
- createJsonValue("tag", i.location().start, i.location().end, string(i.data())));
+ createJsonValue("tag", i.location().start, i.location().end, dev::toString(i.data())));
collection.append(
createJsonValue("JUMPDEST", i.location().start, i.location().end));
break;
@@ -617,8 +617,8 @@ LinkerObject const& Assembly::assemble() const
}
if (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty())
- // Append a STOP just to be sure.
- ret.bytecode.push_back(0);
+ // Append an INVALID here to help tests find miscompilation.
+ ret.bytecode.push_back(byte(Instruction::INVALID));
for (size_t i = 0; i < m_subs.size(); ++i)
{
diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp
index d0b6843c..07ece12c 100644
--- a/libevmasm/ConstantOptimiser.cpp
+++ b/libevmasm/ConstantOptimiser.cpp
@@ -93,6 +93,7 @@ bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items)
bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const
{
+ assertThrow(_data.size() > 0, OptimizerException, "Empty bytecode generated.");
if (m_params.isCreation)
{
bigint gas;
@@ -101,7 +102,7 @@ bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const
return gas;
}
else
- return GasCosts::createDataGas * dataSize();
+ return GasCosts::createDataGas * _data.size();
}
size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h
index f0deb387..2c753fa8 100644
--- a/libevmasm/ConstantOptimiser.h
+++ b/libevmasm/ConstantOptimiser.h
@@ -75,8 +75,6 @@ public:
virtual AssemblyItems execute(Assembly& _assembly) const = 0;
protected:
- size_t dataSize() const { return std::max<size_t>(1, dev::bytesRequired(m_value)); }
-
/// @returns the run gas for the given items ignoring special gas costs
static bigint simpleRunGas(AssemblyItems const& _items);
/// @returns the gas needed to store the given data literally
diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp
index 37c5fdd4..d5b82e75 100644
--- a/libevmasm/Instruction.cpp
+++ b/libevmasm/Instruction.cpp
@@ -330,7 +330,7 @@ void dev::solidity::eachInstruction(
u256 data;
// fill the data with the additional data bytes from the instruction stream
- while (additional > 0 && next(it) < _mem.end())
+ while (additional > 0 && std::next(it) < _mem.end())
{
data <<= 8;
data |= *++it;
diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt
index 49095fff..91a4678a 100644
--- a/libsolidity/CMakeLists.txt
+++ b/libsolidity/CMakeLists.txt
@@ -11,17 +11,11 @@ else()
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp")
endif()
-find_package(GMP QUIET)
find_package(CVC4 QUIET)
if (${CVC4_FOUND})
- if (${GMP_FOUND})
- include_directories(${CVC4_INCLUDE_DIR})
- add_definitions(-DHAVE_CVC4)
- message("CVC4 SMT solver and GMP found. This enables optional SMT checking with CVC4.")
- else()
- message("CVC4 SMT solver found but its dependency GMP was NOT found. Optional SMT checking with CVC4 will not be available. Please install GMP if it is desired.")
- list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
- endif()
+ include_directories(${CVC4_INCLUDE_DIR})
+ add_definitions(-DHAVE_CVC4)
+ message("CVC4 SMT solver found. This enables optional SMT checking with CVC4.")
else()
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
endif()
@@ -38,7 +32,6 @@ if (${Z3_FOUND})
target_link_libraries(solidity PUBLIC ${Z3_LIBRARY})
endif()
-if (${CVC4_FOUND} AND ${GMP_FOUND})
- target_link_libraries(solidity PUBLIC ${CVC4_LIBRARY})
- target_link_libraries(solidity PUBLIC ${GMP_LIBRARY})
+if (${CVC4_FOUND})
+ target_link_libraries(solidity PUBLIC ${CVC4_LIBRARIES})
endif()
diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp
index 483d08c8..ab6569be 100644
--- a/libsolidity/analysis/ControlFlowAnalyzer.cpp
+++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp
@@ -75,7 +75,10 @@ void ControlFlowAnalyzer::checkUnassignedStorageReturnValues(
{
auto& unassignedAtFunctionEntry = unassigned[_functionEntry];
for (auto const& returnParameter: _function.returnParameterList()->parameters())
- if (returnParameter->type()->dataStoredIn(DataLocation::Storage))
+ if (
+ returnParameter->type()->dataStoredIn(DataLocation::Storage) ||
+ returnParameter->type()->category() == Type::Category::Mapping
+ )
unassignedAtFunctionEntry.insert(returnParameter.get());
}
diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp
index 7b4bc3aa..3ac8fd47 100644
--- a/libsolidity/analysis/GlobalContext.cpp
+++ b/libsolidity/analysis/GlobalContext.cpp
@@ -42,7 +42,7 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{
make_shared<MagicVariableDeclaration>("blockhash", make_shared<FunctionType>(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)),
make_shared<MagicVariableDeclaration>("ecrecover", make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)),
make_shared<MagicVariableDeclaration>("gasleft", make_shared<FunctionType>(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)),
- make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA3, false, StateMutability::Pure)),
+ make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, 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)),
@@ -58,7 +58,7 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{
make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)),
make_shared<MagicVariableDeclaration>("selfdestruct", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)),
make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)),
- make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA3, false, StateMutability::Pure)),
+ make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, 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))
})
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index 2cf09eff..fa0888dd 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -344,7 +344,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
"(remove the \"memory\" or \"storage\" keyword)."
);
}
- if (varLoc == Location::Default)
+ if (varLoc == Location::Default || varLoc == Location::CallData)
typeLoc = DataLocation::CallData;
else
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 6882a14f..601a5e7c 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -580,9 +580,6 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
bool TypeChecker::visit(StructDefinition const& _struct)
{
- if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
- m_errorReporter.typeError(_struct.location(), "Structs cannot be defined in interfaces.");
-
for (ASTPointer<VariableDeclaration> const& member: _struct.members())
if (!type(*member)->canBeStored())
m_errorReporter.typeError(member->location(), "Type cannot be used in struct.");
@@ -610,7 +607,10 @@ bool TypeChecker::visit(StructDefinition const& _struct)
if (CycleDetector<StructDefinition>(visitor).run(_struct) != nullptr)
m_errorReporter.fatalTypeError(_struct.location(), "Recursive struct definition.");
+ bool insideStruct = true;
+ swap(insideStruct, m_insideStruct);
ASTNode::listAccept(_struct.members(), *this);
+ m_insideStruct = insideStruct;
return false;
}
@@ -629,7 +629,10 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
}
for (ASTPointer<VariableDeclaration> const& var: _function.parameters() + _function.returnParameters())
{
- if (!type(*var)->canLiveOutsideStorage())
+ if (
+ !type(*var)->canLiveOutsideStorage() &&
+ !(_function.visibility() <= FunctionDefinition::Visibility::Internal)
+ )
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
if (_function.visibility() >= FunctionDefinition::Visibility::Public && !(type(*var)->interfaceType(isLibraryFunction)))
m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions.");
@@ -690,10 +693,12 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
bool TypeChecker::visit(VariableDeclaration const& _variable)
{
// Forbid any variable declarations inside interfaces unless they are part of
- // a function's input/output parameters.
+ // * a function's input/output parameters,
+ // * or inside of a struct definition.
if (
m_scope->contractKind() == ContractDefinition::ContractKind::Interface
&& !_variable.isCallableParameter()
+ && !m_insideStruct
)
m_errorReporter.typeError(_variable.location(), "Variables cannot be declared in interfaces.");
@@ -1626,10 +1631,13 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
else
{
TypePointer const& argType = type(*arguments.front());
+ // Resulting data location is memory unless we are converting from a reference
+ // type with a different data location.
+ // (data location cannot yet be specified for type conversions)
+ DataLocation dataLoc = DataLocation::Memory;
if (auto argRefType = dynamic_cast<ReferenceType const*>(argType.get()))
- // do not change the data location when converting
- // (data location cannot yet be specified for type conversions)
- resultType = ReferenceType::copyForLocationIfReference(argRefType->location(), resultType);
+ dataLoc = argRefType->location();
+ resultType = ReferenceType::copyForLocationIfReference(dataLoc, resultType);
if (!argType->isExplicitlyConvertibleTo(*resultType))
m_errorReporter.typeError(
_functionCall.location(),
@@ -1685,7 +1693,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
if (auto functionName = dynamic_cast<Identifier const*>(&_functionCall.expression()))
{
- if (functionName->name() == "sha3" && functionType->kind() == FunctionType::Kind::SHA3)
+ if (functionName->name() == "sha3" && functionType->kind() == FunctionType::Kind::KECCAK256)
m_errorReporter.typeError(_functionCall.location(), "\"sha3\" has been deprecated in favour of \"keccak256\"");
else if (functionName->name() == "suicide" && functionType->kind() == FunctionType::Kind::Selfdestruct)
m_errorReporter.typeError(_functionCall.location(), "\"suicide\" has been deprecated in favour of \"selfdestruct\"");
@@ -1759,7 +1767,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
msg += " This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it.";
}
else if (
- functionType->kind() == FunctionType::Kind::SHA3 ||
+ functionType->kind() == FunctionType::Kind::KECCAK256 ||
functionType->kind() == FunctionType::Kind::SHA256 ||
functionType->kind() == FunctionType::Kind::RIPEMD160
)
@@ -1804,7 +1812,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
)
msg += " This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it.";
else if (
- functionType->kind() == FunctionType::Kind::SHA3 ||
+ functionType->kind() == FunctionType::Kind::KECCAK256 ||
functionType->kind() == FunctionType::Kind::SHA256 ||
functionType->kind() == FunctionType::Kind::RIPEMD160
)
@@ -2348,22 +2356,6 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte
"."
);
}
-
- if (
- type(_expression)->category() == Type::Category::RationalNumber &&
- _expectedType.category() == Type::Category::FixedBytes
- )
- {
- auto literal = dynamic_cast<Literal const*>(&_expression);
-
- if (literal && !literal->isHexNumber())
- m_errorReporter.warning(
- _expression.location(),
- "Decimal literal assigned to bytesXX variable will be left-aligned. "
- "Use an explicit conversion to silence this warning."
- );
- }
-
}
void TypeChecker::requireLValue(Expression const& _expression)
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index b696de85..ed316f9c 100644
--- a/libsolidity/analysis/TypeChecker.h
+++ b/libsolidity/analysis/TypeChecker.h
@@ -149,6 +149,9 @@ private:
/// Flag indicating whether we are currently inside an EmitStatement.
bool m_insideEmitStatement = false;
+ /// Flag indicating whether we are currently inside a StructDefinition.
+ bool m_insideStruct = false;
+
ErrorReporter& m_errorReporter;
};
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 3dbbca91..68c201a8 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -355,13 +355,7 @@ TypePointer Type::forLiteral(Literal const& _literal)
case Token::FalseLiteral:
return make_shared<BoolType>();
case Token::Number:
- {
- tuple<bool, rational> validLiteral = RationalNumberType::isValidLiteral(_literal);
- if (get<0>(validLiteral) == true)
- return make_shared<RationalNumberType>(get<1>(validLiteral));
- else
- return TypePointer();
- }
+ return RationalNumberType::forLiteral(_literal);
case Token::StringLiteral:
return make_shared<StringLiteralType>(_literal);
default:
@@ -400,17 +394,17 @@ TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool _p
encodingType = encodingType->interfaceType(_inLibraryCall);
if (encodingType)
encodingType = encodingType->encodingType();
- if (auto structType = dynamic_cast<StructType const*>(encodingType.get()))
- {
- // Structs are fine in the following circumstances:
- // - ABIv2 without packed encoding or,
- // - storage struct for a library
- if (!(
- (_encoderV2 && !_packed) ||
- (structType->location() == DataLocation::Storage && _inLibraryCall)
- ))
+ // Structs are fine in the following circumstances:
+ // - ABIv2 without packed encoding or,
+ // - storage struct for a library
+ if (_inLibraryCall && encodingType->dataStoredIn(DataLocation::Storage))
+ return encodingType;
+ TypePointer baseType = encodingType;
+ while (auto const* arrayType = dynamic_cast<ArrayType const*>(baseType.get()))
+ baseType = arrayType->baseType();
+ if (dynamic_cast<StructType const*>(baseType.get()))
+ if (!_encoderV2 || _packed)
return TypePointer();
- }
return encodingType;
}
@@ -779,6 +773,30 @@ tuple<bool, rational> RationalNumberType::parseRational(string const& _value)
}
}
+TypePointer RationalNumberType::forLiteral(Literal const& _literal)
+{
+ solAssert(_literal.token() == Token::Number, "");
+ tuple<bool, rational> validLiteral = isValidLiteral(_literal);
+ if (get<0>(validLiteral))
+ {
+ TypePointer compatibleBytesType;
+ if (_literal.isHexNumber())
+ {
+ size_t digitCount = count_if(
+ _literal.value().begin() + 2, // skip "0x"
+ _literal.value().end(),
+ [](unsigned char _c) -> bool { return isxdigit(_c); }
+ );
+ // require even number of digits
+ if (!(digitCount & 1))
+ compatibleBytesType = make_shared<FixedBytesType>(digitCount / 2);
+ }
+
+ return make_shared<RationalNumberType>(get<1>(validLiteral), compatibleBytesType);
+ }
+ return TypePointer();
+}
+
tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal)
{
rational value;
@@ -918,14 +936,7 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
return false;
}
case Category::FixedBytes:
- {
- FixedBytesType const& fixedBytes = dynamic_cast<FixedBytesType const&>(_convertTo);
- if (isFractional())
- return false;
- if (integerType())
- return fixedBytes.numBytes() * 8 >= integerType()->numBits();
- return false;
- }
+ return (m_value == rational(0)) || (m_compatibleBytesType && *m_compatibleBytesType == _convertTo);
default:
return false;
}
@@ -933,11 +944,15 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
- TypePointer mobType = mobileType();
- return
- (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)) ||
- (!isFractional() && _convertTo.category() == Category::FixedBytes)
- ;
+ if (isImplicitlyConvertibleTo(_convertTo))
+ return true;
+ else if (_convertTo.category() != Category::FixedBytes)
+ {
+ TypePointer mobType = mobileType();
+ return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo));
+ }
+ else
+ return false;
}
TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const
@@ -1263,7 +1278,8 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
return shared_ptr<FixedPointType const>();
// This means we round towards zero for positive and negative values.
bigint v = value.numerator() / value.denominator();
- if (negative)
+
+ if (negative && v != 0)
// modify value to satisfy bit requirements for negative numbers:
// add one bit for sign and decrement because negative numbers can be larger
v = (v - 1) << 1;
@@ -2509,7 +2525,7 @@ string FunctionType::richIdentifier() const
case Kind::Creation: id += "creation"; break;
case Kind::Send: id += "send"; break;
case Kind::Transfer: id += "transfer"; break;
- case Kind::SHA3: id += "sha3"; break;
+ case Kind::KECCAK256: id += "keccak256"; break;
case Kind::Selfdestruct: id += "selfdestruct"; break;
case Kind::Revert: id += "revert"; break;
case Kind::ECRecover: id += "ecrecover"; break;
@@ -2554,28 +2570,10 @@ bool FunctionType::operator==(Type const& _other) const
{
if (_other.category() != category())
return false;
-
FunctionType const& other = dynamic_cast<FunctionType const&>(_other);
- if (
- m_kind != other.m_kind ||
- m_stateMutability != other.stateMutability() ||
- m_parameterTypes.size() != other.m_parameterTypes.size() ||
- m_returnParameterTypes.size() != other.m_returnParameterTypes.size()
- )
- return false;
-
- auto typeCompare = [](TypePointer const& _a, TypePointer const& _b) -> bool { return *_a == *_b; };
- if (
- !equal(m_parameterTypes.cbegin(), m_parameterTypes.cend(), other.m_parameterTypes.cbegin(), typeCompare) ||
- !equal(m_returnParameterTypes.cbegin(), m_returnParameterTypes.cend(), other.m_returnParameterTypes.cbegin(), typeCompare)
- )
- return false;
- //@todo this is ugly, but cannot be prevented right now
- if (m_gasSet != other.m_gasSet || m_valueSet != other.m_valueSet)
+ if (!equalExcludingStateMutability(other))
return false;
- if (bound() != other.bound())
- return false;
- if (bound() && *selfType() != *other.selfType())
+ if (m_stateMutability != other.stateMutability())
return false;
return true;
}
@@ -2591,6 +2589,31 @@ bool FunctionType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return _convertTo.category() == category();
}
+bool FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const
+{
+ if (_convertTo.category() != category())
+ return false;
+
+ FunctionType const& convertTo = dynamic_cast<FunctionType const&>(_convertTo);
+
+ if (!equalExcludingStateMutability(convertTo))
+ return false;
+
+ // non-payable should not be convertible to payable
+ if (m_stateMutability != StateMutability::Payable && convertTo.stateMutability() == StateMutability::Payable)
+ return false;
+
+ // payable should be convertible to non-payable, because you are free to pay 0 ether
+ if (m_stateMutability == StateMutability::Payable && convertTo.stateMutability() == StateMutability::NonPayable)
+ return true;
+
+ // e.g. pure should be convertible to view, but not the other way around.
+ if (m_stateMutability > convertTo.stateMutability())
+ return false;
+
+ return true;
+}
+
TypePointer FunctionType::unaryOperatorResult(Token::Value _operator) const
{
if (_operator == Token::Value::Delete)
@@ -2848,6 +2871,38 @@ bool FunctionType::hasEqualParameterTypes(FunctionType const& _other) const
);
}
+bool FunctionType::hasEqualReturnTypes(FunctionType const& _other) const
+{
+ if (m_returnParameterTypes.size() != _other.m_returnParameterTypes.size())
+ return false;
+ return equal(
+ m_returnParameterTypes.cbegin(),
+ m_returnParameterTypes.cend(),
+ _other.m_returnParameterTypes.cbegin(),
+ [](TypePointer const& _a, TypePointer const& _b) -> bool { return *_a == *_b; }
+ );
+}
+
+bool FunctionType::equalExcludingStateMutability(FunctionType const& _other) const
+{
+ if (m_kind != _other.m_kind)
+ return false;
+
+ if (!hasEqualParameterTypes(_other) || !hasEqualReturnTypes(_other))
+ return false;
+
+ //@todo this is ugly, but cannot be prevented right now
+ if (m_gasSet != _other.m_gasSet || m_valueSet != _other.m_valueSet)
+ return false;
+
+ if (bound() != _other.bound())
+ return false;
+
+ solAssert(!bound() || *selfType() == *_other.selfType(), "");
+
+ return true;
+}
+
bool FunctionType::isBareCall() const
{
switch (m_kind)
@@ -2894,7 +2949,7 @@ bool FunctionType::isPure() const
// FIXME: replace this with m_stateMutability == StateMutability::Pure once
// the callgraph analyzer is in place
return
- m_kind == Kind::SHA3 ||
+ m_kind == Kind::KECCAK256 ||
m_kind == Kind::ECRecover ||
m_kind == Kind::SHA256 ||
m_kind == Kind::RIPEMD160 ||
@@ -2999,7 +3054,7 @@ bool FunctionType::padArguments() const
case Kind::BareDelegateCall:
case Kind::SHA256:
case Kind::RIPEMD160:
- case Kind::SHA3:
+ case Kind::KECCAK256:
case Kind::ABIEncodePacked:
return false;
default:
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 1fa2b2f5..34f862c3 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -423,12 +423,12 @@ public:
virtual Category category() const override { return Category::RationalNumber; }
- /// @returns true if the literal is a valid integer.
- static std::tuple<bool, rational> isValidLiteral(Literal const& _literal);
+ static TypePointer forLiteral(Literal const& _literal);
- explicit RationalNumberType(rational const& _value):
- m_value(_value)
+ explicit RationalNumberType(rational const& _value, TypePointer const& _compatibleBytesType = TypePointer()):
+ m_value(_value), m_compatibleBytesType(_compatibleBytesType)
{}
+
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
@@ -446,7 +446,8 @@ public:
/// @returns the smallest integer type that can hold the value or an empty pointer if not possible.
std::shared_ptr<IntegerType const> integerType() const;
- /// @returns the smallest fixed type that can hold the value or incurs the least precision loss.
+ /// @returns the smallest fixed type that can hold the value or incurs the least precision loss,
+ /// unless the value was truncated, then a suitable type will be chosen to indicate such event.
/// If the integer part does not fit, returns an empty pointer.
std::shared_ptr<FixedPointType const> fixedPointType() const;
@@ -462,6 +463,13 @@ public:
private:
rational m_value;
+ /// Bytes type to which the rational can be explicitly converted.
+ /// Empty for all rationals that are not directly parsed from hex literals.
+ TypePointer m_compatibleBytesType;
+
+ /// @returns true if the literal is a valid integer.
+ static std::tuple<bool, rational> isValidLiteral(Literal const& _literal);
+
/// @returns true if the literal is a valid rational number.
static std::tuple<bool, rational> parseRational(std::string const& _value);
@@ -899,7 +907,7 @@ public:
Creation, ///< external call using CREATE
Send, ///< CALL, but without data and gas
Transfer, ///< CALL, but without data and throws on error
- SHA3, ///< SHA3
+ KECCAK256, ///< KECCAK256
Selfdestruct, ///< SELFDESTRUCT
Revert, ///< REVERT
ECRecover, ///< CALL to special contract for ecrecover
@@ -1005,6 +1013,7 @@ public:
virtual std::string richIdentifier() const override;
virtual bool operator==(Type const& _other) const override;
+ virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override;
@@ -1034,8 +1043,12 @@ public:
/// @param _selfType if the function is bound, this has to be supplied and is the type of the
/// expression the function is called on.
bool canTakeArguments(TypePointers const& _arguments, TypePointer const& _selfType = TypePointer()) const;
- /// @returns true if the types of parameters are equal (doesn't check return parameter types)
+ /// @returns true if the types of parameters are equal (does not check return parameter types)
bool hasEqualParameterTypes(FunctionType const& _other) const;
+ /// @returns true iff the return types are equal (does not check parameter types)
+ bool hasEqualReturnTypes(FunctionType const& _other) const;
+ /// @returns true iff the function type is equal to the given type, ignoring state mutability differences.
+ bool equalExcludingStateMutability(FunctionType const& _other) const;
/// @returns true if the ABI is used for this call (only meaningful for external calls)
bool isBareCall() const;
@@ -1070,7 +1083,7 @@ public:
{
switch (m_kind)
{
- case FunctionType::Kind::SHA3:
+ case FunctionType::Kind::KECCAK256:
case FunctionType::Kind::SHA256:
case FunctionType::Kind::RIPEMD160:
case FunctionType::Kind::BareCall:
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 54518906..412a7255 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -701,7 +701,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context.appendRevert();
break;
}
- case FunctionType::Kind::SHA3:
+ case FunctionType::Kind::KECCAK256:
{
solAssert(arguments.size() == 1, "");
solAssert(!function.padArguments(), "");
diff --git a/libsolidity/formal/CVC4Interface.h b/libsolidity/formal/CVC4Interface.h
index dcd87525..cd6d761d 100644
--- a/libsolidity/formal/CVC4Interface.h
+++ b/libsolidity/formal/CVC4Interface.h
@@ -21,8 +21,19 @@
#include <boost/noncopyable.hpp>
+#if defined(__GLIBC__)
+// The CVC4 headers includes the deprecated system headers <ext/hash_map>
+// and <ext/hash_set>. These headers cause a warning that will break the
+// build, unless _GLIBCXX_PERMIT_BACKWARD_HASH is set.
+#define _GLIBCXX_PERMIT_BACKWARD_HASH
+#endif
+
#include <cvc4/cvc4.h>
+#if defined(__GLIBC__)
+#undef _GLIBCXX_PERMIT_BACKWARD_HASH
+#endif
+
namespace dev
{
namespace solidity
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 836e30d2..e800b278 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -58,22 +58,31 @@ using namespace std;
using namespace dev;
using namespace dev::solidity;
-void CompilerStack::setRemappings(vector<string> const& _remappings)
+boost::optional<CompilerStack::Remapping> CompilerStack::parseRemapping(string const& _remapping)
+{
+ auto eq = find(_remapping.begin(), _remapping.end(), '=');
+ if (eq == _remapping.end())
+ return {};
+
+ auto colon = find(_remapping.begin(), eq, ':');
+
+ Remapping r;
+
+ r.context = colon == eq ? string() : string(_remapping.begin(), colon);
+ r.prefix = colon == eq ? string(_remapping.begin(), eq) : string(colon + 1, eq);
+ r.target = string(eq + 1, _remapping.end());
+
+ if (r.prefix.empty())
+ return {};
+
+ return r;
+}
+
+void CompilerStack::setRemappings(vector<Remapping> const& _remappings)
{
- vector<Remapping> remappings;
for (auto const& remapping: _remappings)
- {
- auto eq = find(remapping.begin(), remapping.end(), '=');
- if (eq == remapping.end())
- continue; // ignore
- auto colon = find(remapping.begin(), eq, ':');
- Remapping r;
- r.context = colon == eq ? string() : string(remapping.begin(), colon);
- r.prefix = colon == eq ? string(remapping.begin(), eq) : string(colon + 1, eq);
- r.target = string(eq + 1, remapping.end());
- remappings.push_back(r);
- }
- swap(m_remappings, remappings);
+ solAssert(!remapping.prefix.empty(), "");
+ m_remappings = _remappings;
}
void CompilerStack::setEVMVersion(EVMVersion _version)
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 2234a8c9..9a15fbf0 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -84,6 +84,13 @@ public:
CompilationSuccessful
};
+ struct Remapping
+ {
+ std::string context;
+ std::string prefix;
+ std::string target;
+ };
+
/// Creates a new compiler stack.
/// @param _readFile callback to used to read files for import statements. Must return
/// and must not emit exceptions.
@@ -103,8 +110,11 @@ public:
/// All settings, with the exception of remappings, are reset.
void reset(bool _keepSources = false);
- /// Sets path remappings in the format "context:prefix=target"
- void setRemappings(std::vector<std::string> const& _remappings);
+ // Parses a remapping of the format "context:prefix=target".
+ static boost::optional<Remapping> parseRemapping(std::string const& _remapping);
+
+ /// Sets path remappings.
+ void setRemappings(std::vector<Remapping> const& _remappings);
/// Sets library addresses. Addresses are cleared iff @a _libraries is missing.
/// Will not take effect before running compile.
@@ -319,13 +329,6 @@ private:
FunctionDefinition const& _function
) const;
- struct Remapping
- {
- std::string context;
- std::string prefix;
- std::string target;
- };
-
ReadCallback::Callback m_readFile;
ReadCallback::Callback m_smtQuery;
bool m_optimize = false;
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 58b84163..c1996777 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -326,9 +326,14 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
m_compilerStack.setEVMVersion(*version);
}
- vector<string> remappings;
+ vector<CompilerStack::Remapping> remappings;
for (auto const& remapping: settings.get("remappings", Json::Value()))
- remappings.push_back(remapping.asString());
+ {
+ if (auto r = CompilerStack::parseRemapping(remapping.asString()))
+ remappings.emplace_back(std::move(*r));
+ else
+ return formatFatalError("JSONError", "Invalid remapping: \"" + remapping.asString() + "\"");
+ }
m_compilerStack.setRemappings(remappings);
Json::Value optimizerSettings = settings.get("optimizer", Json::Value());
diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py
index 1f913504..de2a4438 100755
--- a/scripts/isolate_tests.py
+++ b/scripts/isolate_tests.py
@@ -35,43 +35,26 @@ def extract_test_cases(path):
return tests
# Contract sources are indented by 4 spaces.
-# Look for `pragma solidity` and abort a line not indented properly.
-# If the comment `// This will not compile` is above the pragma,
-# the code is skipped.
+# Look for `pragma solidity`, `contract`, `library` or `interface`
+# and abort a line not indented properly.
def extract_docs_cases(path):
- # Note: this code works, because splitlines() removes empty new lines
- # and thus even if the empty new lines are missing indentation
- lines = open(path, 'rb').read().splitlines()
-
- ignore = False
inside = False
tests = []
- for l in lines:
- if inside:
- # Abort if indentation is missing
- m = re.search(r'^[^ ]+', l)
- if m:
- inside = False
- else:
- tests[-1] += l + '\n'
- else:
- m = re.search(r'^ // This will not compile', l)
- if m:
- ignore = True
-
- if ignore:
- # Abort if indentation is missing
- m = re.search(r'^[^ ]+', l)
- if m:
- ignore = False
- else:
- m = re.search(r'^ pragma solidity .*[0-9]+\.[0-9]+\.[0-9]+;$', l)
- if m:
- inside = True
- tests += [l]
-
- return tests
+ # Collect all snippets of indented blocks
+ for l in open(path, 'rb').read().splitlines():
+ if l != '':
+ if not inside and l.startswith(' '):
+ # start new test
+ tests += ['']
+ inside = l.startswith(' ')
+ if inside:
+ tests[-1] += l + '\n'
+ # Filter all tests that do not contain Solidity
+ return [
+ test for test in tests
+ if re.search(r'^ [ ]*(pragma solidity|contract |library |interface )', test, re.MULTILINE)
+ ]
def write_cases(tests):
for test in tests:
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 429bd637..f7d1c748 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -392,7 +392,18 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings()
{
auto eq = find(path.begin(), path.end(), '=');
if (eq != path.end())
- path = string(eq + 1, path.end());
+ {
+ if (auto r = CompilerStack::parseRemapping(path))
+ {
+ m_remappings.emplace_back(std::move(*r));
+ path = string(eq + 1, path.end());
+ }
+ else
+ {
+ cerr << "Invalid remapping: \"" << path << "\"." << endl;
+ return false;
+ }
+ }
else if (path == "-")
addStdin = true;
else
@@ -808,7 +819,7 @@ bool CommandLineInterface::processInput()
if (m_args.count(g_argMetadataLiteral) > 0)
m_compiler->useMetadataLiteralSources(true);
if (m_args.count(g_argInputFile))
- m_compiler->setRemappings(m_args[g_argInputFile].as<vector<string>>());
+ m_compiler->setRemappings(m_remappings);
for (auto const& sourceCode: m_sourceCodes)
m_compiler->addSource(sourceCode.first, sourceCode.second);
if (m_args.count(g_argLibraries))
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index 45ec1eb5..010dce34 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -97,6 +97,8 @@ private:
boost::program_options::variables_map m_args;
/// map of input files to source code strings
std::map<std::string, std::string> m_sourceCodes;
+ /// list of remappings
+ std::vector<dev::solidity::CompilerStack::Remapping> m_remappings;
/// list of allowed directories to read files from
std::vector<boost::filesystem::path> m_allowedDirectories;
/// map of library names to addresses
diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp
index 00f5e697..ea624735 100644
--- a/test/ExecutionFramework.cpp
+++ b/test/ExecutionFramework.cpp
@@ -85,6 +85,22 @@ std::pair<bool, string> ExecutionFramework::compareAndCreateMessage(
return make_pair(false, message);
}
+u256 ExecutionFramework::gasLimit() const
+{
+ auto latestBlock = m_rpc.eth_getBlockByNumber("latest", false);
+ return u256(latestBlock["gasLimit"].asString());
+}
+
+u256 ExecutionFramework::gasPrice() const
+{
+ return u256(m_rpc.eth_gasPrice());
+}
+
+u256 ExecutionFramework::blockHash(u256 const& _blockNumber) const
+{
+ return u256(m_rpc.eth_getBlockByNumber(toHex(_blockNumber, HexPrefix::Add), false)["hash"].asString());
+}
+
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 cdbec81d..0b42f9d0 100644
--- a/test/ExecutionFramework.h
+++ b/test/ExecutionFramework.h
@@ -194,6 +194,13 @@ public:
return encodeArgs(u256(0x20), u256(_arg.size()), _arg);
}
+ u256 gasLimit() const;
+ u256 gasPrice() const;
+ u256 blockHash(u256 const& _blockNumber) const;
+ u256 const& blockNumber() const {
+ return m_blockNumber;
+ }
+
private:
template <class CppFunction, class... Args>
auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp
index b9b19b2f..9ac24972 100644
--- a/test/RPCSession.cpp
+++ b/test/RPCSession.cpp
@@ -207,6 +207,11 @@ string RPCSession::eth_getStorageRoot(string const& _address, string const& _blo
return rpcCall("eth_getStorageRoot", { quote(address), quote(_blockNumber) }).asString();
}
+string RPCSession::eth_gasPrice()
+{
+ return rpcCall("eth_gasPrice").asString();
+}
+
void RPCSession::personal_unlockAccount(string const& _address, string const& _password, int _duration)
{
BOOST_REQUIRE_MESSAGE(
diff --git a/test/RPCSession.h b/test/RPCSession.h
index 5af2e26a..6e1391b4 100644
--- a/test/RPCSession.h
+++ b/test/RPCSession.h
@@ -113,6 +113,7 @@ public:
std::string eth_sendTransaction(std::string const& _transaction);
std::string eth_getBalance(std::string const& _address, std::string const& _blockNumber);
std::string eth_getStorageRoot(std::string const& _address, std::string const& _blockNumber);
+ std::string eth_gasPrice();
std::string personal_newAccount(std::string const& _password);
void personal_unlockAccount(std::string const& _address, std::string const& _password, int _duration);
void test_setChainParams(std::vector<std::string> const& _accounts);
diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh
index 7256386d..c9acb99a 100755
--- a/test/cmdlineTests.sh
+++ b/test/cmdlineTests.sh
@@ -43,18 +43,42 @@ function printError() { echo "$(tput setaf 1)$1$(tput sgr0)"; }
function compileFull()
{
+ local expected_exit_code=0
+ local expect_output=0
+ if [[ $1 = '-e' ]]
+ then
+ expected_exit_code=1
+ expect_output=1
+ shift;
+ fi
+ if [[ $1 = '-w' ]]
+ then
+ expect_output=1
+ shift;
+ fi
+
local files="$*"
- local output failed
+ local output
+
+ local stderr_path=$(mktemp)
set +e
- output=$( ("$SOLC" $FULLARGS $files) 2>&1 )
- failed=$?
+ "$SOLC" $FULLARGS $files >/dev/null 2>"$stderr_path"
+ local exit_code=$?
+ local errors=$(grep -v -E 'Warning: This is a pre-release compiler version|Warning: Experimental features are turned on|pragma experimental ABIEncoderV2|\^-------------------------------\^' < "$stderr_path")
set -e
+ rm "$stderr_path"
- if [ $failed -ne 0 ]
+ if [[ \
+ "$exit_code" -ne "$expected_exit_code" || \
+ ( $expect_output -eq 0 && -n "$errors" ) || \
+ ( $expect_output -ne 0 && -z "$errors" ) \
+ ]]
then
- printError "Compilation failed on:"
- echo "$output"
+ printError "Unexpected compilation result:"
+ printError "Expected failure: $expected_exit_code - Expected warning / error output: $expect_output"
+ printError "Was failure: $exit_code"
+ echo "$errors"
printError "While calling:"
echo "\"$SOLC\" $FULLARGS $files"
printError "Inside directory:"
@@ -63,22 +87,6 @@ function compileFull()
fi
}
-function compileWithoutWarning()
-{
- local files="$*"
- local output failed
-
- set +e
- output=$("$SOLC" $files 2>&1)
- failed=$?
- # Remove the pre-release warning from the compiler output
- output=$(echo "$output" | grep -v 'pre-release')
- echo "$output"
- set -e
-
- test -z "$output" -a "$failed" -eq 0
-}
-
printTask "Testing unknown options..."
(
set +e
@@ -144,6 +152,10 @@ test_solc_file_input_failures "file_not_found.sol" "" "" "\"file_not_found.sol\"
printTask "Testing passing files that are not files..."
test_solc_file_input_failures "." "" "" "\".\" is not a valid file."
+printTask "Testing passing empty remappings..."
+test_solc_file_input_failures "${0}" "=/some/remapping/target" "" "Invalid remapping: \"=/some/remapping/target\"."
+test_solc_file_input_failures "${0}" "ctx:=/some/remapping/target" "" "Invalid remapping: \"ctx:=/some/remapping/target\"."
+
printTask "Compiling various other contracts and libraries..."
(
cd "$REPO_ROOT"/test/compilationTests/
@@ -153,7 +165,7 @@ do
then
echo " - $dir"
cd "$dir"
- compileFull *.sol */*.sol
+ compileFull -w *.sol */*.sol
cd ..
fi
done
@@ -169,8 +181,25 @@ TMPDIR=$(mktemp -d)
"$REPO_ROOT"/scripts/isolate_tests.py "$REPO_ROOT"/docs/ docs
for f in *.sol
do
+ # The contributors guide uses syntax tests, but we cannot
+ # really handle them here.
+ if grep -E 'DeclarationError:|// ----' "$f" >/dev/null
+ then
+ continue
+ fi
echo "$f"
- compileFull "$TMPDIR/$f"
+ opts=''
+ # We expect errors if explicitly stated, or if imports
+ # are used (in the style guide)
+ if grep -E "This will not compile|import \"" "$f" >/dev/null
+ then
+ opts="-e"
+ fi
+ if grep "This will report a warning" "$f" >/dev/null
+ then
+ opts="$opts -w"
+ fi
+ compileFull $opts "$TMPDIR/$f"
done
)
rm -rf "$TMPDIR"
diff --git a/test/compilationTests/stringutils/strings.sol b/test/compilationTests/stringutils/strings.sol
index 6865664b..f89a2527 100644
--- a/test/compilationTests/stringutils/strings.sol
+++ b/test/compilationTests/stringutils/strings.sol
@@ -83,23 +83,23 @@ library strings {
uint ret;
if (self == 0)
return 0;
- if (self & 0xffffffffffffffffffffffffffffffff == 0) {
+ if (uint256(self) & 0xffffffffffffffffffffffffffffffff == 0) {
ret += 16;
self = bytes32(uint(self) / 0x100000000000000000000000000000000);
}
- if (self & 0xffffffffffffffff == 0) {
+ if (uint256(self) & 0xffffffffffffffff == 0) {
ret += 8;
self = bytes32(uint(self) / 0x10000000000000000);
}
- if (self & 0xffffffff == 0) {
+ if (uint256(self) & 0xffffffff == 0) {
ret += 4;
self = bytes32(uint(self) / 0x100000000);
}
- if (self & 0xffff == 0) {
+ if (uint256(self) & 0xffff == 0) {
ret += 2;
self = bytes32(uint(self) / 0x10000);
}
- if (self & 0xff == 0) {
+ if (uint256(self) & 0xff == 0) {
ret += 1;
}
return 32 - ret;
diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp
new file mode 100644
index 00000000..bc652f56
--- /dev/null
+++ b/test/libevmasm/Assembler.cpp
@@ -0,0 +1,152 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Alex Beregszaszi
+ * @date 2018
+ * Tests for the assembler.
+ */
+
+#include <libdevcore/JSON.h>
+#include <libevmasm/Assembly.h>
+
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <tuple>
+#include <memory>
+
+using namespace std;
+using namespace dev::eth;
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+namespace
+{
+ void checkCompilation(::dev::eth::Assembly const& _assembly)
+ {
+ LinkerObject output = _assembly.assemble();
+ BOOST_CHECK(output.bytecode.size() > 0);
+ BOOST_CHECK(output.toHex().length() > 0);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE(Assembler)
+
+BOOST_AUTO_TEST_CASE(all_assembly_items)
+{
+ Assembly _assembly;
+ _assembly.setSourceLocation(SourceLocation(1, 3, make_shared<string>("root.asm")));
+
+ Assembly _subAsm;
+ _subAsm.setSourceLocation(SourceLocation(6, 8, make_shared<string>("sub.asm")));
+ _subAsm.append(Instruction::INVALID);
+ shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm);
+
+ // Tag
+ auto tag = _assembly.newTag();
+ _assembly.append(tag);
+ // Operation
+ _assembly.append(u256(1));
+ _assembly.append(u256(2));
+ // Push
+ _assembly.append(Instruction::KECCAK256);
+ // PushProgramSize
+ _assembly.appendProgramSize();
+ // PushLibraryAddress
+ _assembly.appendLibraryAddress("someLibrary");
+ // PushTag + Operation
+ _assembly.appendJump(tag);
+ // PushString
+ _assembly.append("Unused feature for pushing string");
+ // PushData
+ _assembly.append(bytes{0x1, 0x2, 0x3, 0x4});
+ // PushSubSize
+ auto sub = _assembly.appendSubroutine(_subAsmPtr);
+ // PushSub
+ _assembly.pushSubroutineOffset(size_t(sub.data()));
+ // PushDeployTimeAddress
+ _assembly.append(PushDeployTimeAddress);
+ // Operation
+ _assembly.append(Instruction::STOP);
+ _assembly.appendAuxiliaryDataToEnd(bytes{0x42, 0x66});
+ _assembly.appendAuxiliaryDataToEnd(bytes{0xee, 0xaa});
+
+ checkCompilation(_assembly);
+
+ BOOST_CHECK_EQUAL(
+ _assembly.assemble().toHex(),
+ "5b6001600220606773__someLibrary___________________________"
+ "6000567f556e75736564206665617475726520666f722070757368696e"
+ "6720737472696e605f6001605e73000000000000000000000000000000000000000000fe"
+ "fe010203044266eeaa"
+ );
+ BOOST_CHECK_EQUAL(
+ _assembly.assemblyString(),
+ " /* \"root.asm\":1:3 */\n"
+ "tag_1:\n"
+ " keccak256(0x2, 0x1)\n"
+ " bytecodeSize\n"
+ " linkerSymbol(\"bf005014d9d0f534b8fcb268bd84c491a2380f4acd260d1ccfe9cd8201f7e994\")\n"
+ " jump(tag_1)\n"
+ " data_027497964124140851e8a9992ba16b5c1aaf9730b78d6036c8d65e3bb5ea4c8f\n"
+ " data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b\n"
+ " dataSize(sub_0)\n"
+ " dataOffset(sub_0)\n"
+ " deployTimeAddress()\n"
+ " stop\n"
+ "stop\n"
+ "data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b 01020304\n"
+ "\n"
+ "sub_0: assembly {\n"
+ " /* \"sub.asm\":6:8 */\n"
+ " invalid\n"
+ "}\n"
+ "\n"
+ "auxdata: 0x4266eeaa\n"
+ );
+ BOOST_CHECK_EQUAL(
+ dev::jsonCompactPrint(_assembly.assemblyJSON()),
+ "{\".auxdata\":\"4266eeaa\",\".code\":[{\"begin\":1,\"end\":3,\"name\":\"tag\",\"value\":\"1\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"JUMPDEST\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"value\":\"1\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"value\":\"2\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"KECCAK256\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSHSIZE\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSHLIB\",\"value\":\"someLibrary\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSH [tag]\",\"value\":\"1\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"JUMP\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSH tag\",\"value\":\"Unused feature for pushing string\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSH data\",\"value\":\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"PUSHDEPLOYADDRESS\"},"
+ "{\"begin\":1,\"end\":3,\"name\":\"STOP\"}],"
+ "\".data\":{\"0\":{\".code\":[{\"begin\":6,\"end\":8,\"name\":\"INVALID\"}]},"
+ "\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"}}"
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+} // end namespaces
diff --git a/test/libjulia/Simplifier.cpp b/test/libjulia/Simplifier.cpp
index e5b7e0d8..3cc95b7a 100644
--- a/test/libjulia/Simplifier.cpp
+++ b/test/libjulia/Simplifier.cpp
@@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(mod_and)
);
}
-BOOST_AUTO_TEST_CASE(not_applied)
+BOOST_AUTO_TEST_CASE(not_applied_removes_non_constant_and_not_movable)
{
CHECK(
// The first argument of div is not constant.
@@ -149,4 +149,30 @@ BOOST_AUTO_TEST_CASE(not_applied)
);
}
+BOOST_AUTO_TEST_CASE(not_applied_function_call_different_names)
+{
+ CHECK(
+ "{ function f1() -> a { } function f2() -> b {} let c := sub(f1(), f2()) }",
+ "{ function f1() -> a { } function f2() -> b {} let c := sub(f1(), f2()) }"
+ );
+}
+
+BOOST_AUTO_TEST_CASE(not_applied_function_call_different_arguments)
+{
+ CHECK(
+ "{ function f(a) -> b { } let c := sub(f(0), f(1)) }",
+ "{ function f(a) -> b { } let c := sub(f(0), f(1)) }"
+ );
+}
+
+BOOST_AUTO_TEST_CASE(not_applied_function_call_equality_not_movable)
+{
+ CHECK(
+ // Even if the functions pass the equality check, they are not movable.
+ "{ function f() -> a { } let b := sub(f(), f()) }",
+ "{ function f() -> a { } let b := sub(f(), f()) }"
+ );
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp
index 28f982c4..f91a4f85 100644
--- a/test/libsolidity/ABIDecoderTests.cpp
+++ b/test/libsolidity/ABIDecoderTests.cpp
@@ -792,8 +792,8 @@ BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_advanced)
a = "1234567890123456789012345678901234567890";
b = uint(-1);
c = new bytes20[](4);
- c[0] = bytes20(1234);
- c[3] = bytes20(6789);
+ c[0] = bytes20(uint160(1234));
+ c[3] = bytes20(uint160(6789));
d = 0x1234;
}
function f() public returns (bytes memory, uint, bytes20[] memory, uint) {
diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp
index b1eda425..06cfb4ec 100644
--- a/test/libsolidity/ABIEncoderTests.cpp
+++ b/test/libsolidity/ABIEncoderTests.cpp
@@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(conversion)
int8 c;
int16 d;
assembly { a := sub(0, 1) c := 0x0101ff d := 0xff01 }
- emit E(10, x, a, uint8(b), c, int8(d));
+ emit E(bytes4(uint32(10)), x, a, uint8(b), c, int8(d));
}
}
)";
diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp
index 84e30033..4887dd5b 100644
--- a/test/libsolidity/GasMeter.cpp
+++ b/test/libsolidity/GasMeter.cpp
@@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs)
function f(uint a) public returns (uint b) {
x.length = a;
for (; a < 200; ++a) {
- x[a] = 9;
+ x[a] = 0x09;
b = a * a;
}
return f(a - 1);
diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp
index df31ac40..dc33d577 100644
--- a/test/libsolidity/Imports.cpp
+++ b/test/libsolidity/Imports.cpp
@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(name_clash_in_import)
BOOST_AUTO_TEST_CASE(remappings)
{
CompilerStack c;
- c.setRemappings(vector<string>{"s=s_1.4.6", "t=Tee"});
+ c.setRemappings(vector<CompilerStack::Remapping>{{"", "s", "s_1.4.6"},{"", "t", "Tee"}});
c.addSource("a", "import \"s/s.sol\"; contract A is S {} pragma solidity >=0.0;");
c.addSource("b", "import \"t/tee.sol\"; contract A is Tee {} pragma solidity >=0.0;");
c.addSource("s_1.4.6/s.sol", "contract S {} pragma solidity >=0.0;");
@@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(remappings)
BOOST_AUTO_TEST_CASE(context_dependent_remappings)
{
CompilerStack c;
- c.setRemappings(vector<string>{"a:s=s_1.4.6", "b:s=s_1.4.7"});
+ c.setRemappings(vector<CompilerStack::Remapping>{{"a", "s", "s_1.4.6"}, {"b", "s", "s_1.4.7"}});
c.addSource("a/a.sol", "import \"s/s.sol\"; contract A is SSix {} pragma solidity >=0.0;");
c.addSource("b/b.sol", "import \"s/s.sol\"; contract B is SSeven {} pragma solidity >=0.0;");
c.addSource("s_1.4.6/s.sol", "contract SSix {} pragma solidity >=0.0;");
@@ -200,7 +200,11 @@ BOOST_AUTO_TEST_CASE(filename_with_period)
BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_preserved)
{
CompilerStack c;
- c.setRemappings(vector<string>{"foo=vendor/foo_2.0.0", "vendor/bar:foo=vendor/foo_1.0.0", "bar=vendor/bar"});
+ c.setRemappings(vector<CompilerStack::Remapping>{
+ {"", "foo", "vendor/foo_2.0.0"},
+ {"vendor/bar", "foo", "vendor/foo_1.0.0"},
+ {"", "bar", "vendor/bar"}
+ });
c.addSource("main.sol", "import \"foo/foo.sol\"; import {Bar} from \"bar/bar.sol\"; contract Main is Foo2, Bar {} pragma solidity >=0.0;");
c.addSource("vendor/bar/bar.sol", "import \"foo/foo.sol\"; contract Bar {Foo1 foo;} pragma solidity >=0.0;");
c.addSource("vendor/foo_1.0.0/foo.sol", "contract Foo1 {} pragma solidity >=0.0;");
@@ -212,7 +216,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_pres
BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent)
{
CompilerStack c;
- c.setRemappings(vector<string>{"a:x/y/z=d", "a/b:x=e"});
+ c.setRemappings(vector<CompilerStack::Remapping>{{"a", "x/y/z", "d"}, {"a/b", "x", "e"}});
c.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;");
c.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;");
c.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;");
@@ -220,7 +224,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent)
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
CompilerStack d;
- d.setRemappings(vector<string>{"a/b:x=e", "a:x/y/z=d"});
+ d.setRemappings(vector<CompilerStack::Remapping>{{"a/b", "x", "e"}, {"a", "x/y/z", "d"}});
d.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;");
d.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;");
d.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;");
diff --git a/test/libsolidity/LibSolc.cpp b/test/libsolidity/LibSolc.cpp
index 9d5ffa27..61e5ebba 100644
--- a/test/libsolidity/LibSolc.cpp
+++ b/test/libsolidity/LibSolc.cpp
@@ -111,12 +111,12 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
BOOST_CHECK(contract["bytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["bytecode"].asString()),
- "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00"
+ "6080604052348015600f57600080fd5b50603580601d6000396000f3fe6080604052600080fdfe"
);
BOOST_CHECK(contract["runtimeBytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()),
- "6080604052600080fd00"
+ "6080604052600080fdfe"
);
BOOST_CHECK(contract["functionHashes"].isObject());
BOOST_CHECK(contract["gasEstimates"].isObject());
@@ -153,12 +153,12 @@ BOOST_AUTO_TEST_CASE(single_compilation)
BOOST_CHECK(contract["bytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["bytecode"].asString()),
- "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00"
+ "6080604052348015600f57600080fd5b50603580601d6000396000f3fe6080604052600080fdfe"
);
BOOST_CHECK(contract["runtimeBytecode"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()),
- "6080604052600080fd00"
+ "6080604052600080fdfe"
);
BOOST_CHECK(contract["functionHashes"].isObject());
BOOST_CHECK(contract["gasEstimates"].isObject());
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index e487f0ae..7b56fa9d 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -1543,6 +1543,92 @@ BOOST_AUTO_TEST_CASE(mapping_local_compound_assignment)
ABI_CHECK(callContractFunction("f()"), encodeArgs(byte(42), byte(0), byte(0), byte(21)));
}
+BOOST_AUTO_TEST_CASE(mapping_internal_argument)
+{
+ char const* sourceCode = R"(
+ contract test {
+ mapping(uint8 => uint8) a;
+ mapping(uint8 => uint8) b;
+ function set_internal(mapping(uint8 => uint8) storage m, uint8 key, uint8 value) internal returns (uint8) {
+ uint8 oldValue = m[key];
+ m[key] = value;
+ return oldValue;
+ }
+ function set(uint8 key, uint8 value_a, uint8 value_b) public returns (uint8 old_a, uint8 old_b) {
+ old_a = set_internal(a, key, value_a);
+ old_b = set_internal(b, key, value_b);
+ }
+ function get(uint8 key) public returns (uint8, uint8) {
+ return (a[key], b[key]);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+
+ ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", byte(1), byte(21), byte(42)), encodeArgs(byte(0), byte(0)));
+ ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(21), byte(42)));
+ ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", byte(1), byte(10), byte(11)), encodeArgs(byte(21), byte(42)));
+ ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(10), byte(11)));
+}
+
+BOOST_AUTO_TEST_CASE(mapping_array_internal_argument)
+{
+ char const* sourceCode = R"(
+ contract test {
+ mapping(uint8 => uint8)[2] a;
+ mapping(uint8 => uint8)[2] b;
+ function set_internal(mapping(uint8 => uint8)[2] storage m, uint8 key, uint8 value1, uint8 value2) internal returns (uint8, uint8) {
+ uint8 oldValue1 = m[0][key];
+ uint8 oldValue2 = m[1][key];
+ m[0][key] = value1;
+ m[1][key] = value2;
+ return (oldValue1, oldValue2);
+ }
+ function set(uint8 key, uint8 value_a1, uint8 value_a2, uint8 value_b1, uint8 value_b2) public returns (uint8 old_a1, uint8 old_a2, uint8 old_b1, uint8 old_b2) {
+ (old_a1, old_a2) = set_internal(a, key, value_a1, value_a2);
+ (old_b1, old_b2) = set_internal(b, key, value_b1, value_b2);
+ }
+ function get(uint8 key) public returns (uint8, uint8, uint8, uint8) {
+ return (a[0][key], a[1][key], b[0][key], b[1][key]);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+
+ ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", byte(1), byte(21), byte(22), byte(42), byte(43)), encodeArgs(byte(0), byte(0), byte(0), byte(0)));
+ ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(21), byte(22), byte(42), byte(43)));
+ ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", byte(1), byte(10), byte(30), byte(11), byte(31)), encodeArgs(byte(21), byte(22), byte(42), byte(43)));
+ ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(10), byte(30), byte(11), byte(31)));
+}
+
+BOOST_AUTO_TEST_CASE(mapping_internal_return)
+{
+ char const* sourceCode = R"(
+ contract test {
+ mapping(uint8 => uint8) a;
+ mapping(uint8 => uint8) b;
+ function f() internal returns (mapping(uint8 => uint8) storage r) {
+ r = a;
+ r[1] = 42;
+ r = b;
+ r[1] = 84;
+ }
+ function g() public returns (uint8, uint8, uint8, uint8, uint8, uint8) {
+ f()[2] = 21;
+ return (a[0], a[1], a[2], b[0], b[1], b[2]);
+ }
+ function h() public returns (uint8, uint8, uint8, uint8, uint8, uint8) {
+ mapping(uint8 => uint8) storage m = f();
+ m[2] = 17;
+ return (a[0], a[1], a[2], b[0], b[1], b[2]);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(byte(0), byte(42), byte(0), byte(0), byte(84), byte (21)));
+ ABI_CHECK(callContractFunction("h()"), encodeArgs(byte(0), byte(42), byte(0), byte(0), byte(84), byte (17)));
+}
BOOST_AUTO_TEST_CASE(structs)
{
@@ -2211,7 +2297,7 @@ BOOST_AUTO_TEST_CASE(log0)
char const* sourceCode = R"(
contract test {
function a() public {
- log0(1);
+ log0(bytes32(uint256(1)));
}
}
)";
@@ -2228,7 +2314,7 @@ BOOST_AUTO_TEST_CASE(log1)
char const* sourceCode = R"(
contract test {
function a() public {
- log1(1, 2);
+ log1(bytes32(uint256(1)), bytes32(uint256(2)));
}
}
)";
@@ -2246,7 +2332,7 @@ BOOST_AUTO_TEST_CASE(log2)
char const* sourceCode = R"(
contract test {
function a() public {
- log2(1, 2, 3);
+ log2(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3)));
}
}
)";
@@ -2265,7 +2351,7 @@ BOOST_AUTO_TEST_CASE(log3)
char const* sourceCode = R"(
contract test {
function a() public {
- log3(1, 2, 3, 4);
+ log3(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3)), bytes32(uint256(4)));
}
}
)";
@@ -2284,7 +2370,7 @@ BOOST_AUTO_TEST_CASE(log4)
char const* sourceCode = R"(
contract test {
function a() public {
- log4(1, 2, 3, 4, 5);
+ log4(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3)), bytes32(uint256(4)), bytes32(uint256(5)));
}
}
)";
@@ -2303,7 +2389,7 @@ BOOST_AUTO_TEST_CASE(log_in_constructor)
char const* sourceCode = R"(
contract test {
constructor() public {
- log1(1, 2);
+ log1(bytes32(uint256(1)), bytes32(uint256(2)));
}
}
)";
@@ -2902,6 +2988,99 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic)
BOOST_REQUIRE(callContractFunction("checkState()") == encodeArgs(false, 20 - 5));
}
+BOOST_AUTO_TEST_CASE(gasleft_decrease)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint v;
+ function f() public returns (bool) {
+ uint startGas = gasleft();
+ v++;
+ assert(startGas > gasleft());
+ return true;
+ }
+ function g() public returns (bool) {
+ uint startGas = gasleft();
+ assert(startGas > gasleft());
+ return true;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(true));
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(true));
+}
+
+BOOST_AUTO_TEST_CASE(gaslimit)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() public returns (uint) {
+ return block.gaslimit;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(gasLimit()));
+}
+
+BOOST_AUTO_TEST_CASE(gasprice)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() public returns (uint) {
+ return tx.gasprice;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(gasPrice()));
+}
+
+BOOST_AUTO_TEST_CASE(blockhash)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint256 counter;
+ function g() public returns (bool) { counter++; return true; }
+ function f() public returns (bytes32[] memory r) {
+ r = new bytes32[](259);
+ for (uint i = 0; i < 259; i++)
+ r[i] = blockhash(block.number - 257 + i);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ // generate a sufficient amount of blocks
+ while (blockNumber() < u256(255))
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(true));
+
+ vector<u256> hashes;
+ // currently the test only works for pre-constantinople
+ if (Options::get().evmVersion() < EVMVersion::constantinople())
+ {
+ // ``blockhash()`` is only valid for the last 256 blocks, otherwise zero
+ hashes.emplace_back(0);
+ for (u256 i = blockNumber() - u256(255); i <= blockNumber(); i++)
+ hashes.emplace_back(blockHash(i));
+ // the current block hash is not yet known at execution time and therefore zero
+ hashes.emplace_back(0);
+ // future block hashes are zero
+ hashes.emplace_back(0);
+ }
+ else
+ // TODO: Starting from constantinople blockhash always seems to return zero.
+ // The blockhash contract introduced in EIP96 seems to break in our setup of
+ // aleth (setting the constantinople fork block to zero and resetting the chain
+ // to block zero before each test run). Pre-deploying the blockchain contract
+ // during genesis seems to help, but currently causes problems with other tests.
+ // Set the expectation to zero for now, so that this test tracks changes in this
+ // behavior.
+ hashes.assign(259, 0);
+
+ ABI_CHECK(callContractFunction("f()"), encodeDyn(hashes));
+}
+
BOOST_AUTO_TEST_CASE(value_complex)
{
char const* sourceCode = R"(
@@ -4576,6 +4755,68 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints)
ABI_CHECK(callContractFunction("test()"), encodeArgs(1));
}
+BOOST_AUTO_TEST_CASE(struct_referencing)
+{
+ static char const* sourceCode = R"(
+ pragma experimental ABIEncoderV2;
+ interface I {
+ struct S { uint a; }
+ }
+ library L {
+ struct S { uint b; uint a; }
+ function f() public pure returns (S) {
+ S memory s;
+ s.a = 3;
+ return s;
+ }
+ function g() public pure returns (I.S) {
+ I.S memory s;
+ s.a = 4;
+ return s;
+ }
+ // argument-dependant lookup tests
+ function a(I.S memory) public pure returns (uint) { return 1; }
+ function a(S memory) public pure returns (uint) { return 2; }
+ }
+ contract C is I {
+ function f() public pure returns (S) {
+ S memory s;
+ s.a = 1;
+ return s;
+ }
+ function g() public pure returns (I.S) {
+ I.S memory s;
+ s.a = 2;
+ return s;
+ }
+ function h() public pure returns (L.S) {
+ L.S memory s;
+ s.a = 5;
+ return s;
+ }
+ function x() public pure returns (L.S) {
+ return L.f();
+ }
+ function y() public pure returns (I.S) {
+ return L.g();
+ }
+ function a1() public pure returns (uint) { S memory s; return L.a(s); }
+ function a2() public pure returns (uint) { L.S memory s; return L.a(s); }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "L");
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(0, 3));
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(4));
+ compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{ {"L", m_contractAddress}});
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(1));
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(2));
+ ABI_CHECK(callContractFunction("h()"), encodeArgs(0, 5));
+ ABI_CHECK(callContractFunction("x()"), encodeArgs(0, 3));
+ ABI_CHECK(callContractFunction("y()"), encodeArgs(4));
+ ABI_CHECK(callContractFunction("a1()"), encodeArgs(1));
+ ABI_CHECK(callContractFunction("a2()"), encodeArgs(2));
+}
+
BOOST_AUTO_TEST_CASE(enum_referencing)
{
char const* sourceCode = R"(
@@ -5017,7 +5258,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_simple)
function test() public returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) {
for (uint i = 0; i < data1.length; ++i)
data1[i] = bytes8(uint64(i));
- data2[8] = data2[9] = 2;
+ data2[8] = data2[9] = bytes8(uint64(2));
data2 = data1;
a = data2[1];
b = data2[2];
@@ -5076,10 +5317,10 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover2)
bytes8[4] data1; // fits into one slot
bytes10[6] data2; // 4 elements need two slots
function test() public returns (bytes10 r1, bytes10 r2, bytes10 r3) {
- data1[0] = 1;
- data1[1] = 2;
- data1[2] = 3;
- data1[3] = 4;
+ data1[0] = bytes8(uint64(1));
+ data1[1] = bytes8(uint64(2));
+ data1[2] = bytes8(uint64(3));
+ data1[3] = bytes8(uint64(4));
for (uint i = 0; i < data2.length; ++i)
data2[i] = bytes10(uint80(0xffff00 | (1 + i)));
data2 = data1;
@@ -5274,13 +5515,13 @@ BOOST_AUTO_TEST_CASE(byte_array_push)
contract c {
bytes data;
function test() public returns (bool x) {
- if (data.push(5) != 1) return true;
- if (data[0] != 5) return true;
- data.push(4);
- if (data[1] != 4) return true;
- uint l = data.push(3);
- if (data[2] != 3) return true;
- if (l != 3) return true;
+ if (data.push(0x05) != 1) return true;
+ if (data[0] != 0x05) return true;
+ data.push(0x04);
+ if (data[1] != 0x04) return true;
+ uint l = data.push(0x03);
+ if (data[2] != 0x03) return true;
+ if (l != 0x03) return true;
}
}
)";
@@ -5453,11 +5694,11 @@ BOOST_AUTO_TEST_CASE(byte_array_pop)
contract c {
bytes data;
function test() public returns (uint x, uint y, uint l) {
- data.push(7);
- x = data.push(3);
+ data.push(0x07);
+ x = data.push(0x03);
data.pop();
data.pop();
- y = data.push(2);
+ y = data.push(0x02);
l = data.length;
}
}
@@ -5490,9 +5731,9 @@ BOOST_AUTO_TEST_CASE(byte_array_pop_storage_empty)
contract c {
bytes data;
function test() public {
- data.push(7);
- data.push(5);
- data.push(3);
+ data.push(0x07);
+ data.push(0x05);
+ data.push(0x03);
data.pop();
data.pop();
data.pop();
@@ -5538,7 +5779,7 @@ BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty_garbage_ref)
bytes data;
function test() public {
for (uint8 i = 0; i <= 40; i++)
- data.push(3);
+ data.push(0x03);
for (uint8 j = 0; j <= 40; j++) {
assembly {
mstore(0, "garbage")
@@ -5560,7 +5801,7 @@ BOOST_AUTO_TEST_CASE(byte_array_pop_masking_long)
bytes data;
function test() public returns (bytes memory) {
for (uint i = 0; i < 34; i++)
- data.push(3);
+ data.push(0x03);
data.pop();
return data;
}
@@ -5582,7 +5823,7 @@ BOOST_AUTO_TEST_CASE(byte_array_pop_copy_long)
bytes data;
function test() public returns (bytes memory) {
for (uint i = 0; i < 33; i++)
- data.push(3);
+ data.push(0x03);
for (uint j = 0; j < 4; j++)
data.pop();
return data;
@@ -5672,10 +5913,10 @@ BOOST_AUTO_TEST_CASE(bytes_index_access)
data[31] = 0x77;
data[32] = 0x14;
- data[31] = 1;
- data[31] |= 8;
- data[30] = 1;
- data[32] = 3;
+ data[31] = 0x01;
+ data[31] |= 0x08;
+ data[30] = 0x01;
+ data[32] = 0x03;
return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32]));
}
}
@@ -5703,7 +5944,7 @@ BOOST_AUTO_TEST_CASE(bytes_delete_element)
delete data[94];
delete data[96];
delete data[98];
- return data[94] == 0 && data[95] == 95 && data[96] == 0 && data[97] == 97;
+ return data[94] == 0 && uint8(data[95]) == 95 && data[96] == 0 && uint8(data[97]) == 97;
}
}
)";
@@ -6060,19 +6301,19 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_bytes)
s2 data;
byte y;
function test() public returns (bool) {
- x = 1;
- data.a = 2;
- data.inner.a = 3;
- data.inner.b = 4;
+ x = 0x01;
+ data.a = 0x02;
+ data.inner.a = 0x03;
+ data.inner.b = 0x04;
data.inner.c = "1234567890";
data.inner.d = "123456789";
data.inner.e = "abcdefghij";
- data.b = 5;
- data.c = 6;
- y = 7;
- return x == 1 && data.a == 2 && data.inner.a == 3 && data.inner.b == 4 &&
+ data.b = 0x05;
+ data.c = byte(0x06);
+ y = 0x07;
+ return x == 0x01 && data.a == 0x02 && data.inner.a == 0x03 && data.inner.b == 0x04 &&
data.inner.c == "1234567890" && data.inner.d == "123456789" &&
- data.inner.e == "abcdefghij" && data.b == 5 && data.c == 6 && y == 7;
+ data.inner.e == "abcdefghij" && data.b == 0x05 && data.c == byte(0x06) && y == 0x07;
}
}
)";
@@ -7961,6 +8202,162 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library)
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4), u256(17)));
}
+BOOST_AUTO_TEST_CASE(mapping_arguments_in_library)
+{
+ char const* sourceCode = R"(
+ library Lib {
+ function set(mapping(uint => uint) storage m, uint key, uint value) internal
+ {
+ m[key] = value;
+ }
+ function get(mapping(uint => uint) storage m, uint key) internal view returns (uint)
+ {
+ return m[key];
+ }
+ }
+ contract Test {
+ mapping(uint => uint) m;
+ function set(uint256 key, uint256 value) public returns (uint)
+ {
+ uint oldValue = Lib.get(m, key);
+ Lib.set(m, key, value);
+ return oldValue;
+ }
+ function get(uint256 key) public view returns (uint) {
+ return Lib.get(m, key);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Lib");
+ compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
+ ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(42)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(84)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(7)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(84)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(7)));
+ ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(21)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(42)), encodeArgs(u256(84)));
+ ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(14)), encodeArgs(u256(7)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(21)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(14)));
+}
+
+BOOST_AUTO_TEST_CASE(mapping_returns_in_library)
+{
+ char const* sourceCode = R"(
+ library Lib {
+ function choose_mapping(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint=>uint) storage)
+ {
+ return c ? a : b;
+ }
+ }
+ contract Test {
+ mapping(uint => uint) a;
+ mapping(uint => uint) b;
+ function set(bool choice, uint256 key, uint256 value) public returns (uint)
+ {
+ mapping(uint => uint) storage m = Lib.choose_mapping(a, b, choice);
+ uint oldValue = m[key];
+ m[key] = value;
+ return oldValue;
+ }
+ function get(bool choice, uint256 key) public view returns (uint) {
+ return Lib.choose_mapping(a, b, choice)[key];
+ }
+ function get_a(uint256 key) public view returns (uint) {
+ return a[key];
+ }
+ function get_b(uint256 key) public view returns (uint) {
+ return b[key];
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Lib");
+ compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(42)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(84)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(7)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(10)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(11)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(12)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(84)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(7)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(84)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(7)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(10)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(11)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(12)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(10)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(11)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(12)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(21)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(42)), encodeArgs(u256(84)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(14)), encodeArgs(u256(7)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(30)), encodeArgs(u256(10)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(31)), encodeArgs(u256(11)));
+ ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(32)), encodeArgs(u256(12)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(21)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(14)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(21)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(42)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(14)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(30)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(31)));
+ ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(32)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(30)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(31)));
+ ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(32)));
+}
+
+BOOST_AUTO_TEST_CASE(mapping_returns_in_library_named)
+{
+ char const* sourceCode = R"(
+ library Lib {
+ function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b) internal returns(mapping(uint=>uint) storage r)
+ {
+ r = a;
+ r[1] = 42;
+ r = b;
+ r[1] = 21;
+ }
+ }
+ contract Test {
+ mapping(uint => uint) a;
+ mapping(uint => uint) b;
+ function f() public returns (uint, uint, uint, uint, uint, uint)
+ {
+ Lib.f(a, b)[2] = 84;
+ return (a[0], a[1], a[2], b[0], b[1], b[2]);
+ }
+ function g() public returns (uint, uint, uint, uint, uint, uint)
+ {
+ mapping(uint => uint) storage m = Lib.f(a, b);
+ m[2] = 17;
+ return (a[0], a[1], a[2], b[0], b[1], b[2]);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Lib");
+ compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(84)));
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(17)));
+}
+
BOOST_AUTO_TEST_CASE(using_library_structs)
{
char const* sourceCode = R"(
@@ -8062,17 +8459,17 @@ BOOST_AUTO_TEST_CASE(short_strings)
if (data1[4] != "4") return 11;
for (uint i = 0; i < data1.length; i ++)
data1[i] = byte(uint8(i * 3));
- if (data1[4] != 4 * 3) return 12;
- if (data1[67] != 67 * 3) return 13;
+ if (uint8(data1[4]) != 4 * 3) return 12;
+ if (uint8(data1[67]) != 67 * 3) return 13;
// change length: long -> short
data1.length = 22;
if (data1.length != 22) return 14;
- if (data1[21] != byte(21 * 3)) return 15;
- if (data1[2] != 2 * 3) return 16;
+ if (uint8(data1[21]) != 21 * 3) return 15;
+ if (uint8(data1[2]) != 2 * 3) return 16;
// change length: short -> shorter
data1.length = 19;
if (data1.length != 19) return 17;
- if (data1[7] != byte(7 * 3)) return 18;
+ if (uint8(data1[7]) != 7 * 3) return 18;
// and now again to original size
data1.length = 22;
if (data1.length != 22) return 19;
@@ -8888,7 +9285,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_length_access)
contract C {
byte a;
function f(bytes32 x) public returns (uint, uint, uint) {
- return (x.length, bytes16(2).length, a.length + 7);
+ return (x.length, bytes16(uint128(2)).length, a.length + 7);
}
}
)";
@@ -9383,9 +9780,9 @@ BOOST_AUTO_TEST_CASE(iszero_bnot_correct)
char const* sourceCode = R"(
contract C {
function f() public returns (bool) {
- bytes32 x = 1;
+ bytes32 x = bytes32(uint256(1));
assembly { x := not(x) }
- if (x != ~bytes32(1)) return false;
+ if (x != ~bytes32(uint256(1))) return false;
assembly { x := iszero(x) }
if (x != bytes32(0)) return false;
return true;
@@ -9404,7 +9801,7 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types)
function f(bytes2 a, uint16 x) public returns (uint) {
if (a != "ab") return 1;
if (x != 0x0102) return 2;
- if (bytes3(uint24(x)) != 0x0102) return 3;
+ if (bytes3(uint24(x)) != 0x000102) return 3;
return 0;
}
}
@@ -9736,7 +10133,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input)
char const* sourceCode = R"(
contract C {
function f() public returns (address) {
- return ecrecover(bytes32(uint(-1)), 1, 2, 3);
+ return ecrecover(bytes32(uint(-1)), 1, bytes32(uint(2)), bytes32(uint(3)));
}
}
)";
@@ -9754,8 +10151,8 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper)
0, // invalid v value
0x6944c77849b18048f6abe0db8084b0d0d0689cdddb53d2671c36967b58691ad4,
0xef4f06ba4f78319baafd0424365777241af4dfd3da840471b4b4b087b7750d0d,
- 0x00ca35b7d915458ef540ade6068dfe2f44e8fa733c,
- 0x00ca35b7d915458ef540ade6068dfe2f44e8fa733c
+ 0x000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c,
+ 0x000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c
);
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s, uint blockExpired, bytes32 salt)
diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp
index db0e3b66..e171d974 100644
--- a/test/libsolidity/SolidityTypes.cpp
+++ b/test/libsolidity/SolidityTypes.cpp
@@ -195,11 +195,11 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
TupleType t({e.type(), s.type(), stringArray, nullptr});
BOOST_CHECK_EQUAL(t.identifier(), "t_tuple$_t_type$_t_enum$_Enum_$4_$_$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$_t_array$_t_string_storage_$20_storage_ptr_$__$");
- TypePointer sha3fun = make_shared<FunctionType>(strings{}, strings{}, FunctionType::Kind::SHA3);
- BOOST_CHECK_EQUAL(sha3fun->identifier(), "t_function_sha3_nonpayable$__$returns$__$");
+ TypePointer keccak256fun = make_shared<FunctionType>(strings{}, strings{}, FunctionType::Kind::KECCAK256);
+ BOOST_CHECK_EQUAL(keccak256fun->identifier(), "t_function_keccak256_nonpayable$__$returns$__$");
- FunctionType metaFun(TypePointers{sha3fun}, TypePointers{s.type()});
- BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_sha3_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$");
+ FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()});
+ BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_keccak256_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$");
TypePointer m = make_shared<MappingType>(Type::fromElementaryTypeName("bytes32"), s.type());
MappingType m2(Type::fromElementaryTypeName("uint64"), m);
diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp
index 16921a24..3aa1dc24 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -238,7 +238,7 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
"settings": {
"outputSelection": {
"fileA": {
- "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "metadata" ],
+ "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "evm.legacyAssembly", "metadata" ],
"": [ "legacyAST" ]
}
}
@@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString());
BOOST_CHECK_EQUAL(
dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()),
- "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00"
+ "6080604052348015600f57600080fd5b50603580601d6000396000f3fe6080604052600080fdfe"
);
BOOST_CHECK(contract["evm"]["assembly"].isString());
BOOST_CHECK(contract["evm"]["assembly"].asString().find(
@@ -280,6 +280,34 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
dev::jsonCompactPrint(contract["evm"]["gasEstimates"]),
"{\"creation\":{\"codeDepositCost\":\"10600\",\"executionCost\":\"66\",\"totalCost\":\"10666\"}}"
);
+ // Lets take the top level `.code` section (the "deployer code"), that should expose most of the features of
+ // the assembly JSON. What we want to check here is Operation, Push, PushTag, PushSub, PushSubSize and Tag.
+ BOOST_CHECK(contract["evm"]["legacyAssembly"].isObject());
+ BOOST_CHECK(contract["evm"]["legacyAssembly"][".code"].isArray());
+ BOOST_CHECK_EQUAL(
+ dev::jsonCompactPrint(contract["evm"]["legacyAssembly"][".code"]),
+ "[{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"80\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"40\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"MSTORE\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"CALLVALUE\"},"
+ "{\"begin\":8,\"end\":17,\"name\":\"DUP1\"},"
+ "{\"begin\":5,\"end\":7,\"name\":\"ISZERO\"},"
+ "{\"begin\":5,\"end\":7,\"name\":\"PUSH [tag]\",\"value\":\"1\"},"
+ "{\"begin\":5,\"end\":7,\"name\":\"JUMPI\"},"
+ "{\"begin\":30,\"end\":31,\"name\":\"PUSH\",\"value\":\"0\"},"
+ "{\"begin\":27,\"end\":28,\"name\":\"DUP1\"},"
+ "{\"begin\":20,\"end\":32,\"name\":\"REVERT\"},"
+ "{\"begin\":5,\"end\":7,\"name\":\"tag\",\"value\":\"1\"},"
+ "{\"begin\":5,\"end\":7,\"name\":\"JUMPDEST\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"POP\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"PUSH #[$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"DUP1\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"PUSH [$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"0\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"CODECOPY\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"value\":\"0\"},"
+ "{\"begin\":0,\"end\":14,\"name\":\"RETURN\"}]"
+ );
BOOST_CHECK(contract["metadata"].isString());
BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString()));
BOOST_CHECK(result["sources"].isObject());
diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol
new file mode 100644
index 00000000..35420b6d
--- /dev/null
+++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol
@@ -0,0 +1,5 @@
+contract C {
+ function f() internal pure returns (mapping(uint=>uint) storage r) { }
+}
+// ----
+// TypeError: (53-82): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol
new file mode 100644
index 00000000..4146192f
--- /dev/null
+++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol
@@ -0,0 +1,5 @@
+contract C {
+ mapping(uint=>uint) m;
+ function f() internal view returns (mapping(uint=>uint) storage r) { r = m; }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol
new file mode 100644
index 00000000..7e8c4501
--- /dev/null
+++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol
@@ -0,0 +1,5 @@
+contract C {
+ function f() internal pure returns (mapping(uint=>uint) storage) {}
+}
+// ----
+// TypeError: (53-72): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol
new file mode 100644
index 00000000..9c5e3149
--- /dev/null
+++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol
@@ -0,0 +1,5 @@
+contract C {
+ mapping(uint=>uint) m;
+ function f() internal view returns (mapping(uint=>uint) storage) { return m; }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/conversion/conversion_to_bytes.sol b/test/libsolidity/syntaxTests/conversion/conversion_to_bytes.sol
new file mode 100644
index 00000000..5946e921
--- /dev/null
+++ b/test/libsolidity/syntaxTests/conversion/conversion_to_bytes.sol
@@ -0,0 +1,5 @@
+contract test {
+ function f() public pure returns (bytes) {
+ return bytes("abc");
+ }
+}
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/161_warns_assigning_decimal_to_bytesxx.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/161_warns_assigning_decimal_to_bytesxx.sol
deleted file mode 100644
index 957322af..00000000
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/161_warns_assigning_decimal_to_bytesxx.sol
+++ /dev/null
@@ -1,5 +0,0 @@
-contract Foo {
- bytes32 a = 7;
-}
-// ----
-// Warning: (31-32): Decimal literal assigned to bytesXX variable will be left-aligned. Use an explicit conversion to silence this warning.
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/162_does_not_warn_assigning_hex_number_to_bytesxx.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/162_does_not_warn_assigning_hex_number_to_bytesxx.sol
deleted file mode 100644
index bc32580a..00000000
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/162_does_not_warn_assigning_hex_number_to_bytesxx.sol
+++ /dev/null
@@ -1,3 +0,0 @@
-contract Foo {
- bytes32 a = 0x1234;
-}
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/163_explicit_conversion_from_decimal_to_bytesxx.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/163_explicit_conversion_from_decimal_to_bytesxx.sol
deleted file mode 100644
index af921869..00000000
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/163_explicit_conversion_from_decimal_to_bytesxx.sol
+++ /dev/null
@@ -1,3 +0,0 @@
-contract Foo {
- bytes32 a = bytes32(7);
-}
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol
index 401c46e2..0f67460f 100644
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol
+++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol
@@ -2,4 +2,4 @@ contract C {
string s = string("\xa0\x00");
}
// ----
-// TypeError: (28-46): Explicit type conversion not allowed from "literal_string (contains invalid UTF-8 sequence at position 0)" to "string storage pointer".
+// TypeError: (28-46): Explicit type conversion not allowed from "literal_string (contains invalid UTF-8 sequence at position 0)" to "string memory".
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol
index c74d52d3..385ed18e 100644
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol
+++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol
@@ -1,9 +1,6 @@
interface I {
struct A {
- // This is currently expected to break, but it *may* change in the future.
int dummy;
}
}
// ----
-// TypeError: (18-136): Structs cannot be defined in interfaces.
-// TypeError: (120-129): Variables cannot be declared in interfaces.
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol
index a83eee72..c44fab55 100644
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol
+++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/482_explicit_literal_to_unspecified_string.sol
@@ -4,4 +4,4 @@ contract C {
}
}
// ----
-// TypeError: (52-65): Explicit type conversion not allowed from "literal_string "abc"" to "string storage pointer".
+// Warning: (52-65): Statement has no effect.
diff --git a/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol
new file mode 100644
index 00000000..036e108a
--- /dev/null
+++ b/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol
@@ -0,0 +1,9 @@
+contract C {
+ struct S { uint x; }
+ function f() public pure {
+ S[] memory s;
+ abi.encodePacked(s);
+ }
+}
+// ----
+// TypeError: (116-117): This type cannot be encoded.
diff --git a/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol b/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol
new file mode 100644
index 00000000..7a4d8250
--- /dev/null
+++ b/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol
@@ -0,0 +1,10 @@
+pragma experimental ABIEncoderV2;
+contract C {
+ struct S { uint x; }
+ function f() public pure {
+ S[] memory s;
+ abi.encode(s);
+ }
+}
+// ----
+// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
diff --git a/test/libsolidity/syntaxTests/types/bytesm.sol b/test/libsolidity/syntaxTests/types/bytesm.sol
index 550760b9..77ff7524 100644
--- a/test/libsolidity/syntaxTests/types/bytesm.sol
+++ b/test/libsolidity/syntaxTests/types/bytesm.sol
@@ -1,5 +1,5 @@
contract C {
- byte b = byte(1);
+ byte b = byte(0x01);
bytes1 b1 = b;
bytes2 b2 = b1;
bytes3 b3 = b2;
diff --git a/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_explicit.sol b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_explicit.sol
new file mode 100644
index 00000000..ff285a07
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_explicit.sol
@@ -0,0 +1,23 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = bytes1(1);
+ bytes2 b2 = bytes2(1);
+ bytes2 b3 = bytes2(256);
+ bytes3 b4 = bytes3(1);
+ bytes3 b5 = bytes3(65536);
+ bytes4 b6 = bytes4(1);
+ bytes4 b7 = bytes4(16777216);
+ bytes16 b8 = bytes16(1);
+ bytes32 b9 = bytes32(1);
+ }
+}
+// ----
+// TypeError: (60-69): Explicit type conversion not allowed from "int_const 1" to "bytes1".
+// TypeError: (88-97): Explicit type conversion not allowed from "int_const 1" to "bytes2".
+// TypeError: (116-127): Explicit type conversion not allowed from "int_const 256" to "bytes2".
+// TypeError: (146-155): Explicit type conversion not allowed from "int_const 1" to "bytes3".
+// TypeError: (174-187): Explicit type conversion not allowed from "int_const 65536" to "bytes3".
+// TypeError: (206-215): Explicit type conversion not allowed from "int_const 1" to "bytes4".
+// TypeError: (234-250): Explicit type conversion not allowed from "int_const 16777216" to "bytes4".
+// TypeError: (270-280): Explicit type conversion not allowed from "int_const 1" to "bytes16".
+// TypeError: (300-310): Explicit type conversion not allowed from "int_const 1" to "bytes32".
diff --git a/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_implicit.sol b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_implicit.sol
new file mode 100644
index 00000000..e472c43b
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/decimal_literal_to_bytesXX_implicit.sol
@@ -0,0 +1,23 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = 1;
+ bytes2 b2 = 1;
+ bytes2 b3 = 256;
+ bytes3 b4 = 1;
+ bytes3 b5 = 65536;
+ bytes4 b6 = 1;
+ bytes4 b7 = 16777216;
+ bytes16 b8 = 1;
+ bytes32 b9 = 1;
+ }
+}
+// ----
+// TypeError: (48-61): Type int_const 1 is not implicitly convertible to expected type bytes1.
+// TypeError: (68-81): Type int_const 1 is not implicitly convertible to expected type bytes2.
+// TypeError: (88-103): Type int_const 256 is not implicitly convertible to expected type bytes2.
+// TypeError: (110-123): Type int_const 1 is not implicitly convertible to expected type bytes3.
+// TypeError: (130-147): Type int_const 65536 is not implicitly convertible to expected type bytes3.
+// TypeError: (154-167): Type int_const 1 is not implicitly convertible to expected type bytes4.
+// TypeError: (174-194): Type int_const 16777216 is not implicitly convertible to expected type bytes4.
+// TypeError: (201-215): Type int_const 1 is not implicitly convertible to expected type bytes16.
+// TypeError: (222-236): Type int_const 1 is not implicitly convertible to expected type bytes32.
diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol
new file mode 100644
index 00000000..0d4fded1
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol
@@ -0,0 +1,42 @@
+contract Test
+{
+ function uint256_to_uint256(uint256 x) internal pure returns (uint256) { return x; }
+ function uint256_to_string(uint256 x) internal pure returns (string memory) { return x == 0 ? "a" : "b"; }
+ function uint256_to_string_storage(uint256) internal pure returns (string storage);
+ function string_to_uint256(string memory x) internal pure returns (uint256) { return bytes(x).length; }
+ function string_to_string(string memory x) internal pure returns (string memory) { return x; }
+
+ function uint256_uint256_to_uint256(uint256 x, uint256 y) internal pure returns (uint256) { return x + y; }
+ function uint256_uint256_to_string(uint256 x, uint256 y) internal pure returns (string memory) { return x == y ? "a" : "b"; }
+ function string_uint256_to_string(string memory x, uint256 y) internal pure returns (string memory) { return y == 0 ? "a" : x; }
+ function string_string_to_string(string memory x, string memory y) internal pure returns (string memory) { return bytes(x).length == 0 ? y : x; }
+ function uint256_string_to_string(uint256 x, string memory y) internal pure returns (string memory) { return x == 0 ? "a" : y; }
+
+ function tests() internal pure
+ {
+ function (uint256) internal pure returns (uint256) var_uint256_to_uint256 = uint256_to_string;
+ function (uint256) internal pure returns (string memory) var_uint256_to_string = uint256_to_string_storage;
+ function (string memory) internal pure returns (uint256) var_string_to_uint256 = uint256_to_string;
+ function (string memory) internal pure returns (string memory) var_string_to_string = var_uint256_to_string;
+
+ function (uint256, uint256) internal pure returns (uint256) var_uint256_uint256_to_uint256 = uint256_to_uint256;
+ function (string memory, uint256) internal pure returns (string memory) var_string_uint256_to_string = string_to_string;
+ function (string memory, string memory) internal pure returns (string memory) var_string_string_to_string = string_to_string;
+
+ var_uint256_to_uint256(1);
+ var_uint256_to_string(2);
+ var_string_to_uint256("a");
+ var_string_to_string("b");
+ var_uint256_uint256_to_uint256(3, 4);
+ var_string_uint256_to_string("c", 7);
+ var_string_string_to_string("d", "e");
+ }
+}
+// ----
+// TypeError: (1218-1311): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (uint256) pure returns (uint256).
+// TypeError: (1319-1425): Type function (uint256) pure returns (string storage pointer) is not implicitly convertible to expected type function (uint256) pure returns (string memory).
+// TypeError: (1433-1531): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (uint256).
+// TypeError: (1539-1646): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (string memory).
+// TypeError: (1655-1766): Type function (uint256) pure returns (uint256) is not implicitly convertible to expected type function (uint256,uint256) pure returns (uint256).
+// TypeError: (1774-1893): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,uint256) pure returns (string memory).
+// TypeError: (1901-2025): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,string memory) pure returns (string memory).
diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol
new file mode 100644
index 00000000..f750632e
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol
@@ -0,0 +1,39 @@
+contract Test
+{
+ function uint256_to_uint256(uint256 x) internal pure returns (uint256) { return x; }
+ function uint256_to_string(uint256 x) internal pure returns (string memory) { return x == 0 ? "a" : "b"; }
+ function string_to_uint256(string memory x) internal pure returns (uint256) { return bytes(x).length; }
+ function string_to_string(string memory x) internal pure returns (string memory) { return x; }
+
+ function uint256_uint256_to_uint256(uint256 x, uint256 y) internal pure returns (uint256) { return x + y; }
+ function uint256_uint256_to_string(uint256 x, uint256 y) internal pure returns (string memory) { return x == y ? "a" : "b"; }
+ function string_uint256_to_string(string memory x, uint256 y) internal pure returns (string memory) { return y == 0 ? "a" : x; }
+ function string_string_to_string(string memory x, string memory y) internal pure returns (string memory) { return bytes(x).length == 0 ? y : x; }
+ function uint256_string_to_string(uint256 x, string memory y) internal pure returns (string memory) { return x == 0 ? "a" : y; }
+
+ function tests() internal pure
+ {
+ function (uint256) internal pure returns (uint256) var_uint256_to_uint256 = uint256_to_uint256;
+ function (uint256) internal pure returns (string memory) var_uint256_to_string = uint256_to_string;
+ function (string memory) internal pure returns (uint256) var_string_to_uint256 = string_to_uint256;
+ function (string memory) internal pure returns (string memory) var_string_to_string = string_to_string;
+
+ function (uint256, uint256) internal pure returns (uint256) var_uint256_uint256_to_uint256 = uint256_uint256_to_uint256;
+ function (uint256, uint256) internal pure returns (string memory) var_uint256_uint256_to_string = uint256_uint256_to_string;
+ function (string memory, uint256) internal pure returns (string memory) var_string_uint256_to_string = string_uint256_to_string;
+ function (string memory, string memory) internal pure returns (string memory) var_string_string_to_string = string_string_to_string;
+ function (uint256, string memory) internal pure returns (string memory) var_uint256_string_to_string = uint256_string_to_string;
+
+ // Avoid unused variable warnings:
+ var_uint256_to_uint256(1);
+ var_uint256_to_string(2);
+ var_string_to_uint256("a");
+ var_string_to_string("b");
+ var_uint256_uint256_to_uint256(3, 4);
+ var_uint256_uint256_to_string(5, 6);
+ var_string_uint256_to_string("c", 7);
+ var_string_string_to_string("d", "e");
+ var_uint256_string_to_string(8, "f");
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol
new file mode 100644
index 00000000..818d7840
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol
@@ -0,0 +1,51 @@
+contract Test
+{
+ function internalPureFunc(uint256 x) internal pure returns (uint256) { return x; }
+ function internalViewFunc(uint256 x) internal view returns (uint256) { return x; }
+ function internalMutableFunc(uint256 x) internal returns (uint256) { return x; }
+
+ function externalPureFunc(uint256 x) external pure returns (uint256) { return x; }
+ function externalViewFunc(uint256 x) external view returns (uint256) { return x; }
+ function externalPayableFunc(uint256 x) external payable returns (uint256) { return x; }
+ function externalMutableFunc(uint256 x) external returns (uint256) { return x; }
+
+ function funcTakesInternalPure(function(uint256) internal pure returns(uint256) a) internal returns (uint256) { return a(4); }
+ function funcTakesInternalView(function(uint256) internal view returns(uint256) a) internal returns (uint256) { return a(4); }
+ function funcTakesInternalMutable(function(uint256) internal returns(uint256) a) internal returns (uint256) { return a(4); }
+
+ function funcTakesExternalPure(function(uint256) external pure returns(uint256) a) internal returns (uint256) { return a(4); }
+ function funcTakesExternalView(function(uint256) external view returns(uint256) a) internal returns (uint256) { return a(4); }
+ function funcTakesExternalPayable(function(uint256) external payable returns(uint256) a) internal returns (uint256) { return a(4); }
+ function funcTakesExternalMutable(function(uint256) external returns(uint256) a) internal returns (uint256) { return a(4); }
+
+ function tests() internal
+ {
+ funcTakesInternalPure(internalViewFunc); // view -> pure should fail
+ funcTakesInternalPure(internalMutableFunc); // mutable -> pure should fail
+
+ funcTakesInternalView(internalMutableFunc); // mutable -> view should fail
+
+ funcTakesExternalPure(this.externalViewFunc); // view -> pure should fail
+ funcTakesExternalPure(this.externalPayableFunc); // payable -> pure should fail
+ funcTakesExternalPure(this.externalMutableFunc); // mutable -> pure should fail
+
+ funcTakesExternalView(this.externalPayableFunc); // payable -> view should fail
+ funcTakesExternalView(this.externalMutableFunc); // mutable -> view should fail
+
+ funcTakesExternalPayable(this.externalPureFunc); // pure -> payable should fail
+ funcTakesExternalPayable(this.externalViewFunc); // view -> payable should fail
+ funcTakesExternalPayable(this.externalMutableFunc); // mutable -> payable should fail
+ }
+}
+// ----
+// TypeError: (1580-1596): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) view returns (uint256) to function (uint256) pure returns (uint256) requested.
+// TypeError: (1653-1672): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) pure returns (uint256) requested.
+// TypeError: (1733-1752): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) view returns (uint256) requested.
+// TypeError: (1813-1834): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) view external returns (uint256) to function (uint256) pure external returns (uint256) requested.
+// TypeError: (1891-1915): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) payable external returns (uint256) to function (uint256) pure external returns (uint256) requested.
+// TypeError: (1975-1999): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) external returns (uint256) to function (uint256) pure external returns (uint256) requested.
+// TypeError: (2060-2084): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) payable external returns (uint256) to function (uint256) view external returns (uint256) requested.
+// TypeError: (2144-2168): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) external returns (uint256) to function (uint256) view external returns (uint256) requested.
+// TypeError: (2232-2253): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) pure external returns (uint256) to function (uint256) payable external returns (uint256) requested.
+// TypeError: (2316-2337): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) view external returns (uint256) to function (uint256) payable external returns (uint256) requested.
+// TypeError: (2400-2424): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) external returns (uint256) to function (uint256) payable external returns (uint256) requested.
diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol
new file mode 100644
index 00000000..4ee515fc
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol
@@ -0,0 +1,46 @@
+contract Test
+{
+ uint y;
+ function internalPureFunc(uint256 x) internal pure returns (uint256) { return x; }
+ function internalViewFunc(uint256 x) internal view returns (uint256) { return x + y; }
+ function internalMutableFunc(uint256 x) internal returns (uint256) { y = x; return x; }
+
+ function externalPureFunc(uint256 x) external pure returns (uint256) { return x; }
+ function externalViewFunc(uint256 x) external view returns (uint256) { return x + y; }
+ function externalPayableFunc(uint256 x) external payable returns (uint256) { return x + y; }
+ function externalMutableFunc(uint256 x) external returns (uint256) { y = x; return x; }
+
+ function funcTakesInternalPure(function(uint256) internal pure returns(uint256) a) internal pure returns (uint256) { return a(4); }
+ function funcTakesInternalView(function(uint256) internal view returns(uint256) a) internal view returns (uint256) { return a(4); }
+ function funcTakesInternalMutable(function(uint256) internal returns(uint256) a) internal returns (uint256) { return a(4); }
+
+ function funcTakesExternalPure(function(uint256) external pure returns(uint256) a) internal pure returns (uint256) { return a(4); }
+ function funcTakesExternalView(function(uint256) external view returns(uint256) a) internal view returns (uint256) { return a(4); }
+ function funcTakesExternalPayable(function(uint256) external payable returns(uint256) a) internal returns (uint256) { return a(4); }
+ function funcTakesExternalMutable(function(uint256) external returns(uint256) a) internal returns (uint256) { return a(4); }
+
+ function tests() internal
+ {
+ funcTakesInternalPure(internalPureFunc);
+
+ funcTakesInternalView(internalPureFunc);
+ funcTakesInternalView(internalViewFunc);
+
+ funcTakesInternalMutable(internalPureFunc);
+ funcTakesInternalMutable(internalViewFunc);
+ funcTakesInternalMutable(internalMutableFunc);
+
+ funcTakesExternalPure(this.externalPureFunc);
+
+ funcTakesExternalView(this.externalPureFunc);
+ funcTakesExternalView(this.externalViewFunc);
+
+ funcTakesExternalPayable(this.externalPayableFunc);
+
+ funcTakesExternalMutable(this.externalPureFunc);
+ funcTakesExternalMutable(this.externalViewFunc);
+ funcTakesExternalMutable(this.externalPayableFunc);
+ funcTakesExternalMutable(this.externalMutableFunc);
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_explicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_explicit.sol
new file mode 100644
index 00000000..e1e9850d
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_explicit.sol
@@ -0,0 +1,31 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = bytes1(0x1);
+ bytes1 b2 = bytes1(0x100);
+ bytes2 b3 = bytes2(0xFF);
+ bytes2 b4 = bytes2(0x100);
+ bytes2 b5 = bytes2(0x10000);
+ bytes3 b6 = bytes3(0xFFFF);
+ bytes3 b7 = bytes3(0x10000);
+ bytes3 b8 = bytes3(0x1000000);
+ bytes4 b9 = bytes4(0xFFFFFF);
+ bytes4 b10 = bytes4(0x1000000);
+ bytes4 b11 = bytes4(0x100000000);
+ bytes16 b12 = bytes16(0x1);
+ bytes32 b13 = bytes32(0x1);
+ }
+}
+// ----
+// TypeError: (60-71): Explicit type conversion not allowed from "int_const 1" to "bytes1".
+// TypeError: (90-103): Explicit type conversion not allowed from "int_const 256" to "bytes1".
+// TypeError: (122-134): Explicit type conversion not allowed from "int_const 255" to "bytes2".
+// TypeError: (153-166): Explicit type conversion not allowed from "int_const 256" to "bytes2".
+// TypeError: (185-200): Explicit type conversion not allowed from "int_const 65536" to "bytes2".
+// TypeError: (219-233): Explicit type conversion not allowed from "int_const 65535" to "bytes3".
+// TypeError: (252-267): Explicit type conversion not allowed from "int_const 65536" to "bytes3".
+// TypeError: (286-303): Explicit type conversion not allowed from "int_const 16777216" to "bytes3".
+// TypeError: (322-338): Explicit type conversion not allowed from "int_const 16777215" to "bytes4".
+// TypeError: (358-375): Explicit type conversion not allowed from "int_const 16777216" to "bytes4".
+// TypeError: (395-414): Explicit type conversion not allowed from "int_const 4294967296" to "bytes4".
+// TypeError: (435-447): Explicit type conversion not allowed from "int_const 1" to "bytes16".
+// TypeError: (468-480): Explicit type conversion not allowed from "int_const 1" to "bytes32".
diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_implicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_implicit.sol
new file mode 100644
index 00000000..44ed9318
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_different_size_implicit.sol
@@ -0,0 +1,31 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = 0x1;
+ bytes1 b2 = 0x100;
+ bytes2 b3 = 0xFF;
+ bytes2 b4 = 0x100;
+ bytes2 b5 = 0x10000;
+ bytes3 b6 = 0xFFFF;
+ bytes3 b7 = 0x10000;
+ bytes3 b8 = 0x1000000;
+ bytes4 b9 = 0xFFFFFF;
+ bytes4 b10 = 0x1000000;
+ bytes4 b11 = 0x100000000;
+ bytes16 b12 = 0x1;
+ bytes32 b13 = 0x1;
+ }
+}
+// ----
+// TypeError: (48-63): Type int_const 1 is not implicitly convertible to expected type bytes1.
+// TypeError: (70-87): Type int_const 256 is not implicitly convertible to expected type bytes1.
+// TypeError: (94-110): Type int_const 255 is not implicitly convertible to expected type bytes2.
+// TypeError: (117-134): Type int_const 256 is not implicitly convertible to expected type bytes2.
+// TypeError: (141-160): Type int_const 65536 is not implicitly convertible to expected type bytes2.
+// TypeError: (167-185): Type int_const 65535 is not implicitly convertible to expected type bytes3.
+// TypeError: (192-211): Type int_const 65536 is not implicitly convertible to expected type bytes3.
+// TypeError: (218-239): Type int_const 16777216 is not implicitly convertible to expected type bytes3.
+// TypeError: (246-266): Type int_const 16777215 is not implicitly convertible to expected type bytes4.
+// TypeError: (273-295): Type int_const 16777216 is not implicitly convertible to expected type bytes4.
+// TypeError: (302-326): Type int_const 4294967296 is not implicitly convertible to expected type bytes4.
+// TypeError: (333-350): Type int_const 1 is not implicitly convertible to expected type bytes16.
+// TypeError: (357-374): Type int_const 1 is not implicitly convertible to expected type bytes32.
diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_explicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_explicit.sol
new file mode 100644
index 00000000..4e18640c
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_explicit.sol
@@ -0,0 +1,13 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = bytes1(0x01);
+ bytes1 b2 = bytes1(0xFF);
+ bytes2 b3 = bytes2(0x0100);
+ bytes2 b4 = bytes2(0xFFFF);
+ bytes3 b5 = bytes3(0x010000);
+ bytes3 b6 = bytes3(0xFFFFFF);
+ bytes4 b7 = bytes4(0x01000000);
+ bytes4 b8 = bytes4(0xFFFFFFFF);
+ b1; b2; b3; b4; b5; b6; b7; b8;
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_implicit.sol b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_implicit.sol
new file mode 100644
index 00000000..daf0bf56
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/hex_literal_to_bytesXX_same_size_implicit.sol
@@ -0,0 +1,13 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = 0x01;
+ bytes1 b2 = 0xFF;
+ bytes2 b3 = 0x0100;
+ bytes2 b4 = 0xFFFF;
+ bytes3 b5 = 0x010000;
+ bytes3 b6 = 0xFFFFFF;
+ bytes4 b7 = 0x01000000;
+ bytes4 b8 = 0xFFFFFFFF;
+ b1; b2; b3; b4; b5; b6; b7; b8;
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol
new file mode 100644
index 00000000..0354893f
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol
@@ -0,0 +1,7 @@
+contract C {
+ function f(mapping(uint => uint) storage) external pure {
+ }
+}
+// ----
+// TypeError: (28-49): Type is required to live outside storage.
+// TypeError: (28-49): Internal or recursive type is not allowed for public or external functions.
diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol
new file mode 100644
index 00000000..3c021515
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol
@@ -0,0 +1,5 @@
+contract C {
+ function f(mapping(uint => uint) storage) internal pure {
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol
new file mode 100644
index 00000000..63733d71
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol
@@ -0,0 +1,5 @@
+contract C {
+ function f(mapping(uint => uint) storage) private pure {
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol
new file mode 100644
index 00000000..e4121c7f
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol
@@ -0,0 +1,7 @@
+contract C {
+ function f(mapping(uint => uint) storage) public pure {
+ }
+}
+// ----
+// TypeError: (28-49): Type is required to live outside storage.
+// TypeError: (28-49): Internal or recursive type is not allowed for public or external functions.
diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol
new file mode 100644
index 00000000..8dea6907
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol
@@ -0,0 +1,6 @@
+contract C {
+ function f(mapping(uint => uint)[] storage) external pure {
+ }
+}
+// ----
+// TypeError: (28-51): Location has to be calldata for external functions (remove the "memory" or "storage" keyword).
diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol
new file mode 100644
index 00000000..352d0982
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol
@@ -0,0 +1,5 @@
+contract C {
+ function f(mapping(uint => uint)[] storage) internal pure {
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol
new file mode 100644
index 00000000..332dbe6c
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol
@@ -0,0 +1,5 @@
+contract C {
+ function f(mapping(uint => uint)[] storage) private pure {
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol
new file mode 100644
index 00000000..69dcec01
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol
@@ -0,0 +1,6 @@
+contract C {
+ function f(mapping(uint => uint)[] storage) public pure {
+ }
+}
+// ----
+// TypeError: (28-51): Location has to be memory for publicly visible functions (remove the "storage" or "calldata" keyword).
diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol
new file mode 100644
index 00000000..7fe74fb6
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol
@@ -0,0 +1,6 @@
+contract C {
+ function f(function(mapping(uint=>uint) storage) external) public pure {
+ }
+}
+// ----
+// TypeError: (37-56): Internal type cannot be used for external function type.
diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol
new file mode 100644
index 00000000..01e2322e
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol
@@ -0,0 +1,4 @@
+contract C {
+ function f(function(mapping(uint=>uint) storage) internal) internal pure {
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol
new file mode 100644
index 00000000..f0f8dea6
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol
@@ -0,0 +1,6 @@
+contract C {
+ function f(function() external returns (mapping(uint=>uint) storage)) public pure {
+ }
+}
+// ----
+// TypeError: (57-76): Internal type cannot be used for external function type.
diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol
new file mode 100644
index 00000000..bd298e5d
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol
@@ -0,0 +1,4 @@
+contract C {
+ function f(function() internal returns (mapping(uint=>uint) storage)) internal pure {
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol
new file mode 100644
index 00000000..e78c6930
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol
@@ -0,0 +1,6 @@
+library L {
+ function f(mapping(uint => uint) storage) external pure {
+ }
+}
+// ----
+// TypeError: (27-48): Type is required to live outside storage.
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol
new file mode 100644
index 00000000..1228b6b6
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol
@@ -0,0 +1,4 @@
+library L {
+ function f(mapping(uint => uint) storage) internal pure {
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol
new file mode 100644
index 00000000..5eaff16b
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol
@@ -0,0 +1,4 @@
+library L {
+ function f(mapping(uint => uint) storage) private pure {
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol
new file mode 100644
index 00000000..56393b68
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol
@@ -0,0 +1,6 @@
+library L {
+ function f(mapping(uint => uint) storage) public pure {
+ }
+}
+// ----
+// TypeError: (27-48): Type is required to live outside storage.
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol
new file mode 100644
index 00000000..f5691675
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol
@@ -0,0 +1,6 @@
+library L {
+ function f(mapping(uint => uint)[] storage) external pure {
+ }
+}
+// ----
+// TypeError: (27-50): Type is required to live outside storage.
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol
new file mode 100644
index 00000000..55c1cea0
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol
@@ -0,0 +1,4 @@
+library L {
+ function f(mapping(uint => uint)[] storage) internal pure {
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol
new file mode 100644
index 00000000..d37d6504
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol
@@ -0,0 +1,4 @@
+library L {
+ function f(mapping(uint => uint)[] storage) private pure {
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol
new file mode 100644
index 00000000..bb06d4bc
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol
@@ -0,0 +1,6 @@
+library L {
+ function f(mapping(uint => uint)[] storage) public pure {
+ }
+}
+// ----
+// TypeError: (27-50): Type is required to live outside storage.
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol
new file mode 100644
index 00000000..a3bb1c32
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol
@@ -0,0 +1,10 @@
+library L
+{
+ function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) external pure returns(mapping(uint => uint) storage) {
+ return c ? a : b;
+ }
+}
+// ----
+// TypeError: (27-58): Type is required to live outside storage.
+// TypeError: (60-91): Type is required to live outside storage.
+// TypeError: (123-144): Type is required to live outside storage.
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol
new file mode 100644
index 00000000..d0fca6bf
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol
@@ -0,0 +1,6 @@
+library L
+{
+ function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint => uint) storage) {
+ return c ? a : b;
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol
new file mode 100644
index 00000000..13c2000f
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol
@@ -0,0 +1,6 @@
+library L
+{
+ function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) private pure returns(mapping(uint => uint) storage) {
+ return c ? a : b;
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol
new file mode 100644
index 00000000..ac52d677
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol
@@ -0,0 +1,10 @@
+library L
+{
+ function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) public pure returns(mapping(uint => uint) storage) {
+ return c ? a : b;
+ }
+}
+// ----
+// TypeError: (27-58): Type is required to live outside storage.
+// TypeError: (60-91): Type is required to live outside storage.
+// TypeError: (121-142): Type is required to live outside storage.
diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol
new file mode 100644
index 00000000..dbe030fb
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol
@@ -0,0 +1,6 @@
+contract C {
+ function f() external pure returns (mapping(uint=>uint)[] storage m) {
+ }
+}
+// ----
+// TypeError: (53-84): Location has to be memory for publicly visible functions (remove the "storage" or "calldata" keyword).
diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol
new file mode 100644
index 00000000..8837c745
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol
@@ -0,0 +1,16 @@
+contract C {
+ mapping(uint=>uint)[] m;
+ function f() internal view returns (mapping(uint=>uint)[] storage) {
+ return m;
+ }
+ function g() private view returns (mapping(uint=>uint)[] storage) {
+ return m;
+ }
+ function h() internal view returns (mapping(uint=>uint)[] storage r) {
+ r = m;
+ }
+ function i() private view returns (mapping(uint=>uint)[] storage r) {
+ (r,r) = (m,m);
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol
new file mode 100644
index 00000000..7dfecf19
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol
@@ -0,0 +1,6 @@
+contract C {
+ function f() public pure returns (mapping(uint=>uint)[] storage m) {
+ }
+}
+// ----
+// TypeError: (51-82): Location has to be memory for publicly visible functions (remove the "storage" or "calldata" keyword).
diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol
index a46003f8..4912836e 100644
--- a/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol
+++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol
@@ -1,4 +1,3 @@
-// This should be allowed in a future release.
contract C {
mapping(uint=>uint) m;
function f() internal view returns (mapping(uint=>uint) storage) {
@@ -15,7 +14,3 @@ contract C {
}
}
// ----
-// TypeError: (127-146): Type is required to live outside storage.
-// TypeError: (221-240): Type is required to live outside storage.
-// TypeError: (316-345): Type is required to live outside storage.
-// TypeError: (409-438): Type is required to live outside storage.
diff --git a/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol
new file mode 100644
index 00000000..66bd9a8e
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol
@@ -0,0 +1,4 @@
+contract C {
+ fixed8x80 a = -1e-100;
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_explicit.sol b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_explicit.sol
new file mode 100644
index 00000000..5d606089
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_explicit.sol
@@ -0,0 +1,30 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = bytes1(0);
+ bytes2 b2 = bytes2(0);
+ bytes3 b3 = bytes3(0);
+ bytes4 b4 = bytes4(0);
+ bytes8 b8 = bytes8(0);
+ bytes16 b16 = bytes16(0);
+ bytes32 b32 = bytes32(0);
+ b1; b2; b3; b4; b8; b16; b32;
+ }
+ function g() public pure {
+ bytes1 b1 = bytes1(0x000);
+ bytes2 b2 = bytes2(0x00000);
+ bytes3 b3 = bytes3(0x0000000);
+ bytes4 b4 = bytes4(0x000000000);
+ bytes8 b8 = bytes8(0x00000000000000000);
+ b1; b2; b3; b4; b8;
+ }
+ function h() public pure {
+ bytes1 b1 = bytes1(0x0);
+ bytes2 b2 = bytes2(0x0);
+ bytes3 b3 = bytes3(0x0);
+ bytes4 b4 = bytes4(0x0);
+ bytes8 b8 = bytes8(0x0);
+ bytes16 b16 = bytes16(0x0);
+ bytes32 b32 = bytes32(0x0);
+ b1; b2; b3; b4; b8; b16; b32;
+ }
+}
diff --git a/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_implicit.sol b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_implicit.sol
new file mode 100644
index 00000000..48be0655
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/zero_literal_to_bytesXX_implicit.sol
@@ -0,0 +1,30 @@
+contract C {
+ function f() public pure {
+ bytes1 b1 = 0;
+ bytes2 b2 = 0;
+ bytes3 b3 = 0;
+ bytes4 b4 = 0;
+ bytes8 b8 = 0;
+ bytes16 b16 = 0;
+ bytes32 b32 = 0;
+ b1; b2; b3; b4; b8; b16; b32;
+ }
+ function g() public pure {
+ bytes1 b1 = 0x000;
+ bytes2 b2 = 0x00000;
+ bytes3 b3 = 0x0000000;
+ bytes4 b4 = 0x000000000;
+ bytes8 b8 = 0x00000000000000000;
+ b1; b2; b3; b4; b8;
+ }
+ function h() public pure {
+ bytes1 b1 = 0x0;
+ bytes2 b2 = 0x0;
+ bytes3 b3 = 0x0;
+ bytes4 b4 = 0x0;
+ bytes8 b8 = 0x0;
+ bytes16 b16 = 0x0;
+ bytes32 b32 = 0x0;
+ b1; b2; b3; b4; b8; b16; b32;
+ }
+}
diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol
index 51e36a58..2cb185c9 100644
--- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol
+++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol
@@ -9,7 +9,7 @@ contract C {
function g() pure public {
bytes32 x = keccak256("abc");
bytes32 y = sha256("abc");
- address z = ecrecover(bytes32(1), uint8(2), bytes32(3), bytes32(4));
+ address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4)));
require(true);
assert(true);
x; y; z;
diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol
index 0b834022..4a651d21 100644
--- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol
+++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_restrict_warning.sol
@@ -2,7 +2,7 @@ contract C {
function f() view public {
bytes32 x = keccak256("abc");
bytes32 y = sha256("abc");
- address z = ecrecover(bytes32(1), uint8(2), bytes32(3), bytes32(4));
+ address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4)));
require(true);
assert(true);
x; y; z;
@@ -10,12 +10,12 @@ contract C {
function g() public {
bytes32 x = keccak256("abc");
bytes32 y = sha256("abc");
- address z = ecrecover(bytes32(1), uint8(2), bytes32(3), bytes32(4));
+ address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4)));
require(true);
assert(true);
x; y; z;
}
}
// ----
-// Warning: (17-261): Function state mutability can be restricted to pure
-// Warning: (266-505): Function state mutability can be restricted to pure
+// Warning: (17-288): Function state mutability can be restricted to pure
+// Warning: (293-559): Function state mutability can be restricted to pure