Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth 2020-05-14 12:33:56 +02:00
commit 257bc6a416
288 changed files with 1934 additions and 409 deletions

View File

@ -18,6 +18,8 @@ Bugfixes:
Important Bugfixes:
* Add missing callvalue check to the creation code of a contract that does not define a constructor but has a base that does define a constructor.
* Disallow index range accesses for arrays with dynamically encoded base types.
* Code Generator: Fixed that string literals containing backslash characters could cause incorrect code to be generated when passed directly to function calls or encoding functions when ABIEncoderV2 is active.
Language Features:
@ -26,6 +28,8 @@ Language Features:
Compiler Features:
* Commandline Interface: Don't ignore `--yul-optimizations` in assembly mode.
* Allow using abi encoding functions for calldata array slices without explicit casts.
* Wasm binary output: Implement ``br`` and ``br_if``.
@ -35,6 +39,7 @@ Bugfixes:
* Fixed an "Assembly Exception in Bytecode" error where requested functions were generated twice.
* Natspec: Fixed a bug that ignored ``@return`` tag when no other developer-documentation tags were present.
* Yul assembler: Fix source location of variable declarations without value.
* Type checker: Checks if a literal exponent in the ``**`` operation is too large or fractional.
### 0.6.7 (2020-05-04)

View File

@ -292,6 +292,7 @@ Consider you have the following pre-0.5.0 contract already deployed:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.4.25;
// This will report a warning until version 0.4.25 of the compiler
// This will not compile after 0.5.0
@ -309,6 +310,7 @@ This will no longer compile with Solidity v0.5.0. However, you can define a comp
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
interface OldContract {
function someOldFunction(uint8 a) external;
@ -326,6 +328,7 @@ Given the interface defined above, you can now easily use the already deployed p
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
interface OldContract {
@ -347,6 +350,7 @@ commandline compiler for linking):
::
// This will not compile after 0.6.0
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.5.99;
library OldLibrary {
@ -370,6 +374,7 @@ Old version:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.4.25;
// This will not compile after 0.5.0
@ -432,6 +437,7 @@ New version:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.5.99;
// This will not compile after 0.6.0

View File

@ -232,6 +232,7 @@ Given the contract:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract Foo {
@ -535,6 +536,7 @@ For example,
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
@ -583,6 +585,7 @@ As an example, the code
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.19 <0.8.0;
pragma experimental ABIEncoderV2;

View File

@ -41,6 +41,7 @@ without a compiler change.
.. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
library GetCode {
@ -66,6 +67,7 @@ efficient code, for example:
.. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
@ -136,6 +138,7 @@ Local Solidity variables are available for assignments, for example:
.. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract C {

View File

@ -1,4 +1,26 @@
[
{
"name": "MissingEscapingInFormatting",
"summary": "String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.",
"description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intemediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.",
"introduced": "0.5.14",
"fixed": "0.6.8",
"severity": "very low",
"conditions": {
"ABIEncoderV2": true
}
},
{
"name": "ArraySliceDynamicallyEncodedBaseType",
"summary": "Accessing array slices of arrays with dynamically encoded base types (e.g. multi-dimensional arrays) can result in invalid data being read.",
"description": "For arrays with dynamically sized base types, index range accesses that use a start expression that is non-zero will result in invalid array slices. Any index access to such array slices will result in data being read from incorrect calldata offsets. Array slices are only supported for dynamic calldata types and all problematic type require ABIEncoderV2 to be enabled.",
"introduced": "0.6.0",
"fixed": "0.6.8",
"severity": "very low",
"conditions": {
"ABIEncoderV2": true
}
},
{
"name": "ImplicitConstructorCallvalueCheck",
"summary": "The creation code of a contract that does not define a constructor but has a base that does define a constructor did not revert for calls with non-zero value.",

View File

@ -923,6 +923,7 @@
},
"0.5.14": {
"bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -934,6 +935,7 @@
},
"0.5.15": {
"bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -944,6 +946,7 @@
},
"0.5.16": {
"bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -953,6 +956,7 @@
},
"0.5.17": {
"bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
@ -1082,6 +1086,8 @@
},
"0.6.0": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -1091,6 +1097,8 @@
},
"0.6.1": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
@ -1099,6 +1107,8 @@
},
"0.6.2": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
@ -1107,6 +1117,8 @@
},
"0.6.3": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
@ -1115,6 +1127,8 @@
},
"0.6.4": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
@ -1123,6 +1137,8 @@
},
"0.6.5": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents"
],
@ -1130,12 +1146,16 @@
},
"0.6.6": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck"
],
"released": "2020-04-09"
},
"0.6.7": {
"bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck"
],
"released": "2020-05-04"

View File

