mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8645 from ethereum/develop
Merge develop into release for 0.6.6.
This commit is contained in:
commit
6c089d02b2
@ -10,7 +10,7 @@ include(EthPolicy)
|
||||
eth_policy()
|
||||
|
||||
# project name and version should be set after cmake_policy CMP0048
|
||||
set(PROJECT_VERSION "0.6.5")
|
||||
set(PROJECT_VERSION "0.6.6")
|
||||
# OSX target needed in order to support std::visit
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
|
||||
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
|
||||
|
13
Changelog.md
13
Changelog.md
@ -1,3 +1,16 @@
|
||||
### 0.6.6 (2020-04-09)
|
||||
|
||||
Important Bugfixes:
|
||||
* Fix tuple assignments with components occupying multiple stack slots and different stack size on left- and right-hand-side.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
* AST export: Export `immutable` property in the field `mutability`.
|
||||
* SMTChecker: Fix internal error in the CHC engine when calling inherited functions internally.
|
||||
* Type Checker: Error when trying to encode functions with call options gas and value set.
|
||||
|
||||
|
||||
|
||||
### 0.6.5 (2020-04-06)
|
||||
|
||||
Important Bugfixes:
|
||||
|
@ -1,4 +1,12 @@
|
||||
[
|
||||
{
|
||||
"name": "TupleAssignmentMultiStackSlotComponents",
|
||||
"summary": "Tuple assignments with components that occupy several stack slots, i.e. nested tuples, pointers to external functions or references to dynamically sized calldata arrays, can result in invalid values.",
|
||||
"description": "Tuple assignments did not correctly account for tuple components that occupy multiple stack slots in case the number of stack slots differs between left-hand-side and right-hand-side. This can either happen in the presence of nested tuples or if the right-hand-side contains external function pointers or references to dynamic calldata arrays, while the left-hand-side contains an omission.",
|
||||
"introduced": "0.1.6",
|
||||
"fixed": "0.6.6",
|
||||
"severity": "very low"
|
||||
},
|
||||
{
|
||||
"name": "MemoryArrayCreationOverflow",
|
||||
"summary": "The creation of very large memory arrays can result in overlapping memory regions and thus memory corruption.",
|
||||
|
@ -111,6 +111,7 @@
|
||||
},
|
||||
"0.1.6": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
"ZeroFunctionSelector",
|
||||
@ -131,6 +132,7 @@
|
||||
},
|
||||
"0.1.7": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
"ZeroFunctionSelector",
|
||||
@ -151,6 +153,7 @@
|
||||
},
|
||||
"0.2.0": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
@ -172,6 +175,7 @@
|
||||
},
|
||||
"0.2.1": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
@ -193,6 +197,7 @@
|
||||
},
|
||||
"0.2.2": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
@ -214,6 +219,7 @@
|
||||
},
|
||||
"0.3.0": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -237,6 +243,7 @@
|
||||
},
|
||||
"0.3.1": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -259,6 +266,7 @@
|
||||
},
|
||||
"0.3.2": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -281,6 +289,7 @@
|
||||
},
|
||||
"0.3.3": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -302,6 +311,7 @@
|
||||
},
|
||||
"0.3.4": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -323,6 +333,7 @@
|
||||
},
|
||||
"0.3.5": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -344,6 +355,7 @@
|
||||
},
|
||||
"0.3.6": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -363,6 +375,7 @@
|
||||
},
|
||||
"0.4.0": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -382,6 +395,7 @@
|
||||
},
|
||||
"0.4.1": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -401,6 +415,7 @@
|
||||
},
|
||||
"0.4.10": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -418,6 +433,7 @@
|
||||
},
|
||||
"0.4.11": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -434,6 +450,7 @@
|
||||
},
|
||||
"0.4.12": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -449,6 +466,7 @@
|
||||
},
|
||||
"0.4.13": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -464,6 +482,7 @@
|
||||
},
|
||||
"0.4.14": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -478,6 +497,7 @@
|
||||
},
|
||||
"0.4.15": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -491,6 +511,7 @@
|
||||
},
|
||||
"0.4.16": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -506,6 +527,7 @@
|
||||
},
|
||||
"0.4.17": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -522,6 +544,7 @@
|
||||
},
|
||||
"0.4.18": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -537,6 +560,7 @@
|
||||
},
|
||||
"0.4.19": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -553,6 +577,7 @@
|
||||
},
|
||||
"0.4.2": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -571,6 +596,7 @@
|
||||
},
|
||||
"0.4.20": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -587,6 +613,7 @@
|
||||
},
|
||||
"0.4.21": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -603,6 +630,7 @@
|
||||
},
|
||||
"0.4.22": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -619,6 +647,7 @@
|
||||
},
|
||||
"0.4.23": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -634,6 +663,7 @@
|
||||
},
|
||||
"0.4.24": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -649,6 +679,7 @@
|
||||
},
|
||||
"0.4.25": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -662,6 +693,7 @@
|
||||
},
|
||||
"0.4.26": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -672,6 +704,7 @@
|
||||
},
|
||||
"0.4.3": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -689,6 +722,7 @@
|
||||
},
|
||||
"0.4.4": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"IncorrectEventSignatureInLibraries_0.4.x",
|
||||
@ -705,6 +739,7 @@
|
||||
},
|
||||
"0.4.5": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"UninitializedFunctionPointerInConstructor_0.4.x",
|
||||
@ -723,6 +758,7 @@
|
||||
},
|
||||
"0.4.6": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"UninitializedFunctionPointerInConstructor_0.4.x",
|
||||
@ -740,6 +776,7 @@
|
||||
},
|
||||
"0.4.7": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -757,6 +794,7 @@
|
||||
},
|
||||
"0.4.8": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -774,6 +812,7 @@
|
||||
},
|
||||
"0.4.9": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -791,6 +830,7 @@
|
||||
},
|
||||
"0.5.0": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -804,6 +844,7 @@
|
||||
},
|
||||
"0.5.1": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -817,6 +858,7 @@
|
||||
},
|
||||
"0.5.10": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
@ -826,6 +868,7 @@
|
||||
},
|
||||
"0.5.11": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
@ -834,6 +877,7 @@
|
||||
},
|
||||
"0.5.12": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
@ -842,6 +886,7 @@
|
||||
},
|
||||
"0.5.13": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
@ -850,6 +895,7 @@
|
||||
},
|
||||
"0.5.14": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
@ -859,6 +905,7 @@
|
||||
},
|
||||
"0.5.15": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
@ -867,6 +914,7 @@
|
||||
},
|
||||
"0.5.16": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden"
|
||||
],
|
||||
@ -874,12 +922,14 @@
|
||||
},
|
||||
"0.5.17": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow"
|
||||
],
|
||||
"released": "2020-03-17"
|
||||
},
|
||||
"0.5.2": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -893,6 +943,7 @@
|
||||
},
|
||||
"0.5.3": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -906,6 +957,7 @@
|
||||
},
|
||||
"0.5.4": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -919,6 +971,7 @@
|
||||
},
|
||||
"0.5.5": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"SignedArrayStorageCopy",
|
||||
@ -934,6 +987,7 @@
|
||||
},
|
||||
"0.5.6": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
|
||||
@ -949,6 +1003,7 @@
|
||||
},
|
||||
"0.5.7": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
|
||||
@ -962,6 +1017,7 @@
|
||||
},
|
||||
"0.5.8": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
@ -974,6 +1030,7 @@
|
||||
},
|
||||
"0.5.9": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
@ -985,6 +1042,7 @@
|
||||
},
|
||||
"0.6.0": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"YulOptimizerRedundantAssignmentBreakContinue"
|
||||
],
|
||||
@ -992,30 +1050,40 @@
|
||||
},
|
||||
"0.6.1": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow"
|
||||
],
|
||||
"released": "2020-01-02"
|
||||
},
|
||||
"0.6.2": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow"
|
||||
],
|
||||
"released": "2020-01-27"
|
||||
},
|
||||
"0.6.3": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow"
|
||||
],
|
||||
"released": "2020-02-18"
|
||||
},
|
||||
"0.6.4": {
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow"
|
||||
],
|
||||
"released": "2020-03-10"
|
||||
},
|
||||
"0.6.5": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"TupleAssignmentMultiStackSlotComponents"
|
||||
],
|
||||
"released": "2020-04-06"
|
||||
},
|
||||
"0.6.6": {
|
||||
"bugs": [],
|
||||
"released": "2020-04-09"
|
||||
}
|
||||
}
|
@ -433,7 +433,7 @@ The full contract
|
||||
.. note::
|
||||
The function ``splitSignature`` does not use all security
|
||||
checks. A real implementation should use a more rigorously tested library,
|
||||
such as openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol>`_ of this code.
|
||||
such as openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol>`_ of this code.
|
||||
|
||||
Verifying Payments
|
||||
------------------
|
||||
|
@ -106,6 +106,8 @@ set(sources
|
||||
formal/Sorts.h
|
||||
formal/SSAVariable.cpp
|
||||
formal/SSAVariable.h
|
||||
formal/SymbolicState.cpp
|
||||
formal/SymbolicState.h
|
||||
formal/SymbolicTypes.cpp
|
||||
formal/SymbolicTypes.h
|
||||
formal/SymbolicVariables.cpp
|
||||
|
@ -54,11 +54,11 @@ public:
|
||||
TypePointer evaluate(Expression const& _expr);
|
||||
|
||||
private:
|
||||
virtual void endVisit(BinaryOperation const& _operation);
|
||||
virtual void endVisit(UnaryOperation const& _operation);
|
||||
virtual void endVisit(Literal const& _literal);
|
||||
virtual void endVisit(Identifier const& _identifier);
|
||||
virtual void endVisit(TupleExpression const& _tuple);
|
||||
void endVisit(BinaryOperation const& _operation) override;
|
||||
void endVisit(UnaryOperation const& _operation) override;
|
||||
void endVisit(Literal const& _literal) override;
|
||||
void endVisit(Identifier const& _identifier) override;
|
||||
void endVisit(TupleExpression const& _tuple) override;
|
||||
|
||||
void setType(ASTNode const& _node, TypePointer const& _type);
|
||||
TypePointer type(ASTNode const& _node);
|
||||
|
@ -50,7 +50,7 @@ class StaticAnalyzer: private ASTConstVisitor
|
||||
public:
|
||||
/// @param _errorReporter provides the error logging functionality.
|
||||
explicit StaticAnalyzer(langutil::ErrorReporter& _errorReporter);
|
||||
~StaticAnalyzer();
|
||||
~StaticAnalyzer() override;
|
||||
|
||||
/// Performs static analysis on the given source unit and all of its sub-nodes.
|
||||
/// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings
|
||||
|
@ -1430,41 +1430,37 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
{
|
||||
if (!components[i])
|
||||
m_errorReporter.fatalTypeError(_tuple.location(), "Tuple component cannot be empty.");
|
||||
else if (components[i])
|
||||
{
|
||||
components[i]->accept(*this);
|
||||
types.push_back(type(*components[i]));
|
||||
|
||||
if (types[i]->category() == Type::Category::Tuple)
|
||||
if (dynamic_cast<TupleType const&>(*types[i]).components().empty())
|
||||
{
|
||||
if (_tuple.isInlineArray())
|
||||
m_errorReporter.fatalTypeError(components[i]->location(), "Array component cannot be empty.");
|
||||
m_errorReporter.typeError(components[i]->location(), "Tuple component cannot be empty.");
|
||||
}
|
||||
components[i]->accept(*this);
|
||||
types.push_back(type(*components[i]));
|
||||
|
||||
// Note: code generation will visit each of the expression even if they are not assigned from.
|
||||
if (types[i]->category() == Type::Category::RationalNumber && components.size() > 1)
|
||||
if (!dynamic_cast<RationalNumberType const&>(*types[i]).mobileType())
|
||||
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number.");
|
||||
|
||||
if (_tuple.isInlineArray())
|
||||
if (types[i]->category() == Type::Category::Tuple)
|
||||
if (dynamic_cast<TupleType const&>(*types[i]).components().empty())
|
||||
{
|
||||
solAssert(!!types[i], "Inline array cannot have empty components");
|
||||
|
||||
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
|
||||
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid mobile type.");
|
||||
|
||||
if (i == 0)
|
||||
inlineArrayType = types[i]->mobileType();
|
||||
else if (inlineArrayType)
|
||||
inlineArrayType = Type::commonType(inlineArrayType, types[i]);
|
||||
if (_tuple.isInlineArray())
|
||||
m_errorReporter.fatalTypeError(components[i]->location(), "Array component cannot be empty.");
|
||||
m_errorReporter.typeError(components[i]->location(), "Tuple component cannot be empty.");
|
||||
}
|
||||
if (!components[i]->annotation().isPure)
|
||||
isPure = false;
|
||||
|
||||
// Note: code generation will visit each of the expression even if they are not assigned from.
|
||||
if (types[i]->category() == Type::Category::RationalNumber && components.size() > 1)
|
||||
if (!dynamic_cast<RationalNumberType const&>(*types[i]).mobileType())
|
||||
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number.");
|
||||
|
||||
if (_tuple.isInlineArray())
|
||||
{
|
||||
solAssert(!!types[i], "Inline array cannot have empty components");
|
||||
|
||||
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
|
||||
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid mobile type.");
|
||||
|
||||
if (i == 0)
|
||||
inlineArrayType = types[i]->mobileType();
|
||||
else if (inlineArrayType)
|
||||
inlineArrayType = Type::commonType(inlineArrayType, types[i]);
|
||||
}
|
||||
else
|
||||
types.push_back(TypePointer());
|
||||
if (!components[i]->annotation().isPure)
|
||||
isPure = false;
|
||||
}
|
||||
_tuple.annotation().isPure = isPure;
|
||||
if (_tuple.isInlineArray())
|
||||
|
@ -217,6 +217,37 @@ ContractDefinitionAnnotation& ContractDefinition::annotation() const
|
||||
return initAnnotation<ContractDefinitionAnnotation>();
|
||||
}
|
||||
|
||||
ContractDefinition const* ContractDefinition::superContract(ContractDefinition const& _mostDerivedContract) const
|
||||
{
|
||||
auto const& hierarchy = _mostDerivedContract.annotation().linearizedBaseContracts;
|
||||
auto it = find(hierarchy.begin(), hierarchy.end(), this);
|
||||
solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy.");
|
||||
++it;
|
||||
if (it == hierarchy.end())
|
||||
return nullptr;
|
||||
else
|
||||
{
|
||||
solAssert(*it != this, "");
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition const& _mostDerivedContract) const
|
||||
{
|
||||
ContractDefinition const* next = superContract(_mostDerivedContract);
|
||||
if (next == nullptr)
|
||||
return nullptr;
|
||||
for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
|
||||
if (c == next || next == nullptr)
|
||||
{
|
||||
if (c->constructor())
|
||||
return c->constructor();
|
||||
next = nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TypeNameAnnotation& TypeName::annotation() const
|
||||
{
|
||||
return initAnnotation<TypeNameAnnotation>();
|
||||
|
@ -518,6 +518,10 @@ public:
|
||||
|
||||
bool abstract() const { return m_abstract; }
|
||||
|
||||
ContractDefinition const* superContract(ContractDefinition const& _mostDerivedContract) const;
|
||||
/// @returns the next constructor in the inheritance hierarchy.
|
||||
FunctionDefinition const* nextConstructor(ContractDefinition const& _mostDerivedContract) const;
|
||||
|
||||
private:
|
||||
std::vector<ASTPointer<InheritanceSpecifier>> m_baseContracts;
|
||||
std::vector<ASTPointer<ASTNode>> m_subNodes;
|
||||
@ -850,7 +854,17 @@ class VariableDeclaration: public Declaration
|
||||
{
|
||||
public:
|
||||
enum Location { Unspecified, Storage, Memory, CallData };
|
||||
enum class Constantness { Mutable, Immutable, Constant };
|
||||
enum class Mutability { Mutable, Immutable, Constant };
|
||||
static std::string mutabilityToString(Mutability _mutability)
|
||||
{
|
||||
switch (_mutability)
|
||||
{
|
||||
case Mutability::Mutable: return "mutable";
|
||||
case Mutability::Immutable: return "immutable";
|
||||
case Mutability::Constant: return "constant";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
VariableDeclaration(
|
||||
int64_t _id,
|
||||
@ -861,7 +875,7 @@ public:
|
||||
Visibility _visibility,
|
||||
bool _isStateVar = false,
|
||||
bool _isIndexed = false,
|
||||
Constantness _constantness = Constantness::Mutable,
|
||||
Mutability _mutability = Mutability::Mutable,
|
||||
ASTPointer<OverrideSpecifier> const& _overrides = nullptr,
|
||||
Location _referenceLocation = Location::Unspecified
|
||||
):
|
||||
@ -870,7 +884,7 @@ public:
|
||||
m_value(_value),
|
||||
m_isStateVariable(_isStateVar),
|
||||
m_isIndexed(_isIndexed),
|
||||
m_constantness(_constantness),
|
||||
m_mutability(_mutability),
|
||||
m_overrides(_overrides),
|
||||
m_location(_referenceLocation) {}
|
||||
|
||||
@ -914,8 +928,9 @@ public:
|
||||
bool hasReferenceOrMappingType() const;
|
||||
bool isStateVariable() const { return m_isStateVariable; }
|
||||
bool isIndexed() const { return m_isIndexed; }
|
||||
bool isConstant() const { return m_constantness == Constantness::Constant; }
|
||||
bool immutable() const { return m_constantness == Constantness::Immutable; }
|
||||
Mutability mutability() const { return m_mutability; }
|
||||
bool isConstant() const { return m_mutability == Mutability::Constant; }
|
||||
bool immutable() const { return m_mutability == Mutability::Immutable; }
|
||||
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
|
||||
Location referenceLocation() const { return m_location; }
|
||||
/// @returns a set of allowed storage locations for the variable.
|
||||
@ -943,7 +958,7 @@ private:
|
||||
bool m_isStateVariable = false; ///< Whether or not this is a contract state variable
|
||||
bool m_isIndexed = false; ///< Whether this is an indexed variable (used by events).
|
||||
/// Whether the variable is "constant", "immutable" or non-marked (mutable).
|
||||
Constantness m_constantness = Constantness::Mutable;
|
||||
Mutability m_mutability = Mutability::Mutable;
|
||||
ASTPointer<OverrideSpecifier> m_overrides; ///< Contains the override specifier node
|
||||
Location m_location = Location::Unspecified; ///< Location of the variable if it is of reference type.
|
||||
};
|
||||
|
@ -378,6 +378,7 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node)
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("typeName", toJsonOrNull(_node.typeName())),
|
||||
make_pair("constant", _node.isConstant()),
|
||||
make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
|
||||
make_pair("stateVariable", _node.isStateVariable()),
|
||||
make_pair("storageLocation", location(_node.referenceLocation())),
|
||||
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||
|
@ -411,11 +411,24 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
|
||||
{
|
||||
astAssert(_node["name"].isString(), "Expected 'name' to be a string!");
|
||||
|
||||
VariableDeclaration::Constantness constantness{};
|
||||
if (memberAsBool(_node, "constant"))
|
||||
constantness = VariableDeclaration::Constantness::Constant;
|
||||
VariableDeclaration::Mutability mutability{};
|
||||
astAssert(member(_node, "mutability").isString(), "'mutability' expected to be string.");
|
||||
string const mutabilityStr = member(_node, "mutability").asString();
|
||||
if (mutabilityStr == "constant")
|
||||
{
|
||||
mutability = VariableDeclaration::Mutability::Constant;
|
||||
astAssert(memberAsBool(_node, "constant"), "");
|
||||
}
|
||||
else
|
||||
constantness = VariableDeclaration::Constantness::Mutable;
|
||||
{
|
||||
astAssert(!memberAsBool(_node, "constant"), "");
|
||||
if (mutabilityStr == "mutable")
|
||||
mutability = VariableDeclaration::Mutability::Mutable;
|
||||
else if (mutabilityStr == "immutable")
|
||||
mutability = VariableDeclaration::Mutability::Immutable;
|
||||
else
|
||||
astAssert(false, "");
|
||||
}
|
||||
|
||||
return createASTNode<VariableDeclaration>(
|
||||
_node,
|
||||
@ -425,7 +438,7 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
|
||||
visibility(_node),
|
||||
memberAsBool(_node, "stateVariable"),
|
||||
_node.isMember("indexed") ? memberAsBool(_node, "indexed") : false,
|
||||
constantness,
|
||||
mutability,
|
||||
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
|
||||
location(_node)
|
||||
);
|
||||
@ -495,7 +508,7 @@ ASTPointer<UserDefinedTypeName> ASTJsonImporter::createUserDefinedTypeName(Json:
|
||||
string nameString = member(_node, "name").asString();
|
||||
boost::algorithm::split(strs, nameString, boost::is_any_of("."));
|
||||
for (string s: strs)
|
||||
namePath.push_back(ASTString(s));
|
||||
namePath.emplace_back(s);
|
||||
return createASTNode<UserDefinedTypeName>(
|
||||
_node,
|
||||
namePath
|
||||
|
@ -3112,6 +3112,8 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const* _sco
|
||||
|
||||
TypePointer FunctionType::encodingType() const
|
||||
{
|
||||
if (m_gasSet || m_valueSet)
|
||||
return nullptr;
|
||||
// Only external functions can be encoded, internal functions cannot leave code boundaries.
|
||||
if (m_kind == Kind::External)
|
||||
return this;
|
||||
|
@ -843,7 +843,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
if (dynamicMember)
|
||||
solAssert(dynamic, "");
|
||||
|
||||
members.push_back({});
|
||||
members.emplace_back();
|
||||
members.back()["preprocess"] = "";
|
||||
|
||||
switch (_from.location())
|
||||
@ -1336,7 +1336,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
|
||||
memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name)));
|
||||
memberTempl("abiDecode", abiDecodingFunction(*member.type, _fromMemory, false));
|
||||
|
||||
members.push_back({});
|
||||
members.emplace_back();
|
||||
members.back()["decode"] = memberTempl.render();
|
||||
members.back()["memberName"] = member.name;
|
||||
headPos += decodingType->calldataHeadSize();
|
||||
|
@ -269,29 +269,11 @@ evmasm::AssemblyItem CompilerContext::functionEntryLabelIfExists(Declaration con
|
||||
FunctionDefinition const& CompilerContext::superFunction(FunctionDefinition const& _function, ContractDefinition const& _base)
|
||||
{
|
||||
solAssert(m_mostDerivedContract, "No most derived contract set.");
|
||||
ContractDefinition const* super = superContract(_base);
|
||||
ContractDefinition const* super = _base.superContract(mostDerivedContract());
|
||||
solAssert(super, "Super contract not available.");
|
||||
return _function.resolveVirtual(mostDerivedContract(), super);
|
||||
}
|
||||
|
||||
FunctionDefinition const* CompilerContext::nextConstructor(ContractDefinition const& _contract) const
|
||||
{
|
||||
ContractDefinition const* next = superContract(_contract);
|
||||
if (next == nullptr)
|
||||
return nullptr;
|
||||
for (ContractDefinition const* c: m_mostDerivedContract->annotation().linearizedBaseContracts)
|
||||
if (next != nullptr && next != c)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
next = nullptr;
|
||||
if (c->constructor())
|
||||
return c->constructor();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ContractDefinition const& CompilerContext::mostDerivedContract() const
|
||||
{
|
||||
solAssert(m_mostDerivedContract, "Most derived contract not set.");
|
||||
@ -536,21 +518,6 @@ LinkerObject const& CompilerContext::assembledObject() const
|
||||
return object;
|
||||
}
|
||||
|
||||
ContractDefinition const* CompilerContext::superContract(ContractDefinition const& _contract) const
|
||||
{
|
||||
auto const& hierarchy = mostDerivedContract().annotation().linearizedBaseContracts;
|
||||
auto it = find(hierarchy.begin(), hierarchy.end(), &_contract);
|
||||
solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy.");
|
||||
++it;
|
||||
if (it == hierarchy.end())
|
||||
return nullptr;
|
||||
else
|
||||
{
|
||||
solAssert(*it != &_contract, "");
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
string CompilerContext::revertReasonIfDebug(string const& _message)
|
||||
{
|
||||
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message);
|
||||
|
@ -117,8 +117,6 @@ public:
|
||||
/// @returns the function that overrides the given declaration from the most derived class just
|
||||
/// above _base in the current inheritance hierarchy.
|
||||
FunctionDefinition const& superFunction(FunctionDefinition const& _function, ContractDefinition const& _base);
|
||||
/// @returns the next constructor in the inheritance hierarchy.
|
||||
FunctionDefinition const* nextConstructor(ContractDefinition const& _contract) const;
|
||||
/// Sets the contract currently being compiled - the most derived one.
|
||||
void setMostDerivedContract(ContractDefinition const& _contract) { m_mostDerivedContract = &_contract; }
|
||||
ContractDefinition const& mostDerivedContract() const;
|
||||
@ -313,8 +311,6 @@ public:
|
||||
RevertStrings revertStrings() const { return m_revertStrings; }
|
||||
|
||||
private:
|
||||
/// @returns a pointer to the contract directly above the given contract.
|
||||
ContractDefinition const* superContract(ContractDefinition const& _contract) const;
|
||||
/// Updates source location set in the assembly.
|
||||
void updateSourceLocation();
|
||||
|
||||
|
@ -1108,12 +1108,12 @@ void CompilerUtils::convertType(
|
||||
// Value shrank
|
||||
for (unsigned j = targetSize; j < sourceSize; ++j)
|
||||
{
|
||||
moveToStackTop(depth - 1, 1);
|
||||
moveToStackTop(depth + targetSize - sourceSize, 1);
|
||||
m_context << Instruction::POP;
|
||||
}
|
||||
// Value grew
|
||||
if (targetSize > sourceSize)
|
||||
moveIntoStack(depth + targetSize - sourceSize - 1, targetSize - sourceSize);
|
||||
moveIntoStack(depth - sourceSize, targetSize - sourceSize);
|
||||
}
|
||||
}
|
||||
depth -= sourceSize;
|
||||
|
@ -159,7 +159,7 @@ void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _c
|
||||
|
||||
if (FunctionDefinition const* constructor = _contract.constructor())
|
||||
appendConstructor(*constructor);
|
||||
else if (auto c = m_context.nextConstructor(_contract))
|
||||
else if (auto c = _contract.nextConstructor(m_context.mostDerivedContract()))
|
||||
appendBaseConstructor(*c);
|
||||
else
|
||||
appendCallValueCheck();
|
||||
@ -596,7 +596,9 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
|
||||
appendStackVariableInitialisation(*variable);
|
||||
|
||||
if (_function.isConstructor())
|
||||
if (auto c = m_context.nextConstructor(dynamic_cast<ContractDefinition const&>(*_function.scope())))
|
||||
if (auto c = dynamic_cast<ContractDefinition const&>(*_function.scope()).nextConstructor(
|
||||
m_context.mostDerivedContract()
|
||||
))
|
||||
appendBaseConstructor(*c);
|
||||
|
||||
solAssert(m_returnTags.empty(), "");
|
||||
|
@ -352,7 +352,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
vector<map<string, string>> functions;
|
||||
for (auto const& function: _contract.interfaceFunctions())
|
||||
{
|
||||
functions.push_back({});
|
||||
functions.emplace_back();
|
||||
map<string, string>& templ = functions.back();
|
||||
templ["functionSelector"] = "0x" + function.first.hex();
|
||||
FunctionTypePointer const& type = function.second;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <libsolidity/formal/BMC.h>
|
||||
|
||||
#include <libsolidity/formal/SMTPortfolio.h>
|
||||
#include <libsolidity/formal/SymbolicState.h>
|
||||
#include <libsolidity/formal/SymbolicTypes.h>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
@ -376,7 +377,7 @@ void BMC::endVisit(FunctionCall const& _funCall)
|
||||
SMTEncoder::endVisit(_funCall);
|
||||
auto value = _funCall.arguments().front();
|
||||
solAssert(value, "");
|
||||
smt::Expression thisBalance = m_context.balance();
|
||||
smt::Expression thisBalance = m_context.state().balance();
|
||||
|
||||
addVerificationTarget(
|
||||
VerificationTarget::Type::Balance,
|
||||
|
@ -961,7 +961,11 @@ smt::Expression CHC::predicate(FunctionCall const& _funCall)
|
||||
for (auto const& var: function->returnParameters())
|
||||
args.push_back(m_context.variable(*var)->currentValue());
|
||||
|
||||
return (*m_summaries.at(contract).at(function))(args);
|
||||
if (contract->isLibrary())
|
||||
return (*m_summaries.at(contract).at(function))(args);
|
||||
|
||||
solAssert(m_currentContract, "");
|
||||
return (*m_summaries.at(m_currentContract).at(function))(args);
|
||||
}
|
||||
|
||||
void CHC::addRule(smt::Expression const& _rule, string const& _ruleName)
|
||||
|
@ -25,13 +25,8 @@ using namespace solidity::util;
|
||||
using namespace solidity::frontend::smt;
|
||||
|
||||
EncodingContext::EncodingContext():
|
||||
m_thisAddress(make_unique<SymbolicAddressVariable>("this", *this))
|
||||
m_state(*this)
|
||||
{
|
||||
auto sort = make_shared<ArraySort>(
|
||||
SortProvider::intSort,
|
||||
SortProvider::intSort
|
||||
);
|
||||
m_balances = make_unique<SymbolicVariable>(sort, "balances", *this);
|
||||
}
|
||||
|
||||
void EncodingContext::reset()
|
||||
@ -39,8 +34,7 @@ void EncodingContext::reset()
|
||||
resetAllVariables();
|
||||
m_expressions.clear();
|
||||
m_globalContext.clear();
|
||||
m_thisAddress->resetIndex();
|
||||
m_balances->resetIndex();
|
||||
m_state.reset();
|
||||
m_assertions.clear();
|
||||
}
|
||||
|
||||
@ -183,40 +177,6 @@ bool EncodingContext::knownGlobalSymbol(string const& _var) const
|
||||
return m_globalContext.count(_var);
|
||||
}
|
||||
|
||||
// Blockchain
|
||||
|
||||
Expression EncodingContext::thisAddress()
|
||||
{
|
||||
return m_thisAddress->currentValue();
|
||||
}
|
||||
|
||||
Expression EncodingContext::balance()
|
||||
{
|
||||
return balance(m_thisAddress->currentValue());
|
||||
}
|
||||
|
||||
Expression EncodingContext::balance(Expression _address)
|
||||
{
|
||||
return Expression::select(m_balances->currentValue(), move(_address));
|
||||
}
|
||||
|
||||
void EncodingContext::transfer(Expression _from, Expression _to, Expression _value)
|
||||
{
|
||||
unsigned indexBefore = m_balances->index();
|
||||
addBalance(_from, 0 - _value);
|
||||
addBalance(_to, move(_value));
|
||||
unsigned indexAfter = m_balances->index();
|
||||
solAssert(indexAfter > indexBefore, "");
|
||||
m_balances->increaseIndex();
|
||||
/// Do not apply the transfer operation if _from == _to.
|
||||
auto newBalances = Expression::ite(
|
||||
move(_from) == move(_to),
|
||||
m_balances->valueAtIndex(indexBefore),
|
||||
m_balances->valueAtIndex(indexAfter)
|
||||
);
|
||||
addAssertion(m_balances->currentValue() == newBalances);
|
||||
}
|
||||
|
||||
/// Solver.
|
||||
|
||||
Expression EncodingContext::assertions()
|
||||
@ -232,7 +192,7 @@ void EncodingContext::pushSolver()
|
||||
if (m_accumulateAssertions)
|
||||
m_assertions.push_back(assertions());
|
||||
else
|
||||
m_assertions.push_back(smt::Expression(true));
|
||||
m_assertions.emplace_back(true);
|
||||
}
|
||||
|
||||
void EncodingContext::popSolver()
|
||||
@ -248,16 +208,3 @@ void EncodingContext::addAssertion(Expression const& _expr)
|
||||
else
|
||||
m_assertions.back() = _expr && move(m_assertions.back());
|
||||
}
|
||||
|
||||
/// Private helpers.
|
||||
|
||||
void EncodingContext::addBalance(Expression _address, Expression _value)
|
||||
{
|
||||
auto newBalances = Expression::store(
|
||||
m_balances->currentValue(),
|
||||
_address,
|
||||
balance(_address) + move(_value)
|
||||
);
|
||||
m_balances->increaseIndex();
|
||||
addAssertion(newBalances == m_balances->currentValue());
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/formal/SolverInterface.h>
|
||||
#include <libsolidity/formal/SymbolicState.h>
|
||||
#include <libsolidity/formal/SymbolicVariables.h>
|
||||
|
||||
#include <unordered_map>
|
||||
@ -121,18 +122,6 @@ public:
|
||||
bool knownGlobalSymbol(std::string const& _var) const;
|
||||
//@}
|
||||
|
||||
/// Blockchain.
|
||||
//@{
|
||||
/// Value of `this` address.
|
||||
Expression thisAddress();
|
||||
/// @returns the symbolic balance of address `this`.
|
||||
Expression balance();
|
||||
/// @returns the symbolic balance of an address.
|
||||
Expression balance(Expression _address);
|
||||
/// Transfer _value from _from to _to.
|
||||
void transfer(Expression _from, Expression _to, Expression _value);
|
||||
//@}
|
||||
|
||||
/// Solver.
|
||||
//@{
|
||||
/// @returns conjunction of all added assertions.
|
||||
@ -148,10 +137,9 @@ public:
|
||||
}
|
||||
//@}
|
||||
|
||||
private:
|
||||
/// Adds _value to _account's balance.
|
||||
void addBalance(Expression _account, Expression _value);
|
||||
SymbolicState& state() { return m_state; }
|
||||
|
||||
private:
|
||||
/// Symbolic expressions.
|
||||
//{@
|
||||
/// Symbolic variables.
|
||||
@ -164,11 +152,8 @@ private:
|
||||
/// variables and functions.
|
||||
std::unordered_map<std::string, std::shared_ptr<smt::SymbolicVariable>> m_globalContext;
|
||||
|
||||
/// Symbolic `this` address.
|
||||
std::unique_ptr<SymbolicAddressVariable> m_thisAddress;
|
||||
|
||||
/// Symbolic balances.
|
||||
std::unique_ptr<SymbolicVariable> m_balances;
|
||||
/// Symbolic representation of the blockchain state.
|
||||
SymbolicState m_state;
|
||||
//@}
|
||||
|
||||
/// Solver related.
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/formal/SMTPortfolio.h>
|
||||
#include <libsolidity/formal/SymbolicState.h>
|
||||
#include <libsolidity/formal/SymbolicTypes.h>
|
||||
|
||||
#include <boost/range/adaptors.hpp>
|
||||
@ -619,10 +620,10 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall)
|
||||
auto const& value = args.front();
|
||||
solAssert(value, "");
|
||||
|
||||
smt::Expression thisBalance = m_context.balance();
|
||||
smt::Expression thisBalance = m_context.state().balance();
|
||||
setSymbolicUnknownValue(thisBalance, TypeProvider::uint256(), m_context);
|
||||
|
||||
m_context.transfer(m_context.thisAddress(), expr(address), expr(*value));
|
||||
m_context.state().transfer(m_context.state().thisAddress(), expr(address), expr(*value));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -711,7 +712,7 @@ void SMTEncoder::endVisit(Identifier const& _identifier)
|
||||
defineGlobalVariable(_identifier.name(), _identifier);
|
||||
else if (_identifier.name() == "this")
|
||||
{
|
||||
defineExpr(_identifier, m_context.thisAddress());
|
||||
defineExpr(_identifier, m_context.state().thisAddress());
|
||||
m_uninterpretedTerms.insert(&_identifier);
|
||||
}
|
||||
else
|
||||
@ -858,7 +859,7 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
|
||||
_memberAccess.expression().accept(*this);
|
||||
if (_memberAccess.memberName() == "balance")
|
||||
{
|
||||
defineExpr(_memberAccess, m_context.balance(expr(_memberAccess.expression())));
|
||||
defineExpr(_memberAccess, m_context.state().balance(expr(_memberAccess.expression())));
|
||||
setSymbolicUnknownValue(*m_context.expression(_memberAccess), m_context);
|
||||
m_uninterpretedTerms.insert(&_memberAccess);
|
||||
return false;
|
||||
|
82
libsolidity/formal/SymbolicState.cpp
Normal file
82
libsolidity/formal/SymbolicState.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <libsolidity/formal/SymbolicState.h>
|
||||
|
||||
#include <libsolidity/formal/EncodingContext.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::frontend::smt;
|
||||
|
||||
SymbolicState::SymbolicState(EncodingContext& _context):
|
||||
m_context(_context)
|
||||
{
|
||||
}
|
||||
|
||||
void SymbolicState::reset()
|
||||
{
|
||||
m_thisAddress.resetIndex();
|
||||
m_balances.resetIndex();
|
||||
}
|
||||
|
||||
// Blockchain
|
||||
|
||||
Expression SymbolicState::thisAddress()
|
||||
{
|
||||
return m_thisAddress.currentValue();
|
||||
}
|
||||
|
||||
Expression SymbolicState::balance()
|
||||
{
|
||||
return balance(m_thisAddress.currentValue());
|
||||
}
|
||||
|
||||
Expression SymbolicState::balance(Expression _address)
|
||||
{
|
||||
return Expression::select(m_balances.currentValue(), move(_address));
|
||||
}
|
||||
|
||||
void SymbolicState::transfer(Expression _from, Expression _to, Expression _value)
|
||||
{
|
||||
unsigned indexBefore = m_balances.index();
|
||||
addBalance(_from, 0 - _value);
|
||||
addBalance(_to, move(_value));
|
||||
unsigned indexAfter = m_balances.index();
|
||||
solAssert(indexAfter > indexBefore, "");
|
||||
m_balances.increaseIndex();
|
||||
/// Do not apply the transfer operation if _from == _to.
|
||||
auto newBalances = Expression::ite(
|
||||
move(_from) == move(_to),
|
||||
m_balances.valueAtIndex(indexBefore),
|
||||
m_balances.valueAtIndex(indexAfter)
|
||||
);
|
||||
m_context.addAssertion(m_balances.currentValue() == newBalances);
|
||||
}
|
||||
|
||||
/// Private helpers.
|
||||
|
||||
void SymbolicState::addBalance(Expression _address, Expression _value)
|
||||
{
|
||||
auto newBalances = Expression::store(
|
||||
m_balances.currentValue(),
|
||||
_address,
|
||||
balance(_address) + move(_value)
|
||||
);
|
||||
m_balances.increaseIndex();
|
||||
m_context.addAssertion(newBalances == m_balances.currentValue());
|
||||
}
|
||||
|
71
libsolidity/formal/SymbolicState.h
Normal file
71
libsolidity/formal/SymbolicState.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/formal/Sorts.h>
|
||||
#include <libsolidity/formal/SolverInterface.h>
|
||||
#include <libsolidity/formal/SymbolicVariables.h>
|
||||
|
||||
namespace solidity::frontend::smt
|
||||
{
|
||||
|
||||
class EncodingContext;
|
||||
|
||||
/**
|
||||
* Symbolic representation of the blockchain state.
|
||||
*/
|
||||
class SymbolicState
|
||||
{
|
||||
public:
|
||||
SymbolicState(EncodingContext& _context);
|
||||
|
||||
void reset();
|
||||
|
||||
/// Blockchain.
|
||||
//@{
|
||||
/// Value of `this` address.
|
||||
Expression thisAddress();
|
||||
/// @returns the symbolic balance of address `this`.
|
||||
Expression balance();
|
||||
/// @returns the symbolic balance of an address.
|
||||
Expression balance(Expression _address);
|
||||
/// Transfer _value from _from to _to.
|
||||
void transfer(Expression _from, Expression _to, Expression _value);
|
||||
//@}
|
||||
|
||||
private:
|
||||
/// Adds _value to _account's balance.
|
||||
void addBalance(Expression _account, Expression _value);
|
||||
|
||||
EncodingContext& m_context;
|
||||
|
||||
/// Symbolic `this` address.
|
||||
SymbolicAddressVariable m_thisAddress{
|
||||
"this",
|
||||
m_context
|
||||
};
|
||||
|
||||
/// Symbolic balances.
|
||||
SymbolicArrayVariable m_balances{
|
||||
std::make_shared<ArraySort>(SortProvider::intSort, SortProvider::intSort),
|
||||
"balances",
|
||||
m_context
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -200,7 +200,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _fil
|
||||
/// for Contract-level targets try both contract name and wildcard
|
||||
vector<string> contracts{ _contract };
|
||||
if (!_contract.empty())
|
||||
contracts.push_back("*");
|
||||
contracts.emplace_back("*");
|
||||
for (auto const& contract: contracts)
|
||||
if (
|
||||
_outputSelection[file].isMember(contract) &&
|
||||
|
@ -695,7 +695,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
||||
);
|
||||
|
||||
bool isIndexed = false;
|
||||
VariableDeclaration::Constantness constantness = VariableDeclaration::Constantness::Mutable;
|
||||
VariableDeclaration::Mutability mutability = VariableDeclaration::Mutability::Mutable;
|
||||
ASTPointer<OverrideSpecifier> overrides = nullptr;
|
||||
Visibility visibility(Visibility::Default);
|
||||
VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified;
|
||||
@ -732,15 +732,15 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
||||
isIndexed = true;
|
||||
else if (token == Token::Constant || token == Token::Immutable)
|
||||
{
|
||||
if (constantness != VariableDeclaration::Constantness::Mutable)
|
||||
if (mutability != VariableDeclaration::Mutability::Mutable)
|
||||
parserError(
|
||||
string("Constantness already set to ") +
|
||||
(constantness == VariableDeclaration::Constantness::Constant ? "\"constant\"" : "\"immutable\"")
|
||||
string("Mutability already set to ") +
|
||||
(mutability == VariableDeclaration::Mutability::Constant ? "\"constant\"" : "\"immutable\"")
|
||||
);
|
||||
else if (token == Token::Constant)
|
||||
constantness = VariableDeclaration::Constantness::Constant;
|
||||
mutability = VariableDeclaration::Mutability::Constant;
|
||||
else if (token == Token::Immutable)
|
||||
constantness = VariableDeclaration::Constantness::Immutable;
|
||||
mutability = VariableDeclaration::Mutability::Immutable;
|
||||
}
|
||||
else if (_options.allowLocationSpecifier && TokenTraits::isLocationSpecifier(token))
|
||||
{
|
||||
@ -800,7 +800,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
||||
visibility,
|
||||
_options.isStateVariable,
|
||||
isIndexed,
|
||||
constantness,
|
||||
mutability,
|
||||
overrides,
|
||||
location
|
||||
);
|
||||
|
@ -38,7 +38,7 @@
|
||||
/// Operators need to stay in the global namespace.
|
||||
|
||||
/// Concatenate the contents of a container onto a vector
|
||||
template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U const& _b)
|
||||
template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U& _b)
|
||||
{
|
||||
for (auto const& i: _b)
|
||||
_a.push_back(i);
|
||||
@ -51,7 +51,7 @@ template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U&& _
|
||||
return _a;
|
||||
}
|
||||
/// Concatenate the contents of a container onto a multiset
|
||||
template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T...>& _a, U const& _b)
|
||||
template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T...>& _a, U& _b)
|
||||
{
|
||||
_a.insert(_b.begin(), _b.end());
|
||||
return _a;
|
||||
@ -64,7 +64,7 @@ template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T..
|
||||
return _a;
|
||||
}
|
||||
/// Concatenate the contents of a container onto a set
|
||||
template <class U, class... T> std::set<T...>& operator+=(std::set<T...>& _a, U const& _b)
|
||||
template <class U, class... T> std::set<T...>& operator+=(std::set<T...>& _a, U& _b)
|
||||
{
|
||||
_a.insert(_b.begin(), _b.end());
|
||||
return _a;
|
||||
|
@ -38,7 +38,7 @@ class EVMAssembly: public AbstractAssembly
|
||||
{
|
||||
public:
|
||||
explicit EVMAssembly(bool _evm15 = false): m_evm15(_evm15) { }
|
||||
virtual ~EVMAssembly() = default;
|
||||
~EVMAssembly() override = default;
|
||||
|
||||
/// Set a new source location valid starting from the next instruction.
|
||||
void setSourceLocation(langutil::SourceLocation const& _location) override;
|
||||
|
@ -92,10 +92,10 @@ public:
|
||||
{}
|
||||
|
||||
public:
|
||||
void operator()(Identifier const& _identifier);
|
||||
void operator()(FunctionDefinition const&);
|
||||
void operator()(ForLoop const&);
|
||||
void operator()(Block const& _block);
|
||||
void operator()(Identifier const& _identifier) override;
|
||||
void operator()(FunctionDefinition const&) override;
|
||||
void operator()(ForLoop const&) override;
|
||||
void operator()(Block const& _block) override;
|
||||
|
||||
private:
|
||||
void increaseRefIfFound(YulString _variableName);
|
||||
|
@ -45,7 +45,7 @@ class NoOutputAssembly: public AbstractAssembly
|
||||
{
|
||||
public:
|
||||
explicit NoOutputAssembly(bool _evm15 = false): m_evm15(_evm15) { }
|
||||
virtual ~NoOutputAssembly() = default;
|
||||
~NoOutputAssembly() override = default;
|
||||
|
||||
void setSourceLocation(langutil::SourceLocation const&) override {}
|
||||
int stackHeight() const override { return m_stackHeight; }
|
||||
|
@ -104,7 +104,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
|
||||
vector<Statement> ret;
|
||||
for (int i = 0; i < 3; i++)
|
||||
ret.push_back(VariableDeclaration{
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
|
||||
make_unique<Expression>(Literal{
|
||||
@ -114,7 +114,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
m_targetDialect.defaultType
|
||||
})
|
||||
});
|
||||
ret.push_back(VariableDeclaration{
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[3], m_targetDialect.defaultType}},
|
||||
std::move(varDecl.value)
|
||||
@ -135,8 +135,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
|
||||
vector<Statement> ret;
|
||||
for (int i = 0; i < 4; i++)
|
||||
ret.push_back(
|
||||
VariableDeclaration{
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
|
||||
std::move(newRhs[i])
|
||||
@ -165,7 +164,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
auto newLhs = generateU64IdentifierNames(assignment.variableNames[0].name);
|
||||
vector<Statement> ret;
|
||||
for (int i = 0; i < 3; i++)
|
||||
ret.push_back(Assignment{
|
||||
ret.emplace_back(Assignment{
|
||||
assignment.location,
|
||||
{Identifier{assignment.location, newLhs[i]}},
|
||||
make_unique<Expression>(Literal{
|
||||
@ -175,7 +174,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
m_targetDialect.defaultType
|
||||
})
|
||||
});
|
||||
ret.push_back(Assignment{
|
||||
ret.emplace_back(Assignment{
|
||||
assignment.location,
|
||||
{Identifier{assignment.location, newLhs[3]}},
|
||||
std::move(assignment.value)
|
||||
@ -196,8 +195,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
YulString lhsName = assignment.variableNames[0].name;
|
||||
vector<Statement> ret;
|
||||
for (int i = 0; i < 4; i++)
|
||||
ret.push_back(
|
||||
Assignment{
|
||||
ret.emplace_back(Assignment{
|
||||
assignment.location,
|
||||
{Identifier{assignment.location, m_variableMapping.at(lhsName)[i]}},
|
||||
std::move(newRhs[i])
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
class ASTCopier: public ExpressionCopier, public StatementCopier
|
||||
{
|
||||
public:
|
||||
virtual ~ASTCopier() = default;
|
||||
~ASTCopier() override = default;
|
||||
Expression operator()(Literal const& _literal) override;
|
||||
Expression operator()(Identifier const& _identifier) override;
|
||||
Expression operator()(FunctionCall const&) override;
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
static void run(OptimiserStepContext&, Block& _ast);
|
||||
|
||||
using ASTModifier::operator();
|
||||
virtual void visit(Expression& _expression);
|
||||
void visit(Expression& _expression) override;
|
||||
|
||||
private:
|
||||
explicit ExpressionSimplifier(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {}
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
static void run(OptimiserStepContext&, Block& _ast) { FunctionHoister{}(_ast); }
|
||||
|
||||
using ASTModifier::operator();
|
||||
virtual void operator()(Block& _block);
|
||||
void operator()(Block& _block) override;
|
||||
|
||||
private:
|
||||
FunctionHoister() = default;
|
||||
|
@ -36,9 +36,9 @@ void NameCollector::operator()(VariableDeclaration const& _varDecl)
|
||||
void NameCollector::operator ()(FunctionDefinition const& _funDef)
|
||||
{
|
||||
m_names.emplace(_funDef.name);
|
||||
for (auto const arg: _funDef.parameters)
|
||||
for (auto const& arg: _funDef.parameters)
|
||||
m_names.emplace(arg.name);
|
||||
for (auto const ret: _funDef.returnVariables)
|
||||
for (auto const& ret: _funDef.returnVariables)
|
||||
m_names.emplace(ret.name);
|
||||
ASTWalker::operator ()(_funDef);
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ public:
|
||||
{}
|
||||
|
||||
using ASTWalker::operator ();
|
||||
virtual void operator()(Identifier const& _identifier);
|
||||
virtual void operator()(FunctionCall const& _funCall);
|
||||
void operator()(Identifier const& _identifier) override;
|
||||
void operator()(FunctionCall const& _funCall) override;
|
||||
|
||||
static std::map<YulString, size_t> countReferences(Block const& _block, CountWhat _countWhat = VariablesAndFunctions);
|
||||
static std::map<YulString, size_t> countReferences(FunctionDefinition const& _function, CountWhat _countWhat = VariablesAndFunctions);
|
||||
|
@ -104,7 +104,7 @@ public:
|
||||
static bool containsMSize(Dialect const& _dialect, Block const& _ast);
|
||||
|
||||
using ASTWalker::operator();
|
||||
void operator()(FunctionCall const& _funCall);
|
||||
void operator()(FunctionCall const& _funCall) override;
|
||||
|
||||
private:
|
||||
MSizeFinder(Dialect const& _dialect): m_dialect(_dialect) {}
|
||||
@ -129,7 +129,7 @@ public:
|
||||
}
|
||||
|
||||
using ASTWalker::operator();
|
||||
void operator()(Leave const&) { m_leaveFound = true; }
|
||||
void operator()(Leave const&) override { m_leaveFound = true; }
|
||||
|
||||
private:
|
||||
LeaveFinder() = default;
|
||||
|
@ -50,12 +50,12 @@ public:
|
||||
ASTWalker::operator()(_funDef);
|
||||
|
||||
auto& funType = functionTypes[_funDef.name];
|
||||
for (auto const arg: _funDef.parameters)
|
||||
for (auto const& arg: _funDef.parameters)
|
||||
{
|
||||
funType.parameters.emplace_back(arg.type);
|
||||
variableTypes[arg.name] = arg.type;
|
||||
}
|
||||
for (auto const ret: _funDef.returnVariables)
|
||||
for (auto const& ret: _funDef.returnVariables)
|
||||
{
|
||||
funType.returns.emplace_back(ret.type);
|
||||
variableTypes[ret.name] = ret.type;
|
||||
|
@ -4,7 +4,7 @@
|
||||
# first exporting a .sol file to JSON, then loading it into the compiler
|
||||
# and exporting it again. The second JSON should be identical to the first
|
||||
|
||||
REPO_ROOT=$(realpath "$(dirname "$0")"/..)
|
||||
REPO_ROOT=$(readlink -f "$(dirname "$0")"/..)
|
||||
SOLIDITY_BUILD_DIR=${SOLIDITY_BUILD_DIR:-build}
|
||||
SOLC=${REPO_ROOT}/${SOLIDITY_BUILD_DIR}/solc/solc
|
||||
SPLITSOURCES=${REPO_ROOT}/scripts/splitSources.py
|
||||
|
@ -160,6 +160,7 @@ JSON AST:
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "",
|
||||
"overrides": null,
|
||||
"scope": 17,
|
||||
|
@ -31,6 +31,7 @@
|
||||
"constant": false,
|
||||
"functionSelector": "97682884",
|
||||
"id": 4,
|
||||
"mutability": "mutable",
|
||||
"name": "m",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -100,6 +101,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 12,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -241,6 +243,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 22,
|
||||
"mutability": "mutable",
|
||||
"name": "c",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -507,6 +510,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 6,
|
||||
"mutability": "mutable",
|
||||
"name": "arg",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -547,6 +551,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 9,
|
||||
"mutability": "mutable",
|
||||
"name": "r",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -41,6 +41,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"functionSelector": "97682884",
|
||||
"mutability": "mutable",
|
||||
"name": "m",
|
||||
"overrides": null,
|
||||
"scope": 39,
|
||||
@ -118,6 +119,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "arg",
|
||||
"overrides": null,
|
||||
"scope": 38,
|
||||
@ -157,6 +159,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "r",
|
||||
"overrides": null,
|
||||
"scope": 38,
|
||||
@ -206,6 +209,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"overrides": null,
|
||||
"scope": 37,
|
||||
@ -359,6 +363,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "c",
|
||||
"overrides": null,
|
||||
"scope": 37,
|
||||
|
@ -30,6 +30,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 3,
|
||||
"mutability": "mutable",
|
||||
"name": "i",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -40,6 +40,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "i",
|
||||
"overrides": null,
|
||||
"scope": 4,
|
||||
|
@ -121,6 +121,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 3,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -77,6 +77,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"overrides": null,
|
||||
"scope": 7,
|
||||
|
@ -35,6 +35,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 2,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -72,6 +73,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 5,
|
||||
"mutability": "mutable",
|
||||
"name": "s",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -50,6 +50,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"overrides": null,
|
||||
"scope": 3,
|
||||
@ -85,6 +86,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "s",
|
||||
"overrides": null,
|
||||
"scope": 11,
|
||||
|
@ -45,6 +45,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 4,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -101,6 +101,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"overrides": null,
|
||||
"scope": 7,
|
||||
|
@ -53,6 +53,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 6,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -85,6 +86,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 3,
|
||||
"mutability": "mutable",
|
||||
"name": "",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -139,6 +141,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 13,
|
||||
"mutability": "mutable",
|
||||
"name": "",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -171,6 +174,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 10,
|
||||
"mutability": "mutable",
|
||||
"name": "",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -64,6 +64,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"overrides": null,
|
||||
"scope": 16,
|
||||
@ -104,6 +105,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "",
|
||||
"overrides": null,
|
||||
"scope": 5,
|
||||
@ -157,6 +159,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "",
|
||||
"overrides": null,
|
||||
"scope": 16,
|
||||
@ -197,6 +200,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "",
|
||||
"overrides": null,
|
||||
"scope": 12,
|
||||
|
@ -19,6 +19,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 2,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -26,6 +26,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"overrides": null,
|
||||
"scope": 3,
|
||||
|
@ -45,6 +45,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 4,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -100,6 +100,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"overrides": null,
|
||||
"scope": 9,
|
||||
|
@ -30,6 +30,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 3,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -87,6 +88,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 10,
|
||||
"mutability": "mutable",
|
||||
"name": "b",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -40,6 +40,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"overrides": null,
|
||||
"scope": 15,
|
||||
@ -143,6 +144,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "b",
|
||||
"overrides": null,
|
||||
"scope": 13,
|
||||
|
@ -58,6 +58,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 8,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -113,6 +114,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 12,
|
||||
"mutability": "mutable",
|
||||
"name": "b",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
@ -166,6 +168,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 16,
|
||||
"mutability": "mutable",
|
||||
"name": "c",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -80,6 +80,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "a",
|
||||
"overrides": null,
|
||||
"scope": 17,
|
||||
@ -134,6 +135,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "b",
|
||||
"overrides": null,
|
||||
"scope": 17,
|
||||
@ -186,6 +188,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "c",
|
||||
"overrides": null,
|
||||
"scope": 17,
|
||||
|
@ -56,6 +56,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 2,
|
||||
"mutability": "mutable",
|
||||
"name": "i",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -54,6 +54,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "i",
|
||||
"overrides": null,
|
||||
"scope": 6,
|
||||
|
@ -56,6 +56,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 2,
|
||||
"mutability": "mutable",
|
||||
"name": "i",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -54,6 +54,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "i",
|
||||
"overrides": null,
|
||||
"scope": 6,
|
||||
|
189
test/libsolidity/ASTJSON/mutability.json
Normal file
189
test/libsolidity/ASTJSON/mutability.json
Normal file
@ -0,0 +1,189 @@
|
||||
{
|
||||
"absolutePath": "a",
|
||||
"exportedSymbols":
|
||||
{
|
||||
"C":
|
||||
[
|
||||
10
|
||||
]
|
||||
},
|
||||
"id": 11,
|
||||
"nodeType": "SourceUnit",
|
||||
"nodes":
|
||||
[
|
||||
{
|
||||
"abstract": false,
|
||||
"baseContracts": [],
|
||||
"contractDependencies": [],
|
||||
"contractKind": "contract",
|
||||
"documentation": null,
|
||||
"fullyImplemented": true,
|
||||
"id": 10,
|
||||
"linearizedBaseContracts":
|
||||
[
|
||||
10
|
||||
],
|
||||
"name": "C",
|
||||
"nodeType": "ContractDefinition",
|
||||
"nodes":
|
||||
[
|
||||
{
|
||||
"constant": false,
|
||||
"functionSelector": "0dbe671f",
|
||||
"id": 3,
|
||||
"mutability": "immutable",
|
||||
"name": "a",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
"scope": 10,
|
||||
"src": "17:27:1",
|
||||
"stateVariable": true,
|
||||
"storageLocation": "default",
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_uint256",
|
||||
"typeString": "uint256"
|
||||
},
|
||||
"typeName":
|
||||
{
|
||||
"id": 1,
|
||||
"name": "uint",
|
||||
"nodeType": "ElementaryTypeName",
|
||||
"src": "17:4:1",
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_uint256",
|
||||
"typeString": "uint256"
|
||||
}
|
||||
},
|
||||
"value":
|
||||
{
|
||||
"argumentTypes": null,
|
||||
"hexValue": "34",
|
||||
"id": 2,
|
||||
"isConstant": false,
|
||||
"isLValue": false,
|
||||
"isPure": true,
|
||||
"kind": "number",
|
||||
"lValueRequested": false,
|
||||
"nodeType": "Literal",
|
||||
"src": "43:1:1",
|
||||
"subdenomination": null,
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_rational_4_by_1",
|
||||
"typeString": "int_const 4"
|
||||
},
|
||||
"value": "4"
|
||||
},
|
||||
"visibility": "public"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"functionSelector": "4df7e3d0",
|
||||
"id": 6,
|
||||
"mutability": "constant",
|
||||
"name": "b",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
"scope": 10,
|
||||
"src": "50:26:1",
|
||||
"stateVariable": true,
|
||||
"storageLocation": "default",
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_uint256",
|
||||
"typeString": "uint256"
|
||||
},
|
||||
"typeName":
|
||||
{
|
||||
"id": 4,
|
||||
"name": "uint",
|
||||
"nodeType": "ElementaryTypeName",
|
||||
"src": "50:4:1",
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_uint256",
|
||||
"typeString": "uint256"
|
||||
}
|
||||
},
|
||||
"value":
|
||||
{
|
||||
"argumentTypes": null,
|
||||
"hexValue": "32",
|
||||
"id": 5,
|
||||
"isConstant": false,
|
||||
"isLValue": false,
|
||||
"isPure": true,
|
||||
"kind": "number",
|
||||
"lValueRequested": false,
|
||||
"nodeType": "Literal",
|
||||
"src": "75:1:1",
|
||||
"subdenomination": null,
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_rational_2_by_1",
|
||||
"typeString": "int_const 2"
|
||||
},
|
||||
"value": "2"
|
||||
},
|
||||
"visibility": "public"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"functionSelector": "c3da42b8",
|
||||
"id": 9,
|
||||
"mutability": "mutable",
|
||||
"name": "c",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
"scope": 10,
|
||||
"src": "82:17:1",
|
||||
"stateVariable": true,
|
||||
"storageLocation": "default",
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_uint256",
|
||||
"typeString": "uint256"
|
||||
},
|
||||
"typeName":
|
||||
{
|
||||
"id": 7,
|
||||
"name": "uint",
|
||||
"nodeType": "ElementaryTypeName",
|
||||
"src": "82:4:1",
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_uint256",
|
||||
"typeString": "uint256"
|
||||
}
|
||||
},
|
||||
"value":
|
||||
{
|
||||
"argumentTypes": null,
|
||||
"hexValue": "33",
|
||||
"id": 8,
|
||||
"isConstant": false,
|
||||
"isLValue": false,
|
||||
"isPure": true,
|
||||
"kind": "number",
|
||||
"lValueRequested": false,
|
||||
"nodeType": "Literal",
|
||||
"src": "98:1:1",
|
||||
"subdenomination": null,
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_rational_3_by_1",
|
||||
"typeString": "int_const 3"
|
||||
},
|
||||
"value": "3"
|
||||
},
|
||||
"visibility": "public"
|
||||
}
|
||||
],
|
||||
"scope": 11,
|
||||
"src": "0:102:1"
|
||||
}
|
||||
],
|
||||
"src": "0:103:1"
|
||||
}
|
8
test/libsolidity/ASTJSON/mutability.sol
Normal file
8
test/libsolidity/ASTJSON/mutability.sol
Normal file
@ -0,0 +1,8 @@
|
||||
contract C
|
||||
{
|
||||
uint public immutable a = 4;
|
||||
uint public constant b = 2;
|
||||
uint public c = 3;
|
||||
}
|
||||
|
||||
// ----
|
195
test/libsolidity/ASTJSON/mutability_legacy.json
Normal file
195
test/libsolidity/ASTJSON/mutability_legacy.json
Normal file
@ -0,0 +1,195 @@
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"absolutePath": "a",
|
||||
"exportedSymbols":
|
||||
{
|
||||
"C":
|
||||
[
|
||||
10
|
||||
]
|
||||
}
|
||||
},
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"abstract": false,
|
||||
"baseContracts":
|
||||
[
|
||||
null
|
||||
],
|
||||
"contractDependencies":
|
||||
[
|
||||
null
|
||||
],
|
||||
"contractKind": "contract",
|
||||
"documentation": null,
|
||||
"fullyImplemented": true,
|
||||
"linearizedBaseContracts":
|
||||
[
|
||||
10
|
||||
],
|
||||
"name": "C",
|
||||
"scope": 11
|
||||
},
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"functionSelector": "0dbe671f",
|
||||
"mutability": "immutable",
|
||||
"name": "a",
|
||||
"overrides": null,
|
||||
"scope": 10,
|
||||
"stateVariable": true,
|
||||
"storageLocation": "default",
|
||||
"type": "uint256",
|
||||
"visibility": "public"
|
||||
},
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"name": "uint",
|
||||
"type": "uint256"
|
||||
},
|
||||
"id": 1,
|
||||
"name": "ElementaryTypeName",
|
||||
"src": "17:4:1"
|
||||
},
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"argumentTypes": null,
|
||||
"hexvalue": "34",
|
||||
"isConstant": false,
|
||||
"isLValue": false,
|
||||
"isPure": true,
|
||||
"lValueRequested": false,
|
||||
"subdenomination": null,
|
||||
"token": "number",
|
||||
"type": "int_const 4",
|
||||
"value": "4"
|
||||
},
|
||||
"id": 2,
|
||||
"name": "Literal",
|
||||
"src": "43:1:1"
|
||||
}
|
||||
],
|
||||
"id": 3,
|
||||
"name": "VariableDeclaration",
|
||||
"src": "17:27:1"
|
||||
},
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"constant": true,
|
||||
"functionSelector": "4df7e3d0",
|
||||
"mutability": "constant",
|
||||
"name": "b",
|
||||
"overrides": null,
|
||||
"scope": 10,
|
||||
"stateVariable": true,
|
||||
"storageLocation": "default",
|
||||
"type": "uint256",
|
||||
"visibility": "public"
|
||||
},
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"name": "uint",
|
||||
"type": "uint256"
|
||||
},
|
||||
"id": 4,
|
||||
"name": "ElementaryTypeName",
|
||||
"src": "50:4:1"
|
||||
},
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"argumentTypes": null,
|
||||
"hexvalue": "32",
|
||||
"isConstant": false,
|
||||
"isLValue": false,
|
||||
"isPure": true,
|
||||
"lValueRequested": false,
|
||||
"subdenomination": null,
|
||||
"token": "number",
|
||||
"type": "int_const 2",
|
||||
"value": "2"
|
||||
},
|
||||
"id": 5,
|
||||
"name": "Literal",
|
||||
"src": "75:1:1"
|
||||
}
|
||||
],
|
||||
"id": 6,
|
||||
"name": "VariableDeclaration",
|
||||
"src": "50:26:1"
|
||||
},
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"functionSelector": "c3da42b8",
|
||||
"mutability": "mutable",
|
||||
"name": "c",
|
||||
"overrides": null,
|
||||
"scope": 10,
|
||||
"stateVariable": true,
|
||||
"storageLocation": "default",
|
||||
"type": "uint256",
|
||||
"visibility": "public"
|
||||
},
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"name": "uint",
|
||||
"type": "uint256"
|
||||
},
|
||||
"id": 7,
|
||||
"name": "ElementaryTypeName",
|
||||
"src": "82:4:1"
|
||||
},
|
||||
{
|
||||
"attributes":
|
||||
{
|
||||
"argumentTypes": null,
|
||||
"hexvalue": "33",
|
||||
"isConstant": false,
|
||||
"isLValue": false,
|
||||
"isPure": true,
|
||||
"lValueRequested": false,
|
||||
"subdenomination": null,
|
||||
"token": "number",
|
||||
"type": "int_const 3",
|
||||
"value": "3"
|
||||
},
|
||||
"id": 8,
|
||||
"name": "Literal",
|
||||
"src": "98:1:1"
|
||||
}
|
||||
],
|
||||
"id": 9,
|
||||
"name": "VariableDeclaration",
|
||||
"src": "82:17:1"
|
||||
}
|
||||
],
|
||||
"id": 10,
|
||||
"name": "ContractDefinition",
|
||||
"src": "0:102:1"
|
||||
}
|
||||
],
|
||||
"id": 11,
|
||||
"name": "SourceUnit",
|
||||
"src": "0:103:1"
|
||||
}
|
@ -45,6 +45,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 3,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -100,6 +100,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"overrides": null,
|
||||
"scope": 6,
|
||||
|
@ -45,6 +45,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 7,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -101,6 +101,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"overrides": null,
|
||||
"scope": 9,
|
||||
|
@ -45,6 +45,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 8,
|
||||
"mutability": "mutable",
|
||||
"name": "rows",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -101,6 +101,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "rows",
|
||||
"overrides": null,
|
||||
"scope": 10,
|
||||
|
@ -45,6 +45,7 @@
|
||||
{
|
||||
"constant": false,
|
||||
"id": 3,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"nodeType": "VariableDeclaration",
|
||||
"overrides": null,
|
||||
|
@ -100,6 +100,7 @@
|
||||
"attributes":
|
||||
{
|
||||
"constant": false,
|
||||
"mutability": "mutable",
|
||||
"name": "x",
|
||||
"overrides": null,
|
||||
"scope": 9,
|
||||
|
@ -34,14 +34,14 @@ namespace solidity::frontend::test
|
||||
class SMTCheckerFramework: public AnalysisFramework
|
||||
{
|
||||
protected:
|
||||
virtual std::pair<SourceUnit const*, ErrorList>
|
||||
std::pair<SourceUnit const*, ErrorList>
|
||||
parseAnalyseAndReturnError(
|
||||
std::string const& _source,
|
||||
bool _reportWarnings = false,
|
||||
bool _insertVersionPragma = true,
|
||||
bool _allowMultipleErrors = false,
|
||||
bool _allowRecoveryErrors = false
|
||||
)
|
||||
) override
|
||||
{
|
||||
return AnalysisFramework::parseAnalyseAndReturnError(
|
||||
"pragma experimental SMTChecker;\n" + _source,
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
ExecutionFramework(_evmVersion), m_showMetadata(solidity::test::CommonOptions::get().showMetadata)
|
||||
{}
|
||||
|
||||
virtual bytes const& compileAndRunWithoutCheck(
|
||||
bytes const& compileAndRunWithoutCheck(
|
||||
std::string const& _sourceCode,
|
||||
u256 const& _value = 0,
|
||||
std::string const& _contractName = "",
|
||||
|
@ -52,15 +52,15 @@ public:
|
||||
FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); }
|
||||
Expression* expression() const { return m_expression; }
|
||||
private:
|
||||
virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); }
|
||||
virtual bool visit(Literal& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(Assignment& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(FunctionCall& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(MemberAccess& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(IndexAccess& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(Identifier& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); }
|
||||
bool visit(Literal& _expression) override { return checkExpression(_expression); }
|
||||
bool checkExpression(Expression& _expression)
|
||||
{
|
||||
if (m_expression == nullptr)
|
||||
|
@ -672,7 +672,7 @@ BOOST_AUTO_TEST_CASE(inline_asm_end_location)
|
||||
{
|
||||
public:
|
||||
bool visited = false;
|
||||
virtual bool visit(InlineAssembly const& _inlineAsm)
|
||||
bool visit(InlineAssembly const& _inlineAsm) override
|
||||
{
|
||||
auto loc = _inlineAsm.location();
|
||||
auto asmStr = loc.source->source().substr(loc.start, loc.end - loc.start);
|
||||
|
17
test/libsolidity/semanticTests/types/nested_tuples_noyul.sol
Normal file
17
test/libsolidity/semanticTests/types/nested_tuples_noyul.sol
Normal file
@ -0,0 +1,17 @@
|
||||
contract test {
|
||||
function f3() public returns(int) {
|
||||
int a = 3;
|
||||
((, ), ) = ((7, 8), 9);
|
||||
return a;
|
||||
}
|
||||
function f4() public returns(int) {
|
||||
int a;
|
||||
(a, ) = (4, (8, 16, 32));
|
||||
return a;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: false
|
||||
// ----
|
||||
// f3() -> 3
|
||||
// f4() -> 4
|
@ -0,0 +1,13 @@
|
||||
contract C {
|
||||
|
||||
function f() public pure returns (uint, uint, uint) {
|
||||
bytes memory a; bytes memory b; bytes memory c;
|
||||
(a, (b, c)) = ("0", ("1", "2"));
|
||||
return (uint8(a[0]), uint8(b[0]), uint8(c[0]));
|
||||
}
|
||||
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 0x30, 0x31, 0x32
|
@ -0,0 +1,20 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
function c() public pure returns (uint) { return 42; }
|
||||
}
|
||||
|
||||
contract B is C {
|
||||
function b() public pure returns (uint) { return c(); }
|
||||
}
|
||||
|
||||
contract A is B {
|
||||
uint public x;
|
||||
|
||||
function a() public {
|
||||
x = b();
|
||||
assert(x < 40);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (254-268): Assertion violation happens here
|
@ -0,0 +1,24 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
uint y;
|
||||
function c(uint _y) public returns (uint) {
|
||||
y = _y;
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
contract B is C {
|
||||
function b() public returns (uint) { return c(42); }
|
||||
}
|
||||
|
||||
contract A is B {
|
||||
uint public x;
|
||||
|
||||
function a() public {
|
||||
x = b();
|
||||
assert(x < 40);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (274-288): Assertion violation happens here
|
@ -3,5 +3,5 @@ contract C {
|
||||
uint immutable constant x;
|
||||
}
|
||||
// ----
|
||||
// ParserError: (32-41): Constantness already set to "immutable"
|
||||
// ParserError: (64-72): Constantness already set to "immutable"
|
||||
// ParserError: (32-41): Mutability already set to "immutable"
|
||||
// ParserError: (64-72): Mutability already set to "immutable"
|
||||
|
@ -0,0 +1,11 @@
|
||||
contract C {
|
||||
function f() public payable {
|
||||
abi.encode(this.f{value: 2});
|
||||
abi.encode(this.f{gas: 2});
|
||||
abi.encode(this.f{value: 2, gas: 1});
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (60-76): This type cannot be encoded.
|
||||
// TypeError: (92-106): This type cannot be encoded.
|
||||
// TypeError: (122-146): This type cannot be encoded.
|
@ -1,12 +1,11 @@
|
||||
contract C {
|
||||
function f() public pure {
|
||||
bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f.gas, blockhash));
|
||||
bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f{gas: 2}, blockhash));
|
||||
h;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (105-115): Using ".gas(...)" is deprecated. Use "{gas: ...}" instead.
|
||||
// TypeError: (91-100): This type cannot be encoded.
|
||||
// TypeError: (102-103): This type cannot be encoded.
|
||||
// TypeError: (105-115): This type cannot be encoded.
|
||||
// TypeError: (117-126): This type cannot be encoded.
|
||||
// TypeError: (105-119): This type cannot be encoded.
|
||||
// TypeError: (121-130): This type cannot be encoded.
|
||||
|
@ -76,13 +76,13 @@ BOOST_AUTO_TEST_CASE(test_alternatives_list)
|
||||
{
|
||||
vector<string> strings;
|
||||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "");
|
||||
strings.push_back("a");
|
||||
strings.emplace_back("a");
|
||||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\"");
|
||||
strings.push_back("b");
|
||||
strings.emplace_back("b");
|
||||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\" or \"b\"");
|
||||
strings.push_back("c");
|
||||
strings.emplace_back("c");
|
||||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\" or \"c\"");
|
||||
strings.push_back("d");
|
||||
strings.emplace_back("d");
|
||||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\", \"c\" or \"d\"");
|
||||
}
|
||||
|
||||
|
@ -47,15 +47,15 @@ string toString(SideEffects const& _sideEffects)
|
||||
{
|
||||
vector<string> ret;
|
||||
if (_sideEffects.movable)
|
||||
ret.push_back("movable");
|
||||
ret.emplace_back("movable");
|
||||
if (_sideEffects.sideEffectFree)
|
||||
ret.push_back("sideEffectFree");
|
||||
ret.emplace_back("sideEffectFree");
|
||||
if (_sideEffects.sideEffectFreeIfNoMSize)
|
||||
ret.push_back("sideEffectFreeIfNoMSize");
|
||||
ret.emplace_back("sideEffectFreeIfNoMSize");
|
||||
if (_sideEffects.invalidatesStorage)
|
||||
ret.push_back("invalidatesStorage");
|
||||
ret.emplace_back("invalidatesStorage");
|
||||
if (_sideEffects.invalidatesMemory)
|
||||
ret.push_back("invalidatesMemory");
|
||||
ret.emplace_back("invalidatesMemory");
|
||||
return joinHumanReadable(ret);
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
return std::make_unique<SyntaxTest>(_config.filename, _config.evmVersion);
|
||||
}
|
||||
SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion);
|
||||
virtual ~SyntaxTest() {}
|
||||
~SyntaxTest() override {}
|
||||
protected:
|
||||
void parseAndAnalyze() override;
|
||||
|
||||
|
@ -104,7 +104,7 @@ Allowed options)",
|
||||
else if (arguments.count("input-files"))
|
||||
inputs = arguments["input-files"].as<vector<string>>();
|
||||
else
|
||||
inputs.push_back("");
|
||||
inputs.emplace_back("");
|
||||
|
||||
bool optimize = !arguments.count("without-optimizer");
|
||||
int retResult = 0;
|
||||
|
@ -308,7 +308,7 @@ pair<
|
||||
for (auto const& scope: m_scopes)
|
||||
{
|
||||
// Copy over all functions.
|
||||
newScopes.push_back({});
|
||||
newScopes.emplace_back();
|
||||
for (auto const& [name, funDef]: scope)
|
||||
if (funDef)
|
||||
newScopes.back().emplace(name, funDef);
|
||||
|
@ -136,7 +136,7 @@ private:
|
||||
/// Evaluates the expression and returns its value.
|
||||
std::vector<u256> evaluateMulti(Expression const& _expression);
|
||||
|
||||
void openScope() { m_scopes.push_back({}); }
|
||||
void openScope() { m_scopes.emplace_back(); }
|
||||
/// Unregisters variables and functions.
|
||||
void closeScope();
|
||||
|
||||
|
@ -32,8 +32,7 @@ void ConstructorKeyword::endVisit(ContractDefinition const& _contract)
|
||||
{
|
||||
for (auto const* function: _contract.definedFunctions())
|
||||
if (function->name() == _contract.name())
|
||||
m_changes.push_back(
|
||||
UpgradeChange{
|
||||
m_changes.emplace_back(
|
||||
UpgradeChange::Level::Safe,
|
||||
function->location(),
|
||||
SourceTransform::replaceFunctionName(
|
||||
@ -41,18 +40,15 @@ void ConstructorKeyword::endVisit(ContractDefinition const& _contract)
|
||||
function->name(),
|
||||
"constructor"
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void VisibilitySpecifier::endVisit(FunctionDefinition const& _function)
|
||||
{
|
||||
if (_function.noVisibilitySpecified())
|
||||
m_changes.push_back(
|
||||
UpgradeChange{
|
||||
m_changes.emplace_back(
|
||||
UpgradeChange::Level::Safe,
|
||||
_function.location(),
|
||||
SourceTransform::insertAfterRightParenthesis(_function.location(), "public")
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
|
||||
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
|
||||
private:
|
||||
void endVisit(frontend::ContractDefinition const& _contract);
|
||||
void endVisit(frontend::ContractDefinition const& _contract) override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -52,7 +52,7 @@ public:
|
||||
|
||||
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
|
||||
private:
|
||||
void endVisit(frontend::FunctionDefinition const& _function);
|
||||
void endVisit(frontend::FunctionDefinition const& _function) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -106,12 +106,10 @@ void AbstractContract::endVisit(ContractDefinition const& _contract)
|
||||
!_contract.abstract() &&
|
||||
!_contract.isInterface()
|
||||
)
|
||||
m_changes.push_back(
|
||||
UpgradeChange{
|
||||
m_changes.emplace_back(
|
||||
UpgradeChange::Level::Safe,
|
||||
_contract.location(),
|
||||
SourceTransform::insertBeforeKeyword(_contract.location(), "contract", "abstract")
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -132,12 +130,10 @@ void OverridingFunction::endVisit(ContractDefinition const& _contract)
|
||||
|
||||
/// Add override with contract list, if needed.
|
||||
if (!function->overrides() && expectedContracts.size() > 1)
|
||||
m_changes.push_back(
|
||||
UpgradeChange{
|
||||
m_changes.emplace_back(
|
||||
UpgradeChange::Level::Safe,
|
||||
function->location(),
|
||||
appendOverride(*function, expectedContracts)
|
||||
}
|
||||
);
|
||||
|
||||
for (auto [begin, end] = inheritedFunctions.equal_range(proxy); begin != end; begin++)
|
||||
@ -151,12 +147,10 @@ void OverridingFunction::endVisit(ContractDefinition const& _contract)
|
||||
/// If function does not specify override and no override with
|
||||
/// contract list was added before.
|
||||
if (!function->overrides() && expectedContracts.size() <= 1)
|
||||
m_changes.push_back(
|
||||
UpgradeChange{
|
||||
m_changes.emplace_back(
|
||||
UpgradeChange::Level::Safe,
|
||||
function->location(),
|
||||
appendOverride(*function, expectedContracts)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -181,12 +175,10 @@ void VirtualFunction::endVisit(ContractDefinition const& _contract)
|
||||
function->visibility() > Visibility::Private
|
||||
)
|
||||
{
|
||||
m_changes.push_back(
|
||||
UpgradeChange{
|
||||
m_changes.emplace_back(
|
||||
UpgradeChange::Level::Safe,
|
||||
function->location(),
|
||||
appendVirtual(*function)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -198,12 +190,10 @@ void VirtualFunction::endVisit(ContractDefinition const& _contract)
|
||||
!super.virtualSemantics()
|
||||
)
|
||||
{
|
||||
m_changes.push_back(
|
||||
UpgradeChange{
|
||||
m_changes.emplace_back(
|
||||
UpgradeChange::Level::Safe,
|
||||
function->location(),
|
||||
appendVirtual(*function)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
|
||||
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
|
||||
private:
|
||||
void endVisit(frontend::ContractDefinition const& _contract);
|
||||
void endVisit(frontend::ContractDefinition const& _contract) override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -49,7 +49,7 @@ public:
|
||||
|
||||
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
|
||||
private:
|
||||
void endVisit(frontend::ContractDefinition const& _contract);
|
||||
void endVisit(frontend::ContractDefinition const& _contract) override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -63,7 +63,7 @@ public:
|
||||
|
||||
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
|
||||
private:
|
||||
void endVisit(frontend::ContractDefinition const& _function);
|
||||
void endVisit(frontend::ContractDefinition const& _function) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user