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

This commit is contained in:
chriseth 2020-10-08 14:56:52 +02:00
commit e16811e79f
40 changed files with 723 additions and 327 deletions

View File

@ -4,20 +4,30 @@ Breaking Changes:
* Type System: Unary negation can only be used on signed integers, not on unsigned integers.
* Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type.
### 0.7.4 (unreleased)
### 0.7.3 (2020-10-07)
Important Bugfixes:
* Code Generator: Properly cleanup after copying dynamic-array to storage for packed types.
Compiler Features:
* Code generator: Implemented events with function type as one of its indexed parameters.
* General: Option to stop compilation after parsing stage. Can be used with ``solc --stop-after parsing``
* Optimizer: Optimize ``exp`` when base is ``-1``.
* SMTChecker: Support ``addmod`` and ``mulmod``.
* SMTChecker: Support array slices.
* SMTChecker: Support type conversions.
* Optimizer: Optimize ``exp`` when base is -1.
* Code generator: Implemented events with function type as one of its indexed parameters.
* General: Option to stop compilation after parsing stage. Can be used with ``solc --stop-after parsing``
Bugfixes:
* Fixed internal compiler errors for certain contracts involving the ``new`` expression.
* JSON AST: Fix internal error when using ``--ast-json`` on a function with memory arguments in ABIEncoderV2 contracts.
* Type Checker: Add missing checks for calls using types incompatible with ABIEncoderV1 in modules where ABIEncoderV2 is not enabled.
* Type Checker: Fix internal compiler error when calling `.push(<arg>)` for a storage array with a nested mapping.
### 0.7.3 (unreleased)
### 0.7.2 (2020-09-28)

View File

@ -1,110 +0,0 @@
#------------------------------------------------------------------------------
# Appveyor configuration file for solidity.
#
# The documentation for solidity is hosted at:
#
# http://solidity.readthedocs.org
#
# ------------------------------------------------------------------------------
# This file is part of solidity.
#
# solidity is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# solidity is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with solidity. If not, see <http://www.gnu.org/licenses/>
#
# (c) 2016 solidity contributors.
#------------------------------------------------------------------------------
branches:
only:
- release
- develop
configuration:
- Release
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
# This is used for pushing to solidity-test-bytecodes
priv_key:
secure: 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
# NB: Appveyor cache is disabled, because it is proving very unreliable.
# We can re-enable it when we find a way to mitigate the unreliability
# issues. Have automated builds be reliable is the more important thing.
#cache: build
#
# In case we'd need a RDP detail to login into appveyor
#init:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
install:
- ps: if ($env:priv_key) {
$fileContent = "-----BEGIN RSA PRIVATE KEY-----`n";
$fileContent += $env:priv_key.Replace(' ', "`n");
$fileContent += "`n-----END RSA PRIVATE KEY-----`n";
Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent
}
- ps: $prerelease = "nightly."
- ps: $prerelease += Get-Date -format "yyyy.M.d"
- ps: if($env:appveyor_repo_branch -eq 'release') { Set-Content prerelease.txt $null } else { Set-Content prerelease.txt $prerelease }
- scripts/install_deps.bat
- set ETHEREUM_DEPS_PATH=%APPVEYOR_BUILD_FOLDER%\deps\install
before_build:
- if not exist build mkdir build
- cd build
- cmake -G "Visual Studio 15 2017 Win64" .. -DTESTS=On -DBoost_USE_STATIC_RUNTIME=OFF
build_script:
- msbuild solidity.sln /p:Configuration=%CONFIGURATION% /m:%NUMBER_OF_PROCESSORS% /v:minimal
- cd %APPVEYOR_BUILD_FOLDER%
- scripts\release.bat %CONFIGURATION% 2017
- ps: $bytecodedir = git show -s --format="%cd-%H" --date="format:%Y-%m-%d-%H-%M"
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\build\test\%CONFIGURATION%
- soltest.exe --show-progress -- --testpath %APPVEYOR_BUILD_FOLDER%\test --no-smt
# Skip bytecode compare if private key is not available
- cd %APPVEYOR_BUILD_FOLDER%
- ps: if ($env:priv_key -and -not $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) {
scripts\bytecodecompare\storebytecode.bat $Env:CONFIGURATION $bytecodedir
}
- cd %APPVEYOR_BUILD_FOLDER%\build\test\%CONFIGURATION%
artifacts:
- path: solidity-windows.zip
name: solidity-windows-zip
# This is the deploy target for Windows which generates ZIPs per commit.
# We are in agreement that generating ZIPs per commit for the develop
# branch is probably just noise, so we only run this deployment target
# on 'release'.
#
# See https://www.appveyor.com/docs/deployment/github for information
# on GitHub Releases in Appveyor.
#
# You need to generate a GitHub personal access token for Appveyor
# See https://github.com/settings/tokens for more information on that.
# The token you generate there (in an encrypted form) is what is
# passed to this deployment target in the 'auth_token' parameter
# below.
deploy:
provider: GitHub
auth_token:
secure: HPjiugbDSCsEFTphj/qwHuSw80/BV1xWoSvj95CPmtb16Ukh2VQbLVB7iFtZSans
artifact: solidity-windows-zip
on:
branch: release
appveyor_repo_tag: true
notifications:
- provider: GitHubPullRequest
on_build_success: false
on_build_failure: false
on_build_status_changed: false

