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: 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. * 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: Language Features:
@ -26,6 +28,8 @@ Language Features:
Compiler Features: Compiler Features:
* Commandline Interface: Don't ignore `--yul-optimizations` in assembly mode. * 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. * 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. * 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. * 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) ### 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; pragma solidity ^0.4.25;
// This will report a warning until version 0.4.25 of the compiler // This will report a warning until version 0.4.25 of the compiler
// This will not compile after 0.5.0 // 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; pragma solidity >=0.5.0 <0.8.0;
interface OldContract { interface OldContract {
function someOldFunction(uint8 a) external; 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; pragma solidity >=0.5.0 <0.8.0;
interface OldContract { interface OldContract {
@ -347,6 +350,7 @@ commandline compiler for linking):
:: ::
// This will not compile after 0.6.0 // This will not compile after 0.6.0
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.5.99; pragma solidity >=0.5.0 <0.5.99;
library OldLibrary { library OldLibrary {
@ -370,6 +374,7 @@ Old version:
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.4.25; pragma solidity ^0.4.25;
// This will not compile after 0.5.0 // 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; pragma solidity >=0.5.0 <0.5.99;
// This will not compile after 0.6.0 // 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; pragma solidity >=0.4.16 <0.8.0;
contract Foo { contract Foo {
@ -535,6 +536,7 @@ For example,
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.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 solidity >=0.4.19 <0.8.0;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;

View File

@ -41,6 +41,7 @@ without a compiler change.
.. code:: .. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
library GetCode { library GetCode {
@ -66,6 +67,7 @@ efficient code, for example:
.. code:: .. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
@ -136,6 +138,7 @@ Local Solidity variables are available for assignments, for example:
.. code:: .. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
contract C { 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", "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.", "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": { "0.5.14": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow", "MemoryArrayCreationOverflow",
@ -934,6 +935,7 @@
}, },
"0.5.15": { "0.5.15": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow", "MemoryArrayCreationOverflow",
@ -944,6 +946,7 @@
}, },
"0.5.16": { "0.5.16": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow", "MemoryArrayCreationOverflow",
@ -953,6 +956,7 @@
}, },
"0.5.17": { "0.5.17": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow" "MemoryArrayCreationOverflow"
@ -1082,6 +1086,8 @@
}, },
"0.6.0": { "0.6.0": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow", "MemoryArrayCreationOverflow",
@ -1091,6 +1097,8 @@
}, },
"0.6.1": { "0.6.1": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow" "MemoryArrayCreationOverflow"
@ -1099,6 +1107,8 @@
}, },
"0.6.2": { "0.6.2": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow" "MemoryArrayCreationOverflow"
@ -1107,6 +1117,8 @@
}, },
"0.6.3": { "0.6.3": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow" "MemoryArrayCreationOverflow"
@ -1115,6 +1127,8 @@
}, },
"0.6.4": { "0.6.4": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents", "TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow" "MemoryArrayCreationOverflow"
@ -1123,6 +1137,8 @@
}, },
"0.6.5": { "0.6.5": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck", "ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents" "TupleAssignmentMultiStackSlotComponents"
], ],
@ -1130,12 +1146,16 @@
}, },
"0.6.6": { "0.6.6": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck" "ImplicitConstructorCallvalueCheck"
], ],
"released": "2020-04-09" "released": "2020-04-09"
}, },
"0.6.7": { "0.6.7": {
"bugs": [ "bugs": [
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck" "ImplicitConstructorCallvalueCheck"
], ],
"released": "2020-05-04" "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; pragma solidity >=0.5.0 <0.8.0;
contract WithdrawalContract { 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; pragma solidity >=0.5.0 <0.8.0;
contract SendContract { contract SendContract {
@ -121,6 +123,7 @@ restrictions highly readable.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0; pragma solidity >=0.4.22 <0.8.0;
contract AccessRestriction { contract AccessRestriction {
@ -273,6 +276,7 @@ function finishes.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0; pragma solidity >=0.4.22 <0.8.0;
contract StateMachine { 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 defined as abstract, because the function ``utterance()`` was defined, but no implementation was
provided (no implementation body ``{ }`` was given).:: provided (no implementation body ``{ }`` was given).::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
abstract contract Feline { 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 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:: 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; pragma solidity >=0.6.0 <0.8.0;
abstract contract Feline { 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; pragma solidity >0.6.4 <0.8.0;
contract C { 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; 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; pragma solidity >=0.4.21 <0.8.0;
contract ClientReceipt { 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; pragma solidity >=0.4.10 <0.8.0;
contract C { 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; pragma solidity >=0.5.0 <0.8.0;
contract owned { 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 For example, if you want your contract to accept one kind of external call
with two integers, you would use something like the following:: with two integers, you would use something like the following::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
contract Simple { 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 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:: 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; pragma solidity >=0.4.16 <0.8.0;
contract Simple { 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`` (either a single or :ref:`multiple ones<multi-return>`) directly with the ``return``
statement:: statement::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
contract Simple { 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; pragma solidity >=0.5.0 <0.8.0;
contract C { 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; pragma solidity >=0.5.0 <0.8.0;
contract C { 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; pragma solidity >=0.6.0 <0.8.0;
// This contract keeps all Ether sent to it with no way // 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; pragma solidity >=0.6.2 <0.8.0;
contract Test { 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; pragma solidity >=0.4.16 <0.8.0;
contract A { 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; pragma solidity >=0.4.16 <0.8.0;
// This will not compile // 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; pragma solidity >=0.4.16 <0.8.0;
contract A { 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; 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 destruction request. The way this is done is problematic, as
seen in the following example:: seen in the following example::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
contract owned { 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 explicitly in the final override, but this function will bypass
``Base1.destroy``. The way around this is to use ``super``:: ``Base1.destroy``. The way around this is to use ``super``::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
contract owned { 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; pragma solidity >=0.6.0 <0.8.0;
contract Base 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; pragma solidity >=0.6.0 <0.8.0;
contract Base1 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; pragma solidity >=0.6.0 <0.8.0;
contract A { function f() public pure{} } 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; pragma solidity >=0.6.0 <0.8.0;
contract A 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; pragma solidity >=0.6.0 <0.8.0;
contract Base contract Base
@ -342,6 +350,7 @@ explicitly:
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
contract Base1 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; pragma solidity >=0.5.0 <0.8.0;
contract A { 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, 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:: 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; pragma solidity >=0.4.22 <0.8.0;
contract Base { 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; pragma solidity >=0.4.0 <0.8.0;
contract X {} 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; pragma solidity >=0.4.22 <0.8.0;
contract Base1 { 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; pragma solidity >=0.6.2 <0.8.0;
interface Token { interface Token {
@ -42,6 +43,7 @@ inheritance.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.8.0; pragma solidity >=0.6.2 <0.8.0;
interface ParentA { 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; 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; pragma solidity >=0.6.0 <0.8.0;
struct bigint { 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; pragma solidity >=0.5.14 <0.8.0;
library L { 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 Let us rewrite the set example from the
:ref:`libraries` in this way:: :ref:`libraries` in this way::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.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:: 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; pragma solidity >=0.4.16 <0.8.0;
library Search { 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; pragma solidity >=0.4.16 <0.8.0;
contract C { 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; pragma solidity >=0.4.16 <0.8.0;
contract C { contract C {
@ -112,6 +114,7 @@ when they are declared.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
contract C { 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; pragma solidity >=0.4.0 <0.8.0;
contract C { 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; pragma solidity >=0.4.16 <0.8.0;
contract arrayExample { 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; pragma solidity >=0.4.0 <0.8.0;
contract Complex { 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 Functions of the current contract can be called directly ("internally"), also recursively, as seen in
this nonsensical example:: this nonsensical example::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0; pragma solidity >=0.4.22 <0.8.0;
contract C { 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; pragma solidity >=0.6.2 <0.8.0;
contract InfoFeed { 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; pragma solidity >=0.4.0 <0.8.0;
contract C { 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; pragma solidity >=0.4.22 <0.8.0;
contract C { 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; pragma solidity >=0.6.2 <0.8.0;
contract D { 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; pragma solidity >=0.6.2 <0.8.0;
contract D { contract D {
@ -307,6 +313,7 @@ groupings of expressions.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0; pragma solidity >=0.5.0 <0.8.0;
contract C { 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; pragma solidity >=0.4.22 <0.8.0;
contract C { 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; pragma solidity >=0.5.0 <0.8.0;
contract C { contract C {
function minimalScoping() pure public { 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; pragma solidity >=0.5.0 <0.8.0;
// This will report a warning // This will report a warning
contract C { 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; pragma solidity >=0.5.0 <0.8.0;
// This will not compile // This will not compile
contract C { 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; pragma solidity >=0.5.0 <0.8.0;
contract Sharer { 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; pragma solidity >=0.5.0 <0.8.0;
contract VendingMachine { 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; pragma solidity >=0.6.0 <0.8.0;
interface DataFeed { function getData(address token) external returns (uint value); } 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; pragma solidity >=0.5.0 <0.8.0;
contract SimpleAuction { contract SimpleAuction {
@ -184,6 +185,7 @@ invalid bids.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0; pragma solidity >=0.5.0 <0.8.0;
contract BlindAuction { 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; pragma solidity >=0.4.24 <0.8.0;
contract ReceiverPays { contract ReceiverPays {
@ -338,6 +339,7 @@ The full contract
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0; pragma solidity >=0.5.0 <0.8.0;
contract SimplePaymentChannel { 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; pragma solidity >=0.5.0 <0.8.0;
library Balances { 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; pragma solidity >=0.5.0 <0.8.0;
contract Purchase { contract Purchase {

View File

@ -32,6 +32,7 @@ of votes.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0; pragma solidity >=0.4.22 <0.8.0;
/// @title Voting with delegation. /// @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``:: 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; 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:: .. code::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
contract A { contract A {
struct S { struct S {

View File

@ -17,6 +17,7 @@ Storage Example
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
contract SimpleStorage { contract SimpleStorage {
@ -31,8 +32,12 @@ Storage Example
} }
} }
The first line tells you that the source code is written for The first line tells you that the source code is licensed under the
Solidity version 0.4.0, or a newer version of the language up to, but not including version 0.7.0. 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. 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 :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>`_). 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; pragma solidity >=0.5.0 <0.8.0;
contract Coin { contract Coin {

View File

@ -7,6 +7,38 @@ Source files can contain an arbitrary number of
:ref:`pragma directives<pragma>` and :ref:`pragma directives<pragma>` and
:ref:`struct<structs>` and :ref:`enum<enums>` definitions. :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 .. index:: ! pragma
.. _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; pragma solidity >=0.4.21 <0.8.0;
/** @title Shape calculator. */ /** @title Shape calculator. */

View File

@ -1,3 +1,5 @@
.. _metadata:
################# #################
Contract Metadata Contract Metadata
################# #################
@ -54,7 +56,9 @@ explanatory purposes.
// Required (unless "content" is used, see below): Sorted URL(s) // Required (unless "content" is used, see below): Sorted URL(s)
// to the source file, protocol is more or less arbitrary, but a // to the source file, protocol is more or less arbitrary, but a
// Swarm URL is recommended // Swarm URL is recommended
"urls": [ "bzzr://56ab..." ] "urls": [ "bzzr://56ab..." ],
// Optional: SPDX license identifier as given in the source file
"license": "MIT"
}, },
"destructible": { "destructible": {
// Required: keccak256 hash of the source file // 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 .. code:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0; pragma solidity >=0.5.0 <0.8.0;
/// @title A simulator for trees /// @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; pragma solidity >=0.4.0 <0.8.0;
// THIS CONTRACT CONTAINS A BUG - DO NOT USE // 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; pragma solidity >=0.6.2 <0.8.0;
// THIS CONTRACT CONTAINS A BUG - DO NOT USE // 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; pragma solidity >=0.4.11 <0.8.0;
contract Fund { 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; pragma solidity >=0.5.0 <0.8.0;
// THIS CONTRACT CONTAINS A BUG - DO NOT USE // 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; pragma solidity >=0.6.0 <0.8.0;
interface TxUserWallet { 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; pragma solidity >=0.6.0 <0.8.0;
contract Map { contract Map {
@ -555,6 +561,7 @@ not mean loss of proving power.
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0; pragma solidity >=0.5.0;
pragma experimental SMTChecker; pragma experimental SMTChecker;
// This may report a warning if no SMT solver available. // 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 solidity >=0.5.0;
pragma experimental SMTChecker; pragma experimental SMTChecker;
// This will report a warning // 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; pragma solidity >=0.4.0 <0.8.0;
contract SimpleStorage { 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; pragma solidity >=0.4.0 <0.8.0;
contract SimpleAuction { 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; pragma solidity >=0.4.22 <0.8.0;
contract Purchase { 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; pragma solidity >=0.4.21 <0.8.0;
contract SimpleAuction { 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; pragma solidity >=0.4.0 <0.8.0;
contract Ballot { 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; pragma solidity >=0.4.0 <0.8.0;
contract Purchase { contract Purchase {

View File

@ -55,6 +55,7 @@ Surround top level declarations in solidity source with two blank lines.
Yes:: Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
contract A { contract A {
@ -73,6 +74,7 @@ Yes::
No:: No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
contract A { contract A {
@ -92,6 +94,7 @@ Blank lines may be omitted between groups of related one-liners (such as stub fu
Yes:: Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
abstract contract A { abstract contract A {
@ -112,6 +115,7 @@ Yes::
No:: No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
abstract contract A { abstract contract A {
@ -246,6 +250,7 @@ Import statements should always be placed at the top of the file.
Yes:: Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
import "./Owned.sol"; import "./Owned.sol";
@ -260,6 +265,7 @@ Yes::
No:: No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
contract A { contract A {
@ -293,6 +299,7 @@ Within a grouping, place the ``view`` and ``pure`` functions last.
Yes:: Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
contract A { contract A {
@ -329,6 +336,7 @@ Yes::
No:: No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
contract A { contract A {
@ -436,6 +444,7 @@ should:
Yes:: Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
contract Coin { contract Coin {
@ -447,6 +456,7 @@ Yes::
No:: No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
contract Coin contract Coin
@ -747,6 +757,7 @@ manner as modifiers if the function declaration is long or hard to read.
Yes:: Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0; pragma solidity >=0.4.22 <0.8.0;
// Base contracts just to make this compile // Base contracts just to make this compile
@ -779,6 +790,7 @@ Yes::
No:: No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.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:: Yes::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.0; pragma solidity >=0.4.22 <0.8.0;
@ -1025,6 +1038,7 @@ Yes::
and in ``Congress.sol``:: and in ``Congress.sol``::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
import "./Owned.sol"; import "./Owned.sol";
@ -1036,6 +1050,7 @@ and in ``Congress.sol``::
No:: No::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.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 For example, the contract from `a simple smart contract <simple-smart-contract>`_ with the comments
added looks like the one below:: added looks like the one below::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.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; pragma solidity >=0.4.0 <0.8.0;
contract MappingExample { 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; pragma solidity >=0.4.22 <0.8.0;
contract MappingExample { 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; pragma solidity >=0.6.0 <0.8.0;
struct IndexValue { uint keyIndex; uint value; } 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; pragma solidity >=0.4.0 <0.8.0;
contract DeleteExample { 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; pragma solidity >=0.5.0 <0.8.0;
contract C { 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; pragma solidity >=0.4.16 <0.8.0;
contract C { 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; pragma solidity >=0.4.16 <0.8.0;
contract C { 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; pragma solidity >=0.4.0 <0.8.0;
// This will not compile. // This will not compile.
@ -274,6 +278,7 @@ Array Members
:: ::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
contract ArrayContract { 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; pragma solidity >=0.6.0 <0.8.0;
contract Proxy { 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; pragma solidity >=0.6.0 <0.8.0;
// Defines a new type with two fields. // 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; pragma solidity >=0.4.16 <0.8.0;
contract test { contract test {
@ -655,7 +656,13 @@ External (or public) functions have the following members:
Example that shows how to use the members:: Example that shows how to use the members::
<<<<<<< HEAD
pragma solidity >=0.6.4 <0.8.0; 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 { contract Example {
function f() public payable returns (bytes4) { 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:: Example that shows how to use internal function types::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0; pragma solidity >=0.4.16 <0.8.0;
library ArrayUtils { library ArrayUtils {
@ -727,6 +735,7 @@ Example that shows how to use internal function types::
Another example that uses external function types:: Another example that uses external function types::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.8.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 .. code-block:: none
// This will not compile after 0.5.0 // This will not compile after 0.5.0
// SPDX-License-Identifier: GPL-3.0
pragma solidity >0.4.23 <0.5.0; pragma solidity >0.4.23 <0.5.0;
contract Updateable { contract Updateable {
@ -709,6 +710,7 @@ The command above applies all changes as shown below. Please review them careful
.. code-block:: solidity .. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.8.0; pragma solidity >=0.6.0 <0.8.0;
abstract contract Updateable { abstract contract Updateable {

View File

@ -134,6 +134,12 @@ public:
return m_errorCount > 0; 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. // @returns true if the maximum error count has been reached.
bool hasExcessiveErrors() const; bool hasExcessiveErrors() const;

View File

@ -148,6 +148,11 @@ void ParserBase::parserWarning(ErrorId _error, string const& _description)
m_errorReporter.warning(_error, currentLocation(), _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) void ParserBase::parserError(ErrorId _error, SourceLocation const& _location, string const& _description)
{ {
m_errorReporter.parserError(_error, _location, _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 /// Creates a @ref ParserWarning and annotates it with the current position and the
/// given @a _description. /// given @a _description.
void parserWarning(ErrorId _error, std::string const& _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 /// Creates a @ref ParserError and annotates it with the current position and the
/// given @a _description. Throws the FatalError. /// 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) void DeclarationTypeChecker::typeError(SourceLocation const& _location, string const& _description)
{ {
m_errorOccurred = true;
m_errorReporter.typeError(2311_error, _location, _description); m_errorReporter.typeError(2311_error, _location, _description);
} }
void DeclarationTypeChecker::fatalTypeError(SourceLocation const& _location, string const& _description) void DeclarationTypeChecker::fatalTypeError(SourceLocation const& _location, string const& _description)
{ {
m_errorOccurred = true;
m_errorReporter.fatalTypeError(5651_error, _location, _description); m_errorReporter.fatalTypeError(5651_error, _location, _description);
} }
void DeclarationTypeChecker::fatalDeclarationError(SourceLocation const& _location, string const& _description) void DeclarationTypeChecker::fatalDeclarationError(SourceLocation const& _location, string const& _description)
{ {
m_errorOccurred = true;
m_errorReporter.fatalDeclarationError(2046_error, _location, _description); m_errorReporter.fatalDeclarationError(2046_error, _location, _description);
} }
bool DeclarationTypeChecker::check(ASTNode const& _node) bool DeclarationTypeChecker::check(ASTNode const& _node)
{ {
unsigned errorCount = m_errorReporter.errorCount();
_node.accept(*this); _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); void fatalDeclarationError(langutil::SourceLocation const& _location, std::string const& _description);
langutil::ErrorReporter& m_errorReporter; langutil::ErrorReporter& m_errorReporter;
bool m_errorOccurred = false;
langutil::EVMVersion m_evmVersion; langutil::EVMVersion m_evmVersion;
bool m_insideFunctionType = false; bool m_insideFunctionType = false;
bool m_recursiveStructSeen = false; bool m_recursiveStructSeen = false;

View File

@ -2866,6 +2866,8 @@ bool TypeChecker::visit(IndexRangeAccess const& _access)
if (arrayType->location() != DataLocation::CallData || !arrayType->isDynamicallySized()) if (arrayType->location() != DataLocation::CallData || !arrayType->isDynamicallySized())
m_errorReporter.typeError(1227_error, _access.location(), "Index range access is only supported for dynamic calldata arrays."); 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().type = TypeProvider::arraySlice(*arrayType);
_access.annotation().isLValue = isLValue; _access.annotation().isLValue = isLValue;
_access.annotation().isPure = isPure; _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 class SourceUnit: public ASTNode
{ {
public: public:
SourceUnit(int64_t _id, SourceLocation const& _location, std::vector<ASTPointer<ASTNode>> _nodes): SourceUnit(
ASTNode(_id, _location), m_nodes(std::move(_nodes)) {} 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(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override; void accept(ASTConstVisitor& _visitor) const override;
SourceUnitAnnotation& annotation() 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; } std::vector<ASTPointer<ASTNode>> nodes() const { return m_nodes; }
/// @returns a set of referenced SourceUnits. Recursively if @a _recurse is true. /// @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; std::set<SourceUnit const*> referencedSourceUnits(bool _recurse = false, std::set<SourceUnit const*> _skipList = std::set<SourceUnit const*>()) const;
private: private:
std::optional<std::string> m_licenseString;
std::vector<ASTPointer<ASTNode>> m_nodes; 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("absolutePath", _node.annotation().path),
make_pair("exportedSymbols", move(exportedSymbols)), make_pair("exportedSymbols", move(exportedSymbols)),
make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
make_pair("nodes", toJson(_node.nodes())) 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) 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; vector<ASTPointer<ASTNode>> nodes;
for (auto& child: member(_node, "nodes")) for (auto& child: member(_node, "nodes"))
nodes.emplace_back(convertJsonToASTNode(child)); nodes.emplace_back(convertJsonToASTNode(child));
ASTPointer<SourceUnit> tmp = createASTNode<SourceUnit>(_node, nodes);
ASTPointer<SourceUnit> tmp = createASTNode<SourceUnit>(_node, license, nodes);
tmp->annotation().path = _srcName; tmp->annotation().path = _srcName;
return tmp; return tmp;
} }

View File

@ -330,7 +330,7 @@ TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c
// Structs are fine in the following circumstances: // Structs are fine in the following circumstances:
// - ABIv2 or, // - ABIv2 or,
// - storage struct for a library // - storage struct for a library
if (_inLibraryCall && encodingType->dataStoredIn(DataLocation::Storage)) if (_inLibraryCall && encodingType && encodingType->dataStoredIn(DataLocation::Storage))
return encodingType; return encodingType;
TypePointer baseType = encodingType; TypePointer baseType = encodingType;
while (auto const* arrayType = dynamic_cast<ArrayType const*>(baseType)) 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)) else if (dynamic_cast<FixedPointType const*>(_other))
return nullptr; 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; return this;
} }
@ -1964,6 +1971,19 @@ string ArraySliceType::toString(bool _short) const
return m_arrayType.toString(_short) + " slice"; 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 std::vector<std::tuple<std::string, TypePointer>> ArraySliceType::makeStackItems() const
{ {
return {{"offset", TypeProvider::uint256()}, {"length", TypeProvider::uint256()}}; return {{"offset", TypeProvider::uint256()}, {"length", TypeProvider::uint256()}};

View File

@ -831,6 +831,7 @@ public:
bool isDynamicallyEncoded() const override { return true; } bool isDynamicallyEncoded() const override { return true; }
bool canLiveOutsideStorage() const override { return m_arrayType.canLiveOutsideStorage(); } bool canLiveOutsideStorage() const override { return m_arrayType.canLiveOutsideStorage(); }
std::string toString(bool _short) const override; std::string toString(bool _short) const override;
TypePointer mobileType() const override;
BoolResult validForLocation(DataLocation _loc) const override { return m_arrayType.validForLocation(_loc); } 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); return abiEncodingFunctionStringLiteral(_from, to, _options);
else if (auto toArray = dynamic_cast<ArrayType const*>(&to)) else if (auto toArray = dynamic_cast<ArrayType const*>(&to))
{ {
solAssert(_from.category() == Type::Category::Array, ""); ArrayType const* fromArray = nullptr;
solAssert(to.dataStoredIn(DataLocation::Memory), ""); switch (_from.category())
ArrayType const& fromArray = dynamic_cast<ArrayType const&>(_from); {
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: case DataLocation::CallData:
if ( if (
fromArray.isByteArray() || fromArray->isByteArray() ||
*fromArray.baseType() == *TypeProvider::uint256() || *fromArray->baseType() == *TypeProvider::uint256() ||
*fromArray.baseType() == FixedBytesType(32) *fromArray->baseType() == FixedBytesType(32)
) )
return abiEncodingFunctionCalldataArrayWithoutCleanup(fromArray, *toArray, _options); return abiEncodingFunctionCalldataArrayWithoutCleanup(*fromArray, *toArray, _options);
else else
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options); return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
case DataLocation::Memory: case DataLocation::Memory:
if (fromArray.isByteArray()) if (fromArray->isByteArray())
return abiEncodingFunctionMemoryByteArray(fromArray, *toArray, _options); return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options);
else else
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options); return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
case DataLocation::Storage: case DataLocation::Storage:
if (fromArray.baseType()->storageBytes() <= 16) if (fromArray->baseType()->storageBytes() <= 16)
return abiEncodingFunctionCompactStorageArray(fromArray, *toArray, _options); return abiEncodingFunctionCompactStorageArray(*fromArray, *toArray, _options);
else else
return abiEncodingFunctionSimpleArray(fromArray, *toArray, _options); return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options);
default: default:
solAssert(false, ""); solAssert(false, "");
} }

View File

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

View File

@ -1769,7 +1769,12 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
case Type::Category::ArraySlice: case Type::Category::ArraySlice:
{ {
auto const& arrayType = dynamic_cast<ArraySliceType const&>(baseType).arrayType(); 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."); solAssert(_indexAccess.indexExpression(), "Index expression expected.");
acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true); acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true);
@ -1852,7 +1857,12 @@ bool ExpressionCompiler::visit(IndexRangeAccess const& _indexAccess)
arrayType = &sliceType->arrayType(); arrayType = &sliceType->arrayType();
solAssert(arrayType, ""); solAssert(arrayType, "");
solUnimplementedAssert(arrayType->location() == DataLocation::CallData && arrayType->isDynamicallySized(), ""); solUnimplementedAssert(
arrayType->location() == DataLocation::CallData &&
arrayType->isDynamicallySized() &&
!arrayType->baseType()->isDynamicallyEncoded(),
""
);
if (_indexAccess.startExpression()) if (_indexAccess.startExpression())
acceptAndConvert(*_indexAccess.startExpression(), *TypeProvider::uint256()); 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); ArraySliceType const& fromType = dynamic_cast<ArraySliceType const&>(_from);
ArrayType const& targetType = dynamic_cast<ArrayType const&>(_to); ArrayType const& targetType = dynamic_cast<ArrayType const&>(_to);
solAssert(!fromType.arrayType().baseType()->isDynamicallyEncoded(), "");
solAssert( solAssert(
*fromType.arrayType().baseType() == *targetType.baseType(), *fromType.arrayType().baseType() == *targetType.baseType(),
"Converting arrays of different type is not possible" "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"); solAssert(s.second.scanner, "Scanner not available");
meta["sources"][s.first]["keccak256"] = "0x" + toHex(s.second.keccak256().asBytes()); 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) if (m_metadataLiteralSources)
meta["sources"][s.first]["content"] = s.second.scanner->source(); meta["sources"][s.first]["content"] = s.second.scanner->source();
else else

View File

@ -30,8 +30,11 @@
#include <liblangutil/SemVerHandler.h> #include <liblangutil/SemVerHandler.h>
#include <liblangutil/SourceLocation.h> #include <liblangutil/SourceLocation.h>
#include <libyul/backends/evm/EVMDialect.h> #include <libyul/backends/evm/EVMDialect.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <cctype> #include <cctype>
#include <vector> #include <vector>
#include <regex>
using namespace std; using namespace std;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -79,6 +82,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
m_recursionDepth = 0; m_recursionDepth = 0;
m_scanner = _scanner; m_scanner = _scanner;
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
vector<ASTPointer<ASTNode>> nodes; vector<ASTPointer<ASTNode>> nodes;
while (m_scanner->currentToken() != Token::EOS) while (m_scanner->currentToken() != Token::EOS)
{ {
@ -107,7 +111,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
} }
} }
solAssert(m_recursionDepth == 0, ""); solAssert(m_recursionDepth == 0, "");
return nodeFactory.createNode<SourceUnit>(nodes); return nodeFactory.createNode<SourceUnit>(findLicenseString(nodes), nodes);
} }
catch (FatalError const&) catch (FatalError const&)
{ {
@ -1981,6 +1985,60 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars
return ret; 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 Parser::LookAheadInfo Parser::peekStatementType() const
{ {
// Distinguish between variable declaration (and potentially assignment) and expression statement // Distinguish between variable declaration (and potentially assignment) and expression statement

View File

@ -175,6 +175,8 @@ private:
bool empty() const; bool empty() const;
}; };
std::optional<std::string> findLicenseString(std::vector<ASTPointer<ASTNode>> const& _nodes);
/// Returns the next AST node ID /// Returns the next AST node ID
int64_t nextID() { return ++m_currentNodeID; } 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 == '"') if (c <= 0x1f || c >= 0x7f || c == '"')
return "0x" + h256(_value, h256::AlignLeft).hex(); 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. /// _value cannot be longer than 32 bytes.
std::string formatAsStringOrNumber(std::string const& _value); 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> template<typename Container, typename Compare>
bool containerEqual(Container const& _lhs, Container const& _rhs, Compare&& _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; break;
} }
string out; return escapeAndQuoteString(_literal.value.str()) + appendTypeName(_literal.type);
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);
} }
string AsmPrinter::operator()(Identifier const& _identifier) const string AsmPrinter::operator()(Identifier const& _identifier) const

View File

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

View File

@ -52,7 +52,7 @@ def extract_docs_cases(path):
if inside: if inside:
extractedLines[-1] += l + '\n' 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. # Filter all tests that do not contain Solidity or are intended incorrectly.
for lines in extractedLines: for lines in extractedLines:

View File

@ -81,12 +81,14 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
m_evmRevision = EVMC_BYZANTIUM; m_evmRevision = EVMC_BYZANTIUM;
else if (_evmVersion == langutil::EVMVersion::constantinople()) else if (_evmVersion == langutil::EVMVersion::constantinople())
m_evmRevision = EVMC_CONSTANTINOPLE; m_evmRevision = EVMC_CONSTANTINOPLE;
else if (_evmVersion == langutil::EVMVersion::petersburg())
m_evmRevision = EVMC_PETERSBURG;
else if (_evmVersion == langutil::EVMVersion::istanbul()) else if (_evmVersion == langutil::EVMVersion::istanbul())
m_evmRevision = EVMC_ISTANBUL; m_evmRevision = EVMC_ISTANBUL;
else if (_evmVersion == langutil::EVMVersion::berlin()) else if (_evmVersion == langutil::EVMVersion::berlin())
assertThrow(false, Exception, "Berlin is not supported yet."); m_evmRevision = EVMC_BERLIN;
else //if (_evmVersion == langutil::EVMVersion::petersburg()) else
m_evmRevision = EVMC_PETERSBURG; assertThrow(false, Exception, "Unsupported EVM version");
// Mark all precompiled contracts as existing. Existing here means to have a balance (as per EIP-161). // 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. // NOTE: keep this in sync with `EVMHost::call` below.
@ -99,17 +101,16 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
evmc::address address{}; evmc::address address{};
address.bytes[19] = precompiledAddress; address.bytes[19] = precompiledAddress;
// 1wei // 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 = evmc::uint256be{200000000};
tx_context.block_difficulty = convertToEVMC(u256("200000000"));
tx_context.block_gas_limit = 20000000; tx_context.block_gas_limit = 20000000;
tx_context.block_coinbase = 0x7878787878787878787878787878787878787878_address; 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; tx_context.tx_origin = 0x9292929292929292929292929292929292929292_address;
// Mainnet according to EIP-155 // 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 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 solidity >=0.0;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
contract C { contract C {
struct S { uint x; } struct S { uint x; }
function f(S memory) public pure { 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; pragma solidity >=0.6.0;
contract C { contract C {

View File

@ -1,5 +1,5 @@
Warning: Unused local variable. 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; pragma solidity >=0.6.0;
contract C {} contract C {}

View File

@ -1,5 +1,5 @@
// checks that error messages around power-or-10 lines are formatted correctly // 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; pragma solidity >=0.0;
contract C contract C

View File

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

View File

@ -2,10 +2,10 @@
"language": "Solidity", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "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": { "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! {"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":"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); } } 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", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "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": { "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! {"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":"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); } } 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", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "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": { "settings": {

View File

@ -1,6 +1,6 @@
{"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version! {"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":"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); } } 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", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "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": { "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! {"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":"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); } } 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", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "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": { "settings": {

View File

@ -2,10 +2,10 @@
"language": "Solidity", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "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": { "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! {"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); } } 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", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "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": { "settings": {

View File

@ -1,13 +1,13 @@
Error: Expected primary expression. 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 ';'. 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; pragma solidity >=0.0.0;
contract Error1 { contract Error1 {

View File

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

View File

@ -4,7 +4,7 @@
{ {
"A": "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": "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 */ } 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 */ } 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. 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)
Note: Candidate: function require(bool, string memory) Note: Candidate: function require(bool, string memory)

View File

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

View File

@ -4,7 +4,7 @@
{ {
"A": "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": "A":
{ {
"content": "pragma solidity >=0.0; contract C { }" "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { }"
} }
}, },
"settings": "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 \".\"; pragma solidity >=0.0; import {A} from \".\";
^------------------^ ^------------------^
","message":"Declaration \"A\" not found in \"\" (referenced as \".\").","severity":"error","type":"DeclarationError"}],"sources":{}} ","message":"Declaration \"A\" not found in \"\" (referenced as \".\").","severity":"error","type":"DeclarationError"}],"sources":{}}

View File

@ -2,7 +2,7 @@
"language": "Solidity", "language": "Solidity",
"sources": { "sources": {
"a.sol": { "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": { "settings": {

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