mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
050 breaking changes in docs
This commit is contained in:
parent
63c6007012
commit
13d8645506
406
docs/050-breaking-changes.rst
Normal file
406
docs/050-breaking-changes.rst
Normal file
@ -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 <https://github.com/ethereum/solidity/releases/tag/v0.5.0>`_.
|
||||
|
||||
.. 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));
|
||||
}
|
||||
}
|
@ -18,3 +18,4 @@ If something is missing here, please contact us on
|
||||
contracts.rst
|
||||
assembly.rst
|
||||
miscellaneous.rst
|
||||
050-breaking-changes.rst
|
||||
|
Loading…
Reference in New Issue
Block a user