View File

@ -1,4 +1,11 @@
[
{
"name": "DynamicArrayCleanup",
"summary": "When assigning a dynamically-sized array with types of size at most 16 bytes in storage causing the assigned array to shrink, some parts of deleted slots were not zeroed out.",
"description": "Consider a dynamically-sized array in storage whose base-type is small enough such that multiple values can be packed into a single slot, such as `uint128[]`. Let us define its length to be `l`. When this array gets assigned from another array with a smaller length, say `m`, the slots between elements `m` and `l` have to be cleaned by zeroing them out. However, this cleaning was not performed properly. Specifically, after the slot corresponding to `m`, only the first packed value was cleaned up. If this array gets resized to a length larger than `m`, the indices corresponding to the unclean parts of the slot contained the original value, instead of 0. The resizing here is performed by assigning to the array `length`, by a `push()` or via inline assembly. You are not affected if you are only using `.push(<arg>)` or if you assign a value (even zero) to the new elements after increasing the length of the array.",
"fixed": "0.7.3",
"severity": "medium"
},
{
"name": "FreeFunctionRedefinition",
"summary": "The compiler does not flag an error when two or more free functions with the same name and parameter types are defined in a source unit or when an imported free function alias shadows another free function with a different name but identical parameter types.",

View File

@ -1,6 +1,7 @@
{
"0.1.0": {
"bugs": [
"DynamicArrayCleanup",
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -19,6 +20,7 @@
},
"0.1.1": {
"bugs": [
"DynamicArrayCleanup",
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -37,6 +39,7 @@
},
"0.1.2": {
"bugs": [
"DynamicArrayCleanup",
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -55,6 +58,7 @@
},
"0.1.3": {
"bugs": [
"DynamicArrayCleanup",
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -73,6 +77,7 @@
},
"0.1.4": {
"bugs": [
"DynamicArrayCleanup",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -92,6 +97,7 @@
},
"0.1.5": {
"bugs": [
"DynamicArrayCleanup",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -111,6 +117,7 @@
},
"0.1.6": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
@ -132,6 +139,7 @@
},
"0.1.7": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
@ -153,6 +161,7 @@
},
"0.2.0": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"ExpExponentCleanup",
@ -175,6 +184,7 @@
},
"0.2.1": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"ExpExponentCleanup",
@ -197,6 +207,7 @@
},
"0.2.2": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"ExpExponentCleanup",
@ -219,6 +230,7 @@
},
"0.3.0": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -243,6 +255,7 @@
},
"0.3.1": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -266,6 +279,7 @@
},
"0.3.2": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -289,6 +303,7 @@
},
"0.3.3": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -311,6 +326,7 @@
},
"0.3.4": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -333,6 +349,7 @@
},
"0.3.5": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -355,6 +372,7 @@
},
"0.3.6": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -375,6 +393,7 @@
},
"0.4.0": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -395,6 +414,7 @@
},
"0.4.1": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -415,6 +435,7 @@
},
"0.4.10": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -434,6 +455,7 @@
},
"0.4.11": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -452,6 +474,7 @@
},
"0.4.12": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -469,6 +492,7 @@
},
"0.4.13": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -486,6 +510,7 @@
},
"0.4.14": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -502,6 +527,7 @@
},
"0.4.15": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -517,6 +543,7 @@
},
"0.4.16": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -534,6 +561,7 @@
},
"0.4.17": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -552,6 +580,7 @@
},
"0.4.18": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -569,6 +598,7 @@
},
"0.4.19": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -587,6 +617,7 @@
},
"0.4.2": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -606,6 +637,7 @@
},
"0.4.20": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -624,6 +656,7 @@
},
"0.4.21": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -642,6 +675,7 @@
},
"0.4.22": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -660,6 +694,7 @@
},
"0.4.23": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -677,6 +712,7 @@
},
"0.4.24": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -694,6 +730,7 @@
},
"0.4.25": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -709,6 +746,7 @@
},
"0.4.26": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -721,6 +759,7 @@
},
"0.4.3": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -739,6 +778,7 @@
},
"0.4.4": {
"bugs": [
"DynamicArrayCleanup",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
@ -756,6 +796,7 @@
},
"0.4.5": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -776,6 +817,7 @@
},
"0.4.6": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -795,6 +837,7 @@
},
"0.4.7": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -814,6 +857,7 @@
},
"0.4.8": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -833,6 +877,7 @@
},
"0.4.9": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -852,6 +897,7 @@
},
"0.5.0": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -867,6 +913,7 @@
},
"0.5.1": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -882,6 +929,7 @@
},
"0.5.10": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -893,6 +941,7 @@
},
"0.5.11": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -903,6 +952,7 @@
},
"0.5.12": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -913,6 +963,7 @@
},
"0.5.13": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -923,6 +974,7 @@
},
"0.5.14": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
@ -935,6 +987,7 @@
},
"0.5.15": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
@ -946,6 +999,7 @@
},
"0.5.16": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
@ -956,6 +1010,7 @@
},
"0.5.17": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
@ -965,6 +1020,7 @@
},
"0.5.2": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -980,6 +1036,7 @@
},
"0.5.3": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -995,6 +1052,7 @@
},
"0.5.4": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -1010,6 +1068,7 @@
},
"0.5.5": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -1027,6 +1086,7 @@
},
"0.5.6": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -1044,6 +1104,7 @@
},
"0.5.7": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -1059,6 +1120,7 @@
},
"0.5.8": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -1073,6 +1135,7 @@
},
"0.5.9": {
"bugs": [
"DynamicArrayCleanup",
"ImplicitConstructorCallvalueCheck",
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
@ -1086,6 +1149,7 @@
},
"0.6.0": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
@ -1097,6 +1161,7 @@
},
"0.6.1": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
@ -1106,19 +1171,26 @@
"released": "2020-01-02"
},
"0.6.10": {
"bugs": [],
"bugs": [
"DynamicArrayCleanup"
],
"released": "2020-06-11"
},
"0.6.11": {
"bugs": [],
"bugs": [
"DynamicArrayCleanup"
],
"released": "2020-07-07"
},
"0.6.12": {
"bugs": [],
"bugs": [
"DynamicArrayCleanup"
],
"released": "2020-07-22"
},
"0.6.2": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
@ -1129,6 +1201,7 @@
},
"0.6.3": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
@ -1139,6 +1212,7 @@
},
"0.6.4": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
@ -1149,6 +1223,7 @@
},
"0.6.5": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck",
@ -1158,6 +1233,7 @@
},
"0.6.6": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck"
@ -1166,6 +1242,7 @@
},
"0.6.7": {
"bugs": [
"DynamicArrayCleanup",
"MissingEscapingInFormatting",
"ArraySliceDynamicallyEncodedBaseType",
"ImplicitConstructorCallvalueCheck"
@ -1173,27 +1250,39 @@
"released": "2020-05-04"
},
"0.6.8": {
"bugs": [],
"bugs": [
"DynamicArrayCleanup"
],
"released": "2020-05-14"
},
"0.6.9": {
"bugs": [
"DynamicArrayCleanup",
"UsingForCalldata"
],
"released": "2020-06-04"
},
"0.7.0": {
"bugs": [],
"bugs": [
"DynamicArrayCleanup"
],
"released": "2020-07-28"
},
"0.7.1": {
"bugs": [
"DynamicArrayCleanup",
"FreeFunctionRedefinition"
],
"released": "2020-09-02"
},
"0.7.2": {
"bugs": [],
"bugs": [
"DynamicArrayCleanup"
],
"released": "2020-09-28"
},
"0.7.3": {
"bugs": [],
"released": "2020-10-07"
}
}

