From 13d8645506e8c934e814e0909deb8aec94be7010 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Tue, 4 Sep 2018 12:46:59 +0200 Subject: [PATCH] 050 breaking changes in docs --- docs/050-breaking-changes.rst | 406 ++++++++++++++++++++++++++++++++++ docs/solidity-in-depth.rst | 1 + 2 files changed, 407 insertions(+) create mode 100644 docs/050-breaking-changes.rst diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst new file mode 100644 index 000000000..a28cc5baf --- /dev/null +++ b/docs/050-breaking-changes.rst @@ -0,0 +1,406 @@ +******************************** +Solidity v0.5.0 Breaking Changes +******************************** + +This section highlights the main breaking changes introduced in Solidity +version 0.5.0, along with the reasoning behind the changes and how to update +affected code. +For the full list check +`the release changelog `_. + +.. note:: + Contracts compiled with Solidity v0.5.0 can still interface with contracts + and even libraries compiled with older versions without recompiling or + redeploying them. Changing the interfaces to include data locations and + visibility and mutability specifiers suffices. + +Semantic Only Changes +===================== + +This section lists the changes that are semantic-only, thus potentially +hiding new and different behavior in existing code. + +* Signed right shift now uses proper arithmetic shift, i.e. rounding towards + negative infinity, instead of rounding towards zero. Signed and unsigned + shift will have dedicated opcodes in Constantinople, and are emulated by + Solidity for the moment. + +* The ``continue`` statement in a ``do...while`` loop now jumps to the + condition, which is the common behavior in such cases. It used to jump to the + loop body. Thus, if the condition is false, the loop terminates. + +* The functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` do not + pad anymore when given a single ``bytes`` parameter. + +* Pure and view functions are now called using the opcode ``STATICCALL`` + instead of ``CALL`` if the EVM version is Byzantium or later. This + disallows state changes on the EVM level. + +* The ABI encoder now properly pads byte arrays and strings from calldata + (``msg.data`` and external function parameters) when used in external + function calls and in ``abi.encode``. For unpadded encoding, use + ``abi.encodePacked``. + +* The ABI decoder reverts in the beginning of functions and in + ``abi.decode()`` if passed calldata is too short or points out of bounds. + Note that dirty higher order bits are still simply ignored. + +* Forward all available gas with external function calls starting from + tangerine whistle. + +Semantic and Syntactic Changes +============================== + +This section highlights changes that affect syntax and semantics. + +* The functions ``.call()``, ``.delegatecall()`, ``staticcall()``, + ``keccak256()``, ``sha256()`` and ``ripemd160()`` now accept only a single + ``bytes`` argument. Moreover, the argument is not padded. This was changed to + make more explicit and clear how the arguments are concatenated. Change every + ``.call()`` (and family) to a ``.call("")`` and every ``.call(signature, a, + b, c)`` to use ``.call(abi.encodeWithSignature(signature, a, b, c))`` (the + last one only works for value types). Change every ``keccak256(a, b, c)`` to + ``keccak256(abi.encodePacked(a, b, c))``. Even though it is not a breaking + change, it is suggested that developers change + ``x.call(bytes4(keccak256("f(uint256)"), a, b)`` to + ``x.call(abi.encodeWithSignature("f(uint256)", a, b))``. + +* Functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` now return + ``(bool, bytes memory)`` to provide access to the return data. Change + ``bool success = otherContract.call("f")`` to ``(bool success, bytes memory + data) = otherContract.call("f")``. + +* Solidity now implements C99-style scoping rules for function local + variables, that is, variables can only be used after they have been + declared and only in the same or nested scopes. Variables declared in the + initialization block of a ``for`` loop are valid at any point inside the + loop. + +Explicitness Requirements +========================= + +This section lists changes where the code now needs to be more explicit. +For most of the topics the compiler will provide suggestions. + +* Explicit function visibility is now mandatory. Add ``public`` to every + function and constructor, and ``external`` to every fallback or interface + function that does not specify its visibility already. + +* Explicit data location for all variables of struct, array or mapping types is + now mandatory. This is also applied to function parameters and return + variables. For example, change ``uint[] x = m_x`` to ``uint[] storage x = + m_x``, and ``function f(uint[][] x)`` to ``function f(uint[][] memory x)`` + where ``memory`` is the data location and might be replaced by ``storage`` or + ``calldata`` accordingly. Note that ``external`` functions require + parameters with a data location of ``calldata``. + +* Contract types do not include ``address`` members anymore in + order to separate the namespaces. Therefore, it is now necessary to + explicitly convert values of contract type to addresses before using an + ``address`` member. Example: if ``c`` is a contract, change + ``c.transfer(...)`` to ``address(c).transfer(...)``, + and ``c.balance`` to ``address(c).balance``. + +* The ``address`` type was split into ``address`` and ``address payable``, + where only ``address payable`` provides the ``transfer`` function. An + ``address payable`` can be directly converted to an ``address``, but the + other way around is not allowed. Converting ``address`` to ``address + payable`` is possible via conversion through ``uint160``. If ``c`` is + a contract, ``address(c)`` results in ``address payable`` if ``c`` has a + payable fallback function. + +* Conversions between ``bytesX`` and ``uintY`` of different size are now + disallowed due to ``bytesX`` padding on the right and ``uintY`` padding on + the left which may cause unexpected conversion results. The size must now be + adjusted within the type before the conversion. For example, you can convert + a ``bytes4`` (4 bytes) to a ``uint64`` (8 bytes) by first converting the + ``bytes4`` variable to ``bytes8`` and then to ``uint64``. You get the + opposite padding when converting through ``uint32``. + +* Using ``msg.value`` in non-payable functions (or introducing it via a + modifier) is disallowed as a security feature. Turn the function into + ``payable`` or create a new internal function for the program logic that + uses ``msg.value``. + +* For clarity reasons, the command line interface now requires ``-`` if the + standard input is used as source. + +Deprecated Elements +=================== + +This section lists changes that deprecate prior features or syntax. Note that +many of these changes were already enabled in the experimental mode +``v0.5.0``. + +Command Line and JSON Interfaces +-------------------------------- + +* The command line option ``--formal`` (used to generate Why3 output for + further formal verification) was deprecated and is now removed. A new + formal verification module, the SMTChecker, is enabled via ``pragma + experimental SMTChecker;``. + +* The command line option ``--julia`` was renamed to ``--yul`` due to the + renaming of the intermediate language ``Julia`` to ``Yul``. + +* The ``--clone-bin`` and ``--combined-json clone-bin`` command line options + were removed. + +* Remappings with empty prefix are disallowed. + +* The Json AST fields ``constant`` and ``payable`` were removed. The + information is now present in the ``stateMutability`` field. + +Constructors +------------ + +* Constructors must now be defined using the ``constructor`` keyword. + +* Calling base constructors without parentheses is now disallowed. + +* Specifying base constructor arguments multiple times in the same inheritance + hierarchy is now disallowed. + +* Calling a constructor with arguments but with wrong argument count is now + disallowed. If you only want to specify an inheritance relation without + giving arguments, do not provide parentheses at all. + +Functions +--------- + +* Function ``callcode`` is now disallowed (in favor of ``delegatecall``). It + is still possible to use it via inline assembly. + +* ``suicide`` is now disallowed (in favor of ``selfdestruct``). + +* ``sha3`` is now disallowed (in favor of ``keccak256``). + +* ``throw`` is now disallowed (in favor of ``revert``, ``require`` and + ``assert``). + +Conversions +----------- + +* Explicit and implicit conversions from decimal literals to ``bytesXX`` types + is now disallowed. + +* Explicit and implicit conversions from hex literals to ``bytesXX`` types + of different size is now disallowed. + +Literals and Suffixes +--------------------- + +* The unit denomination ``years`` is now disallowed due to complications and + confusions about leap years. + +* Trailing dots that are not followed by a number are now disallowed. + +* Combining hex numbers with unit denominations (e.g. ``0x1e wei``) is now + disallowed. + +Variables +--------- + +* Declaring empty structs is now disallowed for clarity. + +* The ``var`` keyword is now disallowed to favor explicitness. + +* Assignments between tuples with different number of components is now + disallowed. + +* Values for constants that are not compile-time constants are disallowed. + +* Multi-variable declarations with mismatching number of values are now + disallowed. + +* Uninitialized storage variables are now disallowed. + +* Empty tuple components are now disallowed. + +* Detecting cyclic dependencies in variables and structs is limited in + recursion to 256. + +Syntax +------ + +* Using ``constant`` as function state mutability modifier is now disallowed. + +* Boolean expressions cannot use arithmetic operations. + +* The unary ``+`` operator is now disallowed. + +* Literals cannot anymore be used with ``abi.encodePacked`` without prior + conversion to an explicit type. + +* Empty return statements for functions with one or more return values are now + disallowed. + +* The "loose assembly" syntax is now disallowed entirely, that is, jump labels, + jumps and non-functional instructions cannot be used anymore. Use the new + ``while``, ``switch`` and ``if`` constructs instead. + +* Functions without implementation cannot use modifiers anymore. + +* Function types with named return values are now disallowed. + +* Single statement variable declarations inside if/while/for bodies that are + not blocks are now disallowed. + +* New keywords: ``calldata`` and ``constructor``. + +* New reserved keywords: ``alias``, ``apply``, ``auto``, ``copyof``, + ``define``, ``immutable``, ``implements``, ``macro``, ``mutable``, + ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, + ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. + +Example +======= + +The following example shows a contract and its updated version for Solidity +v0.5.0 with some of the changes listed in this section. + +Old version: + +:: + + // This will not compile + pragma solidity ^0.4.25; + + contract OtherContract { + uint x; + function f(uint y) external { + x = y; + } + function() payable external {} + } + + contract Old { + OtherContract other; + uint myNumber; + + // Function mutability not provided, not an error. + function someInteger() internal returns (uint) { return 2; } + + // Function visibility not provided, not an error. + // Function mutability not provided, not an error. + function f(uint x) returns (bytes) { + // Var is fine in this version. + var z = someInteger(); + x += z; + // Throw is fine in this version. + if (x > 100) + throw; + bytes b = new bytes(x); + y = -3 >> 1; + // y == -1 (wrong, should be -2) + do { + x += 1; + if (x > 10) continue; + // 'Continue' causes an infinite loop. + } while (x < 11); + // Call returns only a Bool. + bool success = address(other).call("f"); + if (!success) + revert(); + else { + // Local variables could be declared after their use. + int y; + } + return b; + } + + // No need for an explicit data location for 'arr' + function g(uint[] arr, bytes8 x, OtherContract otherContract) public { + otherContract.transfer(1 ether); + + // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes), + // the first 4 bytes of x will be lost. This might lead to + // unexpected behavior since bytesX are right padded. + uint32 y = uint32(x); + myNumber += y + msg.value; + } + } + +New version: + +:: + + pragma solidity >0.4.25; + + contract OtherContract { + uint x; + function f(uint y) external { + x = y; + } + function() payable external {} + } + + contract New { + OtherContract other; + uint myNumber; + + // Function mutability must be specified. + function someInteger() internal pure returns (uint) { return 2; } + + // Function visibility must be specified. + // Function mutability must be specified. + function f(uint x) public returns (bytes memory) { + // The type must now be explicitly given. + uint z = someInteger(); + x += z; + // Throw is now disallowed. + require(x > 100); + int y = -3 >> 1; + // y == -2 (correct) + do { + x += 1; + if (x > 10) continue; + // 'Continue' jumps to the condition below. + } while (x < 11); + + // Call returns (bool, bytes). + // Data location must be specified. + (bool success, bytes memory data) = address(other).call("f"); + if (!success) + revert(); + return data; + } + + using address_make_payable for address; + // Data location for 'arr' must be specified + function g(uint[] memory arr, bytes8 x, OtherContract otherContract, address unknownContract) public payable { + // 'otherContract.transfer' is not provided. + // Since the code of 'OtherContract' is known and has the fallback + // function, address(otherContract) has type 'address payable'. + address(otherContract).transfer(1 ether); + + // 'unknownContract.transfer' is not provided. + // 'address(unknownContract).transfer' is not provided + // since 'address(unknownContract)' is not 'address payable'. + // If the function takes an 'address' which you want to send + // funds to, you can convert it to 'address payable' via 'uint160'. + // Note: This is not recommended and the explicit type + // 'address payable' should be used whenever possible. + // To increase clarity, we suggest the use of a library for + // the conversion (provided after the contract in this example). + address payable addr = unknownContract.make_payable(); + require(addr.send(1 ether)); + + // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes), + // the conversion is not allowed. + // We need to convert to a common size first: + bytes4 x4 = bytes4(x); // Padding happens on the right + uint32 y = uint32(x4); // Conversion is consistent + // 'msg.value' cannot be used in a 'non-payable' function. + // We need to make the function payable + myNumber += y + msg.value; + } + } + + // We can define a library for explicitly converting ``address`` + // to ``address payable`` as a workaround. + library address_make_payable { + function make_payable(address x) internal pure returns (address payable) { + return address(uint160(x)); + } + } diff --git a/docs/solidity-in-depth.rst b/docs/solidity-in-depth.rst index 4a10a5a7d..ddfddb77b 100644 --- a/docs/solidity-in-depth.rst +++ b/docs/solidity-in-depth.rst @@ -18,3 +18,4 @@ If something is missing here, please contact us on contracts.rst assembly.rst miscellaneous.rst + 050-breaking-changes.rst