diff options
25 files changed, 366 insertions, 183 deletions
diff --git a/Changelog.md b/Changelog.md index 7443a0c6..21de2ce6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -41,6 +41,7 @@ Breaking Changes: * Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence. * Parser: Disallow trailing dots that are not followed by a number. * Parser: Remove ``constant`` as function state mutability modifier. + * Parser: Disallow uppercase X in hex number literals * Type Checker: Disallow assignments between tuples with different numbers of components. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow values for constants that are not compile-time constants. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow arithmetic operations for boolean variables. diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst index 7b5acd89..5a7add5d 100644 --- a/docs/050-breaking-changes.rst +++ b/docs/050-breaking-changes.rst @@ -198,6 +198,8 @@ Literals and Suffixes * Combining hex numbers with unit denominations (e.g. ``0x1e wei``) is now disallowed. +* The prefix ``0X`` for hex numbers is disallowed, only ``0x`` is possible. + Variables --------- diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 92af8f0c..4e7c88d0 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -78,8 +78,29 @@ Types can be combined to a tuple by enclosing them inside parentheses, separated It is possible to form tuples of tuples, arrays of tuples and so on. It is also possible to form zero-tuples (where ``n == 0``). -.. note:: - Solidity supports all the types presented above with the same names with the exception of tuples. The ABI tuple type is utilised for encoding Solidity ``structs``. +Mapping Solidity to ABI types +----------------------------- + +Solidity supports all the types presented above with the same names with the +exception of tuples. On the other hand, some Solidity types are not supported +by the ABI. The following table shows on the left column Solidity types that +are not part of the ABI, and on the right column the ABI types that represent +them. + ++-------------------------------+-----------------------------------------------------------------------------+ +| Solidity | ABI | ++===============================+=============================================================================+ +|:ref:`address payable<address>`|``address`` | ++-------------------------------+-----------------------------------------------------------------------------+ +|:ref:`contract<contracts>` |``address`` | ++-------------------------------+-----------------------------------------------------------------------------+ +|:ref:`enum<enums>` |smallest ``uint`` type that is large enough to hold all values | +| | | +| |For example, an ``enum`` of 255 values or less is mapped to ``uint8`` and | +| |an ``enum`` of 256 values is mapped to ``uint16``. | ++-------------------------------+-----------------------------------------------------------------------------+ +|:ref:`struct<structs>` |``tuple`` | ++-------------------------------+-----------------------------------------------------------------------------+ Formal Specification of the Encoding ==================================== diff --git a/docs/contributing.rst b/docs/contributing.rst index 6fe96be4..d1ed9c6b 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -19,6 +19,8 @@ In particular, we need help in the following areas: `up-for-grabs <https://github.com/ethereum/solidity/issues?q=is%3Aopen+is%3Aissue+label%3Aup-for-grabs>`_ which are meant as introductory issues for external contributors. +Please note that this project is released with a `Contributor Code of Conduct <https://raw.githubusercontent.com/ethereum/solidity/develop/CODE_OF_CONDUCT.md>`_. By participating in this project - in the issues, pull requests, or Gitter channels - you agree to abide by its terms. + How to Report Issues ==================== @@ -62,10 +64,6 @@ Finally, please make sure you respect the `coding style for this project. Also, even though we do CI testing, please test your code and ensure that it builds locally before submitting a pull request. -Please note that this project is released with a `Contributor Code of Conduct -<https://raw.githubusercontent.com/ethereum/solidity/develop/CODE_OF_CONDUCT.md>`_. -By participating in this project you agree to abide by its terms. - Thank you for your help! Running the compiler tests diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 745a0599..7c91cab7 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -385,6 +385,8 @@ In any case, you will get a warning about the outer variable being shadowed. .. index:: ! exception, ! throw, ! assert, ! require, ! revert +.. _assert-and-require: + Error handling: Assert, Require, Revert and Exceptions ====================================================== diff --git a/docs/grammar.txt b/docs/grammar.txt index 594998f0..b9c8ddb9 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -132,7 +132,7 @@ HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]* -HexNumber = '0' [xX] [0-9a-fA-F]+ +HexNumber = '0x' [0-9a-fA-F]+ DecimalNumber = [0-9]+ ( '.' [0-9]* )? ( [eE] [0-9]+ )? TupleExpression = '(' ( Expression? ( ',' Expression? )* )? ')' diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index bd30a8fd..5ba7ed12 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -220,7 +220,7 @@ Blockchain Basics Blockchains as a concept are not too hard to understand for programmers. The reason is that most of the complications (mining, `hashing <https://en.wikipedia.org/wiki/Cryptographic_hash_function>`_, `elliptic-curve cryptography <https://en.wikipedia.org/wiki/Elliptic_curve_cryptography>`_, `peer-to-peer networks <https://en.wikipedia.org/wiki/Peer-to-peer>`_, etc.) -are just there to provide a certain set of features and promises. Once you accept these +are just there to provide a certain set of features and promises for the platform. Once you accept these features as given, you do not have to worry about the underlying technology - or do you have to know how Amazon's AWS works internally in order to use it? @@ -235,7 +235,7 @@ If you want to change something in the database, you have to create a so-called which has to be accepted by all others. The word transaction implies that the change you want to make (assume you want to change two values at the same time) is either not done at all or completely applied. Furthermore, -while your transaction is applied to the database, no other transaction can alter it. +while your transaction is being applied to the database, no other transaction can alter it. As an example, imagine a table that lists the balances of all accounts in an electronic currency. If a transfer from one account to another is requested, @@ -254,12 +254,13 @@ only the person holding the keys to the account can transfer money from it. Blocks ====== -One major obstacle to overcome is what, in Bitcoin terms, is called a "double-spend attack": -What happens if two transactions exist in the network that both want to empty an account, -a so-called conflict? +One major obstacle to overcome is what (in Bitcoin terms) is called a "double-spend attack": +What happens if two transactions exist in the network that both want to empty an account? +Only one of the transactions can be valid, typically the one that is accepted first. +The problem is that "first" is not an objective term in a peer-to-peer network. -The abstract answer to this is that you do not have to care. An order of the transactions -will be selected for you, the transactions will be bundled into what is called a "block" +The abstract answer to this is that you do not have to care. A globally accepted order of the transactions +will be selected for you, solving the conflict. The transactions will be bundled into what is called a "block" and then they will be executed and distributed among all participating nodes. If two transactions contradict each other, the one that ends up being second will be rejected and not become part of the block. @@ -270,14 +271,16 @@ Ethereum this is roughly every 17 seconds. As part of the "order selection mechanism" (which is called "mining") it may happen that blocks are reverted from time to time, but only at the "tip" of the chain. The more -blocks that are added on top, the less likely it is. So it might be that your transactions +blocks are added on top of a particular block, the less likely this block will be reverted. So it might be that your transactions are reverted and even removed from the blockchain, but the longer you wait, the less likely it will be. .. note:: - Transactions are not guaranteed to happen on the next block or any future specific block, since it is up to the miners to include transactions and not the submitter of the transaction. This applies to function calls and contract creation transactions alike. + Transactions are not guaranteed to be included in the next block or any specific future block, + since it is not up to the submitter of a transaction, but up to the miners to determine in which block the transaction is included. - If you want to schedule future calls of your contract, you can use the `alarm clock <http://www.ethereum-alarm-clock.com/>`_ service. + If you want to schedule future calls of your contract, you can use + the `alarm clock <http://www.ethereum-alarm-clock.com/>`_ or a similar oracle service. .. _the-ethereum-virtual-machine: @@ -319,7 +322,7 @@ Every account has a persistent key-value store mapping 256-bit words to 256-bit words called **storage**. Furthermore, every account has a **balance** in -Ether (in "Wei" to be exact) which can be modified by sending transactions that +Ether (in "Wei" to be exact, `1 ether` is `10**18 wei`) which can be modified by sending transactions that include Ether. .. index:: ! transaction @@ -329,7 +332,7 @@ Transactions A transaction is a message that is sent from one account to another account (which might be the same or the special zero-account, see below). -It can include binary data (its payload) and Ether. +It can include binary data (which is called "payload") and Ether. If the target account contains code, that code is executed and the payload is provided as input data. @@ -340,7 +343,7 @@ As already mentioned, the address of that contract is not the zero address but an address derived from the sender and its number of transactions sent (the "nonce"). The payload of such a contract creation transaction is taken to be -EVM bytecode and executed. The output of this execution is +EVM bytecode and executed. The output data of this execution is permanently stored as the code of the contract. This means that in order to create a contract, you do not send the actual code of the contract, but in fact code that diff --git a/docs/types.rst b/docs/types.rst index de384e2f..b5e1daa0 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -137,15 +137,26 @@ Operators: Address ------- -``address``: Holds a 20 byte value (size of an Ethereum address). Address types also have members and serve as a base for all contracts. -``address payable``: Same as ``address``, but with the additional members ``transfer`` and ``send``. +The address type comes in two flavours, which are largely identical: + + - ``address``: Holds a 20 byte value (size of an Ethereum address). + - ``address payable``: Same as ``address``, but with the additional members ``transfer`` and ``send``. + +The idea behind this distinction is that ``address payable`` is an address you can send Ether to, +while a plain ``address`` cannot be sent Ether. + +Type conversions: Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable`` are not possible (the only way to perform such a conversion is by using an intermediate conversion to ``uint160``). + +:ref:`Address literals<address_literals>` can be implicitly converted to ``address payable``. + +Explicit conversions to and from ``address`` are allowed for integers, integer literals, ``bytes20`` and contract types with the following +caveat: Conversions of the form ``address payable(x)`` are not allowed. Instead the result of a conversion of the form ``address(x)`` has the type ``address payable``, if ``x`` is of integer or fixed bytes type, a literal or a contract with a payable fallback function. -If ``x`` is a contract without payable fallback function ``address(x)`` will be of type ``address``. The type of address literals -is ``address payable``. +If ``x`` is a contract without payable fallback function, then ``address(x)`` will be of type ``address``. In external function signatures ``address`` is used for both the ``address`` and the ``address payable`` type. Operators: @@ -161,7 +172,8 @@ Operators: or you can use ``address(uint160(uint256(b)))``, which results in ``0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc``. .. note:: - Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to + The distinction between ``address`` and ``address payable`` was introduced with version 0.5.0. + Also starting from that version, contracts do not derive from the address type, but can still be explicitly converted to ``address`` or to ``address payable``, if they have a payable fallback function. .. _members-of-addresses: @@ -169,9 +181,9 @@ Operators: Members of Addresses ^^^^^^^^^^^^^^^^^^^^ -* ``balance`` and ``transfer`` +For a quick reference of all members of address, see :ref:`address_related`. -For a quick reference, see :ref:`address_related`. +* ``balance`` and ``transfer`` It is possible to query the balance of an address using the property ``balance`` and to send Ether (in units of wei) to a payable address using the ``transfer`` function: @@ -179,9 +191,13 @@ and to send Ether (in units of wei) to a payable address using the ``transfer`` :: address payable x = address(0x123); - address myAddress = this; + address myAddress = address(this); if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); +The ``transfer`` function fails if the balance of the current contract is not large enough +or if the Ether transfer is rejected by the receiving account. The ``transfer`` function +reverts on failure. + .. note:: If ``x`` is a contract address, its code (more specifically: its :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. @@ -195,14 +211,23 @@ Send is the low-level counterpart of ``transfer``. If the execution fails, the c to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: use a pattern where the recipient withdraws the money. -* ``call``, ``callcode``, ``delegatecall`` and ``staticcall`` +* ``call``, ``delegatecall`` and ``staticcall`` -Furthermore, to interface with contracts that do not adhere to the ABI, +In order to interface with contracts that do not adhere to the ABI, or to get more direct control over the encoding, -the function ``call`` is provided which takes a single byte array as input. +the functions ``call``, ``delegatecall`` and ``staticcall`` are provided. +They all take a single ``bytes memory`` argument as input and +return the success condition (as a ``bool``) and the returned data +(``bytes memory``). The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` and ``abi.encodeWithSignature`` can be used to encode structured data. +Example:: + + bytes memory payload = abi.encodeWithSignature("register(string)", "MyName"); + (bool success, bytes memory returnData) = address(nameReg).call(payload); + require(success); + .. warning:: All these functions are low-level functions and should be used with care. Specifically, any unknown contract might be malicious and if you call it, you @@ -216,8 +241,6 @@ and ``abi.encodeWithSignature`` can be used to encode structured data. arbitrary arguments and would also handle a first argument of type ``bytes4`` differently. These edge cases were removed in version 0.5.0. -``call`` returns a boolean indicating whether the invoked function terminated (``true``) or caused an EVM exception (``false``). It is not possible to access the actual data returned with plain Solidity. However, using inline assembly it is possible to make a raw ``call`` and access the actual data returned with the ``returndatacopy`` instruction. - It is possible to adjust the supplied gas with the ``.gas()`` modifier:: namReg.call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); @@ -230,17 +253,14 @@ Lastly, these modifiers can be combined. Their order does not matter:: nameReg.call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); -.. note:: - It is not yet possible to use the gas or value modifiers on overloaded functions. - - A workaround is to introduce a special case for gas and value and just re-check - whether they are present at the point of overload resolution. +In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. -In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. +.. note:: + Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. This function was removed in version 0.5.0. -Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert, if the called function modifies the state in any way. +Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert if the called function modifies the state in any way. -All four functions ``call``, ``delegatecall``, ``callcode`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. +All three functions ``call``, ``delegatecall`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. The ``.gas()`` option is available on all three methods, while the ``.value()`` option is not supported for ``delegatecall``. @@ -248,9 +268,6 @@ The ``.gas()`` option is available on all three methods, while the ``.value()`` All contracts can be converted to ``address`` type, so it is possible to query the balance of the current contract using ``address(this).balance``. -.. note:: - The use of ``callcode`` is discouraged and will be removed in the future. - .. index:: ! contract type, ! type; contract .. _contract_types: @@ -259,15 +276,19 @@ Contract 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, if they have no -payable fallback functions, or to and from the ``address payable`` type, if they do -have payable fallback functions. +You can implicitly convert contracts to contracts they inherit from. +Contracts can be explicitly converted to and from all other contract types +and the ``address`` type. + +Explicit conversion to and from the ``address payable`` type +is only possible if the contract type has a payable fallback function. +The conversion is still performed using ``address(x)`` and not +using ``address payable(x)``. You can find more information in the section about +the :ref:`address type<address>`. .. note:: - Starting with version 0.5.0 contracts do not derive from the address type, - but can still be explicitly converted to ``address``, resp. to ``address payable``, - if they have a payable fallback function. + Before version 0.5.0, contracts directly derived from the address type + and there was no distinction between ``address`` and ``address payable``. If you declare a local variable of contract type (`MyContract c`), you can call functions on that contract. Take care to assign it from somewhere that is the @@ -290,25 +311,29 @@ including public state variables. Fixed-size byte arrays ---------------------- -``bytes1``, ``bytes2``, ``bytes3``, ..., ``bytes32``. ``byte`` is an alias for ``bytes1``. +The value types ``bytes1``, ``bytes2``, ``bytes3``, ..., ``bytes32`` +hold a sequence of bytes from one to up to 32. +``byte`` is an alias for ``bytes1``. Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) -* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift) +* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) +* Shift operators: ``<<`` (left shift), ``>>`` (right shift) * Index access: If ``x`` is of type ``bytesI``, then ``x[k]`` for ``0 <= k < I`` returns the ``k`` th byte (read-only). -The shifting operator works with any integer type as right operand (but will -return the type of the left operand), which denotes the number of bits to shift by. -Shifting by a negative amount will cause a runtime exception. +The shifting operator works with any integer type as right operand (but +returns the type of the left operand), which denotes the number of bits to shift by. +Shifting by a negative amount causes a runtime exception. Members: * ``.length`` yields the fixed length of the byte array (read-only). .. note:: - It is possible to use an array of bytes as ``byte[]``, but it is wasting a lot of space, 31 bytes every element, - to be exact, when passing in calls. It is better to use ``bytes``. + The type ``byte[]`` is an array of bytes, but due to padding rules, it wastes + 31 bytes of space for each element (except in storage). It is better to use the ``bytes`` + type instead. Dynamically-sized byte array ---------------------------- @@ -326,7 +351,7 @@ Address Literals ---------------- Hexadecimal literals that pass the address checksum test, for example -``0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`` are of ``address`` type. +``0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`` are of ``address payable`` type. Hexadecimal literals that are between 39 and 41 digits long and do not pass the checksum test produce a warning and are treated as regular rational number literals. @@ -354,10 +379,11 @@ Examples include ``2e10``, ``-2e10``, ``2e-10``, ``2.5e1``. Underscores can be used to separate the digits of a numeric literal to aid readability. For example, decimal ``123_000``, hexadecimal ``0x2eff_abde``, scientific decimal notation ``1_2e345_678`` are all valid. Underscores are only allowed between two digits and only one consecutive underscore is allowed. -There is no additional semantic meaning added to a number literal containing underscores. +There is no additional semantic meaning added to a number literal containing underscores, +the underscores are ignored. Number literal expressions retain arbitrary precision until they are converted to a non-literal type (i.e. by -using them together with a non-literal expression). +using them together with a non-literal expression or by explicit conversion). This means that computations do not overflow and divisions do not truncate in number literal expressions. @@ -379,14 +405,15 @@ a non-rational number). belong to the same number literal type for the rational number three. .. warning:: - Division on integer literals used to truncate in earlier versions, but it will now convert into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``. + Division on integer literals used to truncate in Solidity prior to version 0.4.0, but it now converts into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``. .. note:: Number literal expressions are converted into a non-literal type as soon as they are used with non-literal - expressions. Even though we know that the value of the - expression assigned to ``b`` in the following example evaluates to - an integer, but the partial expression ``2.5 + a`` does not type check so the code - does not compile + expressions. Disregarding types, the value of the expression assigned to ``b`` + below evaluates to an integer. Because ``a`` is of type ``uint128``, the + expression ``2.5 + a`` has to have a proper type, though. Since there is no common type + for the type of ``2.5`` and ``uint128``, the Solidity compiler does not accept + this code. :: @@ -803,13 +830,12 @@ Members ^^^^^^^ **length**: - Arrays have a ``length`` member to hold their number of elements. - Dynamic arrays can be resized in storage (not in memory) by changing the - ``.length`` member. This does not happen automatically when attempting to access elements outside the current length. The size of memory arrays is fixed (but dynamic, i.e. it can depend on runtime parameters) once they are created. + Arrays have a ``length`` member to read their number of elements. + Dynamically-sized arrays (only available for storage) have a read-write ``length`` member to resize the array. Increasing the length adds uninitialized elements to the array, this has *O(1)* complexity. Reducing the length performs :ref:``delete`` on each removed element and has *O(n)* complexity where *n* is the number of elements being deleted. Please note that calling ``length--`` on an empty array will set the length of the array to 2^256-1 due to ``uint256`` underflow wrapping. **push**: Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push`` that can be used to append an element at the end of the array. The function returns the new length. **pop**: - Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``pop`` that can be used to remove an element from the end of the array. + Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``pop`` that can be used to remove an element from the end of the array. This will also implicitly call :ref:``delete`` on the removed element. .. warning:: It is not yet possible to use arrays of arrays in external functions. @@ -1033,11 +1059,13 @@ If ``a`` is an LValue (i.e. a variable or something that can be assigned to), th delete ------ -``delete a`` assigns the initial value for the type to ``a``. I.e. for integers it is equivalent to ``a = 0``, but it can also be used on arrays, where it assigns a dynamic array of length zero or a static array of the same length with all elements reset. For structs, it assigns a struct with all members reset. +``delete a`` assigns the initial value for the type to ``a``. I.e. for integers it is equivalent to ``a = 0``, but it can also be used on arrays, where it assigns a dynamic array of length zero or a static array of the same length with all elements reset. For structs, it assigns a struct with all members reset. In other words, the value of ``a`` after ``delete a`` is the same as if ``a`` would be declared without assignment, with the following caveat: -``delete`` has no effect on whole mappings (as the keys of mappings may be arbitrary and are generally unknown). So if you delete a struct, it will reset all members that are not mappings and also recurse into the members unless they are mappings. However, individual keys and what they map to can be deleted. +``delete`` has no effect on mappings (as the keys of mappings may be arbitrary and are generally unknown). So if you delete a struct, it will reset all members that are not mappings and also recurse into the members unless they are mappings. However, individual keys and what they map to can be deleted: If ``a`` is a mapping, then ``delete a[x]`` will delete the value stored at ``x``. It is important to note that ``delete a`` really behaves like an assignment to ``a``, i.e. it stores a new object in ``a``. +This distinction is visible when ``a`` is reference variable: It will only reset ``a`` itself, not the +value it referred to previously. :: @@ -1050,7 +1078,7 @@ It is important to note that ``delete a`` really behaves like an assignment to ` function f() public { uint x = data; delete x; // sets x to 0, does not affect data - delete data; // sets data to 0, does not affect x which still holds a copy + delete data; // sets data to 0, does not affect x uint[] storage y = dataArray; delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also // y is affected which is an alias to the storage object @@ -1079,12 +1107,15 @@ makes sense semantically and no information is lost: ``uint8`` is convertible to (because ``uint256`` cannot hold e.g. ``-1``). Any integer type that can be converted to ``uint160`` can also be converted to ``address``. +For more details, please consult the sections about the types themselves. + Explicit Conversions -------------------- If the compiler does not allow implicit conversion but you know what you are doing, an explicit type conversion is sometimes possible. Note that this may -give you some unexpected behaviour so be sure to test to ensure that the +give you some unexpected behaviour and allows you to bypass some security +features of the compiler, so be sure to test that the result is what you want! Take the following example where you are converting a negative ``int8`` to a ``uint``: @@ -1183,3 +1214,5 @@ Addresses As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type. + +Explicit conversions from ``bytes20`` or any integer type to ``address`` results in ``address payable``.
\ No newline at end of file diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index d6ef393e..7f62e71e 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -7,15 +7,25 @@ Units and Globally Available Variables Ether Units =========== -A literal number can take a suffix of ``wei``, ``finney``, ``szabo`` or ``ether`` to convert between the subdenominations of Ether, where Ether currency numbers without a postfix are assumed to be Wei, e.g. ``2 ether == 2000 finney`` evaluates to ``true``. +A literal number can take a suffix of ``wei``, ``finney``, ``szabo`` or ``ether`` to specify a subdenomination of Ether, where Ether numbers without a postfix are assumed to be Wei. + +:: + + assert(1 wei == 1); + assert(1 szabo == 1e12); + assert(1 finney == 1e15); + assert(1 ether == 1e18); + +The only effect of the subdenomination suffix is a multiplication by a power of ten. + .. index:: time, seconds, minutes, hours, days, weeks, years Time Units ========== -Suffixes like ``seconds``, ``minutes``, ``hours``, ``days``, ``weeks`` and -``years`` after literal numbers can be used to convert between units of time where seconds are the base +Suffixes like ``seconds``, ``minutes``, ``hours``, ``days`` and ``weeks`` +after literal numbers can be used to specify units of time where seconds are the base unit and units are considered naively in the following way: * ``1 == 1 seconds`` @@ -23,7 +33,6 @@ unit and units are considered naively in the following way: * ``1 hours == 60 minutes`` * ``1 days == 24 hours`` * ``1 weeks == 7 days`` - * ``1 years == 365 days`` Take care if you perform calendar calculations using these units, because not every year equals 365 days and not even every day has 24 hours @@ -32,7 +41,7 @@ Due to the fact that leap seconds cannot be predicted, an exact calendar library has to be updated by an external oracle. .. note:: - The suffix ``years`` has been deprecated due to the reasons above and cannot be used starting version 0.5.0. + The suffix ``years`` has been removed in version 0.5.0 due to the reasons above. These suffixes cannot be applied to variables. If you want to interpret some input variable in e.g. days, you can do it in the following way:: @@ -56,15 +65,14 @@ or are general-use utility functions. Block and Transaction Properties -------------------------------- -- ``block.blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by ``blockhash(uint blockNumber)``. +- ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number - ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch - ``gasleft() returns (uint256)``: remaining gas -- ``msg.data`` (``bytes``): complete calldata -- ``msg.gas`` (``uint``): remaining gas - deprecated in version 0.4.21 and to be replaced by ``gasleft()`` +- ``msg.data`` (``bytes calldata``): complete calldata - ``msg.sender`` (``address payable``): sender of the message (current call) - ``msg.sig`` (``bytes4``): first four bytes of the calldata (i.e. function identifier) - ``msg.value`` (``uint``): number of wei sent with the message @@ -94,20 +102,28 @@ Block and Transaction Properties You can only access the hashes of the most recent 256 blocks, all other values will be zero. +.. note:: + The function ``blockhash`` was previously known as ``block.blockhash``. It was deprecated in + version 0.4.22 and removed in version 0.5.0. + +.. note:: + The function ``gasleft`` was previously known as ``msg.gas``. It was deprecated in + version 0.4.21 and removed in version 0.5.0. + .. index:: abi, encoding, packed ABI Encoding and Decoding Functions ----------------------------------- -- ``abi.decode(bytes encodedData, (...)) returns (...)``: ABI-decodes the given data, while the types are given in parentheses as second argument. Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))`` -- ``abi.encode(...) returns (bytes)``: ABI-encodes the given arguments -- ``abi.encodePacked(...) returns (bytes)``: Performs :ref:`packed encoding <abi_packed_mode>` of the given arguments -- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: ABI-encodes the given arguments starting from the second and prepends the given four-byte selector -- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)``` +- ``abi.decode(bytes memory encodedData, (...)) returns (...)``: ABI-decodes the given data, while the types are given in parentheses as second argument. Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))`` +- ``abi.encode(...) returns (bytes memory)``: ABI-encodes the given arguments +- ``abi.encodePacked(...) returns (bytes memory)``: Performs :ref:`packed encoding <abi_packed_mode>` of the given arguments +- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: ABI-encodes the given arguments starting from the second and prepends the given four-byte selector +- ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)``` .. note:: - These encoding functions can be used to craft data for function calls without actually - calling a function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a way + These encoding functions can be used to craft data for external function calls without actually + calling an external function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a way to compute the hash of structured data (although be aware that it is possible to craft a "hash collision" using different inputs types). @@ -119,15 +135,18 @@ See the documentation about the :ref:`ABI <ABI>` and the Error Handling -------------- +See the dedicated section on :ref:`assert and require<assert-and-require>` for +more details on error handling and when to use which function. + ``assert(bool condition)``: - invalidates the transaction if the condition is not met - to be used for internal errors. + causes an invalid opcode and thus state change reversion if the condition is not met - to be used for internal errors. ``require(bool condition)``: reverts if the condition is not met - to be used for errors in inputs or external components. -``require(bool condition, string message)``: +``require(bool condition, string memory message)``: reverts if the condition is not met - to be used for errors in inputs or external components. Also provides an error message. ``revert()``: abort execution and revert state changes -``revert(string reason)``: +``revert(string memory reason)``: abort execution and revert state changes, providing an explanatory string .. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, @@ -140,11 +159,9 @@ Mathematical and Cryptographic Functions ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. ``keccak256(bytes memory) returns (bytes32)``: - compute the Ethereum-SHA-3 (Keccak-256) hash of the input + compute the Keccak-256 hash of the input ``sha256(bytes memory) returns (bytes32)``: compute the SHA-256 hash of the input -``sha3(bytes memory) returns (bytes32)``: - alias to ``keccak256`` ``ripemd160(bytes memory) returns (bytes20)``: compute RIPEMD-160 hash of the input ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: @@ -158,26 +175,27 @@ Mathematical and Cryptographic Functions It might be that you run into Out-of-Gas for ``sha256``, ``ripemd160`` or ``ecrecover`` on a *private blockchain*. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net. +.. note:: + There used to be an alias for ``keccak256`` called ``sha3``, which was removed in version 0.5.0. + .. index:: balance, send, transfer, call, callcode, delegatecall, staticcall .. _address_related: -Address Related ---------------- +Members of Address Types +------------------------ ``<address>.balance`` (``uint256``): balance of the :ref:`address` in Wei ``<address payable>.transfer(uint256 amount)``: - send given amount of Wei to :ref:`address`, throws on failure, forwards 2300 gas stipend, not adjustable + send given amount of Wei to :ref:`address`, reverts on failure, forwards 2300 gas stipend, not adjustable ``<address payable>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure, forwards 2300 gas stipend, not adjustable -``<address>.call(bytes memory) returns (bool)``: - issue low-level ``CALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable -``<address>.callcode(bytes memory) returns (bool)``: - issue low-level ``CALLCODE`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable -``<address>.delegatecall(bytes memory) returns (bool)``: - issue low-level ``DELEGATECALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable -``<address>.staticcall(bytes memory) returns (bool)``: - issue low-level ``STATICCALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable +``<address>.call(bytes memory) returns (bool, bytes memory)``: + issue low-level ``CALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable +``<address>.delegatecall(bytes memory) returns (bool, bytes memory)``: + issue low-level ``DELEGATECALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable +``<address>.staticcall(bytes memory) returns (bool, bytes memory)``: + issue low-level ``STATICCALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable For more information, see the section on :ref:`address`. @@ -192,14 +210,19 @@ For more information, see the section on :ref:`address`. This is now forbidden and an explicit conversion to address must be done: ``address(this).balance``. .. note:: - If storage variables are accessed via a low-level delegatecall, the storage layout of the two contracts + If state variables are accessed via a low-level delegatecall, the storage layout of the two contracts must align in order for the called contract to correctly access the storage variables of the calling contract by name. This is of course not the case if storage pointers are passed as function arguments as in the case for the high-level libraries. +.. note:: + Prior to version 0.5.0, ``.call``, ``.delegatecall`` and ``.staticcall`` only returned the + success condition and not the return data. .. note:: - The use of ``callcode`` is discouraged and will be removed in the future. + Prior to version 0.5.0, there was a member called ``callcode`` with similar but slightly different + semantics than ``delegatecall``. + .. index:: this, selfdestruct @@ -212,8 +235,9 @@ Contract Related ``selfdestruct(address payable recipient)``: destroy the current contract, sending its funds to the given :ref:`address` -``suicide(address payable recipient)``: - deprecated alias to ``selfdestruct`` - Furthermore, all functions of the current contract are callable directly including the current function. +.. note:: + Prior to version 0.5.0, there was a function called ``suicide`` with the same + semantics as ``selfdestruct``. + diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 0a64d840..1e4bbecc 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -45,6 +45,56 @@ If ``solc`` is called with the option ``--link``, all input files are interprete If ``solc`` is called with the option ``--standard-json``, it will expect a JSON input (as explained below) on the standard input, and return a JSON output on the standard output. +.. _evm-version: +.. index:: ! EVM version, compile target + +Setting the EVM version to target +********************************* + +When you compile your contract code you can specify the Ethereum virtual machine +version to compile for to avoid particular features or behaviours. + +.. warning:: + + Compiling for the wrong EVM version can result in wrong, strange and failing + behaviour. Please ensure, especially if running a private chain, that you + use matching EVM versions. + +You use the ``--evm-version`` option on the command line: + +.. code-block:: shell + + solc --evm-version <VERSION> contract.sol + +Or if using the :ref:`standard JSON interface <compiler-api>`, with the ``evmVersion`` key: + +.. code-block:: json + + { + "evmVersion": "<VERSION>" + } + +Target options +-------------- + +Below is a list of target EVM versions and the compiler-relevant changes introduced +at each version. Backward compatibility is not guaranteed between each version. + +- ``homestead`` +- ``tangerineWhistle`` + - gas cost for access to other accounts increased, relevant for gas estimation and the optimizer. + - all gas sent by default for external calls, previously a certain amount had to be retained. +- ``spuriousDragon`` + - gas cost for the ``exp`` opcode increased, relevant for gas estimation and the optimizer. +- ``byzantium`` (**default**) + - opcodes ``returndatacopy``, ``returndatasize`` and ``staticcall`` are available in assembly. + - the ``staticcall`` opcode is used when calling view or pure functions, which prevents the functions from modifying state at the EVM level, i.e., even applies when you use invalid type conversions. + - it is possible to access dynamic data returned from function calls. + - ``revert`` opcode introduced, which means that ``revert()`` will not waste gas. +- ``constantinople`` (still in progress) + - opcodes ``shl``, ``shr`` and ``sar`` are available in assembly. + - shifting operators use shifting opcodes and thus need less gas. + .. _compiler-api: Compiler Input and Output JSON Description diff --git a/libdevcore/SHA3.cpp b/libdevcore/SHA3.cpp index b0e40ccb..e41a5e3b 100644 --- a/libdevcore/SHA3.cpp +++ b/libdevcore/SHA3.cpp @@ -67,22 +67,22 @@ deckeccak(512) /*** Constants. ***/ static const uint8_t rho[24] = \ - { 1, 3, 6, 10, 15, 21, + { 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44}; static const uint8_t pi[24] = \ - {10, 7, 11, 17, 18, 3, + {10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, - 20, 14, 22, 9, 6, 1}; + 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6, 1}; static const uint64_t RC[24] = \ - {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, - 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, - 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; + {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, + 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; /*** Helper macros to unroll the permutation. ***/ #define rol(x, s) (((x) << s) | ((x) >> (64 - s))) @@ -95,36 +95,37 @@ static const uint64_t RC[24] = \ /*** Keccak-f[1600] ***/ static inline void keccakf(void* state) { - uint64_t* a = (uint64_t*)state; - uint64_t b[5] = {0}; - - for (int i = 0; i < 24; i++) { - uint8_t x, y; - // Theta - FOR5(x, 1, - b[x] = 0; - FOR5(y, 5, - b[x] ^= a[x + y]; )) - FOR5(x, 1, - FOR5(y, 5, - a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) - // Rho and pi - uint64_t t = a[1]; - x = 0; - REPEAT24(b[0] = a[pi[x]]; - a[pi[x]] = rol(t, rho[x]); - t = b[0]; - x++; ) - // Chi - FOR5(y, - 5, - FOR5(x, 1, - b[x] = a[y + x];) - FOR5(x, 1, - a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) - // Iota - a[0] ^= RC[i]; - } + uint64_t* a = (uint64_t*)state; + uint64_t b[5] = {0}; + + for (int i = 0; i < 24; i++) + { + uint8_t x, y; + // Theta + FOR5(x, 1, + b[x] = 0; + FOR5(y, 5, + b[x] ^= a[x + y]; )) + FOR5(x, 1, + FOR5(y, 5, + a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) + // Rho and pi + uint64_t t = a[1]; + x = 0; + REPEAT24(b[0] = a[pi[x]]; + a[pi[x]] = rol(t, rho[x]); + t = b[0]; + x++; ) + // Chi + FOR5(y, + 5, + FOR5(x, 1, + b[x] = a[y + x];) + FOR5(x, 1, + a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) + // Iota + a[0] ^= RC[i]; + } } /******** The FIPS202-defined functions. ********/ @@ -166,24 +167,25 @@ mkapply_sd(setout, dst[i] = src[i]) // setout static inline int hash(uint8_t* out, size_t outlen, const uint8_t* in, size_t inlen, size_t rate, uint8_t delim) { - if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { - return -1; - } - uint8_t a[Plen] = {0}; - // Absorb input. - foldP(in, inlen, xorin); - // Xor in the DS and pad frame. - a[inlen] ^= delim; - a[rate - 1] ^= 0x80; - // Xor in the last block. - xorin(a, in, inlen); - // Apply P - P(a); - // Squeeze output. - foldP(out, outlen, setout); - setout(a, out, outlen); - memset(a, 0, 200); - return 0; + if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) + { + return -1; + } + uint8_t a[Plen] = {0}; + // Absorb input. + foldP(in, inlen, xorin); + // Xor in the DS and pad frame. + a[inlen] ^= delim; + a[rate - 1] ^= 0x80; + // Xor in the last block. + xorin(a, in, inlen); + // Apply P + P(a); + // Squeeze output. + foldP(out, outlen, setout); + setout(a, out, outlen); + memset(a, 0, 200); + return 0; } /*** Helper macros to define SHA3 and SHAKE instances. ***/ diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3056561b..c42a0068 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1778,9 +1778,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) } if (resultType->category() == Type::Category::Address) { - bool payable = true; - if (auto const* contractType = dynamic_cast<ContractType const*>(argType.get())) - payable = contractType->isPayable(); + bool payable = argType->isExplicitlyConvertibleTo(AddressType::addressPayable()); resultType = make_shared<AddressType>(payable ? StateMutability::Payable : StateMutability::NonPayable); } } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 25702f19..f49e1222 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2126,8 +2126,11 @@ bool StructType::canBeUsedExternally(bool _inLibrary) const // passed by value and thus the encoding does not differ, but it will disallow // mappings. for (auto const& var: m_struct.members()) + { + solAssert(var->annotation().type, ""); if (!var->annotation().type->canBeUsedExternally(false)) return false; + } } return true; } @@ -2429,7 +2432,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get())) { if (arrayType->isByteArray()) - // Return byte arrays as as whole. + // Return byte arrays as whole. break; returnType = arrayType->baseType(); m_parameterNames.push_back(""); @@ -2641,8 +2644,8 @@ bool FunctionType::operator==(Type const& _other) const bool FunctionType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - if (m_kind == Kind::External && _convertTo.category() == Category::Address) - return true; + if (m_kind == Kind::External && _convertTo == AddressType::address()) + return true; return _convertTo.category() == category(); } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 65a70019..0f3373a1 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -174,7 +174,7 @@ public: /// Will not contain any character which would be invalid as an identifier. std::string identifier() const; - /// More complex identifier strings use "parentheses", where $_ is interpreted as as + /// More complex identifier strings use "parentheses", where $_ is interpreted as /// "opening parenthesis", _$ as "closing parenthesis", _$_ as "comma" and any $ that /// appears as part of a user-supplied identifier is escaped as _$$$_. /// @returns an escaped identifier (will not contain any parenthesis or commas) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 8645f653..587cf34a 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1230,7 +1230,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) else solAssert(false, "Contract member is neither variable nor function."); m_context << identifier; - /// need to store store it as bytes4 + /// need to store it as bytes4 utils().leftShiftNumberOnStack(224); return false; } @@ -1305,7 +1305,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) if (member == "selector") { m_context << Instruction::SWAP1 << Instruction::POP; - /// need to store store it as bytes4 + /// need to store it as bytes4 utils().leftShiftNumberOnStack(224); } else @@ -1975,7 +1975,7 @@ void ExpressionCompiler::appendExternalFunctionCall( m_context << dupInstruction(m_context.baseToCurrentStackOffset(contractStackPos)); bool existenceChecked = false; - // Check the the target contract exists (has code) for non-low-level calls. + // Check the target contract exists (has code) for non-low-level calls. if (funKind == FunctionType::Kind::External || funKind == FunctionType::Kind::DelegateCall) { m_context << Instruction::DUP1 << Instruction::EXTCODESIZE << Instruction::ISZERO; diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h index a7d7ead1..277e1879 100644 --- a/libsolidity/inlineasm/AsmCodeGen.h +++ b/libsolidity/inlineasm/AsmCodeGen.h @@ -41,7 +41,7 @@ struct Block; class CodeGenerator { public: - /// Performs code generation and appends generated to to _assembly. + /// Performs code generation and appends generated to _assembly. static void assemble( Block const& _parsedData, AsmAnalysisInfo& _analysisInfo, diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp index c9d5b969..0f6d6996 100644 --- a/libsolidity/parsing/Scanner.cpp +++ b/libsolidity/parsing/Scanner.cpp @@ -780,13 +780,13 @@ Token::Value Scanner::scanNumber(char _charSeen) { addLiteralCharAndAdvance(); // either 0, 0exxx, 0Exxx, 0.xxx or a hex number - if (m_char == 'x' || m_char == 'X') + if (m_char == 'x') { // hex number kind = HEX; addLiteralCharAndAdvance(); if (!isHexDigit(m_char)) - return Token::Illegal; // we must have at least one hex digit after 'x'/'X' + return Token::Illegal; // we must have at least one hex digit after 'x' while (isHexDigit(m_char) || m_char == '_') // We keep the underscores for later validation addLiteralCharAndAdvance(); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index a43e789e..8fd0d6ef 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -736,7 +736,8 @@ bool CommandLineInterface::processInput() if (m_args.count(g_argAllowPaths)) { vector<string> paths; - for (string const& path: boost::split(paths, m_args[g_argAllowPaths].as<string>(), boost::is_any_of(","))) { + for (string const& path: boost::split(paths, m_args[g_argAllowPaths].as<string>(), boost::is_any_of(","))) + { auto filesystem_path = boost::filesystem::path(path); // If the given path had a trailing slash, the Boost filesystem // path will have it's last component set to '.'. This breaks diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 3a210f94..93db236b 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -105,6 +105,11 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x765432536763762734623472346"); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + scanner.reset(CharStream("0x1234"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x1234"); + scanner.reset(CharStream("0X1234"), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); } BOOST_AUTO_TEST_CASE(octal_numbers) diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address_payable.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address_payable.sol new file mode 100644 index 00000000..adffb14b --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address_payable.sol @@ -0,0 +1,7 @@ +contract C { + function f() public view returns (address payable) { + return address(this.f); + } +} +// ---- +// TypeError: (85-100): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/types/address/address_to_payable_address_double.sol b/test/libsolidity/syntaxTests/types/address/address_to_payable_address_double.sol new file mode 100644 index 00000000..1e755033 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_to_payable_address_double.sol @@ -0,0 +1,7 @@ +contract C { + function f(address a) public pure returns (address payable) { + return address(address(a)); + } +} +// ---- +// TypeError: (94-113): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/types/address/bytes_long_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/bytes_long_to_payable_address.sol new file mode 100644 index 00000000..ef87ac55 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/bytes_long_to_payable_address.sol @@ -0,0 +1,8 @@ +contract C { + function f(bytes32 x) public pure returns (address payable) { + return address(x); + } +} +// ---- +// TypeError: (94-104): Explicit type conversion not allowed from "bytes32" to "address". +// TypeError: (94-104): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/types/address/bytes_short_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/bytes_short_to_payable_address.sol new file mode 100644 index 00000000..2aa60251 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/bytes_short_to_payable_address.sol @@ -0,0 +1,8 @@ +contract C { + function f(bytes10 x) public pure returns (address payable) { + return address(x); + } +} +// ---- +// TypeError: (94-104): Explicit type conversion not allowed from "bytes10" to "address". +// TypeError: (94-104): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. diff --git a/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol new file mode 100644 index 00000000..5b6a6714 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol @@ -0,0 +1,5 @@ +contract C { + function f(bytes20 x) public pure returns (address payable) { + return address(x); + } +} diff --git a/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol new file mode 100644 index 00000000..9a33985a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol @@ -0,0 +1,5 @@ +contract C { + function f(uint x) public pure returns (address payable) { + return address(x); + } +} |