View File

@ -167,7 +167,7 @@ void ImmutableValidator::analyseVariableReference(VariableDeclaration const& _va
// If this is not an ordinary assignment, we write and read at the same time.
bool write = _expression.annotation().willBeWrittenTo;
bool read = !_expression.annotation().willBeWrittenTo || !*_expression.annotation().lValueOfOrdinaryAssignment;
bool read = !_expression.annotation().willBeWrittenTo || !_expression.annotation().lValueOfOrdinaryAssignment;
if (write)
{
if (!m_currentConstructor)

View File

@ -1420,7 +1420,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
{
requireLValue(
*component,
*_tuple.annotation().lValueOfOrdinaryAssignment
_tuple.annotation().lValueOfOrdinaryAssignment
);
types.push_back(type(*component));
}
@ -1534,6 +1534,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
_operation.annotation().isConstant = false;
_operation.annotation().isPure = !modifying && *_operation.subExpression().annotation().isPure;
_operation.annotation().isLValue = false;
return false;
}
@ -2178,6 +2179,52 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
m_errorReporter.typeError(errorId, paramArgMap[i]->location(), description);
}
}
TypePointers const& returnParameterTypes = _functionType->returnParameterTypes();
bool isLibraryCall = (_functionType->kind() == FunctionType::Kind::DelegateCall);
bool callRequiresABIEncoding =
// ABIEncode/ABIDecode calls not included because they should have been already validated
// at this point and they have variadic arguments so they need special handling.
_functionType->kind() == FunctionType::Kind::DelegateCall ||
_functionType->kind() == FunctionType::Kind::External ||
_functionType->kind() == FunctionType::Kind::Creation ||
_functionType->kind() == FunctionType::Kind::Event;
if (callRequiresABIEncoding && !experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
{
solAssert(!isVariadic, "");
solAssert(parameterTypes.size() == arguments.size(), "");
solAssert(!_functionType->isBareCall(), "");
solAssert(*_functionCall.annotation().kind == FunctionCallKind::FunctionCall, "");
for (size_t i = 0; i < parameterTypes.size(); ++i)
{
solAssert(parameterTypes[i], "");
if (!typeSupportedByOldABIEncoder(*parameterTypes[i], isLibraryCall))
m_errorReporter.typeError(
2443_error,
paramArgMap[i]->location(),
"The type of this parameter, " + parameterTypes[i]->toString(true) + ", "
"is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
);
}
for (size_t i = 0; i < returnParameterTypes.size(); ++i)
{
solAssert(returnParameterTypes[i], "");
if (!typeSupportedByOldABIEncoder(*returnParameterTypes[i], isLibraryCall))
m_errorReporter.typeError(
2428_error,
_functionCall.location(),
"The type of return parameter " + toString(i + 1) + ", " + returnParameterTypes[i]->toString(true) + ", "
"is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
);
}
}
}
bool TypeChecker::visit(FunctionCall const& _functionCall)
@ -2345,6 +2392,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
_functionCallOptions.annotation().isPure = false;
_functionCallOptions.annotation().isConstant = false;
_functionCallOptions.annotation().isLValue = false;
auto expressionFunctionType = dynamic_cast<FunctionType const*>(type(_functionCallOptions.expression()));
if (!expressionFunctionType)
@ -2477,6 +2525,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
solAssert(!!type, "Type name not resolved.");
_newExpression.annotation().isConstant = false;
_newExpression.annotation().isLValue = false;
if (auto contractName = dynamic_cast<UserDefinedTypeName const*>(&_newExpression.typeName()))
{
@ -2537,7 +2586,10 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
_newExpression.annotation().isPure = true;
}
else
{
_newExpression.annotation().isPure = false;
m_errorReporter.fatalTypeError(8807_error, _newExpression.location(), "Contract or array type expected.");
}
}
bool TypeChecker::visit(MemberAccess const& _memberAccess)
@ -2720,6 +2772,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
)
annotation.isPure = *_memberAccess.expression().annotation().isPure;
}
else
annotation.isLValue = false;
}
else if (exprType->category() == Type::Category::Module)
{
@ -3015,6 +3069,7 @@ vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
bool TypeChecker::visit(Identifier const& _identifier)
{
IdentifierAnnotation& annotation = _identifier.annotation();
if (!annotation.referencedDeclaration)
{
annotation.overloadedDeclarations = cleanOverloadedDeclarations(_identifier, annotation.candidateDeclarations);

View File

@ -253,7 +253,8 @@ struct ExpressionAnnotation: ASTAnnotation
bool willBeWrittenTo = false;
/// Whether the expression is an lvalue that is only assigned.
/// Would be false for --, ++, delete, +=, -=, ....
SetOnce<bool> lValueOfOrdinaryAssignment;
/// Only relevant if isLvalue == true
bool lValueOfOrdinaryAssignment;
/// Types and - if given - names of arguments if the expr. is a function
/// that is called, used for overload resolution

View File

@ -313,46 +313,4 @@ private:
std::function<void(ASTNode const&)> m_onEndVisit;
};
/**
* Utility class that visits the AST in depth-first order and calls a function on each node and each edge.
* Child nodes are only visited if the node callback of the parent returns true.
* The node callback of a parent is called before any edge or node callback involving the children.
* The edge callbacks of all children are called before the edge callback of the parent.
* This way, the node callback can be used as an initializing callback and the edge callbacks can be
* used to compute a "reduce" function.
*/
class ASTReduce: public ASTConstVisitor
{
public:
/**
* Constructs a new ASTReduce object with the given callback functions.
* @param _onNode called for each node, before its child edges and nodes, should return true to descend deeper
* @param _onEdge called for each edge with (parent, child)
*/
ASTReduce(
std::function<bool(ASTNode const&)> _onNode,
std::function<void(ASTNode const&, ASTNode const&)> _onEdge
): m_onNode(std::move(_onNode)), m_onEdge(std::move(_onEdge))
{
}
protected:
bool visitNode(ASTNode const& _node) override
{
m_parents.push_back(&_node);
return m_onNode(_node);
}
void endVisitNode(ASTNode const& _node) override
{
m_parents.pop_back();
if (!m_parents.empty())
m_onEdge(*m_parents.back(), _node);
}
private:
std::vector<ASTNode const*> m_parents;
std::function<bool(ASTNode const&)> m_onNode;
std::function<void(ASTNode const&, ASTNode const&)> m_onEdge;
};
}

View File

@ -290,7 +290,10 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end
_context << Instruction::POP << Instruction::SWAP1 << Instruction::POP;
// stack: target_ref target_data_end target_data_pos_updated
utils.clearStorageLoop(targetBaseType);
if (targetBaseType->storageBytes() < 32)
utils.clearStorageLoop(TypeProvider::uint256());
else
utils.clearStorageLoop(targetBaseType);
_context << Instruction::POP;
}
);
@ -922,6 +925,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
void ArrayUtils::clearStorageLoop(TypePointer _type) const
{
solAssert(_type->storageBytes() >= 32, "");
m_context.callLowLevelFunction(
"$clearStorageLoop_" + _type->identifier(),
2,

View File

@ -42,93 +42,6 @@ using namespace solidity::evmasm;
using namespace solidity::frontend;
using namespace solidity::langutil;
GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimation(
AssemblyItems const& _items,
vector<ASTNode const*> const& _ast
) const
{
solAssert(std::count(_ast.begin(), _ast.end(), nullptr) == 0, "");
map<SourceLocation, GasConsumption> particularCosts;
ControlFlowGraph cfg(_items);
for (BasicBlock const& block: cfg.optimisedBlocks())
{
solAssert(!!block.startState, "");
GasMeter meter(block.startState->copy(), m_evmVersion);
auto const end = _items.begin() + static_cast<ptrdiff_t>(block.end);
for (auto iter = _items.begin() + static_cast<ptrdiff_t>(block.begin); iter != end; ++iter)
particularCosts[iter->location()] += meter.estimateMax(*iter);
}
set<ASTNode const*> finestNodes = finestNodesAtLocation(_ast);
ASTGasConsumptionSelfAccumulated gasCosts;
auto onNode = [&](ASTNode const& _node)
{
if (!finestNodes.count(&_node))
return true;
gasCosts[&_node][0] = gasCosts[&_node][1] = particularCosts[_node.location()];
return true;
};
auto onEdge = [&](ASTNode const& _parent, ASTNode const& _child)
{
gasCosts[&_parent][1] += gasCosts[&_child][1];
};
ASTReduce folder(onNode, onEdge);
for (ASTNode const* ast: _ast)
ast->accept(folder);
return gasCosts;
}
map<ASTNode const*, GasMeter::GasConsumption> GasEstimator::breakToStatementLevel(
ASTGasConsumptionSelfAccumulated const& _gasCosts,
vector<ASTNode const*> const& _roots
)
{
solAssert(std::count(_roots.begin(), _roots.end(), nullptr) == 0, "");
// first pass: statementDepth[node] is the distance from the deepend statement to node
// in direction of the tree root (or undefined if not possible)
map<ASTNode const*, int> statementDepth;
auto onNodeFirstPass = [&](ASTNode const& _node)
{
if (dynamic_cast<Statement const*>(&_node))
statementDepth[&_node] = 0;
return true;
};
auto onEdgeFirstPass = [&](ASTNode const& _parent, ASTNode const& _child)
{
if (statementDepth.count(&_child))
statementDepth[&_parent] = max(statementDepth[&_parent], statementDepth[&_child] + 1);
};
ASTReduce firstPass(onNodeFirstPass, onEdgeFirstPass);
for (ASTNode const* node: _roots)
node->accept(firstPass);
// we use the location of a node if
// - its statement depth is 0 or
// - its statement depth is undefined but the parent's statement depth is at least 1
map<ASTNode const*, GasConsumption> gasCosts;
auto onNodeSecondPass = [&](ASTNode const& _node)
{
return statementDepth.count(&_node);
};
auto onEdgeSecondPass = [&](ASTNode const& _parent, ASTNode const& _child)
{
bool useNode = false;
if (statementDepth.count(&_child))
useNode = statementDepth[&_child] == 0;
else
useNode = statementDepth.count(&_parent) && statementDepth.at(&_parent) > 0;
if (useNode)
gasCosts[&_child] = _gasCosts.at(&_child)[1];
};
ASTReduce secondPass(onNodeSecondPass, onEdgeSecondPass);
for (ASTNode const* node: _roots)
node->accept(secondPass);
// gasCosts should only contain non-overlapping locations
return gasCosts;
}
GasEstimator::GasConsumption GasEstimator::functionalEstimation(
AssemblyItems const& _items,
string const& _signature

View File

@ -48,22 +48,6 @@ public:
explicit GasEstimator(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) {}
/// Estimates the gas consumption for every assembly item in the given assembly and stores
/// it by source location.
/// @returns a mapping from each AST node to a pair of its particular and syntactically accumulated gas costs.
ASTGasConsumptionSelfAccumulated structuralEstimation(
evmasm::AssemblyItems const& _items,
std::vector<ASTNode const*> const& _ast
) const;
/// @returns a mapping from nodes with non-overlapping source locations to gas consumptions such that
/// the following source locations are part of the mapping:
/// 1. source locations of statements that do not contain other statements
/// 2. maximal source locations that do not overlap locations coming from the first rule
static ASTGasConsumption breakToStatementLevel(
ASTGasConsumptionSelfAccumulated const& _gasCosts,
std::vector<ASTNode const*> const& _roots
);
/// @returns the estimated gas consumption by the (public or external) function with the
/// given signature. If no signature is given, estimates the maximum gas usage.
GasConsumption functionalEstimation(

View File

@ -101,9 +101,9 @@ void OptimiserSuite::run(
OptimiserSuite suite(_dialect, reservedIdentifiers, Debug::None, ast);
// Some steps depend on properties ensured by FunctionHoister, FunctionGrouper and
// Some steps depend on properties ensured by FunctionHoister, BlockFlattener, FunctionGrouper and
// ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely.
suite.runSequence("fgo", ast);
suite.runSequence("hfgo", ast);
// Now the user-supplied part
suite.runSequence(_optimisationSequence, ast);

View File

@ -1638,18 +1638,6 @@ void CommandLineInterface::handleAst(string const& _argStr)
vector<ASTNode const*> asts;
for (auto const& sourceCode: m_sourceCodes)
asts.push_back(&m_compiler->ast(sourceCode.first));
map<ASTNode const*, evmasm::GasMeter::GasConsumption> gasCosts;
for (auto const& contract: m_compiler->contractNames())
if (m_compiler->compilationSuccessful())
if (auto const* assemblyItems = m_compiler->runtimeAssemblyItems(contract))
{
auto ret = GasEstimator::breakToStatementLevel(
GasEstimator(m_evmVersion).structuralEstimation(*assemblyItems, asts),
asts
);
for (auto const& it: ret)
gasCosts[it.first] += it.second;
}
bool legacyFormat = !m_args.count(g_argAstCompactJson);
if (m_args.count(g_argOutputDir))

View File

@ -49,14 +49,6 @@ public:
m_compiler.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
m_compiler.setEVMVersion(m_evmVersion);
BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
AssemblyItems const* items = m_compiler.runtimeAssemblyItems(m_compiler.lastContractName());
ASTNode const& sourceUnit = m_compiler.ast("");
BOOST_REQUIRE(items != nullptr);
m_gasCosts = GasEstimator::breakToStatementLevel(
GasEstimator(solidity::test::CommonOptions::get().evmVersion()).structuralEstimation(*items, vector<ASTNode const*>({&sourceUnit})),
{&sourceUnit}
);
}
void testCreationTimeGas(string const& _sourceCode, u256 const& _tolerance = u256(0))
@ -118,43 +110,10 @@ public:
gas += i != 0 ? GasCosts::txDataNonZeroGas(evmVersion) : GasCosts::txDataZeroGas;
return gas;
}
protected:
map<ASTNode const*, evmasm::GasMeter::GasConsumption> m_gasCosts;
};
BOOST_FIXTURE_TEST_SUITE(GasMeterTests, GasMeterTestFramework)
BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs)
{
char const* sourceCode = R"(
contract test {
bytes x;
function f(uint a) public returns (uint b) {
for (; a < 200; ++a) {
x.push(0x09);
b = a * a;
}
return f(a - 1);
}
}
)";
compile(sourceCode);
for (auto first = m_gasCosts.cbegin(); first != m_gasCosts.cend(); ++first)
{
auto second = first;
for (++second; second != m_gasCosts.cend(); ++second)
if (first->first->location().intersects(second->first->location()))
{
BOOST_CHECK_MESSAGE(false, "Source locations should not overlap!");
langutil::SourceReferenceFormatter formatter(cout);
formatter.printSourceLocation(&first->first->location());
formatter.printSourceLocation(&second->first->location());
}
}
}
BOOST_AUTO_TEST_CASE(simple_contract)
{
// Tests a simple "deploy contract" code without constructor. The actual contract is not relevant.

View File

@ -633,8 +633,8 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores)
)";
compileBothVersions(sourceCode);
compareVersions("f()");
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 9);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 8);
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 8);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 7);
}
BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy)