@ -27,6 +27,7 @@ you receive the funds of the person who is now the richest.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract WithdrawalContract {
@ -60,6 +61,7 @@ This is as opposed to the more intuitive sending pattern:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract SendContract {
@ -121,6 +123,7 @@ restrictions highly readable.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract AccessRestriction {
@ -273,6 +276,7 @@ function finishes.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract StateMachine {

View File

@ -13,6 +13,7 @@ This can be done by using the ``abstract`` keyword as shown in the following exa
defined as abstract, because the function ``utterance()`` was defined, but no implementation was
provided (no implementation body ``{ }`` was given).::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
abstract contract Feline {
@ -22,6 +23,7 @@ provided (no implementation body ``{ }`` was given).::
Such abstract contracts can not be instantiated directly. This is also true, if an abstract contract itself does implement
all defined functions. The usage of an abstract contract as a base class is shown in the following example::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
abstract contract Feline {

View File

@ -17,6 +17,7 @@ Not all types for constants and immutables are implemented at this time. The onl
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >0.6.4 <0.8.0;
contract C {

View File

@ -34,6 +34,7 @@ This means that cyclic creation dependencies are impossible.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;

View File

@ -65,6 +65,7 @@ is that they are cheaper to deploy and call.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.21 <0.8.0;
contract ClientReceipt {
@ -138,6 +139,7 @@ as topics. The event call above can be performed in the same way as
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.10 <0.8.0;
contract C {

View File

@ -17,6 +17,7 @@ if they are marked ``virtual``. For details, please see
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract owned {

View File

@ -23,6 +23,7 @@ unused parameters can be omitted.
For example, if you want your contract to accept one kind of external call
with two integers, you would use something like the following::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract Simple {
@ -55,6 +56,7 @@ Function return variables are declared with the same syntax after the
For example, suppose you want to return two results: the sum and the product of
two integers passed as function parameters, then you use something like::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract Simple {
@ -79,6 +81,7 @@ or you can provide return values
(either a single or :ref:`multiple ones<multi-return>`) directly with the ``return``
statement::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract Simple {
@ -142,6 +145,7 @@ The following statements are considered modifying the state:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract C {
@ -187,6 +191,7 @@ In addition to the list of state modifying statements explained above, the follo
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract C {
@ -280,6 +285,7 @@ Below you can see an example of a Sink contract that uses function ``receive``.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
// This contract keeps all Ether sent to it with no way
@ -335,6 +341,7 @@ operations as long as there is enough gas passed on to it.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0;
contract Test {
@ -407,6 +414,7 @@ The following example shows overloading of the function
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract A {
@ -425,6 +433,7 @@ externally visible functions differ by their Solidity types but not by their ext
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
// This will not compile
@ -458,6 +467,7 @@ candidate, resolution fails.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract A {

View File

@ -38,6 +38,7 @@ Details are given in the following example.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
@ -125,6 +126,7 @@ Note that above, we call ``Destructible.destroy()`` to "forward" the
destruction request. The way this is done is problematic, as
seen in the following example::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract owned {
@ -154,6 +156,7 @@ A call to ``Final.destroy()`` will call ``Base2.destroy`` because we specify it
explicitly in the final override, but this function will bypass
``Base1.destroy``. The way around this is to use ``super``::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract owned {
@ -204,6 +207,7 @@ use the ``override`` keyword in the function header as shown in this example:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract Base
@ -227,6 +231,7 @@ bases, it has to explicitly override it:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract Base1
@ -253,6 +258,7 @@ that already overrides all other functions.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract A { function f() public pure{} }
@ -293,6 +299,7 @@ of the variable:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract A
@ -324,6 +331,7 @@ and the ``override`` keyword must be used in the overriding modifier:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract Base
@ -342,6 +350,7 @@ explicitly:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract Base1
@ -389,6 +398,7 @@ equivalent to ``constructor() public {}``. For example:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract A {
@ -419,6 +429,7 @@ The constructors of all the base contracts will be called following the
linearization rules explained below. If the base constructors have arguments,
derived contracts need to specify all of them. This can be done in two ways::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract Base {
@ -478,6 +489,7 @@ error "Linearization of inheritance graph impossible".
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract X {}
@ -498,6 +510,7 @@ One area where inheritance linearization is especially important and perhaps not
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract Base1 {

View File

@ -22,6 +22,7 @@ Interfaces are denoted by their own keyword:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0;
interface Token {
@ -42,6 +43,7 @@ inheritance.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0;
interface ParentA {

View File

@ -47,6 +47,7 @@ more advanced example to implement a set).
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
@ -125,6 +126,7 @@ custom types without the overhead of external function calls:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
struct bigint {
@ -239,6 +241,7 @@ Its value can be obtained from Solidity using the ``.selector`` member as follow
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.14 <0.8.0;
library L {

View File

@ -29,6 +29,7 @@ may only be used inside a contract, not inside any of its functions.
Let us rewrite the set example from the
:ref:`libraries` in this way::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
@ -81,6 +82,7 @@ Let us rewrite the set example from the
It is also possible to extend elementary types in that way::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
library Search {

View File

@ -54,6 +54,7 @@ return parameter list for functions.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract C {
@ -68,6 +69,7 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract C {
@ -112,6 +114,7 @@ when they are declared.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract C {
@ -132,6 +135,7 @@ it evaluates to a state variable. If it is accessed externally
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract C {
@ -151,6 +155,7 @@ to write a function, for example:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract arrayExample {
@ -177,6 +182,7 @@ The next example is more complex:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract Complex {

View File

@ -41,6 +41,7 @@ Internal Function Calls
Functions of the current contract can be called directly ("internally"), also recursively, as seen in
this nonsensical example::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract C {
@ -82,6 +83,7 @@ to the total balance of that contract:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0;
contract InfoFeed {
@ -137,6 +139,7 @@ parameters from the function declaration, but can be in arbitrary order.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract C {
@ -160,6 +163,7 @@ Those parameters will still be present on the stack, but they are inaccessible.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract C {
@ -183,6 +187,7 @@ is compiled so recursive creation-dependencies are not possible.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0;
contract D {
@ -238,6 +243,7 @@ which only need to be created if there is a dispute.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0;
contract D {
@ -307,6 +313,7 @@ groupings of expressions.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract C {
@ -352,6 +359,7 @@ because only a reference and not a copy is passed.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract C {
@ -410,6 +418,7 @@ the two variables have the same name but disjoint scopes.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract C {
function minimalScoping() pure public {
@ -431,6 +440,7 @@ In any case, you will get a warning about the outer variable being shadowed.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
// This will report a warning
contract C {
@ -452,6 +462,7 @@ In any case, you will get a warning about the outer variable being shadowed.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
// This will not compile
contract C {
@ -540,6 +551,7 @@ and ``assert`` for internal error checking.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract Sharer {
@ -584,6 +596,7 @@ The following example shows how to use an error string together with ``revert``
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract VendingMachine {
@ -627,6 +640,7 @@ A failure in an external call can be caught using a try/catch statement, as foll
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
interface DataFeed { function getData(address token) external returns (uint value); }

View File

@ -24,6 +24,7 @@ to receive their money - contracts cannot activate themselves.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract SimpleAuction {
@ -184,6 +185,7 @@ invalid bids.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract BlindAuction {

View File

@ -142,6 +142,7 @@ The full contract
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.24 <0.8.0;
contract ReceiverPays {
@ -338,6 +339,7 @@ The full contract
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract SimplePaymentChannel {

View File

@ -19,6 +19,7 @@ and the sum of all balances is an invariant across the lifetime of the contract.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
library Balances {

View File

@ -25,6 +25,7 @@ you can use state machine-like constructs inside a contract.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract Purchase {

View File

@ -32,6 +32,7 @@ of votes.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
/// @title Voting with delegation.

View File

@ -71,6 +71,7 @@ So for the following contract snippet
the position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
@ -171,6 +172,7 @@ value and reference types, types that are encoded packed, and nested types.
.. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract A {
struct S {

View File

@ -17,6 +17,7 @@ Storage Example
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract SimpleStorage {
@ -31,8 +32,12 @@ Storage Example
}
}
The first line tells you that the source code is written for
Solidity version 0.4.0, or a newer version of the language up to, but not including version 0.7.0.
The first line tells you that the source code is licensed under the
GPL version 3.0. Machine-readable license specifiers are important
in a setting where publishing the source code is the default.
The next line specifies that the source code is written for
Solidity version 0.4.16, or a newer version of the language up to, but not including version 0.7.0.
This is to ensure that the contract is not compilable with a new (breaking) compiler version, where it could behave differently.
:ref:`Pragmas<pragma>` are common instructions for compilers about how to treat the
source code (e.g. `pragma once <https://en.wikipedia.org/wiki/Pragma_once>`_).
@ -77,6 +82,7 @@ registering with a username and password, all you need is an Ethereum keypair.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract Coin {

View File

@ -7,6 +7,38 @@ Source files can contain an arbitrary number of
:ref:`pragma directives<pragma>` and
:ref:`struct<structs>` and :ref:`enum<enums>` definitions.
.. index:: ! license, spdx
SPDX License Identifier
=======================
Trust in smart contract can be better established if their source code
is available. Since making source code available always touches on legal problems
with regards to copyright, the Solidity compiler encouranges the use
of machine-readable `SPDX license identifiers <https://spdx.org>`_.
Every source file should start with a comment indicating its license:
``// SPDX-License-Identifier: MIT``
The compiler does not validate that the license is part of the
`list allowed by SPDX <https://spdx.org/licenses/>`_, but
it does include the supplied string in the `bytecode metadata <metadata>`_.
If you do not want to specify a license or if the source code is
not open-source, please use the special value ``UNLICENSED``.
Supplying this comment of course does not free you from other
obligations related to licensing like having to mention
a specific license header in each source file or the
original copyright holder.
The comment is recognized by the compiler anywhere in the file at the
file level, but it is recommended to put it at the top of the file.
More information about how to use SPDX license identifiers
can be found at the `SPDX website <https://spdx.org/ids-how>`_.
.. index:: ! pragma
.. _pragma:
@ -284,6 +316,7 @@ for the two function parameters and two return variables.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.21 <0.8.0;
/** @title Shape calculator. */

View File

@ -1,3 +1,5 @@
.. _metadata:
#################
Contract Metadata
#################
@ -54,7 +56,9 @@ explanatory purposes.
// Required (unless "content" is used, see below): Sorted URL(s)
// to the source file, protocol is more or less arbitrary, but a
// Swarm URL is recommended
"urls": [ "bzzr://56ab..." ]
"urls": [ "bzzr://56ab..." ],
// Optional: SPDX license identifier as given in the source file
"license": "MIT"
},
"destructible": {
// Required: keccak256 hash of the source file

View File

@ -49,6 +49,7 @@ The following example shows a contract and a function using all available tags.
.. code:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
/// @title A simulator for trees

View File

@ -58,6 +58,7 @@ complete contract):
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
@ -81,6 +82,7 @@ as it uses ``call`` which forwards all remaining gas by default:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0;
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
@ -100,6 +102,7 @@ outlined further below:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.11 <0.8.0;
contract Fund {
@ -197,6 +200,7 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
@ -217,6 +221,7 @@ Now someone tricks you into sending Ether to the address of this attack wallet:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
interface TxUserWallet {
@ -277,6 +282,7 @@ field of a ``struct`` that is the base type of a dynamic storage array. The
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract Map {
@ -555,6 +561,7 @@ not mean loss of proving power.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
pragma experimental SMTChecker;
// This may report a warning if no SMT solver available.
@ -609,6 +616,7 @@ types.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
pragma experimental SMTChecker;
// This will report a warning

View File

@ -26,6 +26,7 @@ storage.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract SimpleStorage {
@ -46,6 +47,7 @@ Functions are the executable units of code within a contract.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract SimpleAuction {
@ -74,6 +76,7 @@ Like functions, modifiers can be :ref:`overridden <modifier-overriding>`.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract Purchase {
@ -101,6 +104,7 @@ Events are convenience interfaces with the EVM logging facilities.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.21 <0.8.0;
contract SimpleAuction {
@ -125,6 +129,7 @@ Structs are custom defined types that can group several variables (see
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract Ballot {
@ -146,6 +151,7 @@ Enums can be used to create custom types with a finite set of 'constant values'
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract Purchase {

View File

@ -55,6 +55,7 @@ Surround top level declarations in solidity source with two blank lines.
Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract A {
@ -73,6 +74,7 @@ Yes::
No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract A {
@ -92,6 +94,7 @@ Blank lines may be omitted between groups of related one-liners (such as stub fu
Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
abstract contract A {
@ -112,6 +115,7 @@ Yes::
No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
abstract contract A {
@ -246,6 +250,7 @@ Import statements should always be placed at the top of the file.
Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
import "./Owned.sol";
@ -260,6 +265,7 @@ Yes::
No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract A {
@ -293,6 +299,7 @@ Within a grouping, place the ``view`` and ``pure`` functions last.
Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract A {
@ -329,6 +336,7 @@ Yes::
No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract A {
@ -436,6 +444,7 @@ should:
Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract Coin {
@ -447,6 +456,7 @@ Yes::
No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract Coin
@ -747,6 +757,7 @@ manner as modifiers if the function declaration is long or hard to read.
Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
// Base contracts just to make this compile
@ -779,6 +790,7 @@ Yes::
No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
@ -1002,6 +1014,7 @@ As shown in the example below, if the contract name is ``Congress`` and the libr
Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
@ -1025,6 +1038,7 @@ Yes::
and in ``Congress.sol``::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
import "./Owned.sol";
@ -1036,6 +1050,7 @@ and in ``Congress.sol``::
No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
@ -1140,6 +1155,7 @@ multiline comment starting with ``/**`` and ending with ``*/``.
For example, the contract from `a simple smart contract <simple-smart-contract>`_ with the comments
added looks like the one below::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;

View File

@ -41,6 +41,7 @@ contract that returns the value at the specified address.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract MappingExample {
@ -66,6 +67,7 @@ The example below uses ``_allowances`` to record the amount someone else is allo
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;
contract MappingExample {
@ -120,6 +122,7 @@ the ``sum`` function iterates over to sum all the values.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
struct IndexValue { uint keyIndex; uint value; }

View File

@ -42,6 +42,7 @@ value it referred to previously.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
contract DeleteExample {

View File

@ -57,6 +57,7 @@ Data locations are not only relevant for persistency of data, but also for the s
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract C {
@ -167,6 +168,7 @@ or create a new memory array and copy every element.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract C {
@ -198,6 +200,7 @@ the first element to ``uint``.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract C {
@ -214,6 +217,7 @@ memory arrays, i.e. the following is not possible:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0;
// This will not compile.
@ -274,6 +278,7 @@ Array Members
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract ArrayContract {
@ -406,6 +411,7 @@ Array slices are useful to ABI-decode secondary data passed in function paramete
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
contract Proxy {
@ -443,6 +449,7 @@ shown in the following example:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
// Defines a new type with two fields.

View File

@ -543,6 +543,7 @@ subsequent unsigned integer values starting from ``0``.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
contract test {
@ -655,7 +656,13 @@ External (or public) functions have the following members:
Example that shows how to use the members::
<<<<<<< HEAD
pragma solidity >=0.6.4 <0.8.0;
=======
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.7.0;
// This will report a warning
>>>>>>> origin/develop
contract Example {
function f() public payable returns (bytes4) {
@ -670,6 +677,7 @@ Example that shows how to use the members::
Example that shows how to use internal function types::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;
library ArrayUtils {
@ -727,6 +735,7 @@ Example that shows how to use internal function types::
Another example that uses external function types::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0;

View File

@ -627,6 +627,7 @@ Assume you have the following contracts you want to update declared in ``Source.
.. code-block:: none
// This will not compile after 0.5.0
// SPDX-License-Identifier: GPL-3.0
pragma solidity >0.4.23 <0.5.0;
contract Updateable {
@ -709,6 +710,7 @@ The command above applies all changes as shown below. Please review them careful
.. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0;
abstract contract Updateable {

View File

@ -134,6 +134,12 @@ public:
return m_errorCount > 0;
}
/// @returns the number of errors (ignores warnings).
unsigned errorCount() const
{
return m_errorCount;
}
// @returns true if the maximum error count has been reached.
bool hasExcessiveErrors() const;

View File

@ -148,6 +148,11 @@ void ParserBase::parserWarning(ErrorId _error, string const& _description)
m_errorReporter.warning(_error, currentLocation(), _description);
}
void ParserBase::parserWarning(ErrorId _error, SourceLocation const& _location, string const& _description)
{
m_errorReporter.warning(_error, _location, _description);
}
void ParserBase::parserError(ErrorId _error, SourceLocation const& _location, string const& _description)
{
m_errorReporter.parserError(_error, _location, _description);

View File

@ -95,6 +95,7 @@ protected:
/// Creates a @ref ParserWarning and annotates it with the current position and the
/// given @a _description.
void parserWarning(ErrorId _error, std::string const& _description);
void parserWarning(ErrorId _error, SourceLocation const& _location, std::string const& _description);
/// Creates a @ref ParserError and annotates it with the current position and the
/// given @a _description. Throws the FatalError.

View File

@ -361,24 +361,22 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
void DeclarationTypeChecker::typeError(SourceLocation const& _location, string const& _description)
{
m_errorOccurred = true;
m_errorReporter.typeError(2311_error, _location, _description);
}
void DeclarationTypeChecker::fatalTypeError(SourceLocation const& _location, string const& _description)
{
m_errorOccurred = true;
m_errorReporter.fatalTypeError(5651_error, _location, _description);
}
void DeclarationTypeChecker::fatalDeclarationError(SourceLocation const& _location, string const& _description)
{
m_errorOccurred = true;
m_errorReporter.fatalDeclarationError(2046_error, _location, _description);
}
bool DeclarationTypeChecker::check(ASTNode const& _node)
{
unsigned errorCount = m_errorReporter.errorCount();
_node.accept(*this);
return !m_errorOccurred;
return m_errorReporter.errorCount() == errorCount;
}

View File

@ -69,7 +69,6 @@ private:
void fatalDeclarationError(langutil::SourceLocation const& _location, std::string const& _description);
langutil::ErrorReporter& m_errorReporter;
bool m_errorOccurred = false;
langutil::EVMVersion m_evmVersion;
bool m_insideFunctionType = false;
bool m_recursiveStructSeen = false;

View File

@ -2866,6 +2866,8 @@ bool TypeChecker::visit(IndexRangeAccess const& _access)
if (arrayType->location() != DataLocation::CallData || !arrayType->isDynamicallySized())
m_errorReporter.typeError(1227_error, _access.location(), "Index range access is only supported for dynamic calldata arrays.");
else if (arrayType->baseType()->isDynamicallyEncoded())
m_errorReporter.typeError(1878_error, _access.location(), "Index range access is not supported for arrays with dynamically encoded base types.");
_access.annotation().type = TypeProvider::arraySlice(*arrayType);
_access.annotation().isLValue = isLValue;
_access.annotation().isPure = isPure;

View File

@ -156,19 +156,26 @@ std::vector<T const*> ASTNode::filteredNodes(std::vector<ASTPointer<ASTNode>> co
class SourceUnit: public ASTNode
{
public:
SourceUnit(int64_t _id, SourceLocation const& _location, std::vector<ASTPointer<ASTNode>> _nodes):
ASTNode(_id, _location), m_nodes(std::move(_nodes)) {}
SourceUnit(
int64_t _id,
SourceLocation const& _location,
std::optional<std::string> _licenseString,
std::vector<ASTPointer<ASTNode>> _nodes
):
ASTNode(_id, _location), m_licenseString(std::move(_licenseString)), m_nodes(std::move(_nodes)) {}
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;
SourceUnitAnnotation& annotation() const override;
std::optional<std::string> const& licenseString() const { return m_licenseString; }
std::vector<ASTPointer<ASTNode>> nodes() const { return m_nodes; }
/// @returns a set of referenced SourceUnits. Recursively if @a _recurse is true.
std::set<SourceUnit const*> referencedSourceUnits(bool _recurse = false, std::set<SourceUnit const*> _skipList = std::set<SourceUnit const*>()) const;
private:
std::optional<std::string> m_licenseString;
std::vector<ASTPointer<ASTNode>> m_nodes;
};

View File

@ -225,6 +225,7 @@ bool ASTJsonConverter::visit(SourceUnit const& _node)
{
make_pair("absolutePath", _node.annotation().path),
make_pair("exportedSymbols", move(exportedSymbols)),
make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
make_pair("nodes", toJson(_node.nodes()))
}
);

View File

@ -218,10 +218,15 @@ ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js
ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _node, string const& _srcName)
{
optional<string> license;
if (_node.isMember("license") && !_node["license"].isNull())
license = _node["license"].asString();
vector<ASTPointer<ASTNode>> nodes;
for (auto& child: member(_node, "nodes"))
nodes.emplace_back(convertJsonToASTNode(child));
ASTPointer<SourceUnit> tmp = createASTNode<SourceUnit>(_node, nodes);
ASTPointer<SourceUnit> tmp = createASTNode<SourceUnit>(_node, license, nodes);
tmp->annotation().path = _srcName;
return tmp;
}

View File

@ -330,7 +330,7 @@ TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c
// Structs are fine in the following circumstances:
// - ABIv2 or,
// - storage struct for a library
if (_inLibraryCall && encodingType->dataStoredIn(DataLocation::Storage))
if (_inLibraryCall && encodingType && encodingType->dataStoredIn(DataLocation::Storage))
return encodingType;
TypePointer baseType = encodingType;
while (auto const* arrayType = dynamic_cast<ArrayType const*>(baseType))
@ -613,6 +613,13 @@ TypeResult IntegerType::binaryOperatorResult(Token _operator, Type const* _other
}
else if (dynamic_cast<FixedPointType const*>(_other))
return nullptr;
else if (auto rationalNumberType = dynamic_cast<RationalNumberType const*>(_other))
{
if (rationalNumberType->isFractional())
return TypeResult::err("Exponent is fractional.");
if (!rationalNumberType->integerType())
return TypeResult::err("Exponent too large.");
}
return this;
}
@ -1964,6 +1971,19 @@ string ArraySliceType::toString(bool _short) const
return m_arrayType.toString(_short) + " slice";
}
TypePointer ArraySliceType::mobileType() const
{
if (
m_arrayType.dataStoredIn(DataLocation::CallData) &&
m_arrayType.isDynamicallySized() &&
!m_arrayType.baseType()->isDynamicallyEncoded()
)
return &m_arrayType;
else
return this;
}
std::vector<std::tuple<std::string, TypePointer>> ArraySliceType::makeStackItems() const
{
return {{"offset", TypeProvider::uint256()}, {"length", TypeProvider::uint256()}};

View File

@ -831,6 +831,7 @@ public:
bool isDynamicallyEncoded() const override { return true; }
bool canLiveOutsideStorage() const override { return m_arrayType.canLiveOutsideStorage(); }
std::string toString(bool _short) const override;
TypePointer mobileType() const override;
BoolResult validForLocation(DataLocation _loc) const override { return m_arrayType.validForLocation(_loc); }

View File

@ -279,31 +279,47 @@ string ABIFunctions::abiEncodingFunction(
return abiEncodingFunctionStringLiteral(_from, to, _options);
else if (auto toArray = dynamic_cast<ArrayType const*>(&to))
{
solAssert(_from.category() == Type::Category::Array, "");
solAssert(to.dataStoredIn(DataLocation::Memory), "");
ArrayType const& fromArray = dynamic_cast<ArrayType const&>(_from);
ArrayType const* fromArray = nullptr;
switch (_from.category())
{
case Type::Category::Array:
fromArray = dynamic_cast<ArrayType const*>(&_from);
break;
case Type::Category::ArraySlice:
fromArray = &dynamic_cast<ArraySliceType const*>(&_from)->arrayType();
solAssert(
fromArray->dataStoredIn(DataLocation::CallData) &&
fromArray->isDynamicallySized() &&
!fromArray->baseType()->isDynamicallyEncoded(),
""
);
break;
default:
solAssert(false, "");
break;
}
switch (fromArray.location())
switch (fromArray->location())
{
case DataLocation::CallData:
if (
fromArray.isByteArray() ||
*fromArray.baseType() == *TypeProvider::uint256() ||
*fromArray.baseType() == FixedBytesType(32)
fromArray->isByteArray() ||
*fromArray->baseType() == *TypeProvider::uint256() ||
*fromArray->baseType() == FixedBytesType(32)
)
return abiEncodingFunctionCalldataArrayWithoutCleanup(fromArray, *toArray, _options);
return abiEncodingFunctionCalldataArrayWithoutCleanup(*fromArray, *toArray, _options);
else
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options);
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
case DataLocation::Memory:
if (fromArray.isByteArray())
return abiEncodingFunctionMemoryByteArray(fromArray, *toArray, _options);
if (fromArray->isByteArray())
return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options);
else
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options);
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
case DataLocation::Storage:
if (fromArray.baseType()->storageBytes() <= 16)
return abiEncodingFunctionCompactStorageArray(fromArray, *toArray, _options);
if (fromArray->baseType()->storageBytes() <= 16)
return abiEncodingFunctionCompactStorageArray(*fromArray, *toArray, _options);
else
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options);
return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
default:
solAssert(false, "");
}

View File

@ -480,6 +480,16 @@ void CompilerUtils::encodeToMemory(
convertType(*_givenTypes[i], *targetType, true);
if (auto arrayType = dynamic_cast<ArrayType const*>(type))
ArrayUtils(m_context).copyArrayToMemory(*arrayType, _padToWordBoundaries);
else if (auto arraySliceType = dynamic_cast<ArraySliceType const*>(type))
{
solAssert(
arraySliceType->dataStoredIn(DataLocation::CallData) &&
arraySliceType->isDynamicallySized() &&
!arraySliceType->arrayType().baseType()->isDynamicallyEncoded(),
""
);
ArrayUtils(m_context).copyArrayToMemory(arraySliceType->arrayType(), _padToWordBoundaries);
}
else
storeInMemoryDynamic(*type, _padToWordBoundaries);
}
@ -516,22 +526,39 @@ void CompilerUtils::encodeToMemory(
}
else
{
solAssert(_givenTypes[i]->category() == Type::Category::Array, "Unknown dynamic type.");
auto const& arrayType = dynamic_cast<ArrayType const&>(*_givenTypes[i]);
ArrayType const* arrayType = nullptr;
switch (_givenTypes[i]->category())
{
case Type::Category::Array:
arrayType = dynamic_cast<ArrayType const*>(_givenTypes[i]);
break;
case Type::Category::ArraySlice:
arrayType = &dynamic_cast<ArraySliceType const*>(_givenTypes[i])->arrayType();
solAssert(
arrayType->isDynamicallySized() &&
arrayType->dataStoredIn(DataLocation::CallData) &&
!arrayType->baseType()->isDynamicallyEncoded(),
""
);
break;
default:
solAssert(false, "Unknown dynamic type.");
break;
}
// now copy the array
copyToStackTop(argSize - stackPos + dynPointers + 2, arrayType.sizeOnStack());
copyToStackTop(argSize - stackPos + dynPointers + 2, arrayType->sizeOnStack());
// stack: ... <end_of_mem> <value...>
// copy length to memory
m_context << dupInstruction(1 + arrayType.sizeOnStack());
ArrayUtils(m_context).retrieveLength(arrayType, 1);
m_context << dupInstruction(1 + arrayType->sizeOnStack());
ArrayUtils(m_context).retrieveLength(*arrayType, 1);
// stack: ... <end_of_mem> <value...> <end_of_mem'> <length>
storeInMemoryDynamic(*TypeProvider::uint256(), true);
// stack: ... <end_of_mem> <value...> <end_of_mem''>
// copy the new memory pointer
m_context << swapInstruction(arrayType.sizeOnStack() + 1) << Instruction::POP;
m_context << swapInstruction(arrayType->sizeOnStack() + 1) << Instruction::POP;
// stack: ... <end_of_mem''> <value...>
// copy data part
ArrayUtils(m_context).copyArrayToMemory(arrayType, _padToWordBoundaries);
ArrayUtils(m_context).copyArrayToMemory(*arrayType, _padToWordBoundaries);
// stack: ... <end_of_mem'''>
}
@ -990,7 +1017,8 @@ void CompilerUtils::convertType(
solAssert(_targetType == typeOnStack.arrayType(), "");
solUnimplementedAssert(
typeOnStack.arrayType().location() == DataLocation::CallData &&
typeOnStack.arrayType().isDynamicallySized(),
typeOnStack.arrayType().isDynamicallySized() &&
!typeOnStack.arrayType().baseType()->isDynamicallyEncoded(),
""
);
break;

View File

@ -1769,7 +1769,12 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
case Type::Category::ArraySlice:
{
auto const& arrayType = dynamic_cast<ArraySliceType const&>(baseType).arrayType();
solAssert(arrayType.location() == DataLocation::CallData && arrayType.isDynamicallySized(), "");
solAssert(
arrayType.location() == DataLocation::CallData &&
arrayType.isDynamicallySized() &&
!arrayType.baseType()->isDynamicallyEncoded(),
""
);
solAssert(_indexAccess.indexExpression(), "Index expression expected.");
acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true);
@ -1852,7 +1857,12 @@ bool ExpressionCompiler::visit(IndexRangeAccess const& _indexAccess)
arrayType = &sliceType->arrayType();
solAssert(arrayType, "");
solUnimplementedAssert(arrayType->location() == DataLocation::CallData && arrayType->isDynamicallySized(), "");
solUnimplementedAssert(
arrayType->location() == DataLocation::CallData &&
arrayType->isDynamicallySized() &&
!arrayType->baseType()->isDynamicallyEncoded(),
""
);
if (_indexAccess.startExpression())
acceptAndConvert(*_indexAccess.startExpression(), *TypeProvider::uint256());

View File

@ -1599,6 +1599,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
ArraySliceType const& fromType = dynamic_cast<ArraySliceType const&>(_from);
ArrayType const& targetType = dynamic_cast<ArrayType const&>(_to);
solAssert(!fromType.arrayType().baseType()->isDynamicallyEncoded(), "");
solAssert(
*fromType.arrayType().baseType() == *targetType.baseType(),
"Converting arrays of different type is not possible"

View File

@ -1236,6 +1236,8 @@ string CompilerStack::createMetadata(Contract const& _contract) const
solAssert(s.second.scanner, "Scanner not available");
meta["sources"][s.first]["keccak256"] = "0x" + toHex(s.second.keccak256().asBytes());
if (optional<string> licenseString = s.second.ast->licenseString())
meta["sources"][s.first]["license"] = *licenseString;
if (m_metadataLiteralSources)
meta["sources"][s.first]["content"] = s.second.scanner->source();
else

View File

@ -30,8 +30,11 @@
#include <liblangutil/SemVerHandler.h>
#include <liblangutil/SourceLocation.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <cctype>
#include <vector>
#include <regex>
using namespace std;
using namespace solidity::langutil;
@ -79,6 +82,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
m_recursionDepth = 0;
m_scanner = _scanner;
ASTNodeFactory nodeFactory(*this);
vector<ASTPointer<ASTNode>> nodes;
while (m_scanner->currentToken() != Token::EOS)
{
@ -107,7 +111,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
}
}
solAssert(m_recursionDepth == 0, "");
return nodeFactory.createNode<SourceUnit>(nodes);
return nodeFactory.createNode<SourceUnit>(findLicenseString(nodes), nodes);
}
catch (FatalError const&)
{
@ -1981,6 +1985,60 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars
return ret;
}
optional<string> Parser::findLicenseString(std::vector<ASTPointer<ASTNode>> const& _nodes)
{
// We circumvent the scanner here, because it skips non-docstring comments.
static regex const licenseRegex("SPDX-License-Identifier:\\s*([a-zA-Z0-9 ()+.-]+)");
// Search inside all parts of the source not covered by parsed nodes.
// This will leave e.g. "global comments".
string const& source = m_scanner->source();
using iter = decltype(source.begin());
vector<pair<iter, iter>> sequencesToSearch;
sequencesToSearch.emplace_back(source.begin(), source.end());
for (ASTPointer<ASTNode> const& node: _nodes)
if (node->location().hasText())
{
sequencesToSearch.back().second = source.begin() + node->location().start;
sequencesToSearch.emplace_back(source.begin() + node->location().end, source.end());
}
vector<string> matches;
for (auto const& [start, end]: sequencesToSearch)
{
smatch match;
if (regex_search(start, end, match, licenseRegex))
{
string license{boost::trim_copy(string(match[1]))};
if (!license.empty())
matches.emplace_back(std::move(license));
}
}
if (matches.size() == 1)
return matches.front();
else if (matches.empty())
parserWarning(
1878_error,
{-1, -1, m_scanner->charStream()},
"SPDX license identifier not provided in source file. "
"Before publishing, consider adding a comment containing "
"\"SPDX-License-Identifier: <SPDX-License>\" to each source file. "
"Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. "
"Please see https://spdx.org for more information."
);
else
parserError(
3716_error,
{-1, -1, m_scanner->charStream()},
"Multiple SPDX license identifiers found in source file. "
"Use \"AND\" or \"OR\" to combine multiple licenses. "
"Please see https://spdx.org for more information."
);
return {};
}
Parser::LookAheadInfo Parser::peekStatementType() const
{
// Distinguish between variable declaration (and potentially assignment) and expression statement

View File

@ -175,6 +175,8 @@ private:
bool empty() const;
};
std::optional<std::string> findLicenseString(std::vector<ASTPointer<ASTNode>> const& _nodes);
/// Returns the next AST node ID
int64_t nextID() { return ++m_currentNodeID; }

View File

@ -188,5 +188,39 @@ string solidity::util::formatAsStringOrNumber(string const& _value)
if (c <= 0x1f || c >= 0x7f || c == '"')
return "0x" + h256(_value, h256::AlignLeft).hex();
return "\"" + _value + "\"";
return escapeAndQuoteString(_value);
}
string solidity::util::escapeAndQuoteString(string const& _input)
{
string out;
for (char c: _input)
if (c == '\\')
out += "\\\\";
else if (c == '"')
out += "\\\"";
else if (c == '\b')
out += "\\b";
else if (c == '\f')
out += "\\f";
else if (c == '\n')
out += "\\n";
else if (c == '\r')
out += "\\r";
else if (c == '\t')
out += "\\t";
else if (c == '\v')
out += "\\v";
else if (!isprint(c, locale::classic()))
{
ostringstream o;
o << "\\x" << std::hex << setfill('0') << setw(2) << (unsigned)(unsigned char)(c);
out += o.str();
}
else
out += c;
return "\"" + std::move(out) + "\"";
}

View File

@ -460,6 +460,10 @@ bool isValidDecimal(std::string const& _string);
/// _value cannot be longer than 32 bytes.
std::string formatAsStringOrNumber(std::string const& _value);
/// @returns a string with the usual backslash-escapes for non-ASCII
/// characters and surrounded by '"'-characters.
std::string escapeAndQuoteString(std::string const& _input);
template<typename Container, typename Compare>
bool containerEqual(Container const& _lhs, Container const& _rhs, Compare&& _compare)
{

View File

@ -55,33 +55,7 @@ string AsmPrinter::operator()(Literal const& _literal) const
break;
}
string out;
for (char c: _literal.value.str())
if (c == '\\')
out += "\\\\";
else if (c == '"')
out += "\\\"";
else if (c == '\b')
out += "\\b";
else if (c == '\f')
out += "\\f";
else if (c == '\n')
out += "\\n";
else if (c == '\r')
out += "\\r";
else if (c == '\t')
out += "\\t";
else if (c == '\v')
out += "\\v";
else if (!isprint(c, locale::classic()))
{
ostringstream o;
o << std::hex << setfill('0') << setw(2) << (unsigned)(unsigned char)(c);
out += "\\x" + o.str();
}
else
out += c;
return "\"" + out + "\"" + appendTypeName(_literal.type);
return escapeAndQuoteString(_literal.value.str()) + appendTypeName(_literal.type);
}
string AsmPrinter::operator()(Identifier const& _identifier) const

View File

@ -358,13 +358,13 @@ bytes BinaryTransform::operator()(If const& _if)
toBytes(Opcode::If) +
toBytes(ValueType::Void);
m_labels.push({});
m_labels.emplace_back();
result += visit(_if.statements);
if (_if.elseStatements)
result += toBytes(Opcode::Else) + visit(*_if.elseStatements);
m_labels.pop();
m_labels.pop_back();
result += toBytes(Opcode::End);
return result;
@ -374,26 +374,24 @@ bytes BinaryTransform::operator()(Loop const& _loop)
{
bytes result = toBytes(Opcode::Loop) + toBytes(ValueType::Void);
m_labels.push(_loop.labelName);
m_labels.emplace_back(_loop.labelName);
result += visit(_loop.statements);
m_labels.pop();
m_labels.pop_back();
result += toBytes(Opcode::End);
return result;
}
bytes BinaryTransform::operator()(Break const&)
bytes BinaryTransform::operator()(Break const& _break)
{
yulAssert(false, "br not yet implemented.");
// TODO the index is just the nesting depth.
return {};
return toBytes(Opcode::Br) + encodeLabelIdx(_break.label.name);
}
bytes BinaryTransform::operator()(BreakIf const&)
bytes BinaryTransform::operator()(BreakIf const& _breakIf)
{
yulAssert(false, "br_if not yet implemented.");
// TODO the index is just the nesting depth.
return {};
bytes result = std::visit(*this, *_breakIf.condition);
result += toBytes(Opcode::BrIf) + encodeLabelIdx(_breakIf.label.name);
return result;
}
bytes BinaryTransform::operator()(Return const&)
@ -403,11 +401,14 @@ bytes BinaryTransform::operator()(Return const&)
bytes BinaryTransform::operator()(Block const& _block)
{
return
m_labels.emplace_back(_block.labelName);
bytes result =
toBytes(Opcode::Block) +
toBytes(ValueType::Void) +
visit(_block.statements) +
toBytes(Opcode::End);
m_labels.pop_back();
return result;
}
bytes BinaryTransform::operator()(FunctionDefinition const& _function)
@ -427,9 +428,13 @@ bytes BinaryTransform::operator()(FunctionDefinition const& _function)
for (size_t i = 0; i < _function.locals.size(); ++i)
m_locals[_function.locals[i].variableName] = varIdx++;
yulAssert(m_labels.empty(), "Stray labels.");
ret += visit(_function.body);
ret += toBytes(Opcode::End);
yulAssert(m_labels.empty(), "Stray labels.");
return prefixSize(std::move(ret));
}
@ -581,6 +586,18 @@ bytes BinaryTransform::visitReversed(vector<Expression> const& _expressions)
return result;
}
bytes BinaryTransform::encodeLabelIdx(string const& _label) const
{
yulAssert(!_label.empty(), "Empty label.");
size_t depth = 0;
for (string const& label: m_labels | boost::adaptors::reversed)
if (label == _label)
return lebEncode(depth);
else
++depth;
yulAssert(false, "Label not found.");
}
bytes BinaryTransform::encodeName(std::string const& _name)
{
// UTF-8 is allowed here by the Wasm spec, but since all names here should stem from

View File

@ -77,13 +77,15 @@ private:
bytes visit(std::vector<wasm::Expression> const& _expressions);
bytes visitReversed(std::vector<wasm::Expression> const& _expressions);
bytes encodeLabelIdx(std::string const& _label) const;
static bytes encodeName(std::string const& _name);
std::map<std::string, size_t> m_locals;
std::map<std::string, size_t> m_globals;
std::map<std::string, size_t> m_functions;
std::map<std::string, size_t> m_functionTypes;
std::stack<std::string> m_labels;
std::vector<std::string> m_labels;
std::map<std::string, std::pair<size_t, size_t>> m_subModulePosAndSize;
};

View File

@ -123,7 +123,7 @@ string TextTransform::operator()(wasm::Loop const& _loop)
string TextTransform::operator()(wasm::Break const& _break)
{
return "(break $" + _break.label.name + ")\n";
return "(br $" + _break.label.name + ")\n";
}
string TextTransform::operator()(wasm::BreakIf const& _break)

View File

@ -52,7 +52,7 @@ def extract_docs_cases(path):
if inside:
extractedLines[-1] += l + '\n'
codeStart = "(pragma solidity|contract.*{|library.*{|interface.*{)"
codeStart = "(// SPDX-License-Identifier:|pragma solidity|contract.*{|library.*{|interface.*{)"
# Filter all tests that do not contain Solidity or are intended incorrectly.
for lines in extractedLines:

View File

@ -81,12 +81,14 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
m_evmRevision = EVMC_BYZANTIUM;
else if (_evmVersion == langutil::EVMVersion::constantinople())
m_evmRevision = EVMC_CONSTANTINOPLE;
else if (_evmVersion == langutil::EVMVersion::petersburg())
m_evmRevision = EVMC_PETERSBURG;
else if (_evmVersion == langutil::EVMVersion::istanbul())
m_evmRevision = EVMC_ISTANBUL;
else if (_evmVersion == langutil::EVMVersion::berlin())
assertThrow(false, Exception, "Berlin is not supported yet.");
else //if (_evmVersion == langutil::EVMVersion::petersburg())
m_evmRevision = EVMC_PETERSBURG;
m_evmRevision = EVMC_BERLIN;
else
assertThrow(false, Exception, "Unsupported EVM version");
// Mark all precompiled contracts as existing. Existing here means to have a balance (as per EIP-161).
// NOTE: keep this in sync with `EVMHost::call` below.
@ -99,17 +101,16 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
evmc::address address{};
address.bytes[19] = precompiledAddress;
// 1wei
accounts[address].balance.bytes[31] = 1;
accounts[address].balance = evmc::uint256be{1};
}
// TODO: support short literals in EVMC and use them here
tx_context.block_difficulty = convertToEVMC(u256("200000000"));
tx_context.block_difficulty = evmc::uint256be{200000000};
tx_context.block_gas_limit = 20000000;
tx_context.block_coinbase = 0x7878787878787878787878787878787878787878_address;
tx_context.tx_gas_price = convertToEVMC(u256("3000000000"));
tx_context.tx_gas_price = evmc::uint256be{3000000000};
tx_context.tx_origin = 0x9292929292929292929292929292929292929292_address;
// Mainnet according to EIP-155
tx_context.chain_id = convertToEVMC(u256(1));
tx_context.chain_id = evmc::uint256be{1};
}
void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
pragma experimental ABIEncoderV2;
contract C {
struct S { uint x; }
function f(S memory) public pure {

View File

@ -0,0 +1 @@
--assemble --optimize --yul-dialect evm --machine ewasm

View File

@ -0,0 +1 @@
Warning: Yul is still experimental. Please use the output with care.

View File

@ -0,0 +1,8 @@
{
let x := calldataload(0)
for { } lt(x, 10) { x := add(x, 1) } {
if eq(x, 2) { break }
if eq(x, 4) { continue }
}
sstore(0, x)
}

View File

@ -0,0 +1,551 @@
======= evm_to_wasm_break/input.sol (Ewasm) =======
Pretty printed source:
object "object" {
code {
{
let x := calldataload(0)
for { } lt(x, 10) { x := add(x, 1) }
{
if eq(x, 2) { break }
if eq(x, 4) { continue }
}
sstore(0, x)
}
}
}
==========================
Translated source:
object "object" {
code {
function main()
{
let _1 := 0
let x, x_1, x_2, x_3 := calldataload(_1, _1, _1, _1)
let x_4 := x
let x_5 := x_1
let x_6 := x_2
let x_7 := x_3
let _2 := 1
let _3:i32 := i32.eqz(i32.eqz(i64.eqz(i64.or(i64.or(_1, _1), i64.or(_1, _2)))))
for { }
i32.eqz(_3)
{
let x_8, x_9, x_10, x_11 := add(x_4, x_5, x_6, x_7, _1, _1, _1, _2)
x_4 := x_8
x_5 := x_9
x_6 := x_10
x_7 := x_11
}
{
let _4, _5, _6, _7 := lt(x_4, x_5, x_6, x_7, _1, _1, _1, 10)
let _8, _9, _10, _11 := iszero(_4, _5, _6, _7)
if i32.eqz(i64.eqz(i64.or(i64.or(_8, _9), i64.or(_10, _11)))) { break }
let _12, _13, _14, _15 := eq(x_4, x_5, x_6, x_7, _1, _1, _1, 2)
if i32.eqz(i64.eqz(i64.or(i64.or(_12, _13), i64.or(_14, _15)))) { break }
let _16, _17, _18, _19 := eq(x_4, x_5, x_6, x_7, _1, _1, _1, 4)
if i32.eqz(i64.eqz(i64.or(i64.or(_16, _17), i64.or(_18, _19)))) { continue }
}
sstore(_1, _1, _1, _1, x_4, x_5, x_6, x_7)
}
function add_carry(x, y, c) -> r, r_c
{
let t := i64.add(x, y)
r := i64.add(t, c)
r_c := i64.extend_i32_u(i32.or(i64.lt_u(t, x), i64.lt_u(r, t)))
}
function add(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4
{
let t := i64.add(x4, y4)
r4 := i64.add(t, 0)
let r3_1, carry := add_carry(x3, y3, i64.extend_i32_u(i32.or(i64.lt_u(t, x4), i64.lt_u(r4, t))))
r3 := r3_1
let r2_1, carry_1 := add_carry(x2, y2, carry)
r2 := r2_1
let r1_1, carry_2 := add_carry(x1, y1, carry_1)
r1 := r1_1
}
function iszero(x1, x2, x3, x4) -> r1, r2, r3, r4
{
r4 := i64.extend_i32_u(i64.eqz(i64.or(i64.or(x1, x2), i64.or(x3, x4))))
}
function eq(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4
{
if i64.eq(x1, y1)
{
if i64.eq(x2, y2)
{
if i64.eq(x3, y3) { if i64.eq(x4, y4) { r4 := 1 } }
}
}
}
function cmp(a, b) -> r:i32
{
switch i64.lt_u(a, b)
case 1:i32 { r := 0xffffffff:i32 }
default { r := i64.ne(a, b) }
}
function lt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4
{
let z:i32 := false
switch cmp(x1, y1)
case 0:i32 {
switch cmp(x2, y2)
case 0:i32 {
switch cmp(x3, y3)
case 0:i32 { z := i64.lt_u(x4, y4) }
case 1:i32 { z := 0:i32 }
default { z := 1:i32 }
}
case 1:i32 { z := 0:i32 }
default { z := 1:i32 }
}
case 1:i32 { z := 0:i32 }
default { z := 1:i32 }
z4 := i64.extend_i32_u(z)
}
function calldataload(x1, x2, x3, x4) -> z1, z2, z3, z4
{
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { unreachable() }
if i64.ne(0, i64.shr_u(x4, 32)) { unreachable() }
eth.callDataCopy(0:i32, i32.wrap_i64(x4), 32:i32)
let z1_1 := endian_swap(i64.load(0:i32))
let z2_1 := endian_swap(i64.load(i32.add(0:i32, 8:i32)))
let z3_1 := endian_swap(i64.load(i32.add(0:i32, 16:i32)))
let z4_1 := endian_swap(i64.load(i32.add(0:i32, 24:i32)))
z1 := z1_1
z2 := z2_1
z3 := z3_1
z4 := z4_1
}
function endian_swap_16(x) -> y
{
y := i64.or(i64.and(i64.shl(x, 8), 0xff00), i64.and(i64.shr_u(x, 8), 0xff))
}
function endian_swap_32(x) -> y
{
let hi := i64.shl(endian_swap_16(x), 16)
y := i64.or(hi, endian_swap_16(i64.shr_u(x, 16)))
}
function endian_swap(x) -> y
{
let hi := i64.shl(endian_swap_32(x), 32)
y := i64.or(hi, endian_swap_32(i64.shr_u(x, 32)))
}
function mstore_internal(pos:i32, y1, y2, y3, y4)
{
i64.store(pos, endian_swap(y1))
i64.store(i32.add(pos, 8:i32), endian_swap(y2))
i64.store(i32.add(pos, 16:i32), endian_swap(y3))
i64.store(i32.add(pos, 24:i32), endian_swap(y4))
}
function sstore(x1, x2, x3, x4, y1, y2, y3, y4)
{
mstore_internal(0:i32, x1, x2, x3, x4)
mstore_internal(32:i32, y1, y2, y3, y4)
eth.storageStore(0:i32, 32:i32)
}
}
}
Binary representation:
0061736d0100000001480a60000060017e017e60027e7e017e60037e7e7e017e60047e7e7e7e017e60057e7e7e7e7e0060087e7e7e7e7e7e7e7e0060087e7e7e7e7e7e7e7e017e60027f7f0060037f7f7f0002310208657468657265756d0c73746f7261676553746f7265000808657468657265756d0c63616c6c44617461436f70790009030e0d0003070407020704010101050605030100010610037e0142000b7e0142000b7e0142000b071102066d656d6f72790200046d61696e00020a80090dee02011f7e4200210002402000200020002000100921012300210223012103230221040b2001210520022106200321072004210842012109200020008420002009848450ada745ada745ad210a02400340200aa745ad500d01024002402005200620072008200020002000420a1008210b2300210c2301210d2302210e0b0240200b200c200d200e1005210f2300211023012111230221120b200f20108420112012848450ada745ad42005204400c030b024020052006200720082000200020004202100621132300211423012115230221160b201320148420152016848450ada745ad42005204400c030b0240200520062007200820002000200042041006211723002118230121192302211a0b20172018842019201a848450ada745ad42005204400c010b0b0240200520062007200820002000200020091004211b2300211c2301211d2302211e0b201b2105201c2106201d2107201e21080b0b20002000200020002005200620072008100e0b2c01037e200020017c2105200520027c21032005200054ada72003200554ada772ada7ad21042004240020030b6f010b7e200320077c210c200c42007c210b024020022006200c200354ada7200b200c54ada772ada7ad1003210d2300210e0b200d210a024020012005200e1003210f230021100b200f2109024020002004201010032111230021120b2011210820092400200a2401200b240220080b2301047e200020018420022003848450ada7ad210720052400200624012007240220040b4601047e2000200451ad42005204402001200551ad42005204402002200651ad42005204402003200751ad42005204404201210b0b0b0b0b20092400200a2401200b240220080b2a01027e02402000200154ad21032003420151044042ffffffff0f2102052000200152ad21020b0b20020b930101087e4200210c0240200020041007210d200d42005104400240200120051007210e200e42005104400240200220061007210f200f42005104402003200754ad210c05200f42015104404200210c054201210c0b0b0b05200e42015104404200210c054201210c0b0b0b05200d42015104404200210c054201210c0b0b0b200ca7ad210b20092400200a2401200b240220080b8c0101087e4200200020018420028452ad4200520440000b4200200342208852ad4200520440000b4200a72003a7ada74220a710014200a7290300100c21084200a74208a76aada7290300100c21094200a74210a76aada7290300100c210a4200a74218a76aada7290300100c210b2008210420092105200a2106200b210720052400200624012007240220040b1c01017e20004208864280fe0383200042088842ff018384210120010b1b01027e2000100a421086210220022000421088100a84210120010b1b01027e2000100b422086210220022000422088100b84210120010b3e01007e2000a72001100c3703002000a74208a76aada72002100c3703002000a74210a76aada72003100c3703002000a74218a76aada72004100c3703000b2401007e42002000200120022003100d42202004200520062007100d4200a74220a710000b
Text representation:
(module
(import "ethereum" "storageStore" (func $eth.storageStore (param i32 i32)))
(import "ethereum" "callDataCopy" (func $eth.callDataCopy (param i32 i32 i32)))
(memory $memory (export "memory") 1)
(export "main" (func $main))
(global $global_ (mut i64) (i64.const 0))
(global $global__1 (mut i64) (i64.const 0))
(global $global__2 (mut i64) (i64.const 0))
(func $main
(local $_1 i64)
(local $x i64)
(local $x_1 i64)
(local $x_2 i64)
(local $x_3 i64)
(local $x_4 i64)
(local $x_5 i64)
(local $x_6 i64)
(local $x_7 i64)
(local $_2 i64)
(local $_3 i64)
(local $_4 i64)
(local $_5 i64)
(local $_6 i64)
(local $_7 i64)
(local $_8 i64)
(local $_9 i64)
(local $_10 i64)
(local $_11 i64)
(local $_12 i64)
(local $_13 i64)
(local $_14 i64)
(local $_15 i64)
(local $_16 i64)
(local $_17 i64)
(local $_18 i64)
(local $_19 i64)
(local $x_8 i64)
(local $x_9 i64)
(local $x_10 i64)
(local $x_11 i64)
(local.set $_1 (i64.const 0))
(block
(local.set $x (call $calldataload (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)))
(local.set $x_1 (global.get $global_))
(local.set $x_2 (global.get $global__1))
(local.set $x_3 (global.get $global__2))
)
(local.set $x_4 (local.get $x))
(local.set $x_5 (local.get $x_1))
(local.set $x_6 (local.get $x_2))
(local.set $x_7 (local.get $x_3))
(local.set $_2 (i64.const 1))
(local.set $_3 (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $_1) (local.get $_1)) (i64.or (local.get $_1) (local.get $_2))))))))))))
(block $label_
(loop
(br_if $label_ (i64.eqz (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (local.get $_3))))))
(block $label__3
(block
(local.set $_4 (call $lt (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 10)))
(local.set $_5 (global.get $global_))
(local.set $_6 (global.get $global__1))
(local.set $_7 (global.get $global__2))
)
(block
(local.set $_8 (call $iszero (local.get $_4) (local.get $_5) (local.get $_6) (local.get $_7)))
(local.set $_9 (global.get $global_))
(local.set $_10 (global.get $global__1))
(local.set $_11 (global.get $global__2))
)
(if (i64.ne (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $_8) (local.get $_9)) (i64.or (local.get $_10) (local.get $_11)))))))) (i64.const 0)) (then
(br $label_)
))
(block
(local.set $_12 (call $eq (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 2)))
(local.set $_13 (global.get $global_))
(local.set $_14 (global.get $global__1))
(local.set $_15 (global.get $global__2))
)
(if (i64.ne (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $_12) (local.get $_13)) (i64.or (local.get $_14) (local.get $_15)))))))) (i64.const 0)) (then
(br $label_)
))
(block
(local.set $_16 (call $eq (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 4)))
(local.set $_17 (global.get $global_))
(local.set $_18 (global.get $global__1))
(local.set $_19 (global.get $global__2))
)
(if (i64.ne (i64.extend_i32_u (i32.eqz (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $_16) (local.get $_17)) (i64.or (local.get $_18) (local.get $_19)))))))) (i64.const 0)) (then
(br $label__3)
))
)
(block
(local.set $x_8 (call $add (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_2)))
(local.set $x_9 (global.get $global_))
(local.set $x_10 (global.get $global__1))
(local.set $x_11 (global.get $global__2))
)
(local.set $x_4 (local.get $x_8))
(local.set $x_5 (local.get $x_9))
(local.set $x_6 (local.get $x_10))
(local.set $x_7 (local.get $x_11))
)
)
(call $sstore (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7))
)
(func $add_carry
(param $x i64)
(param $y i64)
(param $c i64)
(result i64)
(local $r i64)
(local $r_c i64)
(local $t i64)
(local.set $t (i64.add (local.get $x) (local.get $y)))
(local.set $r (i64.add (local.get $t) (local.get $c)))
(local.set $r_c (i64.extend_i32_u (i32.wrap_i64 (i64.extend_i32_u (i32.or (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $t) (local.get $x)))) (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $r) (local.get $t)))))))))
(global.set $global_ (local.get $r_c))
(local.get $r)
)
(func $add
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(result i64)
(local $r1 i64)
(local $r2 i64)
(local $r3 i64)
(local $r4 i64)
(local $t i64)
(local $r3_1 i64)
(local $carry i64)
(local $r2_1 i64)
(local $carry_1 i64)
(local $r1_1 i64)
(local $carry_2 i64)
(local.set $t (i64.add (local.get $x4) (local.get $y4)))
(local.set $r4 (i64.add (local.get $t) (i64.const 0)))
(block
(local.set $r3_1 (call $add_carry (local.get $x3) (local.get $y3) (i64.extend_i32_u (i32.wrap_i64 (i64.extend_i32_u (i32.or (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $t) (local.get $x4)))) (i32.wrap_i64 (i64.extend_i32_u (i64.lt_u (local.get $r4) (local.get $t))))))))))
(local.set $carry (global.get $global_))
)
(local.set $r3 (local.get $r3_1))
(block
(local.set $r2_1 (call $add_carry (local.get $x2) (local.get $y2) (local.get $carry)))
(local.set $carry_1 (global.get $global_))
)
(local.set $r2 (local.get $r2_1))
(block
(local.set $r1_1 (call $add_carry (local.get $x1) (local.get $y1) (local.get $carry_1)))
(local.set $carry_2 (global.get $global_))
)
(local.set $r1 (local.get $r1_1))
(global.set $global_ (local.get $r2))
(global.set $global__1 (local.get $r3))
(global.set $global__2 (local.get $r4))
(local.get $r1)
)
(func $iszero
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(result i64)
(local $r1 i64)
(local $r2 i64)
(local $r3 i64)
(local $r4 i64)
(local.set $r4 (i64.extend_i32_u (i32.wrap_i64 (i64.extend_i32_u (i64.eqz (i64.or (i64.or (local.get $x1) (local.get $x2)) (i64.or (local.get $x3) (local.get $x4))))))))
(global.set $global_ (local.get $r2))
(global.set $global__1 (local.get $r3))
(global.set $global__2 (local.get $r4))
(local.get $r1)
)
(func $eq
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(result i64)
(local $r1 i64)
(local $r2 i64)
(local $r3 i64)
(local $r4 i64)
(if (i64.ne (i64.extend_i32_u (i64.eq (local.get $x1) (local.get $y1))) (i64.const 0)) (then
(if (i64.ne (i64.extend_i32_u (i64.eq (local.get $x2) (local.get $y2))) (i64.const 0)) (then
(if (i64.ne (i64.extend_i32_u (i64.eq (local.get $x3) (local.get $y3))) (i64.const 0)) (then
(if (i64.ne (i64.extend_i32_u (i64.eq (local.get $x4) (local.get $y4))) (i64.const 0)) (then
(local.set $r4 (i64.const 1))
))
))
))
))
(global.set $global_ (local.get $r2))
(global.set $global__1 (local.get $r3))
(global.set $global__2 (local.get $r4))
(local.get $r1)
)
(func $cmp
(param $a i64)
(param $b i64)
(result i64)
(local $r i64)
(local $condition i64)
(block
(local.set $condition (i64.extend_i32_u (i64.lt_u (local.get $a) (local.get $b))))
(if (i64.eq (local.get $condition) (i64.const 1)) (then
(local.set $r (i64.const 4294967295))
)(else
(local.set $r (i64.extend_i32_u (i64.ne (local.get $a) (local.get $b))))
))
)
(local.get $r)
)
(func $lt
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(result i64)
(local $z1 i64)
(local $z2 i64)
(local $z3 i64)
(local $z4 i64)
(local $z i64)
(local $condition_4 i64)
(local $condition_5 i64)
(local $condition_6 i64)
(local.set $z (i64.const 0))
(block
(local.set $condition_4 (call $cmp (local.get $x1) (local.get $y1)))
(if (i64.eq (local.get $condition_4) (i64.const 0)) (then
(block
(local.set $condition_5 (call $cmp (local.get $x2) (local.get $y2)))
(if (i64.eq (local.get $condition_5) (i64.const 0)) (then
(block
(local.set $condition_6 (call $cmp (local.get $x3) (local.get $y3)))
(if (i64.eq (local.get $condition_6) (i64.const 0)) (then
(local.set $z (i64.extend_i32_u (i64.lt_u (local.get $x4) (local.get $y4))))
)(else
(if (i64.eq (local.get $condition_6) (i64.const 1)) (then
(local.set $z (i64.const 0))
)(else
(local.set $z (i64.const 1))
))
))
)
)(else
(if (i64.eq (local.get $condition_5) (i64.const 1)) (then
(local.set $z (i64.const 0))
)(else
(local.set $z (i64.const 1))
))
))
)
)(else
(if (i64.eq (local.get $condition_4) (i64.const 1)) (then
(local.set $z (i64.const 0))
)(else
(local.set $z (i64.const 1))
))
))
)
(local.set $z4 (i64.extend_i32_u (i32.wrap_i64 (local.get $z))))
(global.set $global_ (local.get $z2))
(global.set $global__1 (local.get $z3))
(global.set $global__2 (local.get $z4))
(local.get $z1)
)
(func $calldataload
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(result i64)
(local $z1 i64)
(local $z2 i64)
(local $z3 i64)
(local $z4 i64)
(local $z1_1 i64)
(local $z2_1 i64)
(local $z3_1 i64)
(local $z4_1 i64)
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3)))) (i64.const 0)) (then
(unreachable)))
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32)))) (i64.const 0)) (then
(unreachable)))
(call $eth.callDataCopy (i32.wrap_i64 (i64.const 0)) (i32.wrap_i64 (i64.extend_i32_u (i32.wrap_i64 (local.get $x4)))) (i32.wrap_i64 (i64.const 32)))
(local.set $z1_1 (call $endian_swap (i64.load (i32.wrap_i64 (i64.const 0)))))
(local.set $z2_1 (call $endian_swap (i64.load (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (i64.const 0)) (i32.wrap_i64 (i64.const 8))))))))
(local.set $z3_1 (call $endian_swap (i64.load (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (i64.const 0)) (i32.wrap_i64 (i64.const 16))))))))
(local.set $z4_1 (call $endian_swap (i64.load (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (i64.const 0)) (i32.wrap_i64 (i64.const 24))))))))
(local.set $z1 (local.get $z1_1))
(local.set $z2 (local.get $z2_1))
(local.set $z3 (local.get $z3_1))
(local.set $z4 (local.get $z4_1))
(global.set $global_ (local.get $z2))
(global.set $global__1 (local.get $z3))
(global.set $global__2 (local.get $z4))
(local.get $z1)
)
(func $endian_swap_16
(param $x i64)
(result i64)
(local $y i64)
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
(local.get $y)
)
(func $endian_swap_32
(param $x i64)
(result i64)
(local $y i64)
(local $hi i64)
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16)))
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16)))))
(local.get $y)
)
(func $endian_swap
(param $x i64)
(result i64)
(local $y i64)
(local $hi i64)
(local.set $hi (i64.shl (call $endian_swap_32 (local.get $x)) (i64.const 32)))
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $x) (i64.const 32)))))
(local.get $y)
)
(func $mstore_internal
(param $pos i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(i64.store (i32.wrap_i64 (local.get $pos)) (call $endian_swap (local.get $y1)))
(i64.store (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $pos)) (i32.wrap_i64 (i64.const 8))))) (call $endian_swap (local.get $y2)))
(i64.store (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $pos)) (i32.wrap_i64 (i64.const 16))))) (call $endian_swap (local.get $y3)))
(i64.store (i32.wrap_i64 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $pos)) (i32.wrap_i64 (i64.const 24))))) (call $endian_swap (local.get $y4)))
)
(func $sstore
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(call $mstore_internal (i64.const 0) (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4))
(call $mstore_internal (i64.const 32) (local.get $y1) (local.get $y2) (local.get $y3) (local.get $y4))
(call $eth.storageStore (i32.wrap_i64 (i64.const 0)) (i32.wrap_i64 (i64.const 32)))
)
)

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0;
contract C {

View File

@ -1,5 +1,5 @@
Warning: Unused local variable.
--> ir_compiler_subobjects/input.sol:6:9:
--> ir_compiler_subobjects/input.sol:7:9:
|
6 | C c = new C();
7 | C c = new C();
| ^^^

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0;
contract C {}

View File

@ -1,5 +1,5 @@
// checks that error messages around power-or-10 lines are formatted correctly
// SPDX-License-Identifier: GPL-3.0

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract C

View File

@ -1,69 +1,69 @@
======= optimizer_user_yul/input.sol:C =======
EVM assembly:
/* "optimizer_user_yul/input.sol":24:489 contract C... */
/* "optimizer_user_yul/input.sol":60:525 contract C... */
mstore(0x40, 0x80)
/* "optimizer_user_yul/input.sol":72:77 int a */
/* "optimizer_user_yul/input.sol":108:113 int a */
0x00
/* "optimizer_user_yul/input.sol":152:161 let x,y,z */
/* "optimizer_user_yul/input.sol":188:197 let x,y,z */
dup1
0x00
dup1
/* "optimizer_user_yul/input.sol":176:177 1 */
/* "optimizer_user_yul/input.sol":212:213 1 */
0x01
/* "optimizer_user_yul/input.sol":173:174 0 */
/* "optimizer_user_yul/input.sol":209:210 0 */
0x00
/* "optimizer_user_yul/input.sol":166:178 sstore(0, 1) */
/* "optimizer_user_yul/input.sol":202:214 sstore(0, 1) */
sstore
/* "optimizer_user_yul/input.sol":183:229 for { } sload(4) { } {... */
/* "optimizer_user_yul/input.sol":219:265 for { } sload(4) { } {... */
tag_3:
/* "optimizer_user_yul/input.sol":197:198 4 */
/* "optimizer_user_yul/input.sol":233:234 4 */
0x04
/* "optimizer_user_yul/input.sol":191:199 sload(4) */
/* "optimizer_user_yul/input.sol":227:235 sload(4) */
sload
/* "optimizer_user_yul/input.sol":183:229 for { } sload(4) { } {... */
/* "optimizer_user_yul/input.sol":219:265 for { } sload(4) { } {... */
iszero
tag_5
jumpi
pop
/* "optimizer_user_yul/input.sol":215:224 exp(x, y) */
/* "optimizer_user_yul/input.sol":251:260 exp(x, y) */
dup1
dup3
exp
/* "optimizer_user_yul/input.sol":183:229 for { } sload(4) { } {... */
/* "optimizer_user_yul/input.sol":219:265 for { } sload(4) { } {... */
jump(tag_3)
tag_5:
/* "optimizer_user_yul/input.sol":187:190 { } */
/* "optimizer_user_yul/input.sol":223:226 { } */
pop
pop
pop
/* "optimizer_user_yul/input.sol":239:240 2 */
/* "optimizer_user_yul/input.sol":275:276 2 */
0x02
/* "optimizer_user_yul/input.sol":234:240 a := 2 */
/* "optimizer_user_yul/input.sol":270:276 a := 2 */
swap1
pop
/* "optimizer_user_yul/input.sol":340:341 3 */
/* "optimizer_user_yul/input.sol":376:377 3 */
0x03
/* "optimizer_user_yul/input.sol":337:338 2 */
/* "optimizer_user_yul/input.sol":373:374 2 */
0x02
/* "optimizer_user_yul/input.sol":330:342 sstore(2, 3) */
/* "optimizer_user_yul/input.sol":366:378 sstore(2, 3) */
sstore
/* "optimizer_user_yul/input.sol":347:480 for { } sload(5) { } {... */
/* "optimizer_user_yul/input.sol":383:516 for { } sload(5) { } {... */
tag_6:
/* "optimizer_user_yul/input.sol":361:362 5 */
/* "optimizer_user_yul/input.sol":397:398 5 */
0x05
/* "optimizer_user_yul/input.sol":355:363 sload(5) */
/* "optimizer_user_yul/input.sol":391:399 sload(5) */
sload
tag_9
jumpi
jump(tag_8)
tag_9:
/* "optimizer_user_yul/input.sol":347:480 for { } sload(5) { } {... */
/* "optimizer_user_yul/input.sol":383:516 for { } sload(5) { } {... */
jump(tag_6)
tag_8:
/* "optimizer_user_yul/input.sol":311:484 {... */
/* "optimizer_user_yul/input.sol":347:520 {... */
pop
/* "optimizer_user_yul/input.sol":24:489 contract C... */
/* "optimizer_user_yul/input.sol":60:525 contract C... */
dataSize(sub_0)
dup1
dataOffset(sub_0)
@ -74,7 +74,7 @@ tag_8:
stop
sub_0: assembly {
/* "optimizer_user_yul/input.sol":24:489 contract C... */
/* "optimizer_user_yul/input.sol":60:525 contract C... */
mstore(0x40, 0x80)
/* "--CODEGEN--":12:13 */
0x00

View File

@ -2,10 +2,10 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
},
"b.sol": {
"content": "contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
}
},
"settings": {

View File

@ -1,6 +1,6 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:1:15: Warning: Function state mutability can be restricted to pure
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":58,"file":"b.sol","start":14},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -2,10 +2,10 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
},
"b.sol": {
"content": "contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
}
},
"settings": {

View File

@ -1,6 +1,6 @@
{"contracts":{"a.sol":{"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:1:15: Warning: Function state mutability can be restricted to pure
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":58,"file":"b.sol","start":14},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -2,10 +2,10 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
},
"b.sol": {
"content": "contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
}
},
"settings": {

View File

@ -1,6 +1,6 @@
{"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:1:15: Warning: Function state mutability can be restricted to pure
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":58,"file":"b.sol","start":14},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -2,10 +2,10 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
},
"b.sol": {
"content": "contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
}
},
"settings": {

View File

@ -1,6 +1,6 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"B2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:1:15: Warning: Function state mutability can be restricted to pure
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":58,"file":"b.sol","start":14},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -2,10 +2,10 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
},
"b.sol": {
"content": "contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
}
},
"settings": {

View File

@ -2,10 +2,10 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
},
"b.sol": {
"content": "contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
}
},
"settings": {

View File

@ -1,5 +1,5 @@
{"contracts":{"b.sol":{"B2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:1:15: Warning: Function state mutability can be restricted to pure
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":58,"file":"b.sol","start":14},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -2,10 +2,10 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }"
},
"b.sol": {
"content": "contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
"content": "//SPDX-License-Identifier: GPL-3.0\ncontract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }"
}
},
"settings": {

View File

@ -1,13 +1,13 @@
Error: Expected primary expression.
--> recovery_ast_constructor/input.sol:5:27:
--> recovery_ast_constructor/input.sol:6:27:
|
5 | balances[tx.origin] = ; // missing RHS.
6 | balances[tx.origin] = ; // missing RHS.
| ^
Warning: Recovered in Statement at ';'.
--> recovery_ast_constructor/input.sol:5:27:
--> recovery_ast_constructor/input.sol:6:27:
|
5 | balances[tx.origin] = ; // missing RHS.
6 | balances[tx.origin] = ; // missing RHS.
| ^

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0.0;
contract Error1 {

View File

@ -12,7 +12,8 @@ JSON AST:
[
18
]
}
},
"license": "GPL-3.0"
},
"children":
[
@ -29,7 +30,7 @@ JSON AST:
},
"id": 1,
"name": "PragmaDirective",
"src": "0:24:0"
"src": "36:24:0"
},
{
"attributes":
@ -86,7 +87,7 @@ JSON AST:
"children": [],
"id": 2,
"name": "ParameterList",
"src": "57:2:0"
"src": "93:2:0"
},
{
"attributes":
@ -99,7 +100,7 @@ JSON AST:
"children": [],
"id": 3,
"name": "ParameterList",
"src": "67:0:0"
"src": "103:0:0"
},
{
"attributes":
@ -112,12 +113,12 @@ JSON AST:
"children": [],
"id": 8,
"name": "Block",
"src": "67:49:0"
"src": "103:49:0"
}
],
"id": 9,
"name": "FunctionDefinition",
"src": "46:70:0"
"src": "82:70:0"
},
{
"attributes":
@ -151,7 +152,7 @@ JSON AST:
"children": [],
"id": 10,
"name": "ParameterList",
"src": "382:2:0"
"src": "418:2:0"
},
{
"children":
@ -180,17 +181,17 @@ JSON AST:
},
"id": 11,
"name": "ElementaryTypeName",
"src": "405:4:0"
"src": "441:4:0"
}
],
"id": 12,
"name": "VariableDeclaration",
"src": "405:4:0"
"src": "441:4:0"
}
],
"id": 13,
"name": "ParameterList",
"src": "404:6:0"
"src": "440:6:0"
},
{
"children":
@ -218,30 +219,30 @@ JSON AST:
},
"id": 14,
"name": "Literal",
"src": "424:1:0"
"src": "460:1:0"
}
],
"id": 15,
"name": "Return",
"src": "417:8:0"
"src": "453:8:0"
}
],
"id": 16,
"name": "Block",
"src": "411:19:0"
"src": "447:19:0"
}
],
"id": 17,
"name": "FunctionDefinition",
"src": "369:61:0"
"src": "405:61:0"
}
],
"id": 18,
"name": "ContractDefinition",
"src": "26:406:0"
"src": "62:406:0"
}
],
"id": 19,
"name": "SourceUnit",
"src": "0:433:0"
"src": "36:433:0"
}