View File

@ -0,0 +1,23 @@
// Test to see if cleanup is performed properly during array copying
contract C {
uint128[] x;
function f() public returns(bool) {
x.push(42); x.push(42); x.push(42); x.push(42);
uint128[] memory y = new uint128[](1);
y[0] = 23;
x = y;
assembly { sstore(x.slot, 4) }
assert(x[0] == 23);
assert(x[1] == 0);
assert(x[2] == 0);
// Issue 9832: the cleanup was only performed for the first packed type leaving the rest of
// the slot dirty.
assert(x[3] == 0);
return true;
}
}
// ----
// f() -> true

View File

@ -0,0 +1,48 @@
// Issue 9832: Test to see if cleanup is performed properly after array copying
contract C {
uint40[] x;
function f() public returns(bool) {
x.push(42); x.push(42); x.push(42); x.push(42);
x.push(42); x.push(42); x.push(42); x.push(42);
x.push(42); x.push(42); x.push(42); x.push(42);
x.push(42); x.push(42); x.push(42); x.push(42);
x.push(42); x.push(42); x.push(42); x.push(42);
uint40[] memory y = new uint40[](1);
y[0] = 23;
x = y;
assembly { sstore(x.slot, 20) }
assert(x[0] == 23);
assert(x[1] == 0);
assert(x[2] == 0);
assert(x[3] == 0);
assert(x[4] == 0);
assert(x[5] == 0);
assert(x[6] == 0);
assert(x[7] == 0);
assert(x[8] == 0);
assert(x[9] == 0);
assert(x[10] == 0);
assert(x[11] == 0);
assert(x[12] == 0);
assert(x[13] == 0);
assert(x[14] == 0);
assert(x[15] == 0);
assert(x[16] == 0);
assert(x[17] == 0);
assert(x[18] == 0);
assert(x[19] == 0);
return true;
}
}
// ----
// f() -> true

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function set(Item storage _item) external view {}
}
==== Source: B ====
import "A";
contract Test {
L.Item item;
function foo() public view {
L.set(item);
}
}
// ----

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
constructor(Item memory _item) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public {
new C(C.Item(5));
}
}
// ----
// TypeError 2443: (B:71-80): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function set(uint _x, string memory _y, Item memory _item, bool _z) external view {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
C(0x00).set({_item: C.Item(50), _z: false, _y: "abc", _x: 30});
}
}
// ----
// TypeError 2443: (B:90-100): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,22 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get(Item memory _item) external {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public {
C c = new C();
function(C.Item memory) external ptr = c.get;
ptr(C.Item(5));
}
}
// ----
// TypeError 2443: (B:146-155): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,16 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
function f() external view returns (string[] memory) {}
}
==== Source: B ====
import "A";
contract D {
function g() public view {
C(0x00).f();
}
}
// ----
// TypeError 2428: (B:65-76): The type of return parameter 1, string[], is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint[] y;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,19 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
event E(Item _value);
}
==== Source: B ====
import "A";
contract Test {
function foo() public {
emit L.E(L.Item(42));
}
}
// ----
// TypeError 2443: (B:74-84): The type of this parameter, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get(Item storage _item) external view {}
}
==== Source: B ====
import "A";
contract Test {
L.Item item;
function foo() public view {
L.get(item);
}
}
// ----

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
L.get();
}
}
// ----
// TypeError 2428: (B:70-77): The type of return parameter 1, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,13 @@
pragma experimental ABIEncoderV2;
contract C {
function get() public view returns (uint[][] memory) {}
function test() public view returns (bool) {
uint[][] memory x = this.get();
}
}
// ====
// EVMVersion: >=byzantium
// ----
// Warning 2072: (166-183): Unused local variable.