View File

@ -1,7 +1,7 @@
Error: Expected pragma, import directive or contract/interface/library/struct/enum definition.
--> recovery_ast_empty_contract/input.sol:2:1:
--> recovery_ast_empty_contract/input.sol:3:1:
|
2 | c
3 | c
| ^

View File

@ -1,2 +1,3 @@
// SPDX-License-Identifier: GPL-3.0
pragma 0.5.11;
c

View File

@ -4,7 +4,7 @@
{
"A":
{
"content": "pragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }"
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }"
}
},
"settings":

View File

@ -1,7 +1,7 @@
{"errors":[{"component":"general","formattedMessage":"A:1:58: ParserError: Expected type name
{"errors":[{"component":"general","formattedMessage":"A:2:58: ParserError: Expected type name
pragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }
^
","message":"Expected type name","severity":"error","sourceLocation":{"end":58,"file":"A","start":57},"type":"ParserError"},{"component":"general","formattedMessage":"A:1:84: Warning: Recovered in ContractDefinition at '}'.
","message":"Expected type name","severity":"error","sourceLocation":{"end":94,"file":"A","start":93},"type":"ParserError"},{"component":"general","formattedMessage":"A:2:84: Warning: Recovered in ContractDefinition at '}'.
pragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }
^
","message":"Recovered in ContractDefinition at '}'.","severity":"warning","sourceLocation":{"end":84,"file":"A","start":83},"type":"Warning"}],"sources":{"A":{"ast":{"absolutePath":"A","exportedSymbols":{"Errort6":[3]},"id":4,"nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"0:22:0"},{"abstract":false,"baseContracts":[],"contractDependencies":[],"contractKind":"contract","documentation":null,"fullyImplemented":true,"id":3,"linearizedBaseContracts":[3],"name":"Errort6","nodeType":"ContractDefinition","nodes":[],"scope":4,"src":"23:35:0"}],"src":"0:84:0"},"id":0}}}
","message":"Recovered in ContractDefinition at '}'.","severity":"warning","sourceLocation":{"end":120,"file":"A","start":119},"type":"Warning"}],"sources":{"A":{"ast":{"absolutePath":"A","exportedSymbols":{"Errort6":[3]},"id":4,"license":"GPL-3.0","nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"36:22:0"},{"abstract":false,"baseContracts":[],"contractDependencies":[],"contractKind":"contract","documentation":null,"fullyImplemented":true,"id":3,"linearizedBaseContracts":[3],"name":"Errort6","nodeType":"ContractDefinition","nodes":[],"scope":4,"src":"59:35:0"}],"src":"36:84:0"},"id":0}}}