View File

@ -0,0 +1,13 @@
pragma experimental ABIEncoderV2;
contract C {
function get() public view returns (uint[][] memory) {}
function test() public view returns (bool) {
uint[][] memory x = this.get();
}
}
// ====
// EVMVersion: <byzantium
// ----
// TypeError 9574: (166-196): Type inaccessible dynamic type is not implicitly convertible to expected type uint256[] memory[] memory.

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
constructor(Item memory _item) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
new C(C.Item(5));
}
}
// ----

View File

@ -0,0 +1,23 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get(Item memory _item) external {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
C c = new C();
function(C.Item memory) external ptr = c.get;
ptr(C.Item(5));
}
}
// ----

View File

@ -0,0 +1,17 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
function f() external view returns (string[] memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract D {
function g() public view {
C(0x00).f();
}
}
// ----

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint[] y;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
event E(Item _value);
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
emit L.E(L.Item(42));
}
}
// ----

View File

@ -0,0 +1,25 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get(Item memory _item) external {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
// NOTE: This test checks a case that is currently not possible (pointer to an external
// library function) but it might become possible in the future.
function(L.Item memory) external ptr = L.get;
ptr(L.Item(5));
}
}
// ----
// TypeError 9574: (B:269-313): Type function (struct L.Item memory) is not implicitly convertible to expected type function (struct L.Item memory) external.

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public view {
L.get();
}
}
// ----

View File

@ -0,0 +1,30 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
struct Data {
bool flag;
}
contract A {
function get() public view returns (Data memory) {}
}
==== Source: B ====
import "A";
contract B {
modifier validate() {
A(0x00).get();
_;
}
}
==== Source: C ====
import "B";
contract C is B {
function foo()
public
validate()
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,32 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
struct Data {
bool flag;
}
contract A {
function get() public view returns (Data memory) {}
}
==== Source: B ====
import "A";
contract B {
modifier validate() {
A(0x00).get();
_;
}
}
==== Source: C ====
pragma experimental ABIEncoderV2;
import "B";
contract C is B {
function foo()
public
validate()
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,11 @@
contract C {
function foo(uint x) public
{
// Used to cause an ICE
uint p = new uint[] = x;
}
}
// ----
// TypeError 4247: (100-110): Expression has to be an lvalue.
// TypeError 7407: (113-114): Type uint256 is not implicitly convertible to expected type function (uint256) pure returns (uint256[] memory).
// TypeError 9574: (91-114): Type function (uint256) pure returns (uint256[] memory) is not implicitly convertible to expected type uint256.