View File

@ -1,7 +1,7 @@
Error: No matching declaration found after argument-dependent lookup.
--> require_overload/input.sol:4:9:
--> require_overload/input.sol:5:9:
|
4 | require(this);
5 | require(this);
| ^^^^^^^
Note: Candidate: function require(bool)
Note: Candidate: function require(bool, string memory)

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract C {
function f() public pure {

View File

@ -4,7 +4,7 @@
{
"A":
{
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }"
}
}
}

View File

@ -4,7 +4,7 @@
{
"A":
{
"content": "pragma solidity >=0.0; contract C { }"
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { }"
}
},
"settings":

View File

@ -4,7 +4,7 @@
{
"":
{
"content": "pragma solidity >=0.0; import {A} from \".\";"
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; import {A} from \".\";"
}
}
}

View File

@ -1,4 +1,4 @@
{"errors":[{"component":"general","formattedMessage":":1:24: DeclarationError: Declaration \"A\" not found in \"\" (referenced as \".\").
{"errors":[{"component":"general","formattedMessage":":2:24: DeclarationError: Declaration \"A\" not found in \"\" (referenced as \".\").
pragma solidity >=0.0; import {A} from \".\";
^------------------^
","message":"Declaration \"A\" not found in \"\" (referenced as \".\").","severity":"error","type":"DeclarationError"}],"sources":{}}

View File

@ -2,7 +2,7 @@
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A { uint256 immutable x = 1; function f() public view returns (uint256) { return x; } }"
"content": "// SPDX-License-Identifier: GPL-3.0\ncontract A { uint256 immutable x = 1; function f() public view returns (uint256) { return x; } }"
}
},
"settings": {

Some files were not shown because too many files have changed in this diff Show More