From fa78e0f3d44b27901aca53857c7478cd5846b080 Mon Sep 17 00:00:00 2001 From: Soham Zemse <22412996+zemse@users.noreply.github.com> Date: Thu, 11 Aug 2022 17:05:59 +0530 Subject: [PATCH 0001/1140] feat: allow named parameters in mapping types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hari test: add parser and abi test cases docs: add example on using named parameters for mappings - Add changelog feat: update antlr grammar to allow named parameters in mappings fix: prevent conflicting mapping parameter names ref: change order of mapping initializers test: update expectations and fix build test: add more tests fix: use common error & code for conflicting params fix: issue with accessing nested mapping test: add conflicting params tests for more nested levels Update libsolidity/analysis/DeclarationTypeChecker.cpp Co-authored-by: Nikola Matić fix: error reported with the same code twice test: add more tests for 3 level nested mapping Address review comments --- Changelog.md | 1 + docs/grammar/SolidityParser.g4 | 2 +- docs/types/mapping-types.rst | 38 +++++++-- .../analysis/DeclarationTypeChecker.cpp | 47 ++++++++++- libsolidity/ast/AST.h | 15 +++- libsolidity/ast/ASTJsonExporter.cpp | 2 + libsolidity/ast/ASTJsonImporter.cpp | 4 +- libsolidity/ast/TypeProvider.cpp | 4 +- libsolidity/ast/TypeProvider.h | 2 +- libsolidity/ast/Types.cpp | 6 +- libsolidity/ast/Types.h | 8 +- libsolidity/parsing/Parser.cpp | 12 ++- test/libsolidity/ABIJson/mapping.sol | 77 +++++++++++++++++++ test/libsolidity/ASTJSON/address_payable.json | 2 + .../ASTJSON/address_payable_parseOnly.json | 2 + test/libsolidity/ASTJSON/mappings.json | 6 ++ .../ASTJSON/mappings_parseOnly.json | 6 ++ .../ASTJSON/userDefinedValueType.json | 2 + .../userDefinedValueType_parseOnly.json | 2 + test/libsolidity/SolidityTypes.cpp | 12 ++- .../do_not_delete_at_error.sol | 4 +- .../errorRecoveryTests/error_to_eos.sol | 9 ++- .../getters/mapping_with_names.sol | 9 +++ .../invalid/return_param_amount_differs2.sol | 1 + .../parsing/mapping_with_names_1.sol | 4 + .../parsing/mapping_with_names_2.sol | 4 + .../parsing/mapping_with_names_3.sol | 4 + .../parsing/mapping_with_names_5.sol | 4 + .../parsing/mapping_with_names_6.sol | 5 ++ .../parsing/mapping_with_names_7.sol | 4 + .../parsing/mapping_with_names_8.sol | 4 + .../parsing/mapping_with_names_conflict_1.sol | 5 ++ .../parsing/mapping_with_names_conflict_2.sol | 5 ++ .../parsing/mapping_with_names_conflict_3.sol | 7 ++ .../parsing/mapping_with_names_conflict_4.sol | 5 ++ .../parsing/mapping_with_names_conflict_5.sol | 5 ++ .../parsing/mapping_with_names_conflict_6.sol | 5 ++ .../mapping_with_names_func_param_1.sol | 6 ++ .../mapping_with_names_func_param_2.sol | 6 ++ .../mapping_with_names_func_param_3.sol | 6 ++ .../mapping_with_names_func_param_4.sol | 6 ++ .../mapping_with_names_func_param_5.sol | 6 ++ .../mapping_with_names_func_param_6.sol | 7 ++ .../mapping_with_names_func_param_7.sol | 6 ++ .../mapping_with_names_func_type_param_1.sol | 4 + .../mapping_with_names_func_type_param_2.sol | 4 + .../mapping_with_names_func_type_param_3.sol | 4 + .../mapping_with_names_func_type_param_4.sol | 4 + .../mapping_with_names_func_type_param_5.sol | 4 + .../mapping_with_names_func_type_param_6.sol | 5 ++ .../mapping_with_names_func_type_param_7.sol | 4 + .../parsing/mapping_with_names_local_1.sol | 9 +++ .../parsing/mapping_with_names_local_2.sol | 9 +++ .../parsing/mapping_with_names_local_3.sol | 9 +++ .../parsing/mapping_with_names_local_4.sol | 9 +++ .../parsing/mapping_with_names_local_5.sol | 9 +++ .../parsing/mapping_with_names_local_6.sol | 10 +++ .../parsing/mapping_with_names_local_7.sol | 11 +++ .../parsing/mapping_with_names_local_8.sol | 9 +++ .../parsing/mapping_with_names_nested_1.sol | 4 + .../parsing/mapping_with_names_nested_2.sol | 4 + .../parsing/mapping_with_names_nested_3.sol | 4 + .../parsing/mapping_with_names_nested_4.sol | 4 + .../parsing/mapping_with_names_nested_5.sol | 5 ++ .../parsing/mapping_with_names_nested_6.sol | 5 ++ .../parsing/mapping_with_names_nested_7.sol | 5 ++ .../parsing/mapping_with_names_nested_8.sol | 4 + .../mapping_with_names_struct_member_1.sol | 6 ++ .../mapping_with_names_struct_member_2.sol | 6 ++ .../mapping_with_names_struct_member_3.sol | 6 ++ .../mapping_with_names_struct_member_4.sol | 6 ++ .../mapping_with_names_struct_member_5.sol | 6 ++ .../mapping_with_names_struct_member_6.sol | 7 ++ .../mapping_with_names_struct_member_7.sol | 6 ++ .../userDefinedValueType/mapping_key.sol | 1 + 75 files changed, 530 insertions(+), 30 deletions(-) create mode 100644 test/libsolidity/ABIJson/mapping.sol create mode 100644 test/libsolidity/semanticTests/getters/mapping_with_names.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_1.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_2.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_3.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_5.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_6.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_7.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_8.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_1.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_2.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_3.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_4.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_5.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_6.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_1.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_2.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_3.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_4.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_5.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_6.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_7.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_1.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_2.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_3.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_4.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_5.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_6.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_7.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_1.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_2.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_3.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_4.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_5.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_6.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_7.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_local_8.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_1.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_2.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_3.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_4.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_5.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_6.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_7.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_8.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_1.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_2.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_3.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_4.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_5.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_6.sol create mode 100644 test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_7.sol diff --git a/Changelog.md b/Changelog.md index 52addbb6ba..b77be4f396 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.18 (unreleased) Language Features: +* Allow named parameters in mapping types. Compiler Features: diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index 92718b9752..10613c9f24 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -504,7 +504,7 @@ variableDeclarationTuple: variableDeclarationStatement: ((variableDeclaration (Assign expression)?) | (variableDeclarationTuple Assign expression)) Semicolon; expressionStatement: expression Semicolon; -mappingType: Mapping LParen key=mappingKeyType DoubleArrow value=typeName RParen; +mappingType: Mapping LParen key=mappingKeyType name=identifier? DoubleArrow value=typeName name=identifier? RParen; /** * Only elementary types or user defined types are viable as mapping keys. */ diff --git a/docs/types/mapping-types.rst b/docs/types/mapping-types.rst index c59d6e8454..68f963753e 100644 --- a/docs/types/mapping-types.rst +++ b/docs/types/mapping-types.rst @@ -4,12 +4,13 @@ Mapping Types ============= -Mapping types use the syntax ``mapping(KeyType => ValueType)`` and variables -of mapping type are declared using the syntax ``mapping(KeyType => ValueType) VariableName``. -The ``KeyType`` can be any -built-in value type, ``bytes``, ``string``, or any contract or enum type. Other user-defined -or complex types, such as mappings, structs or array types are not allowed. -``ValueType`` can be any type, including mappings, arrays and structs. +Mapping types use the syntax ``mapping(KeyType KeyName? => ValueType ValueName?)`` and variables of +mapping type are declared using the syntax ``mapping(KeyType KeyName? => ValueType ValueName?) +VariableName``. The ``KeyType`` can be any built-in value type, ``bytes``, ``string``, or any +contract or enum type. Other user-defined or complex types, such as mappings, structs or array types +are not allowed. ``ValueType`` can be any type, including mappings, arrays and structs. ``KeyName`` +and ``ValueName`` are optional (so ``mapping(KeyType => ValueType)`` works as well) and can be any +valid identifier that is not a type. You can think of mappings as `hash tables `_, which are virtually initialised such that every possible key exists and is mapped to a value whose @@ -29,8 +30,10 @@ of contract functions that are publicly visible. These restrictions are also true for arrays and structs that contain mappings. You can mark state variables of mapping type as ``public`` and Solidity creates a -:ref:`getter ` for you. The ``KeyType`` becomes a parameter for the getter. -If ``ValueType`` is a value type or a struct, the getter returns ``ValueType``. +:ref:`getter ` for you. The ``KeyType`` becomes a parameter +with name ``KeyName`` (if specified) for the getter. +If ``ValueType`` is a value type or a struct, the getter returns ``ValueType`` with +name ``ValueName`` (if specified). If ``ValueType`` is an array or a mapping, the getter has one parameter for each ``KeyType``, recursively. @@ -64,6 +67,25 @@ contract that returns the value at the specified address. The example below is a simplified version of an `ERC20 token `_. ``_allowances`` is an example of a mapping type inside another mapping type. + +In the example below, the optional ``KeyName`` and ``ValueName`` are provided for the mapping. +It does not affect any contract functionality or bytecode, it only sets the ``name`` field +for the inputs and outputs in the ABI for the mapping's getter. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.18; + + contract MappingExampleWithNames { + mapping(address user => uint balance) public balances; + + function update(uint newBalance) public { + balances[msg.sender] = newBalance; + } + } + + The example below uses ``_allowances`` to record the amount someone else is allowed to withdraw from your account. .. code-block:: solidity diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index 2088293878..effbcb7e77 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -267,14 +267,59 @@ void DeclarationTypeChecker::endVisit(Mapping const& _mapping) solAssert(dynamic_cast(&_mapping.keyType()), ""); Type const* keyType = _mapping.keyType().annotation().type; + ASTString keyName = _mapping.keyName(); + Type const* valueType = _mapping.valueType().annotation().type; + ASTString valueName = _mapping.valueName(); // Convert key type to memory. keyType = TypeProvider::withLocationIfReference(DataLocation::Memory, keyType); // Convert value type to storage reference. valueType = TypeProvider::withLocationIfReference(DataLocation::Storage, valueType); - _mapping.annotation().type = TypeProvider::mapping(keyType, valueType); + _mapping.annotation().type = TypeProvider::mapping(keyType, keyName, valueType, valueName); + + // Check if parameter names are conflicting. + if (!keyName.empty()) + { + auto childMappingType = dynamic_cast(valueType); + ASTString currentValueName = valueName; + bool loop = true; + while (loop) + { + bool isError = false; + // Value type is a mapping. + if (childMappingType) + { + // Compare top mapping's key name with child mapping's key name. + ASTString childKeyName = childMappingType->keyName(); + if (keyName == childKeyName) + isError = true; + + auto valueType = childMappingType->valueType(); + currentValueName = childMappingType->valueName(); + childMappingType = dynamic_cast(valueType); + } + else + { + // Compare top mapping's key name with the value name. + if (keyName == currentValueName) + isError = true; + + loop = false; // We arrived at the end of mapping recursion. + } + + // Report error. + if (isError) + { + m_errorReporter.declarationError( + 1809_error, + _mapping.location(), + "Conflicting parameter name \"" + keyName + "\" in mapping." + ); + } + } + } } void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index f5680acbc8..75b86bc754 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1428,18 +1428,29 @@ class Mapping: public TypeName int64_t _id, SourceLocation const& _location, ASTPointer _keyType, - ASTPointer _valueType + ASTPointer _keyName, + ASTPointer _valueType, + ASTPointer _valueName ): - TypeName(_id, _location), m_keyType(std::move(_keyType)), m_valueType(std::move(_valueType)) {} + TypeName(_id, _location), + m_keyType(std::move(_keyType)), + m_keyName(std::move(_keyName)), + m_valueType(std::move(_valueType)), + m_valueName(std::move(_valueName)) + {} void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; TypeName const& keyType() const { return *m_keyType; } + ASTString keyName() const { return *m_keyName; } TypeName const& valueType() const { return *m_valueType; } + ASTString valueName() const { return *m_valueName; } private: ASTPointer m_keyType; + ASTPointer m_keyName; ASTPointer m_valueType; + ASTPointer m_valueName; }; /** diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index d308cd90ca..7ae528fcda 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -598,7 +598,9 @@ bool ASTJsonExporter::visit(Mapping const& _node) { setJsonNode(_node, "Mapping", { make_pair("keyType", toJson(_node.keyType())), + make_pair("keyName", _node.keyName()), make_pair("valueType", toJson(_node.valueType())), + make_pair("valueName", _node.valueName()), make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }); return false; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 96c37003e5..22b53aa474 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -648,7 +648,9 @@ ASTPointer ASTJsonImporter::createMapping(Json::Value const& _node) return createASTNode( _node, convertJsonToASTNode(member(_node, "keyType")), - convertJsonToASTNode(member(_node, "valueType")) + memberAsASTString(_node, "keyName"), + convertJsonToASTNode(member(_node, "valueType")), + memberAsASTString(_node, "valueName") ); } diff --git a/libsolidity/ast/TypeProvider.cpp b/libsolidity/ast/TypeProvider.cpp index 91d1da4be5..5112784b25 100644 --- a/libsolidity/ast/TypeProvider.cpp +++ b/libsolidity/ast/TypeProvider.cpp @@ -571,9 +571,9 @@ MagicType const* TypeProvider::meta(Type const* _type) return createAndGet(_type); } -MappingType const* TypeProvider::mapping(Type const* _keyType, Type const* _valueType) +MappingType const* TypeProvider::mapping(Type const* _keyType, ASTString _keyName, Type const* _valueType, ASTString _valueName) { - return createAndGet(_keyType, _valueType); + return createAndGet(_keyType, _keyName, _valueType, _valueName); } UserDefinedValueType const* TypeProvider::userDefinedValueType(UserDefinedValueTypeDefinition const& _definition) diff --git a/libsolidity/ast/TypeProvider.h b/libsolidity/ast/TypeProvider.h index b089ff1efe..02b9eb35d2 100644 --- a/libsolidity/ast/TypeProvider.h +++ b/libsolidity/ast/TypeProvider.h @@ -195,7 +195,7 @@ class TypeProvider static MagicType const* meta(Type const* _type); - static MappingType const* mapping(Type const* _keyType, Type const* _valueType); + static MappingType const* mapping(Type const* _keyType, ASTString _keyName, Type const* _valueType, ASTString _valueName); static UserDefinedValueType const* userDefinedValueType(UserDefinedValueTypeDefinition const& _definition); diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 5980f93668..c5d36ce652 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2788,14 +2788,16 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): m_declaration(&_varDecl) { auto returnType = _varDecl.annotation().type; + ASTString returnName; while (true) { if (auto mappingType = dynamic_cast(returnType)) { m_parameterTypes.push_back(mappingType->keyType()); - m_parameterNames.emplace_back(""); + m_parameterNames.push_back(mappingType->keyName()); returnType = mappingType->valueType(); + returnName = mappingType->valueName(); } else if (auto arrayType = dynamic_cast(returnType)) { @@ -2834,7 +2836,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): DataLocation::Memory, returnType )); - m_returnParameterNames.emplace_back(""); + m_returnParameterNames.emplace_back(returnName); } solAssert( diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 735bd69025..9d8d3daf01 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1510,8 +1510,8 @@ class FunctionType: public Type class MappingType: public CompositeType { public: - MappingType(Type const* _keyType, Type const* _valueType): - m_keyType(_keyType), m_valueType(_valueType) {} + MappingType(Type const* _keyType, ASTString _keyName, Type const* _valueType, ASTString _valueName): + m_keyType(_keyType), m_keyName(_keyName), m_valueType(_valueType), m_valueName(_valueName) {} Category category() const override { return Category::Mapping; } @@ -1531,14 +1531,18 @@ class MappingType: public CompositeType std::vector> makeStackItems() const override; Type const* keyType() const { return m_keyType; } + ASTString keyName() const { return m_keyName; } Type const* valueType() const { return m_valueType; } + ASTString valueName() const { return m_valueName; } protected: std::vector decomposition() const override { return {m_valueType}; } private: Type const* m_keyType; + ASTString m_keyName; Type const* m_valueType; + ASTString m_valueName; }; /** diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 8075e63e44..e81f0713fd 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1187,11 +1187,21 @@ ASTPointer Parser::parseMapping() } else fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type"); + ASTPointer keyName; + if (m_scanner->currentToken() == Token::Identifier) + keyName = getLiteralAndAdvance(); + else + keyName = make_shared(""); expectToken(Token::DoubleArrow); ASTPointer valueType = parseTypeName(); + ASTPointer valueName; + if (m_scanner->currentToken() == Token::Identifier) + valueName = getLiteralAndAdvance(); + else + valueName = make_shared(""); nodeFactory.markEndPosition(); expectToken(Token::RParen); - return nodeFactory.createNode(keyType, valueType); + return nodeFactory.createNode(keyType, keyName, valueType, valueName); } ASTPointer Parser::parseParameterList( diff --git a/test/libsolidity/ABIJson/mapping.sol b/test/libsolidity/ABIJson/mapping.sol new file mode 100644 index 0000000000..e84b716f2a --- /dev/null +++ b/test/libsolidity/ABIJson/mapping.sol @@ -0,0 +1,77 @@ +contract test { + mapping(address owner => mapping(address spender => uint value)) public allowance; + mapping(bytes32 => address sender) public commits; + mapping(bytes32 => bytes32) public something; +} +// ---- +// :test +// [ +// { +// "inputs": +// [ +// { +// "internalType": "address", +// "name": "owner", +// "type": "address" +// }, +// { +// "internalType": "address", +// "name": "spender", +// "type": "address" +// } +// ], +// "name": "allowance", +// "outputs": +// [ +// { +// "internalType": "uint256", +// "name": "value", +// "type": "uint256" +// } +// ], +// "stateMutability": "view", +// "type": "function" +// }, +// { +// "inputs": +// [ +// { +// "internalType": "bytes32", +// "name": "", +// "type": "bytes32" +// } +// ], +// "name": "commits", +// "outputs": +// [ +// { +// "internalType": "address", +// "name": "sender", +// "type": "address" +// } +// ], +// "stateMutability": "view", +// "type": "function" +// }, +// { +// "inputs": +// [ +// { +// "internalType": "bytes32", +// "name": "", +// "type": "bytes32" +// } +// ], +// "name": "something", +// "outputs": +// [ +// { +// "internalType": "bytes32", +// "name": "", +// "type": "bytes32" +// } +// ], +// "stateMutability": "view", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index cc87fc3b9a..bf56f067fc 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -48,6 +48,7 @@ "typeName": { "id": 3, + "keyName": "", "keyType": { "id": 1, @@ -67,6 +68,7 @@ "typeIdentifier": "t_mapping$_t_address_$_t_address_payable_$", "typeString": "mapping(address => address payable)" }, + "valueName": "", "valueType": { "id": 2, diff --git a/test/libsolidity/ASTJSON/address_payable_parseOnly.json b/test/libsolidity/ASTJSON/address_payable_parseOnly.json index fd7f772f68..6b72b6fb3c 100644 --- a/test/libsolidity/ASTJSON/address_payable_parseOnly.json +++ b/test/libsolidity/ASTJSON/address_payable_parseOnly.json @@ -29,6 +29,7 @@ "typeName": { "id": 3, + "keyName": "", "keyType": { "id": 1, @@ -40,6 +41,7 @@ "nodeType": "Mapping", "src": "17:35:1", "typeDescriptions": {}, + "valueName": "", "valueType": { "id": 2, diff --git a/test/libsolidity/ASTJSON/mappings.json b/test/libsolidity/ASTJSON/mappings.json index e414b56fad..f63f6689fd 100644 --- a/test/libsolidity/ASTJSON/mappings.json +++ b/test/libsolidity/ASTJSON/mappings.json @@ -79,6 +79,7 @@ "typeName": { "id": 8, + "keyName": "", "keyType": { "id": 6, @@ -110,6 +111,7 @@ "typeIdentifier": "t_mapping$_t_contract$_C_$19_$_t_bool_$", "typeString": "mapping(contract C => bool)" }, + "valueName": "", "valueType": { "id": 7, @@ -144,6 +146,7 @@ "typeName": { "id": 12, + "keyName": "", "keyType": { "id": 10, @@ -163,6 +166,7 @@ "typeIdentifier": "t_mapping$_t_address_$_t_bool_$", "typeString": "mapping(address => bool)" }, + "valueName": "", "valueType": { "id": 11, @@ -197,6 +201,7 @@ "typeName": { "id": 17, + "keyName": "", "keyType": { "id": 15, @@ -228,6 +233,7 @@ "typeIdentifier": "t_mapping$_t_enum$_E_$4_$_t_bool_$", "typeString": "mapping(enum C.E => bool)" }, + "valueName": "", "valueType": { "id": 16, diff --git a/test/libsolidity/ASTJSON/mappings_parseOnly.json b/test/libsolidity/ASTJSON/mappings_parseOnly.json index e4f7ee21af..2471148492 100644 --- a/test/libsolidity/ASTJSON/mappings_parseOnly.json +++ b/test/libsolidity/ASTJSON/mappings_parseOnly.json @@ -60,6 +60,7 @@ "typeName": { "id": 8, + "keyName": "", "keyType": { "id": 6, @@ -81,6 +82,7 @@ "nodeType": "Mapping", "src": "40:18:1", "typeDescriptions": {}, + "valueName": "", "valueType": { "id": 7, @@ -106,6 +108,7 @@ "typeName": { "id": 12, + "keyName": "", "keyType": { "id": 10, @@ -117,6 +120,7 @@ "nodeType": "Mapping", "src": "66:24:1", "typeDescriptions": {}, + "valueName": "", "valueType": { "id": 11, @@ -142,6 +146,7 @@ "typeName": { "id": 17, + "keyName": "", "keyType": { "id": 15, @@ -163,6 +168,7 @@ "nodeType": "Mapping", "src": "98:18:1", "typeDescriptions": {}, + "valueName": "", "valueType": { "id": 16, diff --git a/test/libsolidity/ASTJSON/userDefinedValueType.json b/test/libsolidity/ASTJSON/userDefinedValueType.json index 17bb19efae..743716548b 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType.json @@ -287,6 +287,7 @@ "typeName": { "id": 25, + "keyName": "", "keyType": { "id": 22, @@ -318,6 +319,7 @@ "typeIdentifier": "t_mapping$_t_userDefinedValueType$_MyAddress_$18_$_t_userDefinedValueType$_MyUInt_$20_$", "typeString": "mapping(C.MyAddress => C.MyUInt)" }, + "valueName": "", "valueType": { "id": 24, diff --git a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json index 3cef5ea47e..5e263eaea8 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json @@ -213,6 +213,7 @@ "typeName": { "id": 25, + "keyName": "", "keyType": { "id": 22, @@ -234,6 +235,7 @@ "nodeType": "Mapping", "src": "169:28:1", "typeDescriptions": {}, + "valueName": "", "valueType": { "id": 24, diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index d5fb1a08e8..63b943e979 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -97,12 +97,16 @@ BOOST_AUTO_TEST_CASE(storage_layout_mapping) {"first", TypeProvider::fromElementaryTypeName("uint128")}, {"second", TypeProvider::mapping( TypeProvider::fromElementaryTypeName("uint8"), - TypeProvider::fromElementaryTypeName("uint8") + "", + TypeProvider::fromElementaryTypeName("uint8"), + "" )}, {"third", TypeProvider::fromElementaryTypeName("uint16")}, {"final", TypeProvider::mapping( TypeProvider::fromElementaryTypeName("uint8"), - TypeProvider::fromElementaryTypeName("uint8") + "", + TypeProvider::fromElementaryTypeName("uint8"), + "" )}, })); BOOST_REQUIRE_EQUAL(u256(4), members.storageSize()); @@ -199,8 +203,8 @@ BOOST_AUTO_TEST_CASE(type_identifiers) FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()}, strings{""}, strings{""}); BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_keccak256_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$"); - Type const* m = TypeProvider::mapping(TypeProvider::fromElementaryTypeName("bytes32"), s.type()); - MappingType m2(TypeProvider::fromElementaryTypeName("uint64"), m); + Type const* m = TypeProvider::mapping(TypeProvider::fromElementaryTypeName("bytes32"), "", s.type(), ""); + MappingType m2(TypeProvider::fromElementaryTypeName("uint64"), "", m, ""); BOOST_CHECK_EQUAL(m2.identifier(), "t_mapping$_t_uint64_$_t_mapping$_t_bytes32_$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$_$"); // TypeType is tested with contract diff --git a/test/libsolidity/errorRecoveryTests/do_not_delete_at_error.sol b/test/libsolidity/errorRecoveryTests/do_not_delete_at_error.sol index cc3c1561af..ad228a7e13 100644 --- a/test/libsolidity/errorRecoveryTests/do_not_delete_at_error.sol +++ b/test/libsolidity/errorRecoveryTests/do_not_delete_at_error.sol @@ -10,4 +10,6 @@ contract Error2 { mapping (address => uint balances; // missing ) before "balances" } // ---- -// ParserError 6635: (417-425): Expected ')' but got identifier +// ParserError 6635: (425-426): Expected ')' but got ';' +// ParserError 6635: (425-426): Expected identifier but got ';' +// ParserError 6635: (458-459): Expected ';' but got '}' diff --git a/test/libsolidity/errorRecoveryTests/error_to_eos.sol b/test/libsolidity/errorRecoveryTests/error_to_eos.sol index 17d51a62d3..6ecc6d9d63 100644 --- a/test/libsolidity/errorRecoveryTests/error_to_eos.sol +++ b/test/libsolidity/errorRecoveryTests/error_to_eos.sol @@ -17,7 +17,8 @@ contract SendCoin { } // ---- -// ParserError 6635: (212-220): Expected ')' but got identifier -// ParserError 6635: (220-221): Expected ';' but got ')' -// ParserError 9182: (220-221): Function, variable, struct or modifier declaration expected. -// Warning 3796: (235-236): Recovered in ContractDefinition at '}'. +// ParserError 6635: (235-236): Expected identifier but got '}' +// ParserError 6635: (276-284): Expected ';' but got 'contract' +// ParserError 9182: (276-284): Function, variable, struct or modifier declaration expected. +// Warning 3796: (572-573): Recovered in ContractDefinition at '}'. +// ParserError 7858: (574-575): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. diff --git a/test/libsolidity/semanticTests/getters/mapping_with_names.sol b/test/libsolidity/semanticTests/getters/mapping_with_names.sol new file mode 100644 index 0000000000..290a888094 --- /dev/null +++ b/test/libsolidity/semanticTests/getters/mapping_with_names.sol @@ -0,0 +1,9 @@ +contract C { + mapping(uint a => mapping(uint b => uint c)) public x; + constructor() { + x[1][2] = 3; + } +} +// ---- +// x(uint256,uint256): 1, 2 -> 3 +// x(uint256,uint256): 0, 0 -> 0 diff --git a/test/libsolidity/syntaxTests/natspec/invalid/return_param_amount_differs2.sol b/test/libsolidity/syntaxTests/natspec/invalid/return_param_amount_differs2.sol index 929075be10..cffe2b390f 100644 --- a/test/libsolidity/syntaxTests/natspec/invalid/return_param_amount_differs2.sol +++ b/test/libsolidity/syntaxTests/natspec/invalid/return_param_amount_differs2.sol @@ -13,3 +13,4 @@ contract Thing is IThing { mapping(uint256=>Value) public override value; } +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_1.sol new file mode 100644 index 0000000000..2cdcb419e8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_1.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address user => bytes32 ipfs) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_2.sol new file mode 100644 index 0000000000..63be7caeee --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_2.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address => bytes32 ipfs) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_3.sol new file mode 100644 index 0000000000..c2458c3903 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_3.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address user => bytes32) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_5.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_5.sol new file mode 100644 index 0000000000..e2e510acd4 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_5.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address owner => mapping(address spender => bytes32[] notes)) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_6.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_6.sol new file mode 100644 index 0000000000..ed3b11075a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_6.sol @@ -0,0 +1,5 @@ +contract test { + mapping(address uint => bytes32 ipfs) names; +} +// ---- +// ParserError 2314: (36-40): Expected '=>' but got 'uint' diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_7.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_7.sol new file mode 100644 index 0000000000..548129d04d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_7.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address owner => bytes32[] note) notes; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_8.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_8.sol new file mode 100644 index 0000000000..881b285045 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_8.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address => mapping(address => address) hello) world; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_1.sol new file mode 100644 index 0000000000..551bad6766 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_1.sol @@ -0,0 +1,5 @@ +contract test { + address owner; + mapping(address owner => bytes32 ipfs) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_2.sol new file mode 100644 index 0000000000..c8db832565 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_2.sol @@ -0,0 +1,5 @@ +contract test { + mapping(address owner => address owner) owner; +} +// ---- +// DeclarationError 1809: (20-59): Conflicting parameter name "owner" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_3.sol new file mode 100644 index 0000000000..172acceccd --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_3.sol @@ -0,0 +1,7 @@ +contract test { + mapping(address owner => mapping(address owner => address owner)) owner; +} +// ---- +// DeclarationError 1809: (45-84): Conflicting parameter name "owner" in mapping. +// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping. +// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_4.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_4.sol new file mode 100644 index 0000000000..4e4a858924 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_4.sol @@ -0,0 +1,5 @@ +contract test { + mapping(address owner => mapping(address owner => address hello)) world; +} +// ---- +// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_5.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_5.sol new file mode 100644 index 0000000000..f2ea8315d6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_5.sol @@ -0,0 +1,5 @@ +contract test { + mapping(address owner => mapping(address hello => address owner)) world; +} +// ---- +// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_6.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_6.sol new file mode 100644 index 0000000000..56b3de07c2 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_conflict_6.sol @@ -0,0 +1,5 @@ +contract test { + mapping(address hello => mapping(address owner => address owner)) world; +} +// ---- +// DeclarationError 1809: (45-84): Conflicting parameter name "owner" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_1.sol new file mode 100644 index 0000000000..aaf0d4ed9a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_1.sol @@ -0,0 +1,6 @@ +contract test { + function _main(mapping(uint name1 => uint name2) storage map) internal { + map[1] = 2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_2.sol new file mode 100644 index 0000000000..de3e146803 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_2.sol @@ -0,0 +1,6 @@ +contract test { + function _main(mapping(uint name1 => uint) storage map) internal { + map[1] = 2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_3.sol new file mode 100644 index 0000000000..d0edd59d9a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_3.sol @@ -0,0 +1,6 @@ +contract test { + function _main(mapping(uint => uint name2) storage map) internal { + map[1] = 2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_4.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_4.sol new file mode 100644 index 0000000000..896a5fdce9 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_4.sol @@ -0,0 +1,6 @@ +contract test { + function _main(mapping(uint name1 => mapping(uint name2 => uint name3) name4) storage map) internal { + map[1][2] = 3; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_5.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_5.sol new file mode 100644 index 0000000000..40f4a44be9 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_5.sol @@ -0,0 +1,6 @@ +contract test { + function _main(mapping(uint name1 => uint[] name2) storage map) internal { + map[1].push(2); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_6.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_6.sol new file mode 100644 index 0000000000..660f69907c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_6.sol @@ -0,0 +1,7 @@ +contract test { + function _main(mapping(uint nameSame => mapping(uint name2 => mapping(uint nameSame => uint name3) name4) name5) storage map) internal { + map[1][2][3] = 4; + } +} +// ---- +// DeclarationError 1809: (35-132): Conflicting parameter name "nameSame" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_7.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_7.sol new file mode 100644 index 0000000000..5234e246b8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_param_7.sol @@ -0,0 +1,6 @@ +contract test { + function _main(mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) storage map) internal { + map[1][2][3] = 4; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_1.sol new file mode 100644 index 0000000000..c59ab1f1e9 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_1.sol @@ -0,0 +1,4 @@ +contract test { + function(mapping(uint name1 => uint name2) storage) internal stateVariableName; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_2.sol new file mode 100644 index 0000000000..ce5d6e2097 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_2.sol @@ -0,0 +1,4 @@ +contract test { + function(mapping(uint name1 => uint) storage) internal stateVariableName; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_3.sol new file mode 100644 index 0000000000..8e44113386 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_3.sol @@ -0,0 +1,4 @@ +contract test { + function(mapping(uint => uint name2) storage) internal stateVariableName; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_4.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_4.sol new file mode 100644 index 0000000000..22922611aa --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_4.sol @@ -0,0 +1,4 @@ +contract test { + function(mapping(uint name1 => mapping(uint name2 => uint name3) name4) storage) internal stateVariableName; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_5.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_5.sol new file mode 100644 index 0000000000..38b9c6b123 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_5.sol @@ -0,0 +1,4 @@ +contract test { + function(mapping(uint name1 => uint[] name2) storage) internal stateVariableName; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_6.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_6.sol new file mode 100644 index 0000000000..daf9adc585 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_6.sol @@ -0,0 +1,5 @@ +contract test { + function(mapping(uint nameSame => mapping(uint name2 => mapping(uint nameSame => uint name3) name4) name5) storage) internal stateVariableName; +} +// ---- +// DeclarationError 1809: (29-126): Conflicting parameter name "nameSame" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_7.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_7.sol new file mode 100644 index 0000000000..78e3a513b1 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_func_type_param_7.sol @@ -0,0 +1,4 @@ +contract test { + function(mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) storage) internal stateVariableName; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_1.sol new file mode 100644 index 0000000000..dad80d594d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_1.sol @@ -0,0 +1,9 @@ +contract test { + mapping(uint name1 => uint name2) map; + + function main() external { + mapping(uint name3 => uint name4) storage _map = map; + _map[1] = 2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_2.sol new file mode 100644 index 0000000000..ee61e084dd --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_2.sol @@ -0,0 +1,9 @@ +contract test { + mapping(uint name1 => uint) map; + + function main() external { + mapping(uint => uint name4) storage _map = map; + _map[1] = 2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_3.sol new file mode 100644 index 0000000000..963ff82bf4 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_3.sol @@ -0,0 +1,9 @@ +contract test { + mapping(uint => uint name2) map; + + function main() external { + mapping(uint name3 => uint) storage _map = map; + _map[1] = 2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_4.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_4.sol new file mode 100644 index 0000000000..e4ebf16a37 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_4.sol @@ -0,0 +1,9 @@ +contract test { + mapping(uint name1 => mapping(uint name2 => uint name3) name4) map; + + function main() external { + mapping(uint name5 => uint name6) storage _map = map[1]; + _map[1] = 2; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_5.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_5.sol new file mode 100644 index 0000000000..7558274105 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_5.sol @@ -0,0 +1,9 @@ +contract test { + mapping(uint name1 => uint[] name4) map; + + function main() external { + mapping(uint name5 => uint[] name6) storage _map = map; + _map[1].push(2); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_6.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_6.sol new file mode 100644 index 0000000000..d1bda36fcb --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_6.sol @@ -0,0 +1,10 @@ +contract test { + mapping(uint name1 => mapping(uint name2 => uint name3) name4) map; + + function main() external { + mapping(uint nameSame => mapping(uint name2 => uint nameSame) name4) storage _map = map; + _map[1][2] = 3; + } +} +// ---- +// DeclarationError 1809: (128-196): Conflicting parameter name "nameSame" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_7.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_7.sol new file mode 100644 index 0000000000..ccb44f860d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_7.sol @@ -0,0 +1,11 @@ +contract test { + mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name3) name6) name4) map; + + function main() external { + mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name3) name6) name4) storage _map = map; + _map[1][2][3] = 4; + } +} +// ---- +// DeclarationError 1809: (20-117): Conflicting parameter name "nameSame" in mapping. +// DeclarationError 1809: (163-260): Conflicting parameter name "nameSame" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_8.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_8.sol new file mode 100644 index 0000000000..08bb80c9e1 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_local_8.sol @@ -0,0 +1,9 @@ +contract test { + mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) map; + + function main() external { + mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) storage _map = map; + _map[1][2][3] = 4; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_1.sol new file mode 100644 index 0000000000..b5b2bc55d8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_1.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address owner => mapping(address spender => bytes32 note)) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_2.sol new file mode 100644 index 0000000000..e65e3be2bf --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_2.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address => mapping(address spender => bytes32 note)) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_3.sol new file mode 100644 index 0000000000..c0a7472a24 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_3.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address owner => mapping(address => bytes32 note)) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_4.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_4.sol new file mode 100644 index 0000000000..011ab97fa6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_4.sol @@ -0,0 +1,4 @@ +contract test { + mapping(address owner => mapping(address spender => bytes32)) names; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_5.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_5.sol new file mode 100644 index 0000000000..30e37bfae8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_5.sol @@ -0,0 +1,5 @@ +contract test { + mapping(address owner => mapping(address spender => bytes32 note)); +} +// ---- +// ParserError 2314: (86-87): Expected identifier but got ';' diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_6.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_6.sol new file mode 100644 index 0000000000..a31c8d4ca6 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_6.sol @@ -0,0 +1,5 @@ +contract test { + mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name2) name3) name4) name5; +} +// ---- +// DeclarationError 1809: (20-117): Conflicting parameter name "nameSame" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_7.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_7.sol new file mode 100644 index 0000000000..848f2b5e39 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_7.sol @@ -0,0 +1,5 @@ +contract test { + mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name3) name6) name4) public name5; +} +// ---- +// DeclarationError 1809: (20-117): Conflicting parameter name "nameSame" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_8.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_8.sol new file mode 100644 index 0000000000..a3d839a51a --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_nested_8.sol @@ -0,0 +1,4 @@ +contract test { + mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) public name7; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_1.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_1.sol new file mode 100644 index 0000000000..ce3d88813c --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_1.sol @@ -0,0 +1,6 @@ +contract test { + struct Person { + mapping(uint phone => uint calls) friends; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_2.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_2.sol new file mode 100644 index 0000000000..69c733009f --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_2.sol @@ -0,0 +1,6 @@ +contract test { + struct Person { + mapping(uint phone => uint) friends; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_3.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_3.sol new file mode 100644 index 0000000000..ec078ab26e --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_3.sol @@ -0,0 +1,6 @@ +contract test { + struct Person { + mapping(uint => uint calls) friends; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_4.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_4.sol new file mode 100644 index 0000000000..d3ee618ac7 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_4.sol @@ -0,0 +1,6 @@ +contract test { + struct Person { + mapping(uint phone => mapping(uint call => uint time) callTimes) friends; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_5.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_5.sol new file mode 100644 index 0000000000..ccc6d1a553 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_5.sol @@ -0,0 +1,6 @@ +contract test { + struct Person { + mapping(uint phone => uint[] calls) friends; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_6.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_6.sol new file mode 100644 index 0000000000..8b65f281de --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_6.sol @@ -0,0 +1,7 @@ +contract test { + struct Person { + mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name2) name3) name4) name5; + } +} +// ---- +// DeclarationError 1809: (44-141): Conflicting parameter name "nameSame" in mapping. diff --git a/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_7.sol b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_7.sol new file mode 100644 index 0000000000..08ce99da29 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/mapping_with_names_struct_member_7.sol @@ -0,0 +1,6 @@ +contract test { + struct Person { + mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) name7; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/mapping_key.sol b/test/libsolidity/syntaxTests/userDefinedValueType/mapping_key.sol index ae83ae4c73..d2d5585c16 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/mapping_key.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/mapping_key.sol @@ -2,3 +2,4 @@ type MyInt is int; contract C { mapping(MyInt => int) m; } +// ---- From f5858a118d5a4dfc30c0049add0d15e6284e4ab7 Mon Sep 17 00:00:00 2001 From: John Kane Date: Mon, 5 Dec 2022 11:30:37 +0000 Subject: [PATCH 0002/1140] docs(resources.rst): update editor extensions Update the editor extensions section of the resources page: 1. Remove the Atom section - as Atom is being deprecated on 2022-12-15. See https://github.blog/2022-06-08-sunsetting-atom/. 2. Update the vim syntax plugins - remove the tomlion extension as no longer maintained, add the thesis and TovarishFin forks of the tomlion vim syntax highlighter as these are both maintained. 3. add/rename vscode extensions - add truffle and remix extensions, rename the two Solidity extensions to include the authors for disambiguation. 4. Clarify the Visual Studio Code title by including `VS Code` in brackets, as many people only know it as `VS Code`. 5. Use Sublime Text's full name. Co-authored-by: franzihei <41991517+franzihei@users.noreply.github.com> Co-authored-by: Nuno Santos --- docs/resources.rst | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/docs/resources.rst b/docs/resources.rst index 3b403cd6d0..9084037d9d 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -43,17 +43,6 @@ Integrated (Ethereum) Development Environments Editor Integrations =================== -* Atom - - * `Etheratom `_ - Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible). - - * `Atom Solidity Linter `_ - Plugin for the Atom editor that provides Solidity linting. - - * `Atom Solium Linter `_ - Configurable Solidity linter for Atom using Solium (now Ethlint) as a base. - * Emacs * `Emacs Solidity `_ @@ -62,31 +51,40 @@ Editor Integrations * IntelliJ * `IntelliJ IDEA plugin `_ - Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs) + Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs). -* Sublime +* Sublime Text * `Package for SublimeText - Solidity language syntax `_ Solidity syntax highlighting for SublimeText editor. * Vim - * `Vim Solidity `_ - Plugin for the Vim editor providing syntax highlighting. + * `Vim Solidity by Thesis `_ + Syntax highlighting for Solidity in Vim. + + * `Vim Solidity by TovarishFin `_ + Vim syntax file for Solidity. * `Vim Syntastic `_ Plugin for the Vim editor providing compile checking. -* Visual Studio Code +* Visual Studio Code (VS Code) + + * `Ethereum Remix Visual Studio Code extension `_ + Ethereum Remix extension pack for VS Code - * `Visual Studio Code extension `_ + * `Solidity Visual Studio Code extension, by Juan Blanco `_ Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. + * `Solidity Visual Studio Code extension, by Nomic Foundation `_ + Solidity and Hardhat support by the Hardhat team, including: syntax highlighting, jump to definition, renames, quick fixes and inline solc warnings and errors. + * `Solidity Visual Auditor extension `_ Adds security centric syntax and semantic highlighting to Visual Studio Code. - * `Hardhat + Solidity Visual Studio Code extension `_ - Solidity and Hardhat support by the Hardhat team. + * `Truffle for VS Code `_ + Build, debug and deploy smart contracts on Ethereum and EVM-compatible blockchains. Solidity Tools ============== From a98bb41bd3d120df687ae54c170939fc3a6dbcf6 Mon Sep 17 00:00:00 2001 From: Kaan Uzdogan Date: Wed, 14 Dec 2022 18:15:50 +0100 Subject: [PATCH 0003/1140] Add Solidity favicon to docs --- docs/_static/img/favicon.png | Bin 0 -> 949 bytes docs/conf.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/_static/img/favicon.png diff --git a/docs/_static/img/favicon.png b/docs/_static/img/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..3991d87e98b9348b5e7a7c52ccd67a795361edec GIT binary patch literal 949 zcmV;m14{gfP)Px&Z%IT!R9HvtmQ6^LaU93LbDPc=Cc3%wsL}>ha1Oef)jxMDg$n}8%Co6J3Bk9T_cxAL7`Ci)lq)+z})OC?vSz%+0< zXC{j8E-)-EqP)BmR1#{gVs(j^{>H`zswykc(b);QlKC2M0NMkc9qpKz`NTv|SvY7t z+HUCe1I+wCsII2icrow>AT=7vg@td(%DUhsZZ?}yqAr5d=>**Y+MZr0mCBb zJZWym`1pIzaavj$T3Xvd3yRD9$^e@fZOE#s3ed9JH*(z8)`9b>sa*cKn~)-;ADfX= za{hIG-se~u9}lheIa88D-2*?&X7u;#;Bxsw(DghyIe}f450t1V1%^l7dTmWM5Y7@% z^nE%V=H|Y5y-#<8$!Nm*#yV_&>b^FfYOF#-1iv>?R+nGCH->fTESbkcV zzgDXi+gn?nv(qXShF-mfL?SsF08$xwGmMFe4~*dM?k)@lgQxKbY}IOIdW9OWt6Pig z>>N(#^Z;iG_Eqe5JK9=XV7G5#d3o7qJ=<(HI2{gTWMrbJ_XV#J^b3F7K_j%&N0F*Rqi*w|PU@c0Nh_%81f@D9n(2TuTwJp;c1 XVEC$#J{^j000000NkvXXu0mjfsa3e@ literal 0 HcmV?d00001 diff --git a/docs/conf.py b/docs/conf.py index 10aa406f28..61df2b53ec 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -152,7 +152,7 @@ def setup(sphinx): # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +html_favicon = "_static/img/favicon.png" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, From ab78f69bf531ad30c388073f368d7111e4a2e245 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 15 Dec 2022 12:53:57 +0100 Subject: [PATCH 0004/1140] Pin v4-core dependecy to fix failing exteral pooltogether test --- test/externalTests/pool-together.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index a3461a6b03..80a8f4ad05 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -69,6 +69,9 @@ function pool_together_test force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install + # TODO: Remove this when https://github.com/pooltogether/v4-core/issues/287 gets fixed. + npm install @pooltogether/pooltogether-rng-contracts@1.4.0 + # These come with already compiled artifacts. We want them recompiled with latest compiler. rm -r node_modules/@pooltogether/yield-source-interface/artifacts/ rm -r node_modules/@pooltogether/uniform-random-number/artifacts/ From cca1b460c95c230eabd853aa5c806aaa4545a620 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 15 Dec 2022 15:55:52 +0100 Subject: [PATCH 0005/1140] Unpeg fixed dependency from elementfi external test --- test/externalTests/elementfi.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index 4901c6bf1c..bf68b9adf3 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -87,10 +87,6 @@ function elementfi_test sed -i 's|bytes32(uint256(pool))|bytes32(uint256(uint160(pool)))|g' vault/PoolRegistry.sol popd - # The test suite uses forked Mainnet and an expiration period that's too short. - # TODO: Remove when https://github.com/element-fi/elf-contracts/issues/243 is fixed. - sed -i 's|^\s*require(_expiration - block\.timestamp < _unitSeconds);\s*$||g' contracts/ConvergentCurvePool.sol - # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). From d1a158368a0f67a2673f323a70a20f3508725482 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 16 Dec 2022 11:34:00 +0100 Subject: [PATCH 0006/1140] External tests maintenance --- .gitignore | 1 + test/externalTests/chainlink.sh | 4 ++-- test/externalTests/elementfi.sh | 2 +- test/externalTests/ens.sh | 4 ++-- test/externalTests/euler.sh | 6 +----- test/externalTests/gnosis.sh | 10 +++------- test/externalTests/gp2.sh | 2 +- test/externalTests/perpetual-pools.sh | 2 +- test/externalTests/pool-together.sh | 2 +- test/externalTests/prb-math.sh | 2 +- test/externalTests/trident.sh | 2 +- test/externalTests/uniswap.sh | 2 +- test/externalTests/zeppelin.sh | 6 +++--- 13 files changed, 19 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 4f17171816..773f09be6e 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ emscripten_build/ /docs/_build /docs/_static/robots.txt /deps +/reports # vim stuff [._]*.sw[a-p] diff --git a/test/externalTests/chainlink.sh b/test/externalTests/chainlink.sh index 9f50e1486f..249a1254cd 100755 --- a/test/externalTests/chainlink.sh +++ b/test/externalTests/chainlink.sh @@ -64,7 +64,7 @@ function chainlink_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). + # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). sed -i "s|\(it\)\(('reverts'\)|\1.skip\2|g" test/v0.6/BasicConsumer.test.ts sed -i "s|\(it\)\(('has a reasonable gas cost \[ @skip-coverage \]'\)|\1.skip\2|g" test/v0.6/BasicConsumer.test.ts sed -i "s|\(describe\)\(('#add[^']*'\)|\1.skip\2|g" test/v0.6/Chainlink.test.ts @@ -78,7 +78,7 @@ function chainlink_test sed -i "s|\(context\)\(('when permissions are not set'\)|\1.skip\2|g" test/v0.8/KeeperRegistry.test.ts # In some cases Hardhat does not detect revert reasons properly via IR. - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|\(it\)\(('does not allow the specified address to start new rounds'\)|\1.skip\2|g" test/v0.6/FluxAggregator.test.ts sed -i "s|\(describe\)\(('when called by a stranger'\)|\1.skip\2|g" test/v0.6/FluxAggregator.test.ts sed -i "s|\(describe\)\(('if the access control is turned on'\)|\1.skip\2|g" test/v0.*/Flags.test.ts diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index bf68b9adf3..b667a4bbc0 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -89,7 +89,7 @@ function elementfi_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). + # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). sed -i 's|it(\("fails to withdraw more shares than in balance"\)|it.skip(\1|g' test/compoundAssetProxyTest.ts sed -i 's|it(\("should prevent withdrawal of Principal Tokens and Interest Tokens before the tranche expires "\)|it.skip(\1|g' test/trancheTest.ts sed -i 's|it(\("should prevent withdrawal of more Principal Tokens and Interest Tokens than the user has"\)|it.skip(\1|g' test/trancheTest.ts diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index 5cc2a574d4..1233085382 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -69,9 +69,9 @@ function ens_test neutralize_packaged_contracts # In some cases Hardhat does not detect revert reasons properly via IR. - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2115 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('Does not allow wrapping a name you do not own',\)|it.skip\1|g" test/wrapper/NameWrapper.js - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('can set fuses and then burn ability to burn fuses',\)|it.skip\1|g" test/wrapper/NameWrapper.js sed -i "s|it\(('can set fuses and burn canSetResolver and canSetTTL',\)|it.skip\1|g" test/wrapper/NameWrapper.js sed -i "s|it\(('Cannot be called if CANNOT_TRANSFER is burned\.',\)|it.skip\1|g" test/wrapper/NameWrapper.js diff --git a/test/externalTests/euler.sh b/test/externalTests/euler.sh index e26b892486..78e89d147b 100755 --- a/test/externalTests/euler.sh +++ b/test/externalTests/euler.sh @@ -63,7 +63,7 @@ function euler_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "/expectError: 'JUNK_UPGRADE_TEST_FAILURE'/d" test/moduleUpgrade.js sed -i "/et\.expect(errMsg)\.to\.contain('e\/collateral-violation');/d" test/flashLoanNative.js @@ -73,10 +73,6 @@ function euler_test force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" force_hardhat_unlimited_contract_size "$config_file" npm install - - # TODO: Remove this when https://github.com/Uniswap/v3-periphery/issues/313 gets fixed. - npm install @uniswap/v3-periphery@1.4.1 - replace_version_pragmas neutralize_packaged_contracts diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 81e5180c60..a6ded27e16 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -71,9 +71,9 @@ function gnosis_safe_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). + # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). sed -i "s|\(it\)\(('should not allow to call setup on singleton'\)|\1.skip\2|g" test/core/GnosisSafe.Setup.spec.ts - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i 's|\(it\)\(("changes the expected storage slot without touching the most important ones"\)|\1.skip\2|g' test/libraries/SignMessageLib.spec.ts sed -i "s|\(it\)\(('can be used only via DELEGATECALL opcode'\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts sed -i 's|\(describe\)\(("Upgrade from Safe 1.1.1"\)|\1.skip\2|g' test/migration/UpgradeFromSafe111.spec.ts @@ -82,7 +82,7 @@ function gnosis_safe_test # TODO: Remove this when Gnosis merges https://github.com/gnosis/safe-contracts/pull/394 sed -i "s|\(function isValidSignature(bytes \)calldata\( _data, bytes \)calldata\( _signature)\)|\1memory\2memory\3|g" contracts/handler/CompatibilityFallbackHandler.sol - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('should enforce delegatecall'\)|it.skip\1|g" test/accessors/SimulateTxAccessor.spec.ts sed -i "s|it\(('can only be called from Safe itself'\)|it.skip\1|g" test/libraries/Migration.spec.ts sed -i "s|it\(('should enforce delegatecall to MultiSend'\)|it.skip\1|g" test/libraries/MultiSend.spec.ts @@ -122,10 +122,6 @@ function gnosis_safe_test # TODO: Remove when https://github.com/safe-global/safe-contracts/issues/436 is resolved. npx npm install @nomiclabs/hardhat-ethers@2.1.0 - # Hardhat 2.9.5 introduced a bug with handling padded arguments to getStorageAt(). - # TODO: Remove when https://github.com/NomicFoundation/hardhat/issues/2709 is fixed. - npx npm install hardhat@2.9.4 - replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist" diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index ad75f83bdd..9e9ee72af2 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -99,7 +99,7 @@ function gp2_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). + # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). sed -i 's|it\(("should revert when encoding invalid flags"\)|it.skip\1|g' test/GPv2Trade.test.ts replace_version_pragmas diff --git a/test/externalTests/perpetual-pools.sh b/test/externalTests/perpetual-pools.sh index a389e833f3..18fb308af4 100755 --- a/test/externalTests/perpetual-pools.sh +++ b/test/externalTests/perpetual-pools.sh @@ -61,7 +61,7 @@ function perpetual_pools_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). + # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). sed -i 's|\(it\)\(("Should not allow commits that are too large"\)|\1.skip\2|g' test/PoolCommitter/commit.spec.ts sed -i 's|\(it\)\(("Should not allow for too many commitments (that bring amount over a user'\''s balance)"\)|\1.skip\2|g' test/PoolCommitter/commit.spec.ts diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 80a8f4ad05..14c7853f4e 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -59,7 +59,7 @@ function pool_together_test setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$ref_type" "$ref" "$DIR" - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('should fail to return value if value passed does not fit in [0-9]\+ bits'\)|it.skip\1|g" test/libraries/ExtendedSafeCast.test.ts sed -i "s|it\(('should require an rng to be requested'\)|it.skip\1|g" test/DrawBeacon.test.ts diff --git a/test/externalTests/prb-math.sh b/test/externalTests/prb-math.sh index 98a73627f8..78a39519e4 100755 --- a/test/externalTests/prb-math.sh +++ b/test/externalTests/prb-math.sh @@ -71,7 +71,7 @@ function prb_math_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). + # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). pushd test/contracts/prbMathUd60x18/pure/ sed -i 's|context(\("when the sum overflows"\)|context.skip(\1|g' add.test.ts sed -i 's|context(\("when the sum does not overflow"\)|context.skip(\1|g' add.test.ts diff --git a/test/externalTests/trident.sh b/test/externalTests/trident.sh index 401446f998..b5d48b500a 100755 --- a/test/externalTests/trident.sh +++ b/test/externalTests/trident.sh @@ -89,7 +89,7 @@ function trident_test sed -i 's|IStrategy(0)|IStrategy(address(0))|g' contracts/flat/BentoBoxV1Flat.sol find contracts -name "*.sol" -exec sed -i -e 's/^\(\s*\)\(assembly\)/\1\/\/\/ @solidity memory-safe-assembly\n\1\2/' '{}' \; - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i 's|it\(("Reverts on direct deployment via factory"\)|it.skip\1|g' test/MasterDeployer.test.ts # @sushiswap/core package contains contracts that get built with 0.6.12 and fail our compiler diff --git a/test/externalTests/uniswap.sh b/test/externalTests/uniswap.sh index 5da068df8e..8b07aee84e 100755 --- a/test/externalTests/uniswap.sh +++ b/test/externalTests/uniswap.sh @@ -61,7 +61,7 @@ function uniswap_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2115 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('underpay zero for one and exact in',\)|it.skip\1|g" test/UniswapV3Pool.spec.ts sed -i "s|it\(('pay in the wrong token zero for one and exact in',\)|it.skip\1|g" test/UniswapV3Pool.spec.ts sed -i "s|it\(('underpay zero for one and exact out',\)|it.skip\1|g" test/UniswapV3Pool.spec.ts diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index fafa23ffb3..27198a8f0e 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -63,7 +63,7 @@ function zeppelin_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/2115). + # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). pushd test/utils/ sed -i "s|it(\('reverts \)|it.skip(\1|g" math/SafeMath.test.js sed -i "s|it(\('reverts \)|it.skip(\1|g" math/SignedSafeMath.test.js @@ -75,7 +75,7 @@ function zeppelin_test # In some cases Hardhat does not detect revert reasons properly via IR. - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2453 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it(\('reverts if the current value is 0'\)|it.skip(\1|g" test/utils/Counters.test.js sed -i "s|it(\('prevent unauthorized maintenance'\)|it.skip(\1|g" test/governance/TimelockController.test.js sed -i "s|it(\('cannot cancel invalid operation'\)|it.skip(\1|g" test/governance/TimelockController.test.js @@ -123,7 +123,7 @@ function zeppelin_test - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/2115 gets fixed. + # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|describe\(('Polygon-Child'\)|describe.skip\1|g" test/crosschain/CrossChainEnabled.test.js sed -i "s|it(\('revert with invalid multi proof #2'\)|it.skip(\1|g" test/utils/cryptography/MerkleProof.test.js sed -i "s|describe(\('to a receiver contract that panics'\)|describe.skip(\1|g" test/token/ERC721/ERC721.behavior.js From d5c6fd881b41b0fc11b65a63d34540d752c6cfdc Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Fri, 9 Dec 2022 10:44:38 +0100 Subject: [PATCH 0007/1140] update docs on the required z3 version --- CMakeLists.txt | 2 +- docs/installing-solidity.rst | 2 +- docs/smtchecker.rst | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b43f244949..d04d708ae2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/license.h.in" include/licens include(EthOptions) configure_project(TESTS) set(LATEST_Z3_VERSION "4.11.2") -set(MINIMUM_Z3_VERSION "4.8.0") +set(MINIMUM_Z3_VERSION "4.8.16") find_package(Z3) if (${Z3_FOUND}) if (${STRICT_Z3_VERSION}) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 9a613d75d3..1b6ac66354 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -326,7 +326,7 @@ The following are dependencies for all builds of Solidity: +-----------------------------------+-------------------------------------------------------+ | `Git`_ | Command-line tool for retrieving source code. | +-----------------------------------+-------------------------------------------------------+ -| `z3`_ (version 4.8+, Optional) | For use with SMT checker. | +| `z3`_ (version 4.8.16+, Optional) | For use with SMT checker. | +-----------------------------------+-------------------------------------------------------+ | `cvc4`_ (Optional) | For use with SMT checker. | +-----------------------------------+-------------------------------------------------------+ diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index b1a39ee17d..c16a3e5d71 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -632,7 +632,8 @@ option ``--model-checker-solvers {all,cvc4,eld,smtlib2,z3}`` or the JSON option .. note:: z3 version 4.8.16 broke ABI compatibility with previous versions and cannot be used with solc <=0.8.13. If you are using z3 >=4.8.16 please use solc - >=0.8.14. + >=0.8.14, and conversely, only use older z3 with older solc releases. + We also recommend using the latest z3 release which is what SMTChecker also does. Since both BMC and CHC use ``z3``, and ``z3`` is available in a greater variety of environments, including in the browser, most users will almost never need to be From 4d627e6fc4c32c2db9a1a89ba63da652792a9b6e Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 16 Dec 2022 14:49:01 +0100 Subject: [PATCH 0008/1140] fixup! External tests maintenance --- test/externalTests/ens.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index 1233085382..77395160d3 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -71,7 +71,6 @@ function ens_test # In some cases Hardhat does not detect revert reasons properly via IR. # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('Does not allow wrapping a name you do not own',\)|it.skip\1|g" test/wrapper/NameWrapper.js - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('can set fuses and then burn ability to burn fuses',\)|it.skip\1|g" test/wrapper/NameWrapper.js sed -i "s|it\(('can set fuses and burn canSetResolver and canSetTTL',\)|it.skip\1|g" test/wrapper/NameWrapper.js sed -i "s|it\(('Cannot be called if CANNOT_TRANSFER is burned\.',\)|it.skip\1|g" test/wrapper/NameWrapper.js From e295964f50c317d1e6b0ce6e5273984e956e9692 Mon Sep 17 00:00:00 2001 From: Saw-mon-and-Natalie Date: Fri, 16 Dec 2022 14:58:41 +0000 Subject: [PATCH 0009/1140] fixed some comments in Types.h --- libsolidity/ast/Types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 9fe0b4d928..2f9277808f 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -802,14 +802,14 @@ class ArrayType: public ReferenceType /// Constructor for a byte array ("bytes") and string. explicit ArrayType(DataLocation _location, bool _isString = false); - /// Constructor for a dynamically sized array type ("type[]") + /// Constructor for a dynamically sized array type ("[]") ArrayType(DataLocation _location, Type const* _baseType): ReferenceType(_location), m_baseType(copyForLocationIfReference(_baseType)) { } - /// Constructor for a fixed-size array type ("type[20]") + /// Constructor for a fixed-size array type ("[]") ArrayType(DataLocation _location, Type const* _baseType, u256 _length): ReferenceType(_location), m_baseType(copyForLocationIfReference(_baseType)), From 3bc535e1a1b9c3d6d32d21c798b9bc2f5f12b71f Mon Sep 17 00:00:00 2001 From: andy53 Date: Wed, 2 Nov 2022 20:46:54 -0600 Subject: [PATCH 0010/1140] Report when no contracts to compile updates --- solc/CommandLineInterface.cpp | 5 ++- test/cmdlineTests.sh | 5 +++ .../no_contract_combined_json/args | 1 + .../no_contract_combined_json/input.sol | 2 + .../no_contract_combined_json/output | 36 +++++++++++++++ test/solc/CommandLineInterface.cpp | 45 ++++++++++++++++++- 6 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 test/cmdlineTests/no_contract_combined_json/args create mode 100644 test/cmdlineTests/no_contract_combined_json/input.sol create mode 100644 test/cmdlineTests/no_contract_combined_json/output diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 3973008f95..c687d44b54 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -48,7 +48,6 @@ #include #include -#include #include #include @@ -1193,8 +1192,10 @@ void CommandLineInterface::outputCompilationResults() { if (!m_options.output.dir.empty()) sout() << "Compiler run successful. Artifact(s) can be found in directory " << m_options.output.dir << "." << endl; + else if (contracts.empty()) + sout() << "Compiler run successful. No contracts to compile." << endl; else - serr() << "Compiler run successful, no output requested." << endl; + sout() << "Compiler run successful. No output generated." << endl; } } diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index d04117156a..ce9af142fc 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -225,6 +225,11 @@ EOF sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path" sed -i.bak -e 's/\(Unimplemented feature error.* in \).*$/\1/' "$stderr_path" sed -i.bak -e 's/"version":[ ]*"[^"]*"/"version": ""/' "$stdout_path" + if [[ $stdout_expectation_file != "" && $stderr_expectation_file != "" ]] + then + sed -i.bak -e '/^Compiler run successful\. No contracts to compile\.$/d' "$stdout_path" + sed -i.bak -e '/^Compiler run successful\. No output generated\.$/d' "$stdout_path" + fi # Remove bytecode (but not linker references). Since non-JSON output is unstructured, # use metadata markers for detection to have some confidence that it's actually bytecode diff --git a/test/cmdlineTests/no_contract_combined_json/args b/test/cmdlineTests/no_contract_combined_json/args new file mode 100644 index 0000000000..8d81d1c0f2 --- /dev/null +++ b/test/cmdlineTests/no_contract_combined_json/args @@ -0,0 +1 @@ +--combined-json ast --pretty-json --json-indent 4 \ No newline at end of file diff --git a/test/cmdlineTests/no_contract_combined_json/input.sol b/test/cmdlineTests/no_contract_combined_json/input.sol new file mode 100644 index 0000000000..b926e9263b --- /dev/null +++ b/test/cmdlineTests/no_contract_combined_json/input.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; \ No newline at end of file diff --git a/test/cmdlineTests/no_contract_combined_json/output b/test/cmdlineTests/no_contract_combined_json/output new file mode 100644 index 0000000000..af73008960 --- /dev/null +++ b/test/cmdlineTests/no_contract_combined_json/output @@ -0,0 +1,36 @@ +{ + "sourceList": + [ + "no_contract_combined_json/input.sol" + ], + "sources": + { + "no_contract_combined_json/input.sol": + { + "AST": + { + "absolutePath": "no_contract_combined_json/input.sol", + "exportedSymbols": {}, + "id": 2, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": + [ + { + "id": 1, + "literals": + [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + } + ], + "src": "36:22:0" + } + } + }, + "version": "" +} diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 2ae57541bd..8124b1545f 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -44,6 +45,7 @@ using namespace std; using namespace solidity::frontend; using namespace solidity::test; using namespace solidity::util; +using namespace solidity::langutil; using PathSet = set; @@ -1006,10 +1008,14 @@ BOOST_AUTO_TEST_CASE(cli_include_paths) canonicalWorkDir / "lib", }; + string const expectedStdoutContent = "Compiler run successful. No contracts to compile.\n"; OptionsReaderAndMessages result = runCLI(commandLine, ""); BOOST_TEST(result.stderrContent == ""); - BOOST_TEST(result.stdoutContent == ""); + if (SemVerVersion{string(VersionString)}.isPrerelease()) + BOOST_TEST(result.stdoutContent == ""); + else + BOOST_TEST(result.stdoutContent == expectedStdoutContent); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); BOOST_TEST(result.reader.sourceUnits() == expectedSources); @@ -1018,6 +1024,43 @@ BOOST_AUTO_TEST_CASE(cli_include_paths) BOOST_TEST(result.reader.basePath() == expectedWorkDir / "base/"); } +BOOST_AUTO_TEST_CASE(cli_no_contracts_to_compile) +{ + string const contractSource = R"( + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.0; + enum Status { test } + )"; + + string const expectedStdoutContent = "Compiler run successful. No contracts to compile.\n"; + OptionsReaderAndMessages result = runCLI({"solc", "-"}, contractSource); + + if (SemVerVersion{string(VersionString)}.isPrerelease()) + BOOST_TEST(result.stdoutContent == ""); + else + BOOST_TEST(result.stdoutContent == expectedStdoutContent); + BOOST_REQUIRE(result.success); +} + +BOOST_AUTO_TEST_CASE(cli_no_output) +{ + string const contractSource = R"( + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.0; + abstract contract A { + function B() public virtual returns(uint); + })"; + + string const expectedStdoutContent = "Compiler run successful. No output generated.\n"; + OptionsReaderAndMessages result = runCLI({"solc", "-"}, contractSource); + + if (SemVerVersion{string(VersionString)}.isPrerelease()) + BOOST_TEST(result.stdoutContent == ""); + else + BOOST_TEST(result.stdoutContent == expectedStdoutContent); + BOOST_REQUIRE(result.success); +} + BOOST_AUTO_TEST_CASE(standard_json_include_paths) { TemporaryDirectory tempDir({"base/", "include/", "lib/nested/"}, TEST_CASE_NAME); From 7242d9c2cfc77a416532b470104808e92b824db7 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Tue, 20 Dec 2022 13:21:27 +0100 Subject: [PATCH 0011/1140] Fix sphinx-a4doc version to 1.3.0 --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 23c8f90432..cee188db03 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,7 +4,7 @@ sphinx_rtd_theme>=0.5.2 pygments-lexer-solidity>=0.7.0 -sphinx-a4doc>=1.2.1 +sphinx-a4doc==1.3.0 # Sphinx 2.1.0 is the oldest version that accepts a lexer class in add_lexer() sphinx>=2.1.0 From b314e1b37de5554b8f1e4ae56550038d9404ffcd Mon Sep 17 00:00:00 2001 From: Pierre Grimaud Date: Sun, 25 Dec 2022 22:39:50 +0100 Subject: [PATCH 0012/1140] docs: fix typos --- test/libsolidity/AnalysisFramework.h | 4 ++-- test/libsolidity/SolidityEndToEndTest.cpp | 2 +- test/libsolidity/semanticTests/externalContracts/snark.sol | 6 +++--- .../semanticTests/structs/struct_referencing.sol | 2 +- test/tools/ossfuzz/protoToAbiV2.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index c4b4eda33b..7dbbb902ff 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -72,7 +72,7 @@ class AnalysisFramework std::vector m_warningsToFilter = {"This is a pre-release compiler version"}; std::vector m_messagesToCut = {"Source file requires different compiler version (current compiler is"}; - /// @returns reference to lazy-instanciated CompilerStack. + /// @returns reference to lazy-instantiated CompilerStack. solidity::frontend::CompilerStack& compiler() { if (!m_compiler) @@ -80,7 +80,7 @@ class AnalysisFramework return *m_compiler; } - /// @returns reference to lazy-instanciated CompilerStack. + /// @returns reference to lazy-instantiated CompilerStack. solidity::frontend::CompilerStack const& compiler() const { if (!m_compiler) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 2f0d1a5d08..268861fd2a 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1538,7 +1538,7 @@ BOOST_AUTO_TEST_CASE(struct_referencing) s.a = 4; return s; } - // argument-dependant lookup tests + // argument-dependent lookup tests function a(I.S memory) public pure returns (uint) { return 1; } function a(S memory) public pure returns (uint) { return 2; } } diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index be9fc00729..bb76542111 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -164,10 +164,10 @@ contract Test { Pairing.G1Point memory p2; p1.X = 1; p1.Y = 2; p2.X = 1; p2.Y = 2; - Pairing.G1Point memory explict_sum = Pairing.add(p1, p2); + Pairing.G1Point memory explicit_sum = Pairing.add(p1, p2); Pairing.G1Point memory scalar_prod = Pairing.mul(p1, 2); - return (explict_sum.X == scalar_prod.X && - explict_sum.Y == scalar_prod.Y); + return (explicit_sum.X == scalar_prod.X && + explicit_sum.Y == scalar_prod.Y); } function g() public returns (bool) { Pairing.G1Point memory x = Pairing.add(Pairing.P1(), Pairing.negate(Pairing.P1())); diff --git a/test/libsolidity/semanticTests/structs/struct_referencing.sol b/test/libsolidity/semanticTests/structs/struct_referencing.sol index 0d7d1a7545..cbe8a72bfc 100644 --- a/test/libsolidity/semanticTests/structs/struct_referencing.sol +++ b/test/libsolidity/semanticTests/structs/struct_referencing.sol @@ -15,7 +15,7 @@ library L { s.a = 4; return s; } - // argument-dependant lookup tests + // argument-dependent lookup tests function a(I.S memory) public pure returns (uint) { return 1; } function a(S memory) public pure returns (uint) { return 2; } } diff --git a/test/tools/ossfuzz/protoToAbiV2.cpp b/test/tools/ossfuzz/protoToAbiV2.cpp index f20c0482c9..98de7dd359 100644 --- a/test/tools/ossfuzz/protoToAbiV2.cpp +++ b/test/tools/ossfuzz/protoToAbiV2.cpp @@ -944,7 +944,7 @@ string TypeVisitor::visit(StructType const& _type) structDefinition(_type); // Set last dyn param if struct contains a dyn param e.g., bytes, array etc. m_isLastDynParamRightPadded = DynParamVisitor().visit(_type); - // If top-level struct is a non-emtpy struct, assign the name S + // If top-level struct is a non-empty struct, assign the name S m_baseType = s_structTypeName + to_string(m_structStartCounter); } else From f48cd743d911d6c42aa9dbe64be22e2abc25257f Mon Sep 17 00:00:00 2001 From: vlad Date: Fri, 30 Dec 2022 00:46:32 +0400 Subject: [PATCH 0013/1140] fix sphinx version to 5.* since 6.0 is not supported by code --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index cee188db03..7f1fc578c3 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -7,4 +7,4 @@ pygments-lexer-solidity>=0.7.0 sphinx-a4doc==1.3.0 # Sphinx 2.1.0 is the oldest version that accepts a lexer class in add_lexer() -sphinx>=2.1.0 +sphinx>=2.1.0, <6.0 From 0694f639e4626ba27c3bf1e6b9fb761c79939499 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Mon, 2 Jan 2023 11:50:10 +0100 Subject: [PATCH 0014/1140] Update sphinx-a4doc version --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 7f1fc578c3..b1b21a8691 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,7 +4,7 @@ sphinx_rtd_theme>=0.5.2 pygments-lexer-solidity>=0.7.0 -sphinx-a4doc==1.3.0 +sphinx-a4doc>=1.6.0 # Sphinx 2.1.0 is the oldest version that accepts a lexer class in add_lexer() sphinx>=2.1.0, <6.0 From 17d57da0821050df93130ab5aac58044432e29ce Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 4 Jan 2023 09:48:02 +0100 Subject: [PATCH 0015/1140] Unpin v4-core dependency and neutralize packages --- test/externalTests/pool-together.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 14c7853f4e..86cd3ee684 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -69,15 +69,13 @@ function pool_together_test force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install - # TODO: Remove this when https://github.com/pooltogether/v4-core/issues/287 gets fixed. - npm install @pooltogether/pooltogether-rng-contracts@1.4.0 - # These come with already compiled artifacts. We want them recompiled with latest compiler. rm -r node_modules/@pooltogether/yield-source-interface/artifacts/ rm -r node_modules/@pooltogether/uniform-random-number/artifacts/ rm -r node_modules/@pooltogether/owner-manager-contracts/artifacts/ replace_version_pragmas + neutralize_packaged_contracts for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" From 5ecf3075fbbd2690ad3bbb821d930ecdc7b720ee Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 5 Jan 2023 13:10:42 +0100 Subject: [PATCH 0016/1140] Silence version check grep and up the node heap limit --- test/externalTests/common.sh | 6 +++--- test/externalTests/zeppelin.sh | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index d8f7e80b8e..144c68a890 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -345,7 +345,7 @@ function truffle_verify_compiler_version local full_solc_version="$2" printLog "Verify that the correct version (${solc_version}/${full_solc_version}) of the compiler was used to compile the contracts..." - grep "$full_solc_version" --with-filename --recursive build/contracts || fail "Wrong compiler version detected." + grep "$full_solc_version" --recursive --quiet build/contracts || fail "Wrong compiler version detected." } function hardhat_verify_compiler_version @@ -357,8 +357,8 @@ function hardhat_verify_compiler_version local build_info_files build_info_files=$(find . -path '*artifacts/build-info/*.json') for build_info_file in $build_info_files; do - grep '"solcVersion":[[:blank:]]*"'"${solc_version}"'"' --with-filename "$build_info_file" || fail "Wrong compiler version detected in ${build_info_file}." - grep '"solcLongVersion":[[:blank:]]*"'"${full_solc_version}"'"' --with-filename "$build_info_file" || fail "Wrong compiler version detected in ${build_info_file}." + grep '"solcVersion":[[:blank:]]*"'"${solc_version}"'"' --quiet "$build_info_file" || fail "Wrong compiler version detected in ${build_info_file}." + grep '"solcLongVersion":[[:blank:]]*"'"${full_solc_version}"'"' --quiet "$build_info_file" || fail "Wrong compiler version detected in ${build_info_file}." done } diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 27198a8f0e..11e148c182 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -23,6 +23,8 @@ # shellcheck disable=SC2016 set -e +# Temporary(?) fix to up the heap limit for node in order to prevent 'out of heap errors' +export NODE_OPTIONS="--max-old-space-size=4096" source scripts/common.sh source test/externalTests/common.sh From 03eb17a50f49f3729cbc45752cb55001c0474446 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 5 Jan 2023 12:51:01 +0100 Subject: [PATCH 0017/1140] Disable t_ubu_ossfuzz gitter notifications. --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 784b561d91..802499969b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -919,8 +919,6 @@ jobs: scripts/regressions.py -o test_results - store_test_results: *store_test_results - store_artifacts: *artifacts_test_results - - gitter_notify_failure_unless_pr - - gitter_notify_success_unless_pr b_archlinux: <<: *base_archlinux_large From d4f9383185db10253ce1c1a602bf2cd3ee5c982d Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Thu, 12 Jan 2023 09:08:39 +0100 Subject: [PATCH 0018/1140] Drop `ewasm` from tests --- .circleci/osx_install_dependencies.sh | 7 ------- .circleci/soltest_all.sh | 7 ++----- scripts/tests.sh | 5 +---- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index ff34e2fc98..f742d131b2 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -81,11 +81,4 @@ then tar xzpf "$evmone_package" -C /usr/local rm "$evmone_package" - # hera - hera_version="0.6.0" - hera_package="hera-${hera_version}-darwin-x86_64.tar.gz" - wget "https://github.com/ewasm/hera/releases/download/v${hera_version}/${hera_package}" - validate_checksum "$hera_package" 82ee57404862705ab314f7a4d04bf2cf29d71e8d209850d66c125527cd287f37 - tar xzpf "$hera_package" -C /usr/local - rm "$hera_package" fi diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 23663ce46e..5a5449a948 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -50,9 +50,6 @@ for OPTIMIZE in "${OPTIMIZE_VALUES[@]}" do for EVM in "${EVM_VALUES[@]}" do - # run tests against hera ewasm evmc vm, only if OPTIMIZE == 0 and evm version is byzantium - EWASM_ARGS="" - [ "${EVM}" = "byzantium" ] && [ "${OPTIMIZE}" = "0" ] && EWASM_ARGS="--ewasm" ENFORCE_GAS_ARGS="" [ "${EVM}" = "${DEFAULT_EVM}" ] && ENFORCE_GAS_ARGS="--enforce-gas-cost" # Run SMTChecker tests only when OPTIMIZE == 0 @@ -61,11 +58,11 @@ do EVM="$EVM" \ OPTIMIZE="$OPTIMIZE" \ - SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS $EWASM_ARGS" \ + SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS" \ BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" \ INDEX_SHIFT="$INDEX_SHIFT" \ "${REPODIR}/.circleci/soltest.sh" INDEX_SHIFT=$((INDEX_SHIFT + 1)) done -done \ No newline at end of file +done diff --git a/scripts/tests.sh b/scripts/tests.sh index f8230c54ad..c9a7471343 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -139,11 +139,8 @@ do fi fi - EWASM_ARGS="" - [ "${vm}" = "byzantium" ] && [ "${optimize}" = "" ] && EWASM_ARGS="--ewasm" - set +e - "${SOLIDITY_BUILD_DIR}"/test/soltest --show-progress "${log[@]}" -- ${EWASM_ARGS} --testpath "$REPO_ROOT"/test "$optimize" --evm-version "$vm" "${SMT_FLAGS[@]}" "${force_abiv1_flag[@]}" + "${SOLIDITY_BUILD_DIR}"/test/soltest --show-progress "${log[@]}" -- --testpath "$REPO_ROOT"/test "$optimize" --evm-version "$vm" "${SMT_FLAGS[@]}" "${force_abiv1_flag[@]}" if test "0" -ne "$?"; then exit 1 From 1da82045c4881e5ccd6f15f7abf472272e1028cd Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 11 Jan 2023 10:18:49 +0100 Subject: [PATCH 0019/1140] Use directory_options instead of deprecated symlink_option basename to step --- libsolidity/lsp/LanguageServer.cpp | 2 +- solc/CommandLineInterface.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/lsp/LanguageServer.cpp b/libsolidity/lsp/LanguageServer.cpp index 74d1b4d7cc..2d85c08b0e 100644 --- a/libsolidity/lsp/LanguageServer.cpp +++ b/libsolidity/lsp/LanguageServer.cpp @@ -221,7 +221,7 @@ vector LanguageServer::allSolidityFilesFromProject() co // We explicitly decided against including all files from include paths but leave the possibility // open for a future PR to enable such a feature to be optionally enabled (default disabled). - auto directoryIterator = fs::recursive_directory_iterator(m_fileRepository.basePath(), fs::symlink_option::recurse); + auto directoryIterator = fs::recursive_directory_iterator(m_fileRepository.basePath(), fs::directory_options::follow_directory_symlink); for (fs::directory_entry const& dirEntry: directoryIterator) if ( dirEntry.path().extension() == ".sol" && diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index c687d44b54..1d64fa4946 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -589,7 +589,7 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da void CommandLineInterface::createJson(string const& _fileName, string const& _json) { - createFile(boost::filesystem::basename(_fileName) + string(".json"), _json); + createFile(boost::filesystem::path(_fileName).stem().string() + string(".json"), _json); } bool CommandLineInterface::run(int _argc, char const* const* _argv) From 7063fabf1f5666fad0eaf9790617b61e65eecf30 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 11 Jan 2023 20:55:02 +0100 Subject: [PATCH 0020/1140] Update CI ubuntu version to 2204 Minor fix replace deprecated is_pod --- .circleci/README.md | 10 +-- .circleci/config.yml | 162 ++++++++++++++++++++-------------------- libsolutil/CommonData.h | 2 +- libsolutil/vector_ref.h | 2 +- 4 files changed, 88 insertions(+), 88 deletions(-) diff --git a/.circleci/README.md b/.circleci/README.md index 338e858d9c..6af7fd45cc 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -7,15 +7,15 @@ The docker images are build locally on the developer machine: ```sh cd .circleci/docker/ -docker build -t ethereum/solidity-buildpack-deps:ubuntu2004- -f Dockerfile.ubuntu2004 . -docker push ethereum/solidity-buildpack-deps:ubuntu2004- +docker build -t ethereum/solidity-buildpack-deps:ubuntu2204- -f Dockerfile.ubuntu2204 . +docker push ethereum/solidity-buildpack-deps:ubuntu2204- ``` -The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `-docker-image-rev` (e.g., `ubuntu-2004-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ. +The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `-docker-image-rev` (e.g., `ubuntu-2204-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ. Once the docker image has been built and pushed to Dockerhub, you can find it at: - https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2004- + https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2204- where the image tag reflects the target OS and revision to build Solidity and run its tests on. @@ -24,7 +24,7 @@ where the image tag reflects the target OS and revision to build Solidity and ru ```sh cd solidity # Mounts your local solidity directory in docker container for testing -docker run -v `pwd`:/src/solidity -ti ethereum/solidity-buildpack-deps:ubuntu2004- /bin/bash +docker run -v `pwd`:/src/solidity -ti ethereum/solidity-buildpack-deps:ubuntu2204- /bin/bash cd /src/solidity ``` diff --git a/.circleci/config.yml b/.circleci/config.yml index 802499969b..28253f943a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,18 +7,18 @@ # - ems: Emscripten version: 2.1 parameters: - ubuntu-2004-docker-image: + ubuntu-2204-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-16 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ee1def5806f40c35d583234e172ec5769bb9a08b6f5bbc713c1a2658846dbced" - ubuntu-2004-clang-docker-image: + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-1 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:07419ed58537cbca9d4c30701fb84f6bb517ce2fce7f3b5dccb3db8bf1c30183" + ubuntu-2204-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004.clang-16 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:8f635529a10e0ddf955d6d72360261966e5fee0b5c5211070370ca2fc4e0ab7c" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-1 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:e515710752bfb38ee0e9b2f92ca71612c03ed85290c36c3b3c0a3d9f90187aef" ubuntu-1604-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu1604.clang.ossfuzz-21 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ae6b695fb8a0806702bb6a1a9616fbb33ac3288f25990fa799aab2c045c80ea1" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu1604.clang.ossfuzz-22 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:baf46ad78b131eb6b0bf98d50e9330437a338c6893b53af3853b36f6f4ab18ae" emscripten-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:emscripten-14 @@ -301,17 +301,17 @@ defaults: TERM: xterm MAKEFLAGS: -j 2 - - base_ubuntu2004_clang: &base_ubuntu2004_clang + - base_ubuntu2204_clang: &base_ubuntu2204_clang docker: - - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >> + - image: << pipeline.parameters.ubuntu-2204-clang-docker-image >> environment: TERM: xterm CC: clang CXX: clang++ MAKEFLAGS: -j 3 - - base_ubuntu2004_clang_large: &base_ubuntu2004_clang_large - <<: *base_ubuntu2004_clang + - base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large + <<: *base_ubuntu2204_clang resource_class: large environment: TERM: xterm @@ -319,29 +319,29 @@ defaults: CXX: clang++ MAKEFLAGS: -j 5 - - base_ubuntu2004: &base_ubuntu2004 + - base_ubuntu2204: &base_ubuntu2204 docker: - - image: << pipeline.parameters.ubuntu-2004-docker-image >> + - image: << pipeline.parameters.ubuntu-2204-docker-image >> environment: TERM: xterm MAKEFLAGS: -j 3 - - base_ubuntu2004_small: &base_ubuntu2004_small - <<: *base_ubuntu2004 + - base_ubuntu2204_small: &base_ubuntu2204_small + <<: *base_ubuntu2204 resource_class: small environment: TERM: xterm MAKEFLAGS: -j 2 - - base_ubuntu2004_large: &base_ubuntu2004_large - <<: *base_ubuntu2004 + - base_ubuntu2204_large: &base_ubuntu2204_large + <<: *base_ubuntu2204 resource_class: large environment: TERM: xterm MAKEFLAGS: -j 5 - - base_ubuntu2004_xlarge: &base_ubuntu2004_xlarge - <<: *base_ubuntu2004 + - base_ubuntu2204_xlarge: &base_ubuntu2204_xlarge + <<: *base_ubuntu2204 resource_class: xlarge environment: TERM: xterm @@ -440,7 +440,7 @@ defaults: branches: ignore: /.*/ - - workflow_ubuntu2004: &workflow_ubuntu2004 + - workflow_ubuntu2204: &workflow_ubuntu2204 <<: *workflow_trigger_on_tags requires: - b_ubu @@ -450,17 +450,17 @@ defaults: requires: - b_ubu_ossfuzz - - workflow_ubuntu2004_clang: &workflow_ubuntu2004_clang + - workflow_ubuntu2204_clang: &workflow_ubuntu2204_clang <<: *workflow_trigger_on_tags requires: - b_ubu_clang - - workflow_ubuntu2004_force_release: &workflow_ubuntu2004_force_release + - workflow_ubuntu2204_force_release: &workflow_ubuntu2204_force_release <<: *workflow_trigger_on_tags requires: - b_ubu_force_release - - workflow_ubuntu2004_static: &workflow_ubuntu2004_static + - workflow_ubuntu2204_static: &workflow_ubuntu2204_static <<: *workflow_trigger_on_tags requires: - b_ubu_static @@ -470,7 +470,7 @@ defaults: requires: - b_archlinux - - workflow_ubuntu2004_codecov: &workflow_ubuntu2004_codecov + - workflow_ubuntu2204_codecov: &workflow_ubuntu2204_codecov <<: *workflow_trigger_on_tags requires: - b_ubu_codecov @@ -480,17 +480,17 @@ defaults: requires: - b_osx - - workflow_ubuntu2004_asan: &workflow_ubuntu2004_asan + - workflow_ubuntu2204_asan: &workflow_ubuntu2204_asan <<: *workflow_trigger_on_tags requires: - b_ubu_asan - - workflow_ubuntu2004_asan_clang: &workflow_ubuntu2004_asan_clang + - workflow_ubuntu2204_asan_clang: &workflow_ubuntu2204_asan_clang <<: *workflow_trigger_on_tags requires: - b_ubu_asan_clang - - workflow_ubuntu2004_ubsan_clang: &workflow_ubuntu2004_ubsan_clang + - workflow_ubuntu2204_ubsan_clang: &workflow_ubuntu2204_ubsan_clang <<: *workflow_trigger_on_tags requires: - b_ubu_ubsan_clang @@ -524,91 +524,91 @@ defaults: python2: true - job_native_test_ext_gnosis: &job_native_test_ext_gnosis - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_gnosis project: gnosis binary_type: native nodejs_version: '16.18' - job_native_test_ext_zeppelin: &job_native_test_ext_zeppelin - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_zeppelin project: zeppelin binary_type: native resource_class: large - job_native_test_ext_ens: &job_native_test_ext_ens - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_ens project: ens binary_type: native nodejs_version: '18.11' - job_native_test_ext_trident: &job_native_test_ext_trident - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_trident project: trident binary_type: native nodejs_version: '16.18' - job_native_test_ext_euler: &job_native_test_ext_euler - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_euler project: euler binary_type: native resource_class: medium - job_native_test_ext_yield_liquidator: &job_native_test_ext_yield_liquidator - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_yield_liquidator project: yield-liquidator binary_type: native - job_native_test_ext_bleeps: &job_native_test_ext_bleeps - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_bleeps project: bleeps binary_type: native resource_class: medium - job_native_test_ext_pool_together: &job_native_test_ext_pool_together - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_pool_together project: pool-together binary_type: native nodejs_version: '16.18' - job_native_test_ext_perpetual_pools: &job_native_test_ext_perpetual_pools - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_perpetual_pools project: perpetual-pools binary_type: native nodejs_version: '18.11' - job_native_test_ext_uniswap: &job_native_test_ext_uniswap - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_uniswap project: uniswap binary_type: native nodejs_version: '16.18' - job_native_test_ext_prb_math: &job_native_test_ext_prb_math - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_prb_math project: prb-math binary_type: native nodejs_version: '18.11' - job_native_test_ext_elementfi: &job_native_test_ext_elementfi - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_elementfi project: elementfi binary_type: native resource_class: medium - job_native_test_ext_brink: &job_native_test_ext_brink - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_brink project: brink binary_type: native nodejs_version: '18.11' - job_native_test_ext_chainlink: &job_native_test_ext_chainlink - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_chainlink project: chainlink binary_type: native nodejs_version: '16.18' resource_class: large # Tests run out of memory on a smaller machine - job_native_test_ext_gp2: &job_native_test_ext_gp2 - <<: *workflow_ubuntu2004_static + <<: *workflow_ubuntu2204_static name: t_native_test_ext_gp2 project: gp2 binary_type: native @@ -761,14 +761,14 @@ jobs: - gitter_notify_failure_unless_pr chk_docs_pragma_min_version: - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small steps: - checkout - run: *run_docs_pragma_min_version - gitter_notify_failure_unless_pr t_ubu_pyscripts: - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small steps: - checkout - run: @@ -789,13 +789,13 @@ jobs: b_ubu: &b_ubu # this runs 2x faster on xlarge but takes 4x more resources (compared to medium). # Enough other jobs depend on it that it's worth it though. - <<: *base_ubuntu2004_xlarge + <<: *base_ubuntu2204_xlarge <<: *steps_build # x64 ASAN build, for testing for memory related bugs b_ubu_asan: &b_ubu_asan # Runs slightly faster on large and xlarge but we only run it nightly so efficiency matters more. - <<: *base_ubuntu2004 + <<: *base_ubuntu2204 environment: CMAKE_OPTIONS: -DSANITIZE=address MAKEFLAGS: -j 3 @@ -803,7 +803,7 @@ jobs: <<: *steps_build b_ubu_clang: &b_ubu_clang - <<: *base_ubuntu2004_clang_large + <<: *base_ubuntu2204_clang_large environment: TERM: xterm CC: clang @@ -816,7 +816,7 @@ jobs: parameters: cmake_options: type: string - <<: *base_ubuntu2004_clang + <<: *base_ubuntu2204_clang environment: TERM: xterm CC: clang @@ -833,7 +833,7 @@ jobs: b_ubu_static: # On large runs 2x faster than on medium. 3x on xlarge. - <<: *base_ubuntu2004_xlarge + <<: *base_ubuntu2204_xlarge environment: TERM: xterm MAKEFLAGS: -j 10 @@ -850,7 +850,7 @@ jobs: b_ubu_codecov: # Runs ~30% faster on large but we only run it nightly so efficiency matters more. - <<: *base_ubuntu2004 + <<: *base_ubuntu2204 environment: COVERAGE: ON CMAKE_BUILD_TYPE: Debug @@ -862,7 +862,7 @@ jobs: - gitter_notify_failure_unless_pr t_ubu_codecov: - <<: *base_ubuntu2004_large + <<: *base_ubuntu2204_large environment: EVM: << pipeline.parameters.evm-version >> OPTIMIZE: 1 @@ -886,7 +886,7 @@ jobs: # Builds in C++20 mode and uses debug build in order to speed up. # Do *NOT* store any artifacts or workspace as we don't run tests on this build. b_ubu_cxx20: - <<: *base_ubuntu2004_large + <<: *base_ubuntu2204_large environment: CMAKE_BUILD_TYPE: Debug CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DUSE_CVC4=OFF @@ -1018,7 +1018,7 @@ jobs: - gitter_notify_failure_unless_pr b_docs: - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small steps: - checkout - run: *setup_prerelease_commit_hash @@ -1031,12 +1031,12 @@ jobs: - gitter_notify_failure_unless_pr t_ubu_soltest_all: &t_ubu_soltest_all - <<: *base_ubuntu2004_large + <<: *base_ubuntu2204_large parallelism: 50 <<: *steps_soltest_all t_ubu_lsp: &t_ubu_lsp - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small <<: *steps_test_lsp t_archlinux_soltest: &t_archlinux_soltest @@ -1059,7 +1059,7 @@ jobs: <<: *steps_soltest t_ubu_clang_soltest: &t_ubu_clang_soltest - <<: *base_ubuntu2004_clang + <<: *base_ubuntu2204_clang parallelism: 20 environment: EVM: << pipeline.parameters.evm-version >> @@ -1075,14 +1075,14 @@ jobs: <<: *t_ubu_soltest_all t_ubu_cli: &t_ubu_cli - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small <<: *steps_cmdline_tests t_ubu_force_release_cli: &t_ubu_force_release_cli <<: *t_ubu_cli t_ubu_locale: - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small steps: - checkout - attach_workspace: @@ -1097,14 +1097,14 @@ jobs: t_ubu_asan_cli: # Runs slightly faster on medium but we only run it nightly so efficiency matters more. - <<: *base_ubuntu2004 + <<: *base_ubuntu2204 environment: TERM: xterm ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 <<: *steps_cmdline_tests t_ubu_asan_soltest: - <<: *base_ubuntu2004 + <<: *base_ubuntu2204 parallelism: 20 environment: EVM: << pipeline.parameters.evm-version >> @@ -1114,7 +1114,7 @@ jobs: <<: *steps_soltest t_ubu_asan_clang_soltest: - <<: *base_ubuntu2004_clang + <<: *base_ubuntu2204_clang parallelism: 20 environment: EVM: << pipeline.parameters.evm-version >> @@ -1124,7 +1124,7 @@ jobs: <<: *steps_soltest t_ubu_ubsan_clang_soltest: - <<: *base_ubuntu2004_clang + <<: *base_ubuntu2204_clang parallelism: 20 environment: EVM: << pipeline.parameters.evm-version >> @@ -1132,12 +1132,12 @@ jobs: <<: *steps_soltest t_ubu_ubsan_clang_cli: - <<: *base_ubuntu2004_clang + <<: *base_ubuntu2204_clang <<: *steps_cmdline_tests t_ems_solcjs: # Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small). - <<: *base_ubuntu2004 + <<: *base_ubuntu2204 steps: - checkout - attach_workspace: @@ -1391,7 +1391,7 @@ jobs: - gitter_notify_failure_unless_pr b_bytecode_ubu: - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small environment: TERM: xterm MAKEFLAGS: -j 2 @@ -1461,7 +1461,7 @@ jobs: - gitter_notify_failure_unless_pr t_bytecode_compare: - <<: *base_ubuntu2004_small + <<: *base_ubuntu2204_small environment: REPORT_FILES: | bytecode-report-emscripten.txt @@ -1498,7 +1498,7 @@ jobs: - gitter_notify_failure_unless_pr c_release_binaries: - <<: *base_ubuntu2004 + <<: *base_ubuntu2204 steps: - checkout - attach_workspace: @@ -1575,17 +1575,17 @@ workflows: # Ubuntu build and tests - b_ubu: *workflow_trigger_on_tags - - t_ubu_cli: *workflow_ubuntu2004 - - t_ubu_locale: *workflow_ubuntu2004 - - t_ubu_soltest_all: *workflow_ubuntu2004 + - t_ubu_cli: *workflow_ubuntu2204 + - t_ubu_locale: *workflow_ubuntu2204 + - t_ubu_soltest_all: *workflow_ubuntu2204 - b_ubu_clang: *workflow_trigger_on_tags - - t_ubu_clang_soltest: *workflow_ubuntu2004_clang - - t_ubu_lsp: *workflow_ubuntu2004 + - t_ubu_clang_soltest: *workflow_ubuntu2204_clang + - t_ubu_lsp: *workflow_ubuntu2204 # Ubuntu fake release build and tests - b_ubu_force_release: *workflow_trigger_on_tags - - t_ubu_force_release_cli: *workflow_ubuntu2004_force_release - - t_ubu_force_release_soltest_all: *workflow_ubuntu2004_force_release + - t_ubu_force_release_cli: *workflow_ubuntu2204_force_release + - t_ubu_force_release_soltest_all: *workflow_ubuntu2204_force_release # Emscripten build and tests that take 15 minutes or less - b_ems: *workflow_trigger_on_tags @@ -1685,19 +1685,19 @@ workflows: # Code Coverage enabled build and tests - b_ubu_codecov: *workflow_trigger_on_tags - - t_ubu_codecov: *workflow_ubuntu2004_codecov + - t_ubu_codecov: *workflow_ubuntu2204_codecov # ASan build and tests - b_ubu_asan: *workflow_trigger_on_tags - b_ubu_san_clang: *job_b_ubu_asan_clang - - t_ubu_asan_soltest: *workflow_ubuntu2004_asan - - t_ubu_asan_clang_soltest: *workflow_ubuntu2004_asan_clang - - t_ubu_asan_cli: *workflow_ubuntu2004_asan + - t_ubu_asan_soltest: *workflow_ubuntu2204_asan + - t_ubu_asan_clang_soltest: *workflow_ubuntu2204_asan_clang + - t_ubu_asan_cli: *workflow_ubuntu2204_asan # UBSan build and tests - b_ubu_san_clang: *job_b_ubu_ubsan_clang - - t_ubu_ubsan_clang_soltest: *workflow_ubuntu2004_ubsan_clang - - t_ubu_ubsan_clang_cli: *workflow_ubuntu2004_ubsan_clang + - t_ubu_ubsan_clang_soltest: *workflow_ubuntu2204_ubsan_clang + - t_ubu_ubsan_clang_cli: *workflow_ubuntu2204_ubsan_clang # Emscripten build and tests that take more than 15 minutes to execute - b_ems: *workflow_trigger_on_tags diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index b117c27728..f3c168e651 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -267,7 +267,7 @@ template< typename MapType, typename KeyType, typename ValueType = std::decay_t().find(std::declval())->second)> const&, - typename AllowCopyType = std::conditional_t || std::is_pointer_v, detail::allow_copy, void*> + typename AllowCopyType = std::conditional_t<(std::is_trivial_v && std::is_standard_layout_v) || std::is_pointer_v, detail::allow_copy, void*> > decltype(auto) valueOrDefault( MapType&& _map, diff --git a/libsolutil/vector_ref.h b/libsolutil/vector_ref.h index 46901a46e5..56942b9abb 100644 --- a/libsolutil/vector_ref.h +++ b/libsolutil/vector_ref.h @@ -28,7 +28,7 @@ class vector_ref using iterator = T*; using const_iterator = T const*; - static_assert(std::is_pod::value, "vector_ref can only be used with PODs due to its low-level treatment of data."); + static_assert(std::is_standard_layout_v && std::is_trivial_v, "vector_ref can only be used with PODs due to its low-level treatment of data."); vector_ref(): m_data(nullptr), m_count(0) {} /// Creates a new vector_ref to point to @a _count elements starting at @a _data. From f2e053e0c8a801f2d3404af9b83bde57b4127c7d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 11 Jan 2023 21:46:26 +0100 Subject: [PATCH 0021/1140] disable cxx20 job --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 28253f943a..2783532d8e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1558,7 +1558,8 @@ workflows: # build-only - b_docs: *workflow_trigger_on_tags - - b_ubu_cxx20: *workflow_trigger_on_tags + # DISABLED FOR 0.8.18 - b_ubu_cxx20: *workflow_trigger_on_tags + # Issue: https://github.com/ethereum/solidity/issues/13868 - b_ubu_ossfuzz: *workflow_trigger_on_tags # OS/X build and tests From a01936d5fc7d399caa738d00172ed21320c24404 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 11 Jan 2023 13:51:32 +0100 Subject: [PATCH 0022/1140] Bumping ubuntu images to use boost 1_74_0 --- .../buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz | 10 +++++----- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 | 4 ++-- .../docker/buildpack-deps/Dockerfile.ubuntu2004.clang | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz index 0225f4b2da..469424ab8b 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="21" +LABEL version="22" ARG DEBIAN_FRONTEND=noninteractive @@ -46,18 +46,18 @@ FROM base AS libraries # Boost RUN set -ex; \ cd /usr/src; \ - wget -q 'https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.bz2' -O boost.tar.bz2; \ - test "$(sha256sum boost.tar.bz2)" = "4eb3b8d442b426dc35346235c8733b5ae35ba431690e38c6a8263dce9fcbb402 boost.tar.bz2"; \ + wget -q 'https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2' -O boost.tar.bz2; \ + test "$(sha256sum boost.tar.bz2)" = "83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1 boost.tar.bz2" && \ tar -xf boost.tar.bz2; \ rm boost.tar.bz2; \ - cd boost_1_73_0; \ + cd boost_1_74_0; \ CXXFLAGS="-stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers; \ ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" \ link=static variant=release runtime-link=static \ system filesystem unit_test_framework program_options \ install -j $(($(nproc)/2)); \ - rm -rf /usr/src/boost_1_73_0 + rm -rf /usr/src/boost_1_74_0 # Z3 RUN set -ex; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 242f859e7c..e10c20f196 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -21,8 +21,8 @@ # # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ -FROM buildpack-deps:focal AS base -LABEL version="16" +FROM buildpack-deps:jammy AS base +LABEL version="17" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang index 7b2ae75154..eb257ae48b 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang @@ -21,8 +21,8 @@ # # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ -FROM buildpack-deps:focal AS base -LABEL version="16" +FROM buildpack-deps:jammy AS base +LABEL version="17" ARG DEBIAN_FRONTEND=noninteractive From 904afd8963a309cbfe92b4d676a1714e6e3e7555 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 11 Jan 2023 13:53:05 +0100 Subject: [PATCH 0023/1140] Rename ubuntu dockerfiles --- .github/workflows/buildpack-deps.yml | 6 +++--- .../{Dockerfile.ubuntu2004 => Dockerfile.ubuntu2204} | 0 ...kerfile.ubuntu2004.clang => Dockerfile.ubuntu2204.clang} | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename scripts/docker/buildpack-deps/{Dockerfile.ubuntu2004 => Dockerfile.ubuntu2204} (100%) rename scripts/docker/buildpack-deps/{Dockerfile.ubuntu2004.clang => Dockerfile.ubuntu2204.clang} (100%) diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index e2da2cdea8..afdf03c8f3 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -6,8 +6,8 @@ on: paths: - 'scripts/docker/buildpack-deps/Dockerfile.emscripten' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz' - - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang' - - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204' jobs: buildpack-deps: @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu1604.clang.ossfuzz, ubuntu2004.clang, ubuntu2004] + image_variant: [emscripten, ubuntu1604.clang.ossfuzz, ubuntu2204.clang, ubuntu2204] steps: - uses: actions/checkout@v2 diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 similarity index 100% rename from scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 rename to scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang similarity index 100% rename from scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang rename to scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang From 0178024903448039364e6db34f1ae8e0f2a61859 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 11 Jan 2023 13:55:10 +0100 Subject: [PATCH 0024/1140] Reset label version for new image --- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index e10c20f196..2e7fe79053 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="17" +LABEL version="1" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index eb257ae48b..ea2220ed3c 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="17" +LABEL version="1" ARG DEBIAN_FRONTEND=noninteractive From 43032433fdf0b8bcbc588abc79ea51311786ec69 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 11 Jan 2023 14:08:39 +0100 Subject: [PATCH 0025/1140] Rename buildpack-deps ci scripts --- ...buntu2004.clang.sh => buildpack-deps_test_ubuntu2204.clang.sh} | 0 ...-deps_test_ubuntu2004.sh => buildpack-deps_test_ubuntu2204.sh} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename scripts/ci/{buildpack-deps_test_ubuntu2004.clang.sh => buildpack-deps_test_ubuntu2204.clang.sh} (100%) rename scripts/ci/{buildpack-deps_test_ubuntu2004.sh => buildpack-deps_test_ubuntu2204.sh} (100%) diff --git a/scripts/ci/buildpack-deps_test_ubuntu2004.clang.sh b/scripts/ci/buildpack-deps_test_ubuntu2204.clang.sh similarity index 100% rename from scripts/ci/buildpack-deps_test_ubuntu2004.clang.sh rename to scripts/ci/buildpack-deps_test_ubuntu2204.clang.sh diff --git a/scripts/ci/buildpack-deps_test_ubuntu2004.sh b/scripts/ci/buildpack-deps_test_ubuntu2204.sh similarity index 100% rename from scripts/ci/buildpack-deps_test_ubuntu2004.sh rename to scripts/ci/buildpack-deps_test_ubuntu2204.sh From b07ccd56e18783fc0b2ff0d63a583c17e6e33f2b Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 11 Jan 2023 14:27:02 +0100 Subject: [PATCH 0026/1140] Add CLN library --- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 2e7fe79053..74e61d0ad6 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -38,7 +38,7 @@ RUN set -ex; \ libboost-filesystem-dev libboost-test-dev libboost-system-dev \ libboost-program-options-dev \ libcvc4-dev libz3-static-dev z3-static jq \ - ; \ + libcln-dev; \ apt-get install -qy python3-pip python3-sphinx; \ pip3 install codecov; \ rm -rf /var/lib/apt/lists/* diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index ea2220ed3c..21bd3b3483 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -39,7 +39,7 @@ RUN set -ex; \ libboost-program-options-dev \ clang \ libz3-static-dev z3-static jq \ - ; \ + libcln-dev; \ rm -rf /var/lib/apt/lists/* FROM base AS libraries From b1f728efcdfe486ff3365b44116c059276d2f191 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Thu, 12 Jan 2023 09:14:00 +0100 Subject: [PATCH 0027/1140] Remove `hera` build --- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 12 ------------ .../buildpack-deps/Dockerfile.ubuntu2204.clang | 12 ------------ 2 files changed, 24 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 74e61d0ad6..85cd85ecf2 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -57,18 +57,6 @@ RUN set -ex; \ ninja install/strip; \ rm -rf /usr/src/evmone -# HERA -RUN set -ex; \ - cd /usr/src; \ - git clone --branch="v0.6.0" --depth 1 --recurse-submodules https://github.com/ewasm/hera.git; \ - cd hera; \ - mkdir build; \ - cd build; \ - cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX="/usr" ..; \ - ninja; \ - ninja install/strip; \ - rm -rf /usr/src/hera - FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index 21bd3b3483..d7f1c95f1e 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -59,18 +59,6 @@ RUN set -ex; \ ninja install/strip; \ rm -rf /usr/src/evmone -# HERA -RUN set -ex; \ - cd /usr/src; \ - git clone --branch="v0.6.0" --depth 1 --recurse-submodules https://github.com/ewasm/hera.git; \ - cd hera; \ - mkdir build; \ - cd build; \ - cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX="/usr" ..; \ - ninja; \ - ninja install/strip; \ - rm -rf /usr/src/hera - FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin From 0ca97ba8b876388167b188f48ebe672e0a80288c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 10 Jan 2023 13:16:59 +0100 Subject: [PATCH 0028/1140] Add snark verifier benchmark test --- test/benchmarks/run.sh | 2 +- test/benchmarks/verifier.sol | 208 +++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 test/benchmarks/verifier.sol diff --git a/test/benchmarks/run.sh b/test/benchmarks/run.sh index c4f35ba477..ef1c146f00 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/run.sh @@ -40,7 +40,7 @@ trap cleanup SIGINT SIGTERM solc="${SOLIDITY_BUILD_DIR}/solc/solc" benchmarks_dir="${REPO_ROOT}/test/benchmarks" -benchmarks=("chains.sol" "OptimizorClub.sol") +benchmarks=("chains.sol" "OptimizorClub.sol" "verifier.sol") time_bin_path=$(type -P time) for input_file in "${benchmarks[@]}" diff --git a/test/benchmarks/verifier.sol b/test/benchmarks/verifier.sol new file mode 100644 index 0000000000..dcfc97abf7 --- /dev/null +++ b/test/benchmarks/verifier.sol @@ -0,0 +1,208 @@ +// This file is MIT Licensed. +// +// Copyright 2017 Christian Reitwiessner +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +pragma solidity ^0.8.0; +library Pairing { + struct G1Point { + uint X; + uint Y; + } + // Encoding of field elements is: X[0] * z + X[1] + struct G2Point { + uint[2] X; + uint[2] Y; + } + /// @return the generator of G1 + function P1() pure internal returns (G1Point memory) { + return G1Point(1, 2); + } + /// @return the generator of G2 + function P2() pure internal returns (G2Point memory) { + return G2Point( + [10857046999023057135944570762232829481370756359578518086990519993285655852781, + 11559732032986387107991004021392285783925812861821192530917403151452391805634], + [8495653923123431417604973247489272438418190587263600148770280649306958101930, + 4082367875863433681332203403145435568316851327593401208105741076214120093531] + ); + } + /// @return the negation of p, i.e. p.addition(p.negate()) should be zero. + function negate(G1Point memory p) pure internal returns (G1Point memory) { + // The prime q in the base field F_q for G1 + uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + if (p.X == 0 && p.Y == 0) + return G1Point(0, 0); + return G1Point(p.X, q - (p.Y % q)); + } + /// @return r the sum of two points of G1 + function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { + uint[4] memory input; + input[0] = p1.X; + input[1] = p1.Y; + input[2] = p2.X; + input[3] = p2.Y; + bool success; + assembly { + success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + } + + + /// @return r the product of a point on G1 and a scalar, i.e. + /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. + function scalar_mul(G1Point memory p, uint s) internal view returns (G1Point memory r) { + uint[3] memory input; + input[0] = p.X; + input[1] = p.Y; + input[2] = s; + bool success; + assembly { + success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require (success); + } + /// @return the result of computing the pairing check + /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 + /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should + /// return true. + function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) { + require(p1.length == p2.length); + uint elements = p1.length; + uint inputSize = elements * 6; + uint[] memory input = new uint[](inputSize); + for (uint i = 0; i < elements; i++) + { + input[i * 6 + 0] = p1[i].X; + input[i * 6 + 1] = p1[i].Y; + input[i * 6 + 2] = p2[i].X[1]; + input[i * 6 + 3] = p2[i].X[0]; + input[i * 6 + 4] = p2[i].Y[1]; + input[i * 6 + 5] = p2[i].Y[0]; + } + uint[1] memory out; + bool success; + assembly { + success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + return out[0] != 0; + } + /// Convenience method for a pairing check for two pairs. + function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal view returns (bool) { + G1Point[] memory p1 = new G1Point[](2); + G2Point[] memory p2 = new G2Point[](2); + p1[0] = a1; + p1[1] = b1; + p2[0] = a2; + p2[1] = b2; + return pairing(p1, p2); + } + /// Convenience method for a pairing check for three pairs. + function pairingProd3( + G1Point memory a1, G2Point memory a2, + G1Point memory b1, G2Point memory b2, + G1Point memory c1, G2Point memory c2 + ) internal view returns (bool) { + G1Point[] memory p1 = new G1Point[](3); + G2Point[] memory p2 = new G2Point[](3); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + return pairing(p1, p2); + } + /// Convenience method for a pairing check for four pairs. + function pairingProd4( + G1Point memory a1, G2Point memory a2, + G1Point memory b1, G2Point memory b2, + G1Point memory c1, G2Point memory c2, + G1Point memory d1, G2Point memory d2 + ) internal view returns (bool) { + G1Point[] memory p1 = new G1Point[](4); + G2Point[] memory p2 = new G2Point[](4); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p1[3] = d1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + p2[3] = d2; + return pairing(p1, p2); + } +} + +contract Verifier { + using Pairing for *; + struct VerifyingKey { + Pairing.G1Point alpha; + Pairing.G2Point beta; + Pairing.G2Point gamma; + Pairing.G2Point delta; + Pairing.G1Point[] gamma_abc; + } + struct Proof { + Pairing.G1Point a; + Pairing.G2Point b; + Pairing.G1Point c; + } + function verifyingKey() pure internal returns (VerifyingKey memory vk) { + vk.alpha = Pairing.G1Point(uint256(0x1e19a8a58ad52243374aeded373b7e89656ea339b9fa8ace98dd5fb221885ea2), uint256(0x2e66a9a67f1a9060a51da039c91c3402d1f46b71bbf10c7348ac4f13c3906736)); + vk.beta = Pairing.G2Point([uint256(0x1ca3e556290187c64a1057061f419a078dc71353f6af1066c03d7e1448bbc119), uint256(0x2bbc1b80e59743b489ec811b4ebf30a1ff540c2c37ced63d360b94f92f0a41fb)], [uint256(0x07eceb98d2fb10fa7363b45f51aa3d3ef3d511b482790645039a2562e2070f30), uint256(0x1c3e076d2aaf914abd6a49b72c4205669d3d1cbe4a4bf97b9ee49ac0fbbdbda9)]); + vk.gamma = Pairing.G2Point([uint256(0x222c0019521d3e52881431be17cacaf8a7379398dd0833f60a2ac45f1c3fcd42), uint256(0x1018dbb94cd920bd55af4e2b12a9f740c6b38748a163b5dbd37c5ef6cf74708f)], [uint256(0x18bf34dc86b549a92f316f7a32070a3ce45a0f38fa45dda1162c4b6498baf286), uint256(0x12848d5a670b6102d5bd45d2b8250d50361001ea335ff6a1405a52504c22b8ac)]); + vk.delta = Pairing.G2Point([uint256(0x13b8e16c40a6a299ea42107a97f881f9fa89986dcd5234ecb6919caf756ac1cb), uint256(0x25b64e4978690cd7cb531dbab0119148c96f5fc0c984c0cafb290bb75f033a09)], [uint256(0x1758eaa970929deff5e96e5852d21790c32591dbb13bc63e3df046f0271479a4), uint256(0x14d0b4222ad1710c6330e4bd8ad8f0d7b8f4cff0a37793d53001800e49f41192)]); + vk.gamma_abc = new Pairing.G1Point[](9); + vk.gamma_abc[0] = Pairing.G1Point(uint256(0x0925dc800d3a577859439a049f8ed0ae7a37dcd36652de478d662c08907a7626), uint256(0x1f7f76e299220ebf3da17bb415d25e6574e142391972dbd1513cf81341975cb5)); + vk.gamma_abc[1] = Pairing.G1Point(uint256(0x0e67dddfd91adad72376c56cbd98d5cfa4df5217d6115ff26ec741d0154f0bd8), uint256(0x0b97b2ddfdf4c31916d98e384bee3b24bfa0fc59a21ab489153f4dcd1a9a48ca)); + vk.gamma_abc[2] = Pairing.G1Point(uint256(0x1416b354665883cbbc5f5541012d1f8dd87ebb4415b3ee431be0804fff290bbf), uint256(0x1a284dd2eff43e6cb5aaea43dd9bee022ef0c91d90d0803cf5f7e4677e94a271)); + vk.gamma_abc[3] = Pairing.G1Point(uint256(0x2526852e7f009b4afa1fe0e1d30334c6e516fac223866b81a830b472164bdfe7), uint256(0x28adf6fbe54ba40afa91555c18477ad3a2f0a460f68d55a15b4e0c264b9c11c2)); + vk.gamma_abc[4] = Pairing.G1Point(uint256(0x22feae4a12bfb751638cd76b2373e84884ba4adef575ea14ed50c5954d31d410), uint256(0x108c3da0ffd7eda1fe7789e41693146beb979bd1644b19bbd517742ca3841348)); + vk.gamma_abc[5] = Pairing.G1Point(uint256(0x081477a5c52f41533cf6ca4f778ab922d59ba44b5a5e3fbdbf34ed8dc1a47a8d), uint256(0x0f2624780bd75b9f6c47f7bee582d02f1f983529b8aa9493ca848e38f2ec8447)); + vk.gamma_abc[6] = Pairing.G1Point(uint256(0x0603e7413c605d1e9b9352a62f0208e2bbd247d3cf3b3721f72c3a9407d679b9), uint256(0x0ce2d2dca8ae14ac4fd2f3fd89e602cdb45de815cf3ba183a25a47d877d9f6f5)); + vk.gamma_abc[7] = Pairing.G1Point(uint256(0x05bbe6b58285021fb843123971f8e2cfdd207b02c0aef5923ffe7ac841ee0cc9), uint256(0x2da1d3c2049546a7b46aaf89a8a7de493470087ce9af8ba37673f5ee8c35eb1b)); + vk.gamma_abc[8] = Pairing.G1Point(uint256(0x2c721270df9ba8884d309140f3a4b150a8e53a6c9d09bd8fc7c9aa3c4901aa8d), uint256(0x0de2cb1684759e693e855711fa1c381ae737e463447c3817df507a02064b470f)); + } + function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { + uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + VerifyingKey memory vk = verifyingKey(); + require(input.length + 1 == vk.gamma_abc.length); + // Compute the linear combination vk_x + Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); + for (uint i = 0; i < input.length; i++) { + require(input[i] < snark_scalar_field); + vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.gamma_abc[i + 1], input[i])); + } + vk_x = Pairing.addition(vk_x, vk.gamma_abc[0]); + if(!Pairing.pairingProd4( + proof.a, proof.b, + Pairing.negate(vk_x), vk.gamma, + Pairing.negate(proof.c), vk.delta, + Pairing.negate(vk.alpha), vk.beta)) return 1; + return 0; + } + function verifyTx( + Proof memory proof, uint[8] memory input + ) public view returns (bool r) { + uint[] memory inputValues = new uint[](8); + + for(uint i = 0; i < input.length; i++){ + inputValues[i] = input[i]; + } + if (verify(inputValues, proof) == 0) { + return true; + } else { + return false; + } + } +} From 82806c4236af8aa7fb9ee1a270bc9b2fcf887485 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 16 Jan 2023 12:54:02 -0300 Subject: [PATCH 0029/1140] Change filename in sed command --- test/externalTests/gnosis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index a6ded27e16..f33e723b6d 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -72,7 +72,7 @@ function gnosis_safe_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). - sed -i "s|\(it\)\(('should not allow to call setup on singleton'\)|\1.skip\2|g" test/core/GnosisSafe.Setup.spec.ts + sed -i "s|\(it\)\(('should not allow to call setup on singleton'\)|\1.skip\2|g" test/core/Safe.Setup.spec.ts # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i 's|\(it\)\(("changes the expected storage slot without touching the most important ones"\)|\1.skip\2|g' test/libraries/SignMessageLib.spec.ts sed -i "s|\(it\)\(('can be used only via DELEGATECALL opcode'\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts From 83774c28bfe300c73bfc54b535c0f5e893e069c2 Mon Sep 17 00:00:00 2001 From: Big-Aaron <37289216+Big-Aaron@users.noreply.github.com> Date: Tue, 17 Jan 2023 11:30:30 +0800 Subject: [PATCH 0030/1140] Update ir-breaking-changes.rst Fix errors in the doc --- docs/ir-breaking-changes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ir-breaking-changes.rst b/docs/ir-breaking-changes.rst index 7e4efce688..2d972baa79 100644 --- a/docs/ir-breaking-changes.rst +++ b/docs/ir-breaking-changes.rst @@ -122,8 +122,8 @@ hiding new and different behavior in existing code. modifier mod() { _; _; } } - If you execute ``f(0)`` in the old code generator, it will return ``2``, while - it will return ``1`` when using the new code generator. + If you execute ``f(0)`` in the old code generator, it will return ``1``, while + it will return ``0`` when using the new code generator. .. code-block:: solidity From 83c1f620263433418383e88e0b67fc167ca5a3c0 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 17 Jan 2023 11:52:45 +0100 Subject: [PATCH 0031/1140] Source location for named mapping keys --- libsolidity/ast/AST.h | 12 ++- libsolidity/ast/ASTJsonExporter.cpp | 2 + libsolidity/ast/ASTJsonImporter.cpp | 18 +++- libsolidity/ast/ASTJsonImporter.h | 4 + libsolidity/parsing/Parser.cpp | 16 ++-- test/libsolidity/ASTJSON/address_payable.json | 2 + .../ASTJSON/address_payable_parseOnly.json | 2 + test/libsolidity/ASTJSON/mappings.json | 93 ++++++++++++++++--- test/libsolidity/ASTJSON/mappings.sol | 1 + .../ASTJSON/mappings_parseOnly.json | 54 ++++++++++- .../ASTJSON/userDefinedValueType.json | 2 + .../userDefinedValueType_parseOnly.json | 2 + 12 files changed, 177 insertions(+), 31 deletions(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 3ba28a4390..06575beece 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1428,28 +1428,36 @@ class Mapping: public TypeName SourceLocation const& _location, ASTPointer _keyType, ASTPointer _keyName, + SourceLocation _keyNameLocation, ASTPointer _valueType, - ASTPointer _valueName + ASTPointer _valueName, + SourceLocation _valueNameLocation ): TypeName(_id, _location), m_keyType(std::move(_keyType)), m_keyName(std::move(_keyName)), + m_keyNameLocation(std::move(_keyNameLocation)), m_valueType(std::move(_valueType)), - m_valueName(std::move(_valueName)) + m_valueName(std::move(_valueName)), + m_valueNameLocation(std::move(_valueNameLocation)) {} void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; TypeName const& keyType() const { return *m_keyType; } ASTString keyName() const { return *m_keyName; } + SourceLocation keyNameLocation() const { return m_keyNameLocation; } TypeName const& valueType() const { return *m_valueType; } ASTString valueName() const { return *m_valueName; } + SourceLocation valueNameLocation() const { return m_valueNameLocation; } private: ASTPointer m_keyType; ASTPointer m_keyName; + SourceLocation m_keyNameLocation; ASTPointer m_valueType; ASTPointer m_valueName; + SourceLocation m_valueNameLocation; }; /** diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 7ae528fcda..8b46684bc4 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -599,8 +599,10 @@ bool ASTJsonExporter::visit(Mapping const& _node) setJsonNode(_node, "Mapping", { make_pair("keyType", toJson(_node.keyType())), make_pair("keyName", _node.keyName()), + make_pair("keyNameLocation", sourceLocationToString(_node.keyNameLocation())), make_pair("valueType", toJson(_node.valueType())), make_pair("valueName", _node.valueName()), + make_pair("valueNameLocation", sourceLocationToString(_node.valueNameLocation())), make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }); return false; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 22b53aa474..0797049468 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -116,6 +116,20 @@ SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _nod return solidity::langutil::parseSourceLocation(_node["nameLocation"].asString(), m_sourceNames); } +SourceLocation ASTJsonImporter::createKeyNameSourceLocation(Json::Value const& _node) +{ + astAssert(member(_node, "keyNameLocation").isString(), "'keyNameLocation' must be a string"); + + return solidity::langutil::parseSourceLocation(_node["keyNameLocation"].asString(), m_sourceNames); +} + +SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json::Value const& _node) +{ + astAssert(member(_node, "valueNameLocation").isString(), "'valueNameLocation' must be a string"); + + return solidity::langutil::parseSourceLocation(_node["valueNameLocation"].asString(), m_sourceNames); +} + template ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node) { @@ -649,8 +663,10 @@ ASTPointer ASTJsonImporter::createMapping(Json::Value const& _node) _node, convertJsonToASTNode(member(_node, "keyType")), memberAsASTString(_node, "keyName"), + createKeyNameSourceLocation(_node), convertJsonToASTNode(member(_node, "valueType")), - memberAsASTString(_node, "valueName") + memberAsASTString(_node, "valueName"), + createValueNameSourceLocation(_node) ); } diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index 1216d29b15..b9a4d49505 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -69,6 +69,10 @@ class ASTJsonImporter ASTPointer convertJsonToASTNode(Json::Value const& _node); langutil::SourceLocation createNameSourceLocation(Json::Value const& _node); + /// @returns source location of a mapping key name + langutil::SourceLocation createKeyNameSourceLocation(Json::Value const& _node); + /// @returns source location of a mapping value name + langutil::SourceLocation createValueNameSourceLocation(Json::Value const& _node); /// \defgroup nodeCreators JSON to AST-Nodes ///@{ diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index e81f0713fd..fee21e5184 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1187,21 +1187,19 @@ ASTPointer Parser::parseMapping() } else fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type"); - ASTPointer keyName; + ASTPointer keyName = make_shared(""); + SourceLocation keyNameLocation{}; if (m_scanner->currentToken() == Token::Identifier) - keyName = getLiteralAndAdvance(); - else - keyName = make_shared(""); + tie(keyName, keyNameLocation) = expectIdentifierWithLocation(); expectToken(Token::DoubleArrow); ASTPointer valueType = parseTypeName(); - ASTPointer valueName; + ASTPointer valueName = make_shared(""); + SourceLocation valueNameLocation{}; if (m_scanner->currentToken() == Token::Identifier) - valueName = getLiteralAndAdvance(); - else - valueName = make_shared(""); + tie(valueName, valueNameLocation) = expectIdentifierWithLocation(); nodeFactory.markEndPosition(); expectToken(Token::RParen); - return nodeFactory.createNode(keyType, keyName, valueType, valueName); + return nodeFactory.createNode(keyType, keyName, keyNameLocation, valueType, valueName, valueNameLocation); } ASTPointer Parser::parseParameterList( diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index bf56f067fc..83ba2c6d7c 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -49,6 +49,7 @@ { "id": 3, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 1, @@ -69,6 +70,7 @@ "typeString": "mapping(address => address payable)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 2, diff --git a/test/libsolidity/ASTJSON/address_payable_parseOnly.json b/test/libsolidity/ASTJSON/address_payable_parseOnly.json index 6b72b6fb3c..9d095dc686 100644 --- a/test/libsolidity/ASTJSON/address_payable_parseOnly.json +++ b/test/libsolidity/ASTJSON/address_payable_parseOnly.json @@ -30,6 +30,7 @@ { "id": 3, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 1, @@ -42,6 +43,7 @@ "src": "17:35:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 2, diff --git a/test/libsolidity/ASTJSON/mappings.json b/test/libsolidity/ASTJSON/mappings.json index f63f6689fd..0bf816eb49 100644 --- a/test/libsolidity/ASTJSON/mappings.json +++ b/test/libsolidity/ASTJSON/mappings.json @@ -4,10 +4,10 @@ { "C": [ - 19 + 23 ] }, - "id": 20, + "id": 24, "nodeType": "SourceUnit", "nodes": [ @@ -18,10 +18,10 @@ "contractDependencies": [], "contractKind": "contract", "fullyImplemented": true, - "id": 19, + "id": 23, "linearizedBaseContracts": [ - 19 + 23 ], "name": "C", "nameLocation": "9:1:1", @@ -67,19 +67,20 @@ "name": "a", "nameLocation": "59:1:1", "nodeType": "VariableDeclaration", - "scope": 19, + "scope": 23, "src": "40:20:1", "stateVariable": true, "storageLocation": "default", "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_contract$_C_$19_$_t_bool_$", + "typeIdentifier": "t_mapping$_t_contract$_C_$23_$_t_bool_$", "typeString": "mapping(contract C => bool)" }, "typeName": { "id": 8, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 6, @@ -93,14 +94,14 @@ "48:1:1" ], "nodeType": "IdentifierPath", - "referencedDeclaration": 19, + "referencedDeclaration": 23, "src": "48:1:1" }, - "referencedDeclaration": 19, + "referencedDeclaration": 23, "src": "48:1:1", "typeDescriptions": { - "typeIdentifier": "t_contract$_C_$19", + "typeIdentifier": "t_contract$_C_$23", "typeString": "contract C" } }, @@ -108,10 +109,11 @@ "src": "40:18:1", "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_contract$_C_$19_$_t_bool_$", + "typeIdentifier": "t_mapping$_t_contract$_C_$23_$_t_bool_$", "typeString": "mapping(contract C => bool)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 7, @@ -134,7 +136,7 @@ "name": "b", "nameLocation": "91:1:1", "nodeType": "VariableDeclaration", - "scope": 19, + "scope": 23, "src": "66:26:1", "stateVariable": true, "storageLocation": "default", @@ -147,6 +149,7 @@ { "id": 12, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 10, @@ -167,6 +170,7 @@ "typeString": "mapping(address => bool)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 11, @@ -189,7 +193,7 @@ "name": "c", "nameLocation": "117:1:1", "nodeType": "VariableDeclaration", - "scope": 19, + "scope": 23, "src": "98:20:1", "stateVariable": true, "storageLocation": "default", @@ -202,6 +206,7 @@ { "id": 17, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 15, @@ -234,6 +239,7 @@ "typeString": "mapping(enum C.E => bool)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 16, @@ -248,12 +254,69 @@ } }, "visibility": "internal" + }, + { + "constant": false, + "id": 22, + "mutability": "mutable", + "name": "d", + "nameLocation": "169:1:1", + "nodeType": "VariableDeclaration", + "scope": 23, + "src": "124:46:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_mapping$_t_address_$_t_uint256_$", + "typeString": "mapping(address => uint256)" + }, + "typeName": + { + "id": 21, + "keyName": "keyAddress", + "keyNameLocation": "140:10:1", + "keyType": + { + "id": 19, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "132:7:1", + "typeDescriptions": + { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Mapping", + "src": "124:44:1", + "typeDescriptions": + { + "typeIdentifier": "t_mapping$_t_address_$_t_uint256_$", + "typeString": "mapping(address => uint256)" + }, + "valueName": "value", + "valueNameLocation": "162:5:1", + "valueType": + { + "id": 20, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "154:7:1", + "typeDescriptions": + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + }, + "visibility": "internal" } ], - "scope": 20, - "src": "0:121:1", + "scope": 24, + "src": "0:173:1", "usedErrors": [] } ], - "src": "0:122:1" + "src": "0:174:1" } diff --git a/test/libsolidity/ASTJSON/mappings.sol b/test/libsolidity/ASTJSON/mappings.sol index 794396a7d2..05912d21f7 100644 --- a/test/libsolidity/ASTJSON/mappings.sol +++ b/test/libsolidity/ASTJSON/mappings.sol @@ -3,6 +3,7 @@ contract C { mapping(C => bool) a; mapping(address => bool) b; mapping(E => bool) c; + mapping(address keyAddress => uint256 value) d; } // ---- diff --git a/test/libsolidity/ASTJSON/mappings_parseOnly.json b/test/libsolidity/ASTJSON/mappings_parseOnly.json index 2471148492..9690f7c9ef 100644 --- a/test/libsolidity/ASTJSON/mappings_parseOnly.json +++ b/test/libsolidity/ASTJSON/mappings_parseOnly.json @@ -1,6 +1,6 @@ { "absolutePath": "a", - "id": 20, + "id": 24, "nodeType": "SourceUnit", "nodes": [ @@ -9,7 +9,7 @@ "baseContracts": [], "contractDependencies": [], "contractKind": "contract", - "id": 19, + "id": 23, "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", @@ -61,6 +61,7 @@ { "id": 8, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 6, @@ -83,6 +84,7 @@ "src": "40:18:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 7, @@ -109,6 +111,7 @@ { "id": 12, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 10, @@ -121,6 +124,7 @@ "src": "66:24:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 11, @@ -147,6 +151,7 @@ { "id": 17, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 15, @@ -169,6 +174,7 @@ "src": "98:18:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 16, @@ -179,11 +185,51 @@ } }, "visibility": "internal" + }, + { + "constant": false, + "id": 22, + "mutability": "mutable", + "name": "d", + "nameLocation": "169:1:1", + "nodeType": "VariableDeclaration", + "src": "124:46:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": {}, + "typeName": + { + "id": 21, + "keyName": "keyAddress", + "keyNameLocation": "140:10:1", + "keyType": + { + "id": 19, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "132:7:1", + "typeDescriptions": {} + }, + "nodeType": "Mapping", + "src": "124:44:1", + "typeDescriptions": {}, + "valueName": "value", + "valueNameLocation": "162:5:1", + "valueType": + { + "id": 20, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "154:7:1", + "typeDescriptions": {} + } + }, + "visibility": "internal" } ], - "src": "0:121:1", + "src": "0:173:1", "usedErrors": [] } ], - "src": "0:122:1" + "src": "0:174:1" } diff --git a/test/libsolidity/ASTJSON/userDefinedValueType.json b/test/libsolidity/ASTJSON/userDefinedValueType.json index 743716548b..eb44509466 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType.json @@ -288,6 +288,7 @@ { "id": 25, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 22, @@ -320,6 +321,7 @@ "typeString": "mapping(C.MyAddress => C.MyUInt)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 24, diff --git a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json index 5e263eaea8..0dc95e13f9 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json @@ -214,6 +214,7 @@ { "id": 25, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 22, @@ -236,6 +237,7 @@ "src": "169:28:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 24, From df2ea195350aa3ad1eb8ce7271c60463999457de Mon Sep 17 00:00:00 2001 From: andy53 Date: Sat, 3 Dec 2022 12:07:06 -0700 Subject: [PATCH 0032/1140] Remove solidity-upgrade update config.yaml Update using-the-compiler.rst removed bug reports section added changelog entry removed trailing whitespace removed trailing whitespace --- .circleci/config.yml | 7 - Changelog.md | 1 + docs/using-the-compiler.rst | 227 +------- tools/CMakeLists.txt | 14 - tools/solidityUpgrade/SourceTransform.h | 309 ---------- tools/solidityUpgrade/SourceUpgrade.cpp | 541 ------------------ tools/solidityUpgrade/SourceUpgrade.h | 173 ------ tools/solidityUpgrade/Upgrade050.cpp | 55 -- tools/solidityUpgrade/Upgrade050.h | 59 -- tools/solidityUpgrade/Upgrade060.cpp | 197 ------- tools/solidityUpgrade/Upgrade060.h | 79 --- tools/solidityUpgrade/Upgrade070.cpp | 85 --- tools/solidityUpgrade/Upgrade070.h | 53 -- tools/solidityUpgrade/UpgradeChange.cpp | 80 --- tools/solidityUpgrade/UpgradeChange.h | 79 --- tools/solidityUpgrade/UpgradeSuite.h | 99 ---- .../contracts/DocsExamplePass.sol | 23 - tools/solidityUpgrade/contracts/Test.sol | 18 - .../contracts/TestMultiline.sol | 21 - .../contracts/TestNonFixable.sol | 15 - tools/solidityUpgrade/main.cpp | 99 ---- 21 files changed, 2 insertions(+), 2232 deletions(-) delete mode 100644 tools/solidityUpgrade/SourceTransform.h delete mode 100644 tools/solidityUpgrade/SourceUpgrade.cpp delete mode 100644 tools/solidityUpgrade/SourceUpgrade.h delete mode 100644 tools/solidityUpgrade/Upgrade050.cpp delete mode 100644 tools/solidityUpgrade/Upgrade050.h delete mode 100644 tools/solidityUpgrade/Upgrade060.cpp delete mode 100644 tools/solidityUpgrade/Upgrade060.h delete mode 100644 tools/solidityUpgrade/Upgrade070.cpp delete mode 100644 tools/solidityUpgrade/Upgrade070.h delete mode 100644 tools/solidityUpgrade/UpgradeChange.cpp delete mode 100644 tools/solidityUpgrade/UpgradeChange.h delete mode 100644 tools/solidityUpgrade/UpgradeSuite.h delete mode 100644 tools/solidityUpgrade/contracts/DocsExamplePass.sol delete mode 100644 tools/solidityUpgrade/contracts/Test.sol delete mode 100644 tools/solidityUpgrade/contracts/TestMultiline.sol delete mode 100644 tools/solidityUpgrade/contracts/TestNonFixable.sol delete mode 100644 tools/solidityUpgrade/main.cpp diff --git a/.circleci/config.yml b/.circleci/config.yml index 2783532d8e..b2c1ab9209 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -173,11 +173,6 @@ defaults: - artifact_solc_windows: &artifact_solc_windows path: upload/ - # compiled tool executable target - - artifact_solidity_upgrade: &artifact_solidity_upgrade - path: build/tools/solidity-upgrade - destination: solidity-upgrade - - artifact_yul_phaser: &artifact_yul_phaser path: build/tools/yul-phaser destination: yul-phaser @@ -251,7 +246,6 @@ defaults: - checkout - run: *run_build - store_artifacts: *artifacts_solc - - store_artifacts: *artifact_solidity_upgrade - store_artifacts: *artifact_yul_phaser - persist_to_workspace: *artifacts_executables - gitter_notify_failure_unless_pr @@ -952,7 +946,6 @@ jobs: <<: *steps_install_dependencies_osx - run: *run_build - store_artifacts: *artifacts_solc - - store_artifacts: *artifact_solidity_upgrade - store_artifacts: *artifact_yul_phaser - persist_to_workspace: root: . diff --git a/Changelog.md b/Changelog.md index b77be4f396..ad463630b4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,6 +18,7 @@ Compiler Features: * SMTChecker: Support Eldarica as a Horn solver for the CHC engine when using the CLI option ``--model-checker-solvers eld``. The binary `eld` must be available in the system. * SMTChecker: Make ``z3`` the default solver for the BMC and CHC engines instead of all solvers. * Parser: More detailed error messages about invalid version pragmas. + * Removed support for the ``solidity-upgrade`` tool. Bugfixes: diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index e5b5f00ec0..fca81760c4 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -630,229 +630,4 @@ Error Types 12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue. 13. ``YulException``: Error during Yul Code generation - this should be reported as an issue. 14. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible. -15. ``Info``: Information that the compiler thinks the user might find useful, but is not dangerous and does not necessarily need to be addressed. - - -.. _compiler-tools: - -Compiler Tools -************** - -solidity-upgrade ----------------- - -``solidity-upgrade`` can help you to semi-automatically upgrade your contracts -to breaking language changes. While it does not and cannot implement all -required changes for every breaking release, it still supports the ones, that -would need plenty of repetitive manual adjustments otherwise. - -.. note:: - - ``solidity-upgrade`` carries out a large part of the work, but your - contracts will most likely need further manual adjustments. We recommend - using a version control system for your files. This helps reviewing and - eventually rolling back the changes made. - -.. warning:: - - ``solidity-upgrade`` is not considered to be complete or free from bugs, so - please use with care. - -How it Works -~~~~~~~~~~~~ - -You can pass (a) Solidity source file(s) to ``solidity-upgrade [files]``. If -these make use of ``import`` statement which refer to files outside the -current source file's directory, you need to specify directories that -are allowed to read and import files from, by passing -``--allow-paths [directory]``. You can ignore missing files by passing -``--ignore-missing``. - -``solidity-upgrade`` is based on ``libsolidity`` and can parse, compile and -analyse your source files, and might find applicable source upgrades in them. - -Source upgrades are considered to be small textual changes to your source code. -They are applied to an in-memory representation of the source files -given. The corresponding source file is updated by default, but you can pass -``--dry-run`` to simulate to whole upgrade process without writing to any file. - -The upgrade process itself has two phases. In the first phase source files are -parsed, and since it is not possible to upgrade source code on that level, -errors are collected and can be logged by passing ``--verbose``. No source -upgrades available at this point. - -In the second phase, all sources are compiled and all activated upgrade analysis -modules are run alongside compilation. By default, all available modules are -activated. Please read the documentation on -:ref:`available modules ` for further details. - - -This can result in compilation errors that may -be fixed by source upgrades. If no errors occur, no source upgrades are being -reported and you're done. -If errors occur and some upgrade module reported a source upgrade, the first -reported one gets applied and compilation is triggered again for all given -source files. The previous step is repeated as long as source upgrades are -reported. If errors still occur, you can log them by passing ``--verbose``. -If no errors occur, your contracts are up to date and can be compiled with -the latest version of the compiler. - -.. _upgrade-modules: - -Available Upgrade Modules -~~~~~~~~~~~~~~~~~~~~~~~~~ - -+----------------------------+---------+--------------------------------------------------+ -| Module | Version | Description | -+============================+=========+==================================================+ -| ``constructor`` | 0.5.0 | Constructors must now be defined using the | -| | | ``constructor`` keyword. | -+----------------------------+---------+--------------------------------------------------+ -| ``visibility`` | 0.5.0 | Explicit function visibility is now mandatory, | -| | | defaults to ``public``. | -+----------------------------+---------+--------------------------------------------------+ -| ``abstract`` | 0.6.0 | The keyword ``abstract`` has to be used if a | -| | | contract does not implement all its functions. | -+----------------------------+---------+--------------------------------------------------+ -| ``virtual`` | 0.6.0 | Functions without implementation outside an | -| | | interface have to be marked ``virtual``. | -+----------------------------+---------+--------------------------------------------------+ -| ``override`` | 0.6.0 | When overriding a function or modifier, the new | -| | | keyword ``override`` must be used. | -+----------------------------+---------+--------------------------------------------------+ -| ``dotsyntax`` | 0.7.0 | The following syntax is deprecated: | -| | | ``f.gas(...)()``, ``f.value(...)()`` and | -| | | ``(new C).value(...)()``. Replace these calls by | -| | | ``f{gas: ..., value: ...}()`` and | -| | | ``(new C){value: ...}()``. | -+----------------------------+---------+--------------------------------------------------+ -| ``now`` | 0.7.0 | The ``now`` keyword is deprecated. Use | -| | | ``block.timestamp`` instead. | -+----------------------------+---------+--------------------------------------------------+ -| ``constructor-visibility`` | 0.7.0 | Removes visibility of constructors. | -| | | | -+----------------------------+---------+--------------------------------------------------+ - -Please read :doc:`0.5.0 release notes <050-breaking-changes>`, -:doc:`0.6.0 release notes <060-breaking-changes>`, -:doc:`0.7.0 release notes <070-breaking-changes>` and :doc:`0.8.0 release notes <080-breaking-changes>` for further details. - -Synopsis -~~~~~~~~ - -.. code-block:: none - - Usage: solidity-upgrade [options] contract.sol - - Allowed options: - --help Show help message and exit. - --version Show version and exit. - --allow-paths path(s) - Allow a given path for imports. A list of paths can be - supplied by separating them with a comma. - --ignore-missing Ignore missing files. - --modules module(s) Only activate a specific upgrade module. A list of - modules can be supplied by separating them with a comma. - --dry-run Apply changes in-memory only and don't write to input - file. - --verbose Print logs, errors and changes. Shortens output of - upgrade patches. - --unsafe Accept *unsafe* changes. - - - -Bug Reports / Feature Requests -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you found a bug or if you have a feature request, please -`file an issue `_ on Github. - - -Example -~~~~~~~ - -Assume that you have the following contract in ``Source.sol``: - -.. code-block:: Solidity - - pragma solidity >=0.6.0 <0.6.4; - // This will not compile after 0.7.0 - // SPDX-License-Identifier: GPL-3.0 - contract C { - // FIXME: remove constructor visibility and make the contract abstract - constructor() internal {} - } - - contract D { - uint time; - - function f() public payable { - // FIXME: change now to block.timestamp - time = now; - } - } - - contract E { - D d; - - // FIXME: remove constructor visibility - constructor() public {} - - function g() public { - // FIXME: change .value(5) => {value: 5} - d.f.value(5)(); - } - } - - - -Required Changes -^^^^^^^^^^^^^^^^ - -The above contract will not compile starting from 0.7.0. To bring the contract up to date with the -current Solidity version, the following upgrade modules have to be executed: -``constructor-visibility``, ``now`` and ``dotsyntax``. Please read the documentation on -:ref:`available modules ` for further details. - - -Running the Upgrade -^^^^^^^^^^^^^^^^^^^ - -It is recommended to explicitly specify the upgrade modules by using ``--modules`` argument. - -.. code-block:: bash - - solidity-upgrade --modules constructor-visibility,now,dotsyntax Source.sol - -The command above applies all changes as shown below. Please review them carefully (the pragmas will -have to be updated manually.) - -.. code-block:: Solidity - - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.7.0 <0.9.0; - abstract contract C { - // FIXME: remove constructor visibility and make the contract abstract - constructor() {} - } - - contract D { - uint time; - - function f() public payable { - // FIXME: change now to block.timestamp - time = block.timestamp; - } - } - - contract E { - D d; - - // FIXME: remove constructor visibility - constructor() {} - - function g() public { - // FIXME: change .value(5) => {value: 5} - d.f{value: 5}(); - } - } +15. ``Info``: Information that the compiler thinks the user might find useful, but is not dangerous and does not necessarily need to be addressed. \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index b442ba96a6..c67a509e1b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,18 +1,4 @@ -add_executable(solidity-upgrade - solidityUpgrade/main.cpp - solidityUpgrade/UpgradeChange.h - solidityUpgrade/UpgradeChange.cpp - solidityUpgrade/UpgradeSuite.h - solidityUpgrade/Upgrade050.cpp - solidityUpgrade/Upgrade060.cpp - solidityUpgrade/Upgrade070.cpp - solidityUpgrade/SourceTransform.h - solidityUpgrade/SourceUpgrade.cpp -) -target_link_libraries(solidity-upgrade PRIVATE solidity Boost::boost Boost::program_options Boost::system) - include(GNUInstallDirs) -install(TARGETS solidity-upgrade DESTINATION "${CMAKE_INSTALL_BINDIR}") set(libphaser_sources yulPhaser/Common.h diff --git a/tools/solidityUpgrade/SourceTransform.h b/tools/solidityUpgrade/SourceTransform.h deleted file mode 100644 index 04d1282981..0000000000 --- a/tools/solidityUpgrade/SourceTransform.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 - -#pragma once - -#include - -#include - -#include -#include - -#include -#include - -namespace solidity::tools -{ - -/** - * Helper for displaying location during asserts - */ -class LocationHelper -{ - std::stringstream m_stream; - -public: - - template - LocationHelper& operator<<(T const& data) - { - m_stream << data; - return *this; - } - - operator std::string() { return m_stream.str(); } -}; - -class SourceTextRetriever -{ -public: - explicit SourceTextRetriever(langutil::CharStreamProvider const& _charStreamProvider): - m_charStreamProvider(_charStreamProvider) {} - std::string text(langutil::SourceLocation const& _location) const - { - solAssert(_location.hasText(), ""); - return std::string{m_charStreamProvider.charStream(*_location.sourceName).text(_location)}; - } -protected: - langutil::CharStreamProvider const& m_charStreamProvider; -}; - -/** - * Helper that provides functions which analyze certain source locations - * on a textual base. They utilize regular expression to search for - * keywords or to determine formatting. - */ -class SourceAnalysis: public SourceTextRetriever -{ -public: - using SourceTextRetriever::SourceTextRetriever; - - bool isMultilineKeyword( - langutil::SourceLocation const& _location, - std::string const& _keyword - ) const - { - return regex_search( - text(_location), - std::regex{"(\\b" + _keyword + "\\b\\n|\\r|\\r\\n)"} - ); - } - - bool hasMutabilityKeyword(langutil::SourceLocation const& _location) const - { - return regex_search( - text(_location), - std::regex{"(\\b(pure|view|nonpayable|payable)\\b)"} - ); - } - - bool hasVirtualKeyword(langutil::SourceLocation const& _location) const - { - return regex_search(text(_location), std::regex{"(\\b(virtual)\\b)"}); - } - - bool hasVisibilityKeyword(langutil::SourceLocation const& _location) const - { - return regex_search(text(_location), std::regex{"\\bpublic\\b"}); - } -}; - -/** - * Helper that provides functions which can analyse declarations and - * generate source snippets based on the information retrieved. - */ -class SourceGeneration -{ -public: - using CompareFunction = frontend::OverrideChecker::CompareByID; - using Contracts = std::set; - - /// Generates an `override` declaration for single overrides - /// or `override(...)` with contract list for multiple overrides. - static std::string functionOverride(Contracts const& _contracts) - { - if (_contracts.size() <= 1) - return "override"; - - std::string overrideList; - for (auto inheritedContract: _contracts) - overrideList += inheritedContract->name() + ","; - - // Note: Can create incorrect replacements - return "override(" + overrideList.substr(0, overrideList.size() - 1) + ")"; - } -}; - -/** - * Helper that provides functions which apply changes to Solidity source code - * on a textual base. In general, these utilize regular expressions applied - * to the given source location. - */ -class SourceTransform: public SourceTextRetriever -{ -public: - using SourceTextRetriever::SourceTextRetriever; - - /// Searches for the keyword given and prepends the expression. - /// E.g. `function f() view;` -> `function f() public view;` - std::string insertBeforeKeyword( - langutil::SourceLocation const& _location, - std::string const& _keyword, - std::string const& _expression - ) const - { - auto _regex = std::regex{"(\\b" + _keyword + "\\b)"}; - if (regex_search(text(_location), _regex)) - return regex_replace( - text(_location), - _regex, - _expression + " " + _keyword, - std::regex_constants::format_first_only - ); - else - solAssert( - false, - LocationHelper() << "Could not fix: " << text(_location) << " at " << _location << - "\nNeeds to be fixed manually." - ); - - return ""; - } - - /// Searches for the keyword given and appends the expression. - /// E.g. `function f() public {}` -> `function f() public override {}` - std::string insertAfterKeyword( - langutil::SourceLocation const& _location, - std::string const& _keyword, - std::string const& _expression - ) const - { - bool isMultiline = SourceAnalysis{m_charStreamProvider}.isMultilineKeyword(_location, _keyword); - std::string toAppend = isMultiline ? ("\n " + _expression) : (" " + _expression); - std::regex keyword{"(\\b" + _keyword + "\\b)"}; - - if (regex_search(text(_location), keyword)) - return regex_replace(text(_location), keyword, _keyword + toAppend); - else - solAssert( - false, - LocationHelper() << "Could not fix: " << text(_location) << " at " << _location << - "\nNeeds to be fixed manually." - ); - - return ""; - - } - - /// Searches for the first right parenthesis and appends the expression - /// given. - /// E.g. `function f() {}` -> `function f() public {}` - std::string insertAfterRightParenthesis( - langutil::SourceLocation const& _location, - std::string const& _expression - ) const - { - auto _regex = std::regex{"(\\))"}; - if (regex_search(text(_location), _regex)) - return regex_replace( - text(_location), - std::regex{"(\\))"}, - ") " + _expression - ); - else - solAssert( - false, - LocationHelper() << "Could not fix: " << text(_location) << " at " << _location << - "\nNeeds to be fixed manually." - ); - - return ""; - } - - /// Searches for the `function` keyword and its identifier and replaces - /// both by the expression given. - /// E.g. `function Storage() {}` -> `constructor() {}` - std::string replaceFunctionName( - langutil::SourceLocation const& _location, - std::string const& _name, - std::string const& _expression - ) const - { - auto _regex = std::regex{ "(\\bfunction\\s*" + _name + "\\b)"}; - if (regex_search(text(_location), _regex)) - return regex_replace( - text(_location), - _regex, - _expression - ); - else - solAssert( - false, - LocationHelper() << "Could not fix: " << text(_location) << " at " << _location << - "\nNeeds to be fixed manually." - ); - - return ""; - } - - std::string gasUpdate(langutil::SourceLocation const& _location) const - { - // dot, "gas", any number of whitespaces, left bracket - std::regex gasReg{"\\.gas\\s*\\("}; - - if (regex_search(text(_location), gasReg)) - { - std::string out = regex_replace( - text(_location), - gasReg, - "{gas: ", - std::regex_constants::format_first_only - ); - return regex_replace(out, std::regex{"\\)$"}, "}"); - } - else - solAssert( - false, - LocationHelper() << "Could not fix: " << text(_location) << " at " << _location << - "\nNeeds to be fixed manually." - ); - - return ""; - } - - std::string valueUpdate(langutil::SourceLocation const& _location) const - { - // dot, "value", any number of whitespaces, left bracket - std::regex valueReg{"\\.value\\s*\\("}; - - if (regex_search(text(_location), valueReg)) - { - std::string out = regex_replace( - text(_location), - valueReg, - "{value: ", - std::regex_constants::format_first_only - ); - return regex_replace(out, std::regex{"\\)$"}, "}"); - } - else - solAssert( - false, - LocationHelper() << "Could not fix: " << text(_location) << " at " << _location << - "\nNeeds to be fixed manually." - ); - - return ""; - } - - std::string nowUpdate(langutil::SourceLocation const& _location) const - { - return regex_replace(text(_location), std::regex{"now"}, "block.timestamp"); - } - - std::string removeVisibility(langutil::SourceLocation const& _location) const - { - std::string replacement = text(_location); - for (auto const& replace: {"public ", "public", "internal ", "internal", "external ", "external"}) - replacement = regex_replace(replacement, std::regex{replace}, ""); - return replacement; - } -}; - -} diff --git a/tools/solidityUpgrade/SourceUpgrade.cpp b/tools/solidityUpgrade/SourceUpgrade.cpp deleted file mode 100644 index b98b050d6f..0000000000 --- a/tools/solidityUpgrade/SourceUpgrade.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#include - -#include -#include - -#include - -#include -#include -#include - -#include - -#ifdef _WIN32 // windows - #include - #define isatty _isatty - #define fileno _fileno -#else // unix - #include -#endif - - -namespace po = boost::program_options; -namespace fs = boost::filesystem; - -using namespace solidity; -using namespace solidity::langutil; -using namespace solidity::tools; -using namespace solidity::util; -using namespace solidity::frontend; -using namespace std; - - -static string const g_argHelp = "help"; -static string const g_argVersion = "version"; -static string const g_argInputFile = "input-file"; -static string const g_argModules = "modules"; -static string const g_argDryRun = "dry-run"; -static string const g_argUnsafe = "unsafe"; -static string const g_argVerbose = "verbose"; -static string const g_argIgnoreMissingFiles = "ignore-missing"; -static string const g_argAllowPaths = "allow-paths"; - -namespace -{ - -ostream& out() -{ - return cout; -} - -AnsiColorized log() -{ - return AnsiColorized(cout, true, {}); -} - -AnsiColorized success() -{ - return AnsiColorized(cout, true, {formatting::CYAN}); -} - -AnsiColorized warning() -{ - return AnsiColorized(cout, true, {formatting::YELLOW}); -} - -AnsiColorized error() -{ - return AnsiColorized(cout, true, {formatting::MAGENTA}); -} - -void logVersion() -{ - /// TODO Replace by variable that can be set during build. - out() << "0.1.0" << endl; -} - -void logProgress() -{ - out() << "."; - out().flush(); -} - -} - -bool SourceUpgrade::parseArguments(int _argc, char** _argv) -{ - po::options_description desc(R"(solidity-upgrade, the Solidity upgrade assistant. - -The solidity-upgrade tool can help upgrade smart contracts to breaking language features. - -It does not support all breaking changes for each version, but will hopefully assist -upgrading your contracts to the desired Solidity version. - -solidity-upgrade is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY. Please be careful when running upgrades on -your contracts. - -Usage: solidity-upgrade [options] contract.sol - -Allowed options)", - po::options_description::m_default_line_length, - po::options_description::m_default_line_length - 23 - ); - desc.add_options() - (g_argHelp.c_str(), "Show help message and exit.") - (g_argVersion.c_str(), "Show version and exit.") - ( - g_argAllowPaths.c_str(), - po::value()->value_name("path(s)"), - "Allow a given path for imports. A list of paths can be supplied by separating them " - "with a comma." - ) - (g_argIgnoreMissingFiles.c_str(), "Ignore missing files.") - ( - g_argModules.c_str(), - po::value()->value_name("module(s)"), - "Only activate a specific upgrade module. A list of " - "modules can be supplied by separating them with a comma." - ) - (g_argDryRun.c_str(), "Apply changes in-memory only and don't write to input file.") - (g_argVerbose.c_str(), "Print logs, errors and changes. Shortens output of upgrade patches.") - (g_argUnsafe.c_str(), "Accept *unsafe* changes."); - - - po::options_description allOptions = desc; - allOptions.add_options()("input-file", po::value>(), "input file"); - - po::positional_options_description filesPositions; - filesPositions.add("input-file", -1); - - // parse the compiler arguments - try - { - po::command_line_parser cmdLineParser(_argc, _argv); - cmdLineParser.style( - po::command_line_style::default_style & (~po::command_line_style::allow_guessing) - ); - cmdLineParser.options(allOptions).positional(filesPositions); - po::store(cmdLineParser.run(), m_args); - } - catch (po::error const& _exception) - { - error() << _exception.what() << endl; - return false; - } - - if (m_args.count(g_argHelp) || (isatty(fileno(stdin)) && _argc == 1)) - { - out() << endl; - log() << desc; - return false; - } - - if (m_args.count(g_argVersion)) - { - logVersion(); - return false; - } - - if (m_args.count(g_argModules)) - { - vector moduleArgs; - auto modules = boost::split( - moduleArgs, m_args[g_argModules].as(), boost::is_any_of(",") - ); - - /// All modules are activated by default. Clear them before activating single ones. - m_suite.deactivateModules(); - - for (string const& module: modules) - { - if (module == "constructor") - m_suite.activateModule(Module::ConstructorKeyword); - else if (module == "visibility") - m_suite.activateModule(Module::VisibilitySpecifier); - else if (module == "abstract") - m_suite.activateModule(Module::AbstractContract); - else if (module == "override") - m_suite.activateModule(Module::OverridingFunction); - else if (module == "virtual") - m_suite.activateModule(Module::VirtualFunction); - else if (module == "dotsyntax") - m_suite.activateModule(Module::DotSyntax); - else if (module == "now") - m_suite.activateModule(Module::NowKeyword); - else if (module == "constructor-visibility") - m_suite.activateModule(Module::ConstrutorVisibility); - else - { - error() << "Unknown upgrade module \"" + module + "\"" << endl; - return false; - } - } - } - - /// TODO Share with solc commandline interface. - if (m_args.count(g_argAllowPaths)) - { - vector paths; - auto allowedPaths = boost::split( - paths, m_args[g_argAllowPaths].as(), boost::is_any_of(",") - ); - for (string const& path: allowedPaths) - { - auto filesystem_path = boost::filesystem::path(path); - /// If the given path had a trailing slash, the Boost filesystem - /// path will have it's last component set to '.'. This breaks - /// path comparison in later parts of the code, so we need to strip - /// it. - if (filesystem_path.filename() == ".") - filesystem_path.remove_filename(); - m_allowedDirectories.push_back(filesystem_path); - } - } - - - return true; -} - -void SourceUpgrade::printPrologue() -{ - out() << endl; - out() << endl; - - log() << - "solidity-upgrade does not support all breaking changes for each version." << - endl << - "Please run `solidity-upgrade --help` and get a list of implemented upgrades." << - endl << - endl; - - log() << - "Running analysis (and upgrade) on given source files." << - endl; -} - -bool SourceUpgrade::processInput() -{ - if (!readInputFiles()) - return false; - - resetCompiler(fileReader()); - - tryCompile(); - runUpgrade(); - - printStatistics(); - - return true; -} - -void SourceUpgrade::tryCompile() const -{ - bool verbose = m_args.count(g_argVerbose); - - if (verbose) - log() << "Running compilation phases." << endl << endl; - else - logProgress(); - - try - { - if (m_compiler->parse()) - { - if (m_compiler->analyze()) - m_compiler->compile(); - else - if (verbose) - { - error() << - "Compilation errors that solidity-upgrade may resolve occurred." << - endl << - endl; - - printErrors(); - } - } - else - if (verbose) - { - error() << - "Compilation errors that solidity-upgrade cannot resolve occurred." << - endl << - endl; - - printErrors(); - } - } - catch (Exception const& _exception) - { - error() << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; - } - catch (std::exception const& _exception) - { - error() << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; - } - catch (...) - { - error() << "Unknown exception during compilation: " << boost::current_exception_diagnostic_information() << endl; - } -} - -void SourceUpgrade::runUpgrade() -{ - bool recompile = true; - - while (recompile && !m_compiler->errors().empty()) - { - for (auto& sourceCode: m_sourceCodes) - { - recompile = analyzeAndUpgrade(sourceCode); - if (recompile) - break; - } - - if (recompile) - { - m_suite.reset(); - resetCompiler(); - tryCompile(); - } - } -} - -bool SourceUpgrade::analyzeAndUpgrade(pair const& _sourceCode) -{ - bool applyUnsafe = m_args.count(g_argUnsafe); - bool verbose = m_args.count(g_argVerbose); - - if (verbose) - log() << "Analyzing and upgrading " << _sourceCode.first << "." << endl; - - if (m_compiler->state() >= CompilerStack::State::AnalysisPerformed) - m_suite.analyze(*m_compiler, m_compiler->ast(_sourceCode.first)); - - if (!m_suite.changes().empty()) - { - auto& change = m_suite.changes().front(); - - if (verbose) - change.log(*m_compiler, true); - - if (change.level() == UpgradeChange::Level::Safe) - { - applyChange(_sourceCode, change); - return true; - } - else if (change.level() == UpgradeChange::Level::Unsafe) - { - if (applyUnsafe) - { - applyChange(_sourceCode, change); - return true; - } - } - } - - return false; -} - -void SourceUpgrade::applyChange( - pair const& _sourceCode, - UpgradeChange& _change -) -{ - bool dryRun = m_args.count(g_argDryRun); - bool verbose = m_args.count(g_argVerbose); - - if (verbose) - { - log() << "Applying change to " << _sourceCode.first << endl << endl; - log() << _change.patch(); - } - - m_sourceCodes[_sourceCode.first] = _change.apply(_sourceCode.second); - - if (!dryRun) - writeInputFile(_sourceCode.first, m_sourceCodes[_sourceCode.first]); -} - -void SourceUpgrade::printErrors() const -{ - langutil::SourceReferenceFormatter formatter{cout, *m_compiler, true, false}; - - for (auto const& error: m_compiler->errors()) - if (error->type() != langutil::Error::Type::Warning) - formatter.printErrorInformation(*error); -} - -void SourceUpgrade::printStatistics() const -{ - out() << endl; - out() << endl; - out() << "After upgrade:" << endl; - out() << endl; - error() << "Found " << m_compiler->errors().size() << " errors." << endl; - success() << "Found " << m_suite.changes().size() << " upgrades." << endl; -} - -bool SourceUpgrade::readInputFiles() -{ - bool ignoreMissing = m_args.count(g_argIgnoreMissingFiles); - - /// TODO Share with solc commandline interface. - if (m_args.count(g_argInputFile)) - for (string path: m_args[g_argInputFile].as>()) - { - boost::filesystem::path infile = path; - if (!boost::filesystem::exists(infile)) - { - if (!ignoreMissing) - { - error() << infile << " is not found." << endl; - return false; - } - else - error() << infile << " is not found. Skipping." << endl; - - continue; - } - - if (!boost::filesystem::is_regular_file(infile)) - { - if (!ignoreMissing) - { - error() << infile << " is not a valid file." << endl; - return false; - } - else - error() << infile << " is not a valid file. Skipping." << endl; - - continue; - } - - m_sourceCodes[infile.generic_string()] = readFileAsString(infile); - } - - if (m_sourceCodes.size() == 0) - { - warning() << "No input files given." << endl; - return false; - } - - return true; -} - -bool SourceUpgrade::writeInputFile(string const& _path, string const& _source) -{ - bool verbose = m_args.count(g_argVerbose); - - if (verbose) - { - out() << endl; - log() << "Writing to input file " << _path << "." << endl; - } - - ofstream file(_path, ios::trunc); - file << _source; - - return true; -} - -ReadCallback::Callback SourceUpgrade::fileReader() -{ - /// TODO Share with solc commandline interface. - ReadCallback::Callback fileReader = [this](string const&, string const& _path) - { - try - { - boost::filesystem::path path = _path; - boost::filesystem::path canonicalPath = boost::filesystem::weakly_canonical(path); - bool isAllowed = false; - for (auto const& allowedDir: m_allowedDirectories) - { - // If dir is a prefix of boostPath, we are fine. - if ( - std::distance(allowedDir.begin(), allowedDir.end()) <= std::distance(canonicalPath.begin(), canonicalPath.end()) && - std::equal(allowedDir.begin(), allowedDir.end(), canonicalPath.begin()) - ) - { - isAllowed = true; - break; - } - } - if (!isAllowed) - return ReadCallback::Result{false, "File outside of allowed directories."}; - - if (!boost::filesystem::exists(canonicalPath)) - return ReadCallback::Result{false, "File not found."}; - - if (!boost::filesystem::is_regular_file(canonicalPath)) - return ReadCallback::Result{false, "Not a valid file."}; - - string contents = readFileAsString(canonicalPath); - m_sourceCodes[path.generic_string()] = contents; - return ReadCallback::Result{true, contents}; - } - catch (Exception const& _exception) - { - return ReadCallback::Result{false, "Exception in read callback: " + boost::diagnostic_information(_exception)}; - } - catch (...) - { - return ReadCallback::Result{false, "Unknown exception in read callback: " + boost::current_exception_diagnostic_information()}; - } - }; - - return fileReader; -} - -void SourceUpgrade::resetCompiler() -{ - m_compiler->reset(); - m_compiler->setSources(m_sourceCodes); - m_compiler->setParserErrorRecovery(true); -} - -void SourceUpgrade::resetCompiler(ReadCallback::Callback const& _callback) -{ - m_compiler = std::make_unique(_callback); - m_compiler->setSources(m_sourceCodes); - m_compiler->setParserErrorRecovery(true); -} diff --git a/tools/solidityUpgrade/SourceUpgrade.h b/tools/solidityUpgrade/SourceUpgrade.h deleted file mode 100644 index f3b5d3572a..0000000000 --- a/tools/solidityUpgrade/SourceUpgrade.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#pragma once - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -namespace solidity::tools -{ - -/** - * The Solidity source upgrade tool. It supplies a command line interface - * and connects this to a compiler stack that the upgrade logic is facilitated - * with. - */ -class SourceUpgrade -{ -public: - /// Parse command line arguments and return false in case of a failure. - bool parseArguments(int _argc, char** _argv); - /// Prints additional information on the upgrade tool. - void printPrologue(); - /// Parse / compile files and runs upgrade analysis on them. - bool processInput(); - -private: - /// All available upgrade modules - enum class Module - { - ConstructorKeyword, - VisibilitySpecifier, - AbstractContract, - OverridingFunction, - VirtualFunction, - DotSyntax, - NowKeyword, - ConstrutorVisibility - }; - - /// Upgrade suite that hosts all available modules. - class Suite: public UpgradeSuite - { - public: - void analyze(langutil::CharStreamProvider const& _charStreamProvider, frontend::SourceUnit const& _sourceUnit) - { - /// Solidity 0.5.0 - if (isActivated(Module::ConstructorKeyword)) - ConstructorKeyword{_charStreamProvider, m_changes}.analyze(_sourceUnit); - if (isActivated(Module::VisibilitySpecifier)) - VisibilitySpecifier{_charStreamProvider, m_changes}.analyze(_sourceUnit); - - /// Solidity 0.6.0 - if (isActivated(Module::AbstractContract)) - AbstractContract{_charStreamProvider, m_changes}.analyze(_sourceUnit); - if (isActivated(Module::OverridingFunction)) - OverridingFunction{_charStreamProvider, m_changes}.analyze(_sourceUnit); - if (isActivated(Module::VirtualFunction)) - VirtualFunction{_charStreamProvider, m_changes}.analyze(_sourceUnit); - - /// Solidity 0.7.0 - if (isActivated(Module::DotSyntax)) - DotSyntax{_charStreamProvider, m_changes}.analyze(_sourceUnit); - if (isActivated(Module::NowKeyword)) - NowKeyword{_charStreamProvider, m_changes}.analyze(_sourceUnit); - if (isActivated(Module::ConstrutorVisibility)) - ConstructorVisibility{_charStreamProvider, m_changes}.analyze(_sourceUnit); - } - - void activateModule(Module _module) { m_modules.insert(_module); } - void deactivateModules() { m_modules.clear(); } - - private: - bool isActivated(Module _module) const - { - return m_modules.find(_module) != m_modules.end(); - } - - /// All modules are activated by default. Clear them before activating - /// single ones. - std::set m_modules = { - Module::ConstructorKeyword, - Module::VisibilitySpecifier, - Module::AbstractContract, - Module::OverridingFunction, - Module::VirtualFunction, - Module::DotSyntax, - Module::NowKeyword, - Module::ConstrutorVisibility - }; - }; - - /// Parses the current sources and runs analyses as well as compilation on - /// them if parsing was successful. - void tryCompile() const; - /// Analyses and upgrades the sources given. The upgrade happens in a loop, - /// applying one change at a time, which is run until no applicable changes - /// are found any more. Only one change is done at a time and all sources - /// are being compiled again after each change. - void runUpgrade(); - /// Runs upgrade analysis on source and applies upgrades changes to it. - /// Returns `true` if there're still changes that can be applied, - /// `false` otherwise. - bool analyzeAndUpgrade( - std::pair const& _sourceCode - ); - - /// Applies the change given to its source code. If no `--dry-run` was - /// passed via the commandline, the upgraded source code is written back - /// to its file. - void applyChange( - std::pair const& _sourceCode, - UpgradeChange& _change - ); - - /// Prints all errors (excluding warnings) the compiler currently reported. - void printErrors() const; - /// Prints error and upgrade overview at the end of each full run. - void printStatistics() const; - - /// Reads all input files given and stores sources in the internal data - /// structure. Reports errors if files cannot be found. - bool readInputFiles(); - /// Writes source to file given. - bool writeInputFile(std::string const& _path, std::string const& _source); - /// Returns a file reader function that fills `m_sources`. - frontend::ReadCallback::Callback fileReader(); - - /// Resets the compiler stack and configures sources to compile. - /// Also enables error recovery. - void resetCompiler(); - /// Resets the compiler stack and configures sources to compile. - /// Also enables error recovery. Passes read callback to the compiler stack. - void resetCompiler(frontend::ReadCallback::Callback const& _callback); - - /// Compiler arguments variable map - boost::program_options::variables_map m_args; - /// Map of input files to source code strings - std::map m_sourceCodes; - /// Solidity compiler stack - std::unique_ptr m_compiler; - /// List of allowed directories to read files from - std::vector m_allowedDirectories; - /// Holds all upgrade modules and source upgrades. - Suite m_suite; -}; - -} diff --git a/tools/solidityUpgrade/Upgrade050.cpp b/tools/solidityUpgrade/Upgrade050.cpp deleted file mode 100644 index c8b4de9e84..0000000000 --- a/tools/solidityUpgrade/Upgrade050.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#include -#include - -#include - -#include - -#include - -using namespace std; -using namespace solidity; -using namespace solidity::frontend; -using namespace solidity::tools; - -void ConstructorKeyword::endVisit(ContractDefinition const& _contract) -{ - for (auto const* function: _contract.definedFunctions()) - if (function->name() == _contract.name()) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - function->location(), - SourceTransform{m_charStreamProvider}.replaceFunctionName( - function->location(), - function->name(), - "constructor" - ) - ); -} - -void VisibilitySpecifier::endVisit(FunctionDefinition const& _function) -{ - if (_function.noVisibilitySpecified()) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - _function.location(), - SourceTransform{m_charStreamProvider}.insertAfterRightParenthesis(_function.location(), "public") - ); -} diff --git a/tools/solidityUpgrade/Upgrade050.h b/tools/solidityUpgrade/Upgrade050.h deleted file mode 100644 index a678b04e5a..0000000000 --- a/tools/solidityUpgrade/Upgrade050.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#pragma once - -#include -#include - -#include - -namespace solidity::tools -{ - -/** - * Module that performs analysis on the AST. It visits all contract - * definitions and its defined functions and reports a source upgrade, - * if one of the declared functions is the constructor but does not - * use the `constructor` keyword. - */ -class ConstructorKeyword: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - void endVisit(frontend::ContractDefinition const& _contract) override; -}; - -/** - * Module that performs analysis on the AST. It visits function definitions - * and reports a source upgrade, if this function's visibility is `public`, - * but not marked explicitly as such. - */ -class VisibilitySpecifier: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - void endVisit(frontend::FunctionDefinition const& _function) override; -}; - -} diff --git a/tools/solidityUpgrade/Upgrade060.cpp b/tools/solidityUpgrade/Upgrade060.cpp deleted file mode 100644 index 8caff02c9f..0000000000 --- a/tools/solidityUpgrade/Upgrade060.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#include -#include - -#include - -#include - -#include - -using namespace std; -using namespace solidity; -using namespace solidity::frontend; -using namespace solidity::tools; - -void AbstractContract::endVisit(ContractDefinition const& _contract) -{ - bool isFullyImplemented = _contract.annotation().unimplementedDeclarations->empty(); - - if ( - !isFullyImplemented && - !_contract.abstract() && - !_contract.isInterface() - ) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - _contract.location(), - SourceTransform{m_charStreamProvider}.insertBeforeKeyword(_contract.location(), "contract", "abstract") - ); -} - -void OverridingFunction::endVisit(ContractDefinition const& _contract) -{ - auto const& inheritedFunctions = m_overrideChecker.inheritedFunctions(_contract); - - for (auto const* function: _contract.definedFunctions()) - { - Contracts expectedContracts; - OverrideProxy proxy{function}; - - if (!function->isConstructor()) - { - /// Build list of contracts expected to be mentioned in the override list (if any). - for (auto [begin, end] = inheritedFunctions.equal_range(proxy); begin != end; begin++) - expectedContracts.insert(&begin->contract()); - - /// Add override with contract list, if needed. - if (!function->overrides() && expectedContracts.size() > 1) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - function->location(), - appendOverride(*function, expectedContracts) - ); - - for (auto [begin, end] = inheritedFunctions.equal_range(proxy); begin != end; begin++) - { - auto& super = (*begin); - auto functionType = FunctionType(*function).asExternallyCallableFunction(false); - auto superType = super.externalFunctionType(); - - if (functionType && functionType->hasEqualParameterTypes(*superType)) - { - /// If function does not specify override and no override with - /// contract list was added before. - if (!function->overrides() && expectedContracts.size() <= 1) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - function->location(), - appendOverride(*function, expectedContracts) - ); - } - } - } - } -} - -string OverridingFunction::appendOverride( - FunctionDefinition const& _function, - Contracts const& _expectedContracts -) -{ - auto location = _function.location(); - string upgradedCode; - string overrideExpression = SourceGeneration::functionOverride(_expectedContracts); - - if (SourceAnalysis{m_charStreamProvider}.hasVirtualKeyword(location)) - upgradedCode = SourceTransform{m_charStreamProvider}.insertAfterKeyword( - location, - "virtual", - overrideExpression - ); - else if (SourceAnalysis{m_charStreamProvider}.hasMutabilityKeyword(location)) - upgradedCode = SourceTransform{m_charStreamProvider}.insertAfterKeyword( - location, - stateMutabilityToString(_function.stateMutability()), - overrideExpression - ); - else if (SourceAnalysis{m_charStreamProvider}.hasVisibilityKeyword(location)) - upgradedCode = SourceTransform{m_charStreamProvider}.insertAfterKeyword( - location, - Declaration::visibilityToString(_function.visibility()), - overrideExpression - ); - else - upgradedCode = SourceTransform{m_charStreamProvider}.insertAfterRightParenthesis( - location, - overrideExpression - ); - - return upgradedCode; -} - -void VirtualFunction::endVisit(ContractDefinition const& _contract) -{ - auto const& inheritedFunctions = m_overrideChecker.inheritedFunctions(_contract); - - for (FunctionDefinition const* function: _contract.definedFunctions()) - { - OverrideProxy proxy{function}; - - if (!function->isConstructor()) - { - if ( - !function->markedVirtual() && - !function->isImplemented() && - !function->virtualSemantics() && - function->visibility() > Visibility::Private - ) - { - m_changes.emplace_back( - UpgradeChange::Level::Safe, - function->location(), - appendVirtual(*function) - ); - } - - for (auto [begin, end] = inheritedFunctions.equal_range(proxy); begin != end; begin++) - { - auto& super = (*begin); - if ( - !function->markedVirtual() && - !super.virtualSemantics() - ) - { - m_changes.emplace_back( - UpgradeChange::Level::Safe, - function->location(), - appendVirtual(*function) - ); - } - } - } - } -} - -string VirtualFunction::appendVirtual(FunctionDefinition const& _function) const -{ - auto location = _function.location(); - string upgradedCode; - - if (SourceAnalysis{m_charStreamProvider}.hasMutabilityKeyword(location)) - upgradedCode = SourceTransform{m_charStreamProvider}.insertAfterKeyword( - location, - stateMutabilityToString(_function.stateMutability()), - "virtual" - ); - else if (SourceAnalysis{m_charStreamProvider}.hasVisibilityKeyword(location)) - upgradedCode = SourceTransform{m_charStreamProvider}.insertAfterKeyword( - location, - Declaration::visibilityToString(_function.visibility()), - "virtual" - ); - else - upgradedCode = SourceTransform{m_charStreamProvider}.insertAfterRightParenthesis( - _function.location(), - "virtual" - ); - - return upgradedCode; -} - diff --git a/tools/solidityUpgrade/Upgrade060.h b/tools/solidityUpgrade/Upgrade060.h deleted file mode 100644 index 46b10a3a0f..0000000000 --- a/tools/solidityUpgrade/Upgrade060.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#pragma once - -#include -#include - -#include - -namespace solidity::tools -{ - -/** - * Module that performs analysis on the AST. Finds abstract contracts that are - * not marked as such and adds the `abstract` keyword. - */ -class AbstractContract: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - void endVisit(frontend::ContractDefinition const& _contract) override; -}; - -/** - * Module that performs analysis on the AST. Finds functions that need to be - * marked `override` and adds the keyword to the function header. - */ -class OverridingFunction: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - using Contracts = std::set; - - void endVisit(frontend::ContractDefinition const& _contract) override; - - std::string appendOverride( - frontend::FunctionDefinition const& _function, - Contracts const& _expectedContracts - ); -}; - -/** - * Module that performs analysis on the AST. Finds functions that need to be - * marked `virtual` and adds the keyword to the function header. - */ -class VirtualFunction: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - void endVisit(frontend::ContractDefinition const& _function) override; - - std::string appendVirtual(frontend::FunctionDefinition const& _function) const; -}; - -} diff --git a/tools/solidityUpgrade/Upgrade070.cpp b/tools/solidityUpgrade/Upgrade070.cpp deleted file mode 100644 index 6a26b14008..0000000000 --- a/tools/solidityUpgrade/Upgrade070.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - 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. - -n You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -#include -#include - -using namespace solidity::frontend; -using namespace solidity::tools; - -void DotSyntax::endVisit(FunctionCall const& _functionCall) -{ - Type const* type = _functionCall.annotation().type; - if (auto const funcType = dynamic_cast(type)) - { - if (funcType->valueSet()) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - _functionCall.location(), - SourceTransform{m_charStreamProvider}.valueUpdate(_functionCall.location()) - ); - - if (funcType->gasSet()) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - _functionCall.location(), - SourceTransform{m_charStreamProvider}.gasUpdate(_functionCall.location()) - ); - } -} - -void NowKeyword::endVisit(Identifier const& _identifier) -{ - IdentifierAnnotation& annotation = _identifier.annotation(); - - if ( - MagicVariableDeclaration const* magicVar = - dynamic_cast(annotation.referencedDeclaration) - ) - if (magicVar->type()->category() == Type::Category::Integer) - { - solAssert(_identifier.name() == "now", ""); - m_changes.emplace_back( - UpgradeChange::Level::Safe, - _identifier.location(), - SourceTransform{m_charStreamProvider}.nowUpdate(_identifier.location()) - ); - } -} - -void ConstructorVisibility::endVisit(ContractDefinition const& _contract) -{ - if (!_contract.abstract()) - for (FunctionDefinition const* function: _contract.definedFunctions()) - if ( - function->isConstructor() && - !function->noVisibilitySpecified() && - function->visibility() == Visibility::Internal - ) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - _contract.location(), - SourceTransform{m_charStreamProvider}.insertBeforeKeyword(_contract.location(), "contract", "abstract") - ); - - for (FunctionDefinition const* function: _contract.definedFunctions()) - if (function->isConstructor() && !function->noVisibilitySpecified()) - m_changes.emplace_back( - UpgradeChange::Level::Safe, - function->location(), - SourceTransform{m_charStreamProvider}.removeVisibility(function->location()) - ); -} diff --git a/tools/solidityUpgrade/Upgrade070.h b/tools/solidityUpgrade/Upgrade070.h deleted file mode 100644 index b99f9d306a..0000000000 --- a/tools/solidityUpgrade/Upgrade070.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - 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 . -*/ -#pragma once - -#include - -#include - -namespace solidity::tools -{ - -class DotSyntax: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - void endVisit(frontend::FunctionCall const& _expression) override; -}; - -class NowKeyword: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - void endVisit(frontend::Identifier const& _expression) override; -}; - -class ConstructorVisibility: public AnalysisUpgrade -{ -public: - using AnalysisUpgrade::AnalysisUpgrade; - void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } -private: - void endVisit(frontend::ContractDefinition const& _contract) override; -}; - -} diff --git a/tools/solidityUpgrade/UpgradeChange.cpp b/tools/solidityUpgrade/UpgradeChange.cpp deleted file mode 100644 index ce1627d0a7..0000000000 --- a/tools/solidityUpgrade/UpgradeChange.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#include - -#include -#include -#include - -using namespace std; -using namespace solidity; -using namespace solidity::langutil; -using namespace solidity::util; -using namespace solidity::tools; - -string UpgradeChange::apply(string _source) const -{ - _source.replace( - static_cast(m_location.start), - static_cast(m_location.end - m_location.start), - m_patch - ); - return _source; -} - -void UpgradeChange::log(CharStreamProvider const& _charStreamProvider, bool const _shorten) const -{ - stringstream os; - SourceReferenceFormatter formatter{os, _charStreamProvider, true, false}; - - string start = to_string(m_location.start); - string end = to_string(m_location.end); - - auto color = m_level == Level::Unsafe ? formatting::MAGENTA : formatting::CYAN; - auto level = m_level == Level::Unsafe ? "unsafe" : "safe"; - - os << endl; - AnsiColorized(os, true, {formatting::BOLD, color}) << "Upgrade change (" << level << ")" << endl; - os << "=======================" << endl; - formatter.printSourceLocation(SourceReferenceExtractor::extract(_charStreamProvider, &m_location)); - os << endl; - - LineColumn lineEnd = _charStreamProvider.charStream(*m_location.sourceName).translatePositionToLineColumn(m_location.end); - int const leftpad = static_cast(log10(max(lineEnd.line, 1))) + 2; - - stringstream output; - output << (_shorten ? shortenSource(m_patch) : m_patch); - - string line; - while (getline(output, line)) - { - os << string(static_cast(leftpad), ' '); - AnsiColorized(os, true, {formatting::BOLD, formatting::BLUE}) << "| "; - AnsiColorized(os, true, {}) << line << endl; - } - cout << os.str(); - cout << endl; -} - -string UpgradeChange::shortenSource(string const& _source) -{ - size_t constexpr maxSourceLength = 1000; - if (_source.size() > maxSourceLength) - return _source.substr(0, min(_source.size(), maxSourceLength)) + "..."; - return _source; -} diff --git a/tools/solidityUpgrade/UpgradeChange.h b/tools/solidityUpgrade/UpgradeChange.h deleted file mode 100644 index 6cccc154bc..0000000000 --- a/tools/solidityUpgrade/UpgradeChange.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - 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 . -*/ -#pragma once - -#include - -#include -#include - -#include -#include - -namespace solidity::tools -{ - -/** - * Models a single source code change, based on the initial source location - * and a patch, which needs to be applied. - * It implements the concept of level of confidence in the change and distiguishes - * safe from unsafe changes. A "safe" change is considered to not break - * compilation or change semantics. An "unsafe" change is considered to potentially - * change semantics or require further manual management. - */ -class UpgradeChange -{ -public: - enum class Level - { - Safe, - Unsafe - }; - - UpgradeChange( - Level _level, - langutil::SourceLocation _location, - std::string _patch - ): - m_location(_location), - m_patch(std::move(_patch)), - m_level(_level) - {} - - ~UpgradeChange() {} - - langutil::SourceLocation const& location() const { return m_location; } - std::string patch() const { return m_patch; } - Level level() const { return m_level; } - - /// Performs the actual replacement on the provided original source code - /// and returns the modified source code. - std::string apply(std::string _source) const; - /// Does a pretty-print of this upgrade change. Since the patch - /// can contain a lot of code lines, it can be shortened, which is signaled - /// by setting the flag. - void log(langutil::CharStreamProvider const& _charStreamProvider, bool const _shorten = true) const; -private: - langutil::SourceLocation m_location; - std::string m_patch; - Level m_level; - - /// Shortens the given source to a constant limit. - static std::string shortenSource(std::string const& _source); -}; - -} diff --git a/tools/solidityUpgrade/UpgradeSuite.h b/tools/solidityUpgrade/UpgradeSuite.h deleted file mode 100644 index 2bde6ec0e2..0000000000 --- a/tools/solidityUpgrade/UpgradeSuite.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#pragma once - -#include - -#include -#include - -#include -#include - -#include - -namespace solidity::tools -{ - -/** - * The base upgrade module that can be inherited from. Doing so - * creates a basic upgrade module that facilitates access to - * change reporting. - */ -class Upgrade -{ -public: - Upgrade( - langutil::CharStreamProvider const& _charStreamProvider, - std::vector& _changes - ): m_changes(_changes), m_charStreamProvider(_charStreamProvider) {} - -protected: - /// A reference to a suite-specific set of changes. - /// It is passed to all upgrade modules and meant to collect - /// reported changes. - std::vector& m_changes; - langutil::CharStreamProvider const& m_charStreamProvider; -}; - -/** - * A specific upgrade module meant to be run after the analysis phase - * of the compiler. - */ -class AnalysisUpgrade: public Upgrade, public frontend::ASTConstVisitor -{ -public: - AnalysisUpgrade( - langutil::CharStreamProvider const& _charStreamProvider, - std::vector& _changes - ): - Upgrade(_charStreamProvider, _changes), - m_errorReporter(m_errors), - m_overrideChecker(m_errorReporter) - {} - /// Interface function for all upgrade modules that are meant - /// be run after the analysis phase of the compiler. - void analyze(frontend::SourceUnit const&) {} -protected: - langutil::ErrorList m_errors; - langutil::ErrorReporter m_errorReporter; - frontend::OverrideChecker m_overrideChecker; -}; - -/** - * The generic upgrade suite. Should be inherited from for each set of - * desired upgrade modules. - */ -class UpgradeSuite -{ -public: - /// The base interface function that needs to be implemented for each - /// suite. It should create suite-specific upgrade modules and trigger - /// their analysis. - void analyze(frontend::SourceUnit const& _sourceUnit); - /// Resets all changes collected so far. - void reset() { m_changes.clear(); } - - std::vector& changes() { return m_changes; } - std::vector const& changes() const { return m_changes; } - -protected: - std::vector m_changes; -}; - -} diff --git a/tools/solidityUpgrade/contracts/DocsExamplePass.sol b/tools/solidityUpgrade/contracts/DocsExamplePass.sol deleted file mode 100644 index d8e4dc8e09..0000000000 --- a/tools/solidityUpgrade/contracts/DocsExamplePass.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity >0.4.23; - -contract Updateable { - function run() public view returns (bool); - function update() public; -} - -contract Upgradable { - function run() public view returns (bool); - function upgrade(); -} - -contract Source is Updateable, Upgradable { - function Source() public {} - - function run() - public - view - returns (bool) {} - - function update() {} - function upgrade() {} -} \ No newline at end of file diff --git a/tools/solidityUpgrade/contracts/Test.sol b/tools/solidityUpgrade/contracts/Test.sol deleted file mode 100644 index 8958a091a0..0000000000 --- a/tools/solidityUpgrade/contracts/Test.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity >0.4.23; - -contract Storage { - function Storage() public {} - function start(); - function state() public view returns (bool); - function stop() public; -} - -contract Observable { - function state() public view returns (bool); -} - -contract VolatileStorage is Storage, Observable { - function start() {} - function state() public view returns (bool) {} - function stop() {} -} \ No newline at end of file diff --git a/tools/solidityUpgrade/contracts/TestMultiline.sol b/tools/solidityUpgrade/contracts/TestMultiline.sol deleted file mode 100644 index 7083da4ea6..0000000000 --- a/tools/solidityUpgrade/contracts/TestMultiline.sol +++ /dev/null @@ -1,21 +0,0 @@ -pragma solidity >0.4.23; - -contract Storage { - function Storage() {} - function init() public; - function idle(); - function destroy() public view; -} - -contract VolatileStorage is Storage { - function init() - public - {} - - function idle() {} - - function destroy() - public - view - {} -} \ No newline at end of file diff --git a/tools/solidityUpgrade/contracts/TestNonFixable.sol b/tools/solidityUpgrade/contracts/TestNonFixable.sol deleted file mode 100644 index 0a5c2f00e8..0000000000 --- a/tools/solidityUpgrade/contracts/TestNonFixable.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity >0.4.23; - -contract Storage { - function Storage() {} - function init() public; - function idle(); - function destroy() public view; -} - -contract VolatileStorage is Storage { - uint[] array; - function init() public { array.length = 3; } - function idle() {} - function destroy() public view {} -} \ No newline at end of file diff --git a/tools/solidityUpgrade/main.cpp b/tools/solidityUpgrade/main.cpp deleted file mode 100644 index 5a6962661d..0000000000 --- a/tools/solidityUpgrade/main.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - 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 . -*/ -// SPDX-License-Identifier: GPL-3.0 -#include - -#include -#include - -//#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if defined(_WIN32) -#include -#endif - -using namespace solidity; -using namespace std; -namespace po = boost::program_options; -namespace fs = boost::filesystem; - -namespace -{ - -void setupTerminal() -{ -#if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) - // Set output mode to handle virtual terminal (ANSI escape sequences) - // ignore any error, as this is just a "nice-to-have" - // only windows needs to be taken care of, as other platforms (Linux/OSX) support them natively. - HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (hOut == INVALID_HANDLE_VALUE) - return; - - DWORD dwMode = 0; - if (!GetConsoleMode(hOut, &dwMode)) - return; - - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if (!SetConsoleMode(hOut, dwMode)) - return; -#endif -} - -} - -int main(int argc, char** argv) -{ - setupTerminal(); - - tools::SourceUpgrade upgrade; - if (!upgrade.parseArguments(argc, argv)) - return 1; - upgrade.printPrologue(); - - try - { - if (!upgrade.processInput()) - return 1; - } - catch (boost::exception const& _exception) - { - cerr << "Exception while processing input:" << endl; - cerr << boost::diagnostic_information(_exception) << endl; - return 2; - } - catch (...) - { - cerr << "Uncaught exception while processing input:" << endl; - cerr << boost::current_exception_diagnostic_information() << endl; - return 2; - } - - return 0; -} From 7779b6f3523a7c6951cbacac2cd323a260fe035a Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 10 Jan 2023 18:16:56 -0300 Subject: [PATCH 0033/1140] Forbid private library functions to be attached outside their declaration scope --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 25 +++++++++++++++++++ .../using/private_library_function.sol | 10 ++++++++ .../private_library_function_inside_scope.sol | 5 ++++ ...private_library_function_outside_scope.sol | 12 +++++++++ 5 files changed, 53 insertions(+) create mode 100644 test/libsolidity/semanticTests/using/private_library_function.sol create mode 100644 test/libsolidity/syntaxTests/using/private_library_function_inside_scope.sol create mode 100644 test/libsolidity/syntaxTests/using/private_library_function_outside_scope.sol diff --git a/Changelog.md b/Changelog.md index b77be4f396..aaadcae9db 100644 --- a/Changelog.md +++ b/Changelog.md @@ -30,6 +30,7 @@ Bugfixes: * SMTChecker: Fix internal error on chain assignments using static fully specified state variables. * SMTChecker: Fix internal error when using user defined types as mapping indices or struct members. * SMTChecker: Fix internal error when deleting struct member of function type. + * TypeChecker: Fix bug where private library functions could be attached with ``using for`` outside of their declaration scope. ### 0.8.17 (2022-09-08) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 93558ff89a..00c763a90b 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3809,6 +3809,10 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) m_errorReporter.fatalTypeError( 4731_error, path->location(), + SecondarySourceLocation().append( + "Function defined here:", + functionDefinition.location() + ), fmt::format( "The function \"{}\" does not have any parameters, and therefore cannot be attached to the type \"{}\".", joinHumanReadable(path->path(), "."), @@ -3816,6 +3820,27 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) ) ); + if ( + functionDefinition.visibility() == Visibility::Private && + functionDefinition.scope() != m_currentContract + ) + { + solAssert(functionDefinition.libraryFunction()); + m_errorReporter.typeError( + 6772_error, + path->location(), + SecondarySourceLocation().append( + "Function defined here:", + functionDefinition.location() + ), + fmt::format( + "Function \"{}\" is private and therefore cannot be attached" + " to a type outside of the library where it is defined.", + joinHumanReadable(path->path(), ".") + ) + ); + } + FunctionType const* functionType = dynamic_cast(*functionDefinition.type()).withBoundFirstArgument(); solAssert(functionType && functionType->selfType(), ""); BoolResult result = normalizedType->isImplicitlyConvertibleTo( diff --git a/test/libsolidity/semanticTests/using/private_library_function.sol b/test/libsolidity/semanticTests/using/private_library_function.sol new file mode 100644 index 0000000000..e144049219 --- /dev/null +++ b/test/libsolidity/semanticTests/using/private_library_function.sol @@ -0,0 +1,10 @@ +library L { + using {L.privateFunction} for uint; + function privateFunction(uint x) private pure returns (uint) { return x + 1; } + function f() public pure returns (uint) { + uint x = 1; + return x.privateFunction(); + } +} +// ---- +// f() -> 2 diff --git a/test/libsolidity/syntaxTests/using/private_library_function_inside_scope.sol b/test/libsolidity/syntaxTests/using/private_library_function_inside_scope.sol new file mode 100644 index 0000000000..1f036d83b2 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/private_library_function_inside_scope.sol @@ -0,0 +1,5 @@ +library L { + using {L.privateFunction} for uint; + function privateFunction(uint) private pure {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/private_library_function_outside_scope.sol b/test/libsolidity/syntaxTests/using/private_library_function_outside_scope.sol new file mode 100644 index 0000000000..2be2010c6e --- /dev/null +++ b/test/libsolidity/syntaxTests/using/private_library_function_outside_scope.sol @@ -0,0 +1,12 @@ +library L { + function privateFunction(uint) private pure {} +} + +using {L.privateFunction} for uint; + +contract C { + using {L.privateFunction} for uint; +} +// ---- +// TypeError 6772: (73-90): Function "L.privateFunction" is private and therefore cannot be attached to a type outside of the library where it is defined. +// TypeError 6772: (127-144): Function "L.privateFunction" is private and therefore cannot be attached to a type outside of the library where it is defined. From 6df65ca1a1514c09d86752dd8b263f4d93932e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 17 Jan 2023 13:53:37 +0100 Subject: [PATCH 0034/1140] gnosis ext test: Remove workarounds that used to be necessary to make the test work with latest versions of its dependencies --- test/externalTests/gnosis.sh | 42 ++++-------------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index f33e723b6d..ace87d3b80 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -31,8 +31,8 @@ BINARY_TYPE="$1" BINARY_PATH="$(realpath "$2")" SELECTED_PRESETS="$3" -function compile_fn { npx npm run build; } -function test_fn { npx npm test; } +function compile_fn { npm run build; } +function test_fn { npm test; } function gnosis_safe_test { @@ -73,54 +73,20 @@ function gnosis_safe_test # them for other presets but that's fine - we want same code run for benchmarks to be comparable. # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). sed -i "s|\(it\)\(('should not allow to call setup on singleton'\)|\1.skip\2|g" test/core/Safe.Setup.spec.ts - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i 's|\(it\)\(("changes the expected storage slot without touching the most important ones"\)|\1.skip\2|g' test/libraries/SignMessageLib.spec.ts sed -i "s|\(it\)\(('can be used only via DELEGATECALL opcode'\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts sed -i 's|\(describe\)\(("Upgrade from Safe 1.1.1"\)|\1.skip\2|g' test/migration/UpgradeFromSafe111.spec.ts sed -i 's|\(describe\)\(("Upgrade from Safe 1.2.0"\)|\1.skip\2|g' test/migration/UpgradeFromSafe120.spec.ts - - # TODO: Remove this when Gnosis merges https://github.com/gnosis/safe-contracts/pull/394 - sed -i "s|\(function isValidSignature(bytes \)calldata\( _data, bytes \)calldata\( _signature)\)|\1memory\2memory\3|g" contracts/handler/CompatibilityFallbackHandler.sol - - # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('should enforce delegatecall'\)|it.skip\1|g" test/accessors/SimulateTxAccessor.spec.ts sed -i "s|it\(('can only be called from Safe itself'\)|it.skip\1|g" test/libraries/Migration.spec.ts sed -i "s|it\(('should enforce delegatecall to MultiSend'\)|it.skip\1|g" test/libraries/MultiSend.spec.ts - # Force nested abstract-provider dependencies to be at version 5.6.0. Version 5.7.0 of @ethersproject/abstract-provider - # introduced a new field in FeeData, which causes clashes unless all dependency packages of abstract-provider are pegged - # to the same version. As we've already had to peg @ethersproject/contracts to 5.6.0 earlier, we are doing so now with - # @ethersproject/abstract-provider as well. - jq '.overrides."@ethersproject/abstract-provider"="5.6.0" | - .overrides."@ethersproject/abstract-signer@5.6.0" - ."@ethersproject/abstract-provider"="5.6.0"' package.json > package.json.tmp - mv package.json.tmp package.json - neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" - # npm@8.3.0+ is required for `overrides` support - npm install npm@>8.3.0 - npx npm install - npx npm install hardhat-gas-reporter - - # Typescript compilation fails with typescript >= 4.7: - # Error: Debug Failure. False expression: Non-string value passed to `ts.resolveTypeReferenceDirective` - npx npm install "typescript@<4.7.0" - - # With ethers.js 5.6.2 many tests for revert messages fail. - # TODO: Remove when https://github.com/ethers-io/ethers.js/discussions/2849 is resolved. - npx npm install ethers@5.6.1 - - # Note that ethers@5.6.1 depends on @ethersproject/contracts@5.6.0 while the dependency on hardhat-deploy - # pulls @ethersproject/contracts@5.6.1 (latest). Force 5.6.0 to avoid errors due to having two copies. - npx npm install @ethersproject/contracts@5.6.0 - - # 2.1.1 started causing failures in safe-contracts external tests after a contract address check was introduced - # in https://github.com/NomicFoundation/hardhat/pull/2916, and so to avoid errors, the package is now pegged. - # TODO: Remove when https://github.com/safe-global/safe-contracts/issues/436 is resolved. - npx npm install @nomiclabs/hardhat-ethers@2.1.0 + npm install + npm install hardhat-gas-reporter replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist" From a9757e963eb2f1c7beb8de0cc3792836036d00ea Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 18 Jan 2023 09:24:23 +0000 Subject: [PATCH 0035/1140] Remove more workarounds --- test/externalTests/gnosis.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index ace87d3b80..ab1fbf3e17 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -73,13 +73,8 @@ function gnosis_safe_test # them for other presets but that's fine - we want same code run for benchmarks to be comparable. # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). sed -i "s|\(it\)\(('should not allow to call setup on singleton'\)|\1.skip\2|g" test/core/Safe.Setup.spec.ts - sed -i 's|\(it\)\(("changes the expected storage slot without touching the most important ones"\)|\1.skip\2|g' test/libraries/SignMessageLib.spec.ts sed -i "s|\(it\)\(('can be used only via DELEGATECALL opcode'\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts - sed -i 's|\(describe\)\(("Upgrade from Safe 1.1.1"\)|\1.skip\2|g' test/migration/UpgradeFromSafe111.spec.ts - sed -i 's|\(describe\)\(("Upgrade from Safe 1.2.0"\)|\1.skip\2|g' test/migration/UpgradeFromSafe120.spec.ts - sed -i "s|it\(('should enforce delegatecall'\)|it.skip\1|g" test/accessors/SimulateTxAccessor.spec.ts sed -i "s|it\(('can only be called from Safe itself'\)|it.skip\1|g" test/libraries/Migration.spec.ts - sed -i "s|it\(('should enforce delegatecall to MultiSend'\)|it.skip\1|g" test/libraries/MultiSend.spec.ts neutralize_package_lock neutralize_package_json_hooks From c2e2adb953a397b322eb875a42d58406fee64a15 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 18 Jan 2023 09:01:33 +0100 Subject: [PATCH 0036/1140] Allow support for older boost and adjust docs --- docs/installing-solidity.rst | 7 ++++--- libsolidity/lsp/LanguageServer.cpp | 6 +++++- libsolutil/Common.h | 3 --- libsolutil/Numeric.h | 3 --- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 1b6ac66354..8c2830451c 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -319,9 +319,10 @@ The following are dependencies for all builds of Solidity: +-----------------------------------+-------------------------------------------------------+ | Software | Notes | +===================================+=======================================================+ -| `CMake`_ (version 3.13+) | Cross-platform build file generator. | +| `CMake`_ (version 3.21.3+ on | Cross-platform build file generator. | +| Windows, 3.13+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ -| `Boost`_ (version 1.77+ on | C++ libraries. | +| `Boost`_ (version 1.77 on | C++ libraries. | | Windows, 1.65+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Git`_ | Command-line tool for retrieving source code. | @@ -408,7 +409,7 @@ You need to install the following dependencies for Windows builds of Solidity: +-----------------------------------+-------------------------------------------------------+ | `Visual Studio 2019`_ (Optional) | C++ compiler and dev environment. | +-----------------------------------+-------------------------------------------------------+ -| `Boost`_ (version 1.77+) | C++ libraries. | +| `Boost`_ (version 1.77) | C++ libraries. | +-----------------------------------+-------------------------------------------------------+ If you already have one IDE and only need the compiler and libraries, diff --git a/libsolidity/lsp/LanguageServer.cpp b/libsolidity/lsp/LanguageServer.cpp index 2d85c08b0e..aaa63b7f84 100644 --- a/libsolidity/lsp/LanguageServer.cpp +++ b/libsolidity/lsp/LanguageServer.cpp @@ -220,8 +220,12 @@ vector LanguageServer::allSolidityFilesFromProject() co // We explicitly decided against including all files from include paths but leave the possibility // open for a future PR to enable such a feature to be optionally enabled (default disabled). - + // Note: Newer versions of boost have deprecated symlink_option::recurse +#if (BOOST_VERSION < 107200) + auto directoryIterator = fs::recursive_directory_iterator(m_fileRepository.basePath(), fs::symlink_option::recurse); +#else auto directoryIterator = fs::recursive_directory_iterator(m_fileRepository.basePath(), fs::directory_options::follow_directory_symlink); +#endif for (fs::directory_entry const& dirEntry: directoryIterator) if ( dirEntry.path().extension() == ".sol" && diff --git a/libsolutil/Common.h b/libsolutil/Common.h index 5c78146137..eea9dacd54 100644 --- a/libsolutil/Common.h +++ b/libsolutil/Common.h @@ -41,9 +41,6 @@ #include #include -#if (BOOST_VERSION < 106500) -#error "Unsupported Boost version. At least 1.65 required." -#endif #include #include diff --git a/libsolutil/Numeric.h b/libsolutil/Numeric.h index c0f33e4906..be9f0bea24 100644 --- a/libsolutil/Numeric.h +++ b/libsolutil/Numeric.h @@ -25,9 +25,6 @@ #include #include -#if (BOOST_VERSION < 106500) -#error "Unsupported Boost version. At least 1.65 required." -#endif // TODO: do this only conditionally as soon as a boost version with gcc 12 support is released. #if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12) From 6a0ea174b845efffeac2c854132a7659af10340e Mon Sep 17 00:00:00 2001 From: vlad Date: Sat, 17 Dec 2022 14:16:24 +0400 Subject: [PATCH 0037/1140] Disallow several indexed attributes for the same event parameter --- Changelog.md | 1 + libsolidity/parsing/Parser.cpp | 5 +++++ .../events/event_several_indexed_of_one_parameter.sol | 9 +++++++++ 3 files changed, 15 insertions(+) create mode 100644 test/libsolidity/syntaxTests/events/event_several_indexed_of_one_parameter.sol diff --git a/Changelog.md b/Changelog.md index a665eb5761..954518dc5d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Compiler Features: Bugfixes: + * Parser: Disallow several ``indexed`` attributes for the same event parameter. * Yul Optimizer: Hash hex and decimal literals according to their value instead of their representation, improving the detection of equivalent functions. * Solidity Upgrade Tool ``solidity-upgrade``: Fix the tool returning success code on uncaught exceptions. * SMTChecker: Fix display error for negative integers that are one more than powers of two. diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index fee21e5184..e028b13ac6 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -785,7 +785,12 @@ ASTPointer Parser::parseVariableDeclaration( else { if (_options.allowIndexed && token == Token::Indexed) + { + if (isIndexed) + parserError(5399_error, "Indexed already specified."); + isIndexed = true; + } else if (token == Token::Constant || token == Token::Immutable) { if (mutability != VariableDeclaration::Mutability::Mutable) diff --git a/test/libsolidity/syntaxTests/events/event_several_indexed_of_one_parameter.sol b/test/libsolidity/syntaxTests/events/event_several_indexed_of_one_parameter.sol new file mode 100644 index 0000000000..dd6edd825e --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_several_indexed_of_one_parameter.sol @@ -0,0 +1,9 @@ +contract c { + event e(uint indexed a, bytes3 indexed indexed s, bool indexed indexed indexed b); + event e2(uint indexed indexed a, bytes3 indexed s); +} +// ---- +// ParserError 5399: (56-63): Indexed already specified. +// ParserError 5399: (80-87): Indexed already specified. +// ParserError 5399: (88-95): Indexed already specified. +// ParserError 5399: (126-133): Indexed already specified. From 7fbd36855d643f09f591613961c367396c858e31 Mon Sep 17 00:00:00 2001 From: vlad Date: Sun, 25 Dec 2022 20:14:23 +0400 Subject: [PATCH 0038/1140] Disallow usage of the indexed attribute for modifier parameters Added tests for edge cases of several keywords --- Changelog.md | 1 + libsolidity/parsing/Parser.cpp | 1 - .../syntaxTests/modifiers/invalid_parameter_indexed.sol | 5 +++++ 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/modifiers/invalid_parameter_indexed.sol diff --git a/Changelog.md b/Changelog.md index 954518dc5d..2877bbf8c5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -23,6 +23,7 @@ Compiler Features: Bugfixes: * Parser: Disallow several ``indexed`` attributes for the same event parameter. + * Parser: Disallow usage of the ``indexed`` attribute for modifier parameters. * Yul Optimizer: Hash hex and decimal literals according to their value instead of their representation, improving the detection of equivalent functions. * Solidity Upgrade Tool ``solidity-upgrade``: Fix the tool returning success code on uncaught exceptions. * SMTChecker: Fix display error for negative integers that are one more than powers of two. diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index e028b13ac6..a9065b176b 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -879,7 +879,6 @@ ASTPointer Parser::parseModifierDefinition() if (m_scanner->currentToken() == Token::LParen) { VarDeclParserOptions options; - options.allowIndexed = true; options.allowLocationSpecifier = true; parameters = parseParameterList(options); } diff --git a/test/libsolidity/syntaxTests/modifiers/invalid_parameter_indexed.sol b/test/libsolidity/syntaxTests/modifiers/invalid_parameter_indexed.sol new file mode 100644 index 0000000000..a19d7beb2d --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/invalid_parameter_indexed.sol @@ -0,0 +1,5 @@ +contract B { + modifier mod1(uint indexed a) { _; } +} +// ---- +// ParserError 2314: (36-43): Expected ',' but got 'indexed' From 484ee8a62162680acea3fbc37ab2a8eadc5758dd Mon Sep 17 00:00:00 2001 From: vlad Date: Thu, 29 Dec 2022 23:43:12 +0400 Subject: [PATCH 0039/1140] Additional tests for edge cases for mutability, visibility, location, experimental, global, indexed and anonymous --- .../file_level_multiple_constant_keywords.sol | 4 + ...ddress_state_mutability_error_argument.sol | 85 +++++++++ .../errors/invalid_parameter_indexed.sol | 5 + .../errors/invalid_parameter_location.sol | 16 ++ .../errors/invalid_parameter_mutability.sol | 7 + .../errors/invalid_parameter_visibility.sol | 21 +++ ...us_event_multiple_anonymous_specifiers.sol | 5 + ...ddress_state_mutability_event_argument.sol | 85 +++++++++ ...ent_multiple_indexed_of_one_parameter.sol} | 0 .../events/invalid_parameter_location.sol | 16 ++ .../events/invalid_parameter_mutability.sol | 7 + .../events/invalid_parameter_visibility.sol | 21 +++ ...ess_state_mutability_modifier_argument.sol | 85 +++++++++ .../invalid_parameter_mutability.sol | 7 + .../invalid_parameter_visibility.sol | 21 +++ .../modifiers/multiple_parameter_location.sol | 21 +++ .../address_invalid_state_mutability.sol | 70 +++++--- ...ary_non_address_payable_state_variable.sol | 29 ---- ...lementary_non_address_payable_argument.sol | 29 ---- .../elementary_non_address_payable_local.sol | 31 ---- .../elementary_non_address_payable_return.sol | 29 ---- ..._non_address_state_mutability_argument.sol | 85 +++++++++ ..._non_address_state_mutability_file_var.sol | 81 +++++++++ ...ary_non_address_state_mutability_local.sol | 91 ++++++++++ ...ry_non_address_state_mutability_return.sol | 85 +++++++++ ...ddress_state_mutability_state_variable.sol | 85 +++++++++ ...ction_parameter_and_return_var_indexed.sol | 11 ++ ...on_parameter_and_return_var_mutability.sol | 9 + .../invalid_state_variable_location.sol | 11 ++ .../parsing/invalid_variable_indexed.sol | 16 ++ .../parsing/invalid_variable_mutablity.sol | 15 ++ ...location_specifiers_for_file_level_var.sol | 10 ++ ...cation_specifiers_for_fn_returns_multi.sol | 21 +++ .../location_specifiers_for_locals_multi.sol | 16 ++ .../location_specifiers_for_params_multi.sol | 14 ++ ...n_specifiers_for_state_variables_multi.sol | 8 +- .../multiple_mutability_specifiers.sol | 11 ++ .../multiple_state_mutability_specifiers.sol | 103 +++++++++++ .../multiple_statemutability_specifiers.sol | 29 ---- .../multiple_visibility_specifiers.sol | 7 - .../syntaxTests/parsing/payable_accessor.sol | 5 - .../experimental_multiple_experimental.sol | 4 + ...ary_non_address_state_mutability_catch.sol | 31 ++++ ...n_address_state_mutability_try_returns.sol | 163 ++++++++++++++++++ ...alid_catch_parameter_location_calldata.sol | 7 + ...valid_catch_parameter_location_storage.sol | 7 + .../tryCatch/invalid_returns_var_location.sol | 7 + ...turns_vars_and_catch_parameter_indexed.sol | 27 +++ ...ns_vars_and_catch_parameter_mutability.sol | 30 ++++ ...ns_vars_and_catch_parameter_visibility.sol | 105 +++++++++++ ...urns_vars_and_catch_parameter_location.sol | 132 ++++++++++++++ .../using/global_multiple_global_keywords.sol | 5 + .../file_level_variable_visibility.sol | 13 ++ ...on_parameter_and_return_var_visibility.sol | 41 +++++ .../invalid_variable_visibility.sol | 29 ++++ .../multiple_visibility_specifiers.sol | 53 ++++++ ...ultiple_visibility_specifiers_external.sol | 16 ++ 57 files changed, 1794 insertions(+), 183 deletions(-) create mode 100644 test/libsolidity/syntaxTests/constants/file_level_multiple_constant_keywords.sol create mode 100644 test/libsolidity/syntaxTests/errors/elementary_non_address_state_mutability_error_argument.sol create mode 100644 test/libsolidity/syntaxTests/errors/invalid_parameter_indexed.sol create mode 100644 test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol create mode 100644 test/libsolidity/syntaxTests/errors/invalid_parameter_mutability.sol create mode 100644 test/libsolidity/syntaxTests/errors/invalid_parameter_visibility.sol create mode 100644 test/libsolidity/syntaxTests/events/anonymous_event_multiple_anonymous_specifiers.sol create mode 100644 test/libsolidity/syntaxTests/events/elementary_non_address_state_mutability_event_argument.sol rename test/libsolidity/syntaxTests/events/{event_several_indexed_of_one_parameter.sol => event_multiple_indexed_of_one_parameter.sol} (100%) create mode 100644 test/libsolidity/syntaxTests/events/invalid_parameter_location.sol create mode 100644 test/libsolidity/syntaxTests/events/invalid_parameter_mutability.sol create mode 100644 test/libsolidity/syntaxTests/events/invalid_parameter_visibility.sol create mode 100644 test/libsolidity/syntaxTests/modifiers/elementary_non_address_state_mutability_modifier_argument.sol create mode 100644 test/libsolidity/syntaxTests/modifiers/invalid_parameter_mutability.sol create mode 100644 test/libsolidity/syntaxTests/modifiers/invalid_parameter_visibility.sol create mode 100644 test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol delete mode 100644 test/libsolidity/syntaxTests/parsing/elemantary_non_address_payable_state_variable.sol delete mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_argument.sol delete mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_local.sol delete mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_return.sol create mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_argument.sol create mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_file_var.sol create mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_local.sol create mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_return.sol create mode 100644 test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_state_variable.sol create mode 100644 test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_indexed.sol create mode 100644 test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_mutability.sol create mode 100644 test/libsolidity/syntaxTests/parsing/invalid_state_variable_location.sol create mode 100644 test/libsolidity/syntaxTests/parsing/invalid_variable_indexed.sol create mode 100644 test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol create mode 100644 test/libsolidity/syntaxTests/parsing/location_specifiers_for_file_level_var.sol create mode 100644 test/libsolidity/syntaxTests/parsing/location_specifiers_for_fn_returns_multi.sol create mode 100644 test/libsolidity/syntaxTests/parsing/multiple_mutability_specifiers.sol create mode 100644 test/libsolidity/syntaxTests/parsing/multiple_state_mutability_specifiers.sol delete mode 100644 test/libsolidity/syntaxTests/parsing/multiple_statemutability_specifiers.sol delete mode 100644 test/libsolidity/syntaxTests/parsing/multiple_visibility_specifiers.sol delete mode 100644 test/libsolidity/syntaxTests/parsing/payable_accessor.sol create mode 100644 test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_catch.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_try_returns.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_calldata.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_storage.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_returns_var_location.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_indexed.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_mutability.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_visibility.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/multiple_returns_vars_and_catch_parameter_location.sol create mode 100644 test/libsolidity/syntaxTests/using/global_multiple_global_keywords.sol create mode 100644 test/libsolidity/syntaxTests/visibility/file_level_variable_visibility.sol create mode 100644 test/libsolidity/syntaxTests/visibility/invalid_function_parameter_and_return_var_visibility.sol create mode 100644 test/libsolidity/syntaxTests/visibility/invalid_variable_visibility.sol create mode 100644 test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers.sol create mode 100644 test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers_external.sol diff --git a/test/libsolidity/syntaxTests/constants/file_level_multiple_constant_keywords.sol b/test/libsolidity/syntaxTests/constants/file_level_multiple_constant_keywords.sol new file mode 100644 index 0000000000..1ca07c6607 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/file_level_multiple_constant_keywords.sol @@ -0,0 +1,4 @@ +uint constant constant x; +// ---- +// ParserError 3109: (14-22): Mutability already set to "constant" + diff --git a/test/libsolidity/syntaxTests/errors/elementary_non_address_state_mutability_error_argument.sol b/test/libsolidity/syntaxTests/errors/elementary_non_address_state_mutability_error_argument.sol new file mode 100644 index 0000000000..110af7e34c --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/elementary_non_address_state_mutability_error_argument.sol @@ -0,0 +1,85 @@ +contract C { + error a(bool payable); + error b(string payable); + error c(int payable); + error d(int256 payable); + error e(uint payable); + error f(uint256 payable); + error g(bytes1 payable); + error h(bytes payable); + error i(bytes32 payable); + error j(fixed payable); + error k(fixed80x80 payable); + error l(ufixed payable); + error m(ufixed80x80 payable); +} +contract C2 { + error a(bool view); + error b(string view); + error c(int view); + error d(int256 view); + error e(uint view); + error f(uint256 view); + error g(bytes1 view); + error h(bytes view); + error i(bytes32 view); + error j(fixed view); + error k(fixed80x80 view); + error l(ufixed view); + error m(ufixed80x80 view); +} +contract C3 { + error a(bool pure); + error b(string pure); + error c(int pure); + error d(int256 pure); + error e(uint pure); + error f(uint256 pure); + error g(bytes1 pure); + error h(bytes pure); + error i(bytes32 pure); + error j(fixed pure); + error k(fixed80x80 pure); + error l(ufixed pure); + error m(ufixed80x80 pure); +} +// ---- +// ParserError 9106: (30-37): State mutability can only be specified for address types. +// ParserError 9106: (59-66): State mutability can only be specified for address types. +// ParserError 9106: (85-92): State mutability can only be specified for address types. +// ParserError 9106: (114-121): State mutability can only be specified for address types. +// ParserError 9106: (141-148): State mutability can only be specified for address types. +// ParserError 9106: (171-178): State mutability can only be specified for address types. +// ParserError 9106: (200-207): State mutability can only be specified for address types. +// ParserError 9106: (228-235): State mutability can only be specified for address types. +// ParserError 9106: (258-265): State mutability can only be specified for address types. +// ParserError 9106: (286-293): State mutability can only be specified for address types. +// ParserError 9106: (319-326): State mutability can only be specified for address types. +// ParserError 9106: (348-355): State mutability can only be specified for address types. +// ParserError 9106: (382-389): State mutability can only be specified for address types. +// ParserError 9106: (425-429): State mutability can only be specified for address types. +// ParserError 9106: (451-455): State mutability can only be specified for address types. +// ParserError 9106: (474-478): State mutability can only be specified for address types. +// ParserError 9106: (500-504): State mutability can only be specified for address types. +// ParserError 9106: (524-528): State mutability can only be specified for address types. +// ParserError 9106: (551-555): State mutability can only be specified for address types. +// ParserError 9106: (577-581): State mutability can only be specified for address types. +// ParserError 9106: (602-606): State mutability can only be specified for address types. +// ParserError 9106: (629-633): State mutability can only be specified for address types. +// ParserError 9106: (654-658): State mutability can only be specified for address types. +// ParserError 9106: (684-688): State mutability can only be specified for address types. +// ParserError 9106: (710-714): State mutability can only be specified for address types. +// ParserError 9106: (741-745): State mutability can only be specified for address types. +// ParserError 9106: (781-785): State mutability can only be specified for address types. +// ParserError 9106: (807-811): State mutability can only be specified for address types. +// ParserError 9106: (830-834): State mutability can only be specified for address types. +// ParserError 9106: (856-860): State mutability can only be specified for address types. +// ParserError 9106: (880-884): State mutability can only be specified for address types. +// ParserError 9106: (907-911): State mutability can only be specified for address types. +// ParserError 9106: (933-937): State mutability can only be specified for address types. +// ParserError 9106: (958-962): State mutability can only be specified for address types. +// ParserError 9106: (985-989): State mutability can only be specified for address types. +// ParserError 9106: (1010-1014): State mutability can only be specified for address types. +// ParserError 9106: (1040-1044): State mutability can only be specified for address types. +// ParserError 9106: (1066-1070): State mutability can only be specified for address types. +// ParserError 9106: (1097-1101): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/errors/invalid_parameter_indexed.sol b/test/libsolidity/syntaxTests/errors/invalid_parameter_indexed.sol new file mode 100644 index 0000000000..99b629cd37 --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/invalid_parameter_indexed.sol @@ -0,0 +1,5 @@ +contract C { + error e1(uint indexed x); +} +// ---- +// ParserError 2314: (31-38): Expected ',' but got 'indexed' \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol b/test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol new file mode 100644 index 0000000000..a116188d23 --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol @@ -0,0 +1,16 @@ +==== Source: A ==== +contract test { + error e1(string storage a); +} +==== Source: B ==== +contract test { + error e1(string memory a); +} +==== Source: C ==== +contract test { + error e1(string calldata a); +} +// ---- +// ParserError 2314: (A:36-43): Expected ',' but got 'storage' +// ParserError 2314: (B:36-42): Expected ',' but got 'memory' +// ParserError 2314: (C:36-44): Expected ',' but got 'calldata' diff --git a/test/libsolidity/syntaxTests/errors/invalid_parameter_mutability.sol b/test/libsolidity/syntaxTests/errors/invalid_parameter_mutability.sol new file mode 100644 index 0000000000..fc5b4609b9 --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/invalid_parameter_mutability.sol @@ -0,0 +1,7 @@ +contract C { + error e1(uint constant x); + error e2(uint immutable x); +} +// ---- +// DeclarationError 1788: (26-41): The "constant" keyword can only be used for state variables or variables at file level. +// DeclarationError 8297: (57-73): The "immutable" keyword can only be used for state variables. diff --git a/test/libsolidity/syntaxTests/errors/invalid_parameter_visibility.sol b/test/libsolidity/syntaxTests/errors/invalid_parameter_visibility.sol new file mode 100644 index 0000000000..c35e759df5 --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/invalid_parameter_visibility.sol @@ -0,0 +1,21 @@ +==== Source: A ==== +contract C { + error e1(uint external x); +} +==== Source: B ==== +contract C { + error e1(uint internal x); +} +==== Source: C ==== +contract C { + error e1(uint public x); +} +==== Source: D ==== +contract C { + error e1(uint private x); +} +// ---- +// ParserError 2314: (A:31-39): Expected ',' but got 'external' +// ParserError 2314: (B:31-39): Expected ',' but got 'internal' +// ParserError 2314: (C:31-37): Expected ',' but got 'public' +// ParserError 2314: (D:31-38): Expected ',' but got 'private' diff --git a/test/libsolidity/syntaxTests/events/anonymous_event_multiple_anonymous_specifiers.sol b/test/libsolidity/syntaxTests/events/anonymous_event_multiple_anonymous_specifiers.sol new file mode 100644 index 0000000000..fd3e317b82 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/anonymous_event_multiple_anonymous_specifiers.sol @@ -0,0 +1,5 @@ +contract c { + event e(uint a) anonymous anonymous; +} +// ---- +// ParserError 2314: (43-52): Expected ';' but got 'anonymous' \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/events/elementary_non_address_state_mutability_event_argument.sol b/test/libsolidity/syntaxTests/events/elementary_non_address_state_mutability_event_argument.sol new file mode 100644 index 0000000000..a3e08411b1 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/elementary_non_address_state_mutability_event_argument.sol @@ -0,0 +1,85 @@ +contract C { + event a(bool payable); + event b(string payable); + event c(int payable); + event d(int256 payable); + event e(uint payable); + event f(uint256 payable); + event g(bytes1 payable); + event h(bytes payable); + event i(bytes32 payable); + event j(fixed payable); + event k(fixed80x80 payable); + event l(ufixed payable); + event m(ufixed80x80 payable); +} +contract C2 { + event a(bool view); + event b(string view); + event c(int view); + event d(int256 view); + event e(uint view); + event f(uint256 view); + event g(bytes1 view); + event h(bytes view); + event i(bytes32 view); + event j(fixed view); + event k(fixed80x80 view); + event l(ufixed view); + event m(ufixed80x80 view); +} +contract C3 { + event a(bool pure); + event b(string pure); + event c(int pure); + event d(int256 pure); + event e(uint pure); + event f(uint256 pure); + event g(bytes1 pure); + event h(bytes pure); + event i(bytes32 pure); + event j(fixed pure); + event k(fixed80x80 pure); + event l(ufixed pure); + event m(ufixed80x80 pure); +} +// ---- +// ParserError 9106: (30-37): State mutability can only be specified for address types. +// ParserError 9106: (59-66): State mutability can only be specified for address types. +// ParserError 9106: (85-92): State mutability can only be specified for address types. +// ParserError 9106: (114-121): State mutability can only be specified for address types. +// ParserError 9106: (141-148): State mutability can only be specified for address types. +// ParserError 9106: (171-178): State mutability can only be specified for address types. +// ParserError 9106: (200-207): State mutability can only be specified for address types. +// ParserError 9106: (228-235): State mutability can only be specified for address types. +// ParserError 9106: (258-265): State mutability can only be specified for address types. +// ParserError 9106: (286-293): State mutability can only be specified for address types. +// ParserError 9106: (319-326): State mutability can only be specified for address types. +// ParserError 9106: (348-355): State mutability can only be specified for address types. +// ParserError 9106: (382-389): State mutability can only be specified for address types. +// ParserError 9106: (425-429): State mutability can only be specified for address types. +// ParserError 9106: (451-455): State mutability can only be specified for address types. +// ParserError 9106: (474-478): State mutability can only be specified for address types. +// ParserError 9106: (500-504): State mutability can only be specified for address types. +// ParserError 9106: (524-528): State mutability can only be specified for address types. +// ParserError 9106: (551-555): State mutability can only be specified for address types. +// ParserError 9106: (577-581): State mutability can only be specified for address types. +// ParserError 9106: (602-606): State mutability can only be specified for address types. +// ParserError 9106: (629-633): State mutability can only be specified for address types. +// ParserError 9106: (654-658): State mutability can only be specified for address types. +// ParserError 9106: (684-688): State mutability can only be specified for address types. +// ParserError 9106: (710-714): State mutability can only be specified for address types. +// ParserError 9106: (741-745): State mutability can only be specified for address types. +// ParserError 9106: (781-785): State mutability can only be specified for address types. +// ParserError 9106: (807-811): State mutability can only be specified for address types. +// ParserError 9106: (830-834): State mutability can only be specified for address types. +// ParserError 9106: (856-860): State mutability can only be specified for address types. +// ParserError 9106: (880-884): State mutability can only be specified for address types. +// ParserError 9106: (907-911): State mutability can only be specified for address types. +// ParserError 9106: (933-937): State mutability can only be specified for address types. +// ParserError 9106: (958-962): State mutability can only be specified for address types. +// ParserError 9106: (985-989): State mutability can only be specified for address types. +// ParserError 9106: (1010-1014): State mutability can only be specified for address types. +// ParserError 9106: (1040-1044): State mutability can only be specified for address types. +// ParserError 9106: (1066-1070): State mutability can only be specified for address types. +// ParserError 9106: (1097-1101): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/events/event_several_indexed_of_one_parameter.sol b/test/libsolidity/syntaxTests/events/event_multiple_indexed_of_one_parameter.sol similarity index 100% rename from test/libsolidity/syntaxTests/events/event_several_indexed_of_one_parameter.sol rename to test/libsolidity/syntaxTests/events/event_multiple_indexed_of_one_parameter.sol diff --git a/test/libsolidity/syntaxTests/events/invalid_parameter_location.sol b/test/libsolidity/syntaxTests/events/invalid_parameter_location.sol new file mode 100644 index 0000000000..04ee9b7bc4 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/invalid_parameter_location.sol @@ -0,0 +1,16 @@ +==== Source: A ==== +contract test { + event e1(string storage a); +} +==== Source: B ==== +contract test { + event e1(string memory a); +} +==== Source: C ==== +contract test { + event e1(string calldata a); +} +// ---- +// ParserError 2314: (A:36-43): Expected ',' but got 'storage' +// ParserError 2314: (B:36-42): Expected ',' but got 'memory' +// ParserError 2314: (C:36-44): Expected ',' but got 'calldata' diff --git a/test/libsolidity/syntaxTests/events/invalid_parameter_mutability.sol b/test/libsolidity/syntaxTests/events/invalid_parameter_mutability.sol new file mode 100644 index 0000000000..f7314e6f59 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/invalid_parameter_mutability.sol @@ -0,0 +1,7 @@ +contract test { + event e1(uint constant a); + event e2(uint immutable a); +} +// ---- +// DeclarationError 1788: (29-44): The "constant" keyword can only be used for state variables or variables at file level. +// DeclarationError 8297: (60-76): The "immutable" keyword can only be used for state variables. diff --git a/test/libsolidity/syntaxTests/events/invalid_parameter_visibility.sol b/test/libsolidity/syntaxTests/events/invalid_parameter_visibility.sol new file mode 100644 index 0000000000..bcb6d4306d --- /dev/null +++ b/test/libsolidity/syntaxTests/events/invalid_parameter_visibility.sol @@ -0,0 +1,21 @@ +==== Source: A ==== +contract test { + event e1(uint external a); +} +==== Source: B ==== +contract test { + event e1(uint internal a); +} +==== Source: C ==== +contract test { + event e1(uint public a); +} +==== Source: D ==== +contract test { + event e1(uint private a); +} +// ---- +// ParserError 2314: (A:34-42): Expected ',' but got 'external' +// ParserError 2314: (B:34-42): Expected ',' but got 'internal' +// ParserError 2314: (C:34-40): Expected ',' but got 'public' +// ParserError 2314: (D:34-41): Expected ',' but got 'private' diff --git a/test/libsolidity/syntaxTests/modifiers/elementary_non_address_state_mutability_modifier_argument.sol b/test/libsolidity/syntaxTests/modifiers/elementary_non_address_state_mutability_modifier_argument.sol new file mode 100644 index 0000000000..568743b363 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/elementary_non_address_state_mutability_modifier_argument.sol @@ -0,0 +1,85 @@ +contract C { + modifier a(bool payable) {} + modifier b(string payable) {} + modifier c(int payable) {} + modifier d(int256 payable) {} + modifier e(uint payable) {} + modifier f(uint256 payable) {} + modifier g(bytes1 payable) {} + modifier h(bytes payable) {} + modifier i(bytes32 payable) {} + modifier j(fixed payable) {} + modifier k(fixed80x80 payable) {} + modifier l(ufixed payable) {} + modifier m(ufixed80x80 payable) {} +} +contract C2 { + modifier a(bool view) {} + modifier b(string view) {} + modifier c(int view) {} + modifier d(int256 view) {} + modifier e(uint view) {} + modifier f(uint256 view) {} + modifier g(bytes1 view) {} + modifier h(bytes view) {} + modifier i(bytes32 view) {} + modifier j(fixed view) {} + modifier k(fixed80x80 view) {} + modifier l(ufixed view) {} + modifier m(ufixed80x80 view) {} +} +contract C3 { + modifier a(bool pure) {} + modifier b(string pure) {} + modifier c(int pure) {} + modifier d(int256 pure) {} + modifier e(uint pure) {} + modifier f(uint256 pure) {} + modifier g(bytes1 pure) {} + modifier h(bytes pure) {} + modifier i(bytes32 pure) {} + modifier j(fixed pure) {} + modifier k(fixed80x80 pure) {} + modifier l(ufixed pure) {} + modifier m(ufixed80x80 pure) {} +} +// ---- +// ParserError 9106: (33-40): State mutability can only be specified for address types. +// ParserError 9106: (67-74): State mutability can only be specified for address types. +// ParserError 9106: (98-105): State mutability can only be specified for address types. +// ParserError 9106: (132-139): State mutability can only be specified for address types. +// ParserError 9106: (164-171): State mutability can only be specified for address types. +// ParserError 9106: (199-206): State mutability can only be specified for address types. +// ParserError 9106: (233-240): State mutability can only be specified for address types. +// ParserError 9106: (266-273): State mutability can only be specified for address types. +// ParserError 9106: (301-308): State mutability can only be specified for address types. +// ParserError 9106: (334-341): State mutability can only be specified for address types. +// ParserError 9106: (372-379): State mutability can only be specified for address types. +// ParserError 9106: (406-413): State mutability can only be specified for address types. +// ParserError 9106: (445-452): State mutability can only be specified for address types. +// ParserError 9106: (493-497): State mutability can only be specified for address types. +// ParserError 9106: (524-528): State mutability can only be specified for address types. +// ParserError 9106: (552-556): State mutability can only be specified for address types. +// ParserError 9106: (583-587): State mutability can only be specified for address types. +// ParserError 9106: (612-616): State mutability can only be specified for address types. +// ParserError 9106: (644-648): State mutability can only be specified for address types. +// ParserError 9106: (675-679): State mutability can only be specified for address types. +// ParserError 9106: (705-709): State mutability can only be specified for address types. +// ParserError 9106: (737-741): State mutability can only be specified for address types. +// ParserError 9106: (767-771): State mutability can only be specified for address types. +// ParserError 9106: (802-806): State mutability can only be specified for address types. +// ParserError 9106: (833-837): State mutability can only be specified for address types. +// ParserError 9106: (869-873): State mutability can only be specified for address types. +// ParserError 9106: (914-918): State mutability can only be specified for address types. +// ParserError 9106: (945-949): State mutability can only be specified for address types. +// ParserError 9106: (973-977): State mutability can only be specified for address types. +// ParserError 9106: (1004-1008): State mutability can only be specified for address types. +// ParserError 9106: (1033-1037): State mutability can only be specified for address types. +// ParserError 9106: (1065-1069): State mutability can only be specified for address types. +// ParserError 9106: (1096-1100): State mutability can only be specified for address types. +// ParserError 9106: (1126-1130): State mutability can only be specified for address types. +// ParserError 9106: (1158-1162): State mutability can only be specified for address types. +// ParserError 9106: (1188-1192): State mutability can only be specified for address types. +// ParserError 9106: (1223-1227): State mutability can only be specified for address types. +// ParserError 9106: (1254-1258): State mutability can only be specified for address types. +// ParserError 9106: (1290-1294): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/modifiers/invalid_parameter_mutability.sol b/test/libsolidity/syntaxTests/modifiers/invalid_parameter_mutability.sol new file mode 100644 index 0000000000..f23861ebf4 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/invalid_parameter_mutability.sol @@ -0,0 +1,7 @@ +contract A { + modifier mod1(uint constant a) { _; } + modifier mod2(uint immutable a) { _; } +} +// ---- +// DeclarationError 1788: (31-46): The "constant" keyword can only be used for state variables or variables at file level. +// DeclarationError 8297: (73-89): The "immutable" keyword can only be used for state variables. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/modifiers/invalid_parameter_visibility.sol b/test/libsolidity/syntaxTests/modifiers/invalid_parameter_visibility.sol new file mode 100644 index 0000000000..0ef9e5c056 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/invalid_parameter_visibility.sol @@ -0,0 +1,21 @@ +==== Source: A ==== +contract A { + modifier mod(uint internal a) { _; } +} +==== Source: B ==== +contract A { + modifier mod(uint external a) { _; } +} +==== Source: C ==== +contract A { + modifier mod(uint public a) { _; } +} +==== Source: D ==== +contract A { + modifier mod(uint private a) { _; } +} +// ---- +// ParserError 2314: (A:35-43): Expected ',' but got 'internal' +// ParserError 2314: (B:35-43): Expected ',' but got 'external' +// ParserError 2314: (C:35-41): Expected ',' but got 'public' +// ParserError 2314: (D:35-42): Expected ',' but got 'private' diff --git a/test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol b/test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol new file mode 100644 index 0000000000..e264a593ff --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol @@ -0,0 +1,21 @@ +contract A { + modifier mod1(string storage storage a) { _; } + modifier mod2(string storage memory a) { _; } + modifier mod3(string storage calldata a) { _; } + modifier mod4(string memory storage a) { _; } + modifier mod5(string memory memory a) { _; } + modifier mod6(string memory calldata a) { _; } + modifier mod7(string calldata storage a) { _; } + modifier mod8(string calldata memory a) { _; } + modifier mod9(string calldata calldata a) { _; } +} +// ---- +// ParserError 3548: (46-53): Location already specified. +// ParserError 3548: (97-103): Location already specified. +// ParserError 3548: (147-155): Location already specified. +// ParserError 3548: (198-205): Location already specified. +// ParserError 3548: (248-254): Location already specified. +// ParserError 3548: (297-305): Location already specified. +// ParserError 3548: (350-357): Location already specified. +// ParserError 3548: (402-408): Location already specified. +// ParserError 3548: (453-461): Location already specified. diff --git a/test/libsolidity/syntaxTests/parsing/address_invalid_state_mutability.sol b/test/libsolidity/syntaxTests/parsing/address_invalid_state_mutability.sol index 90968ebc69..2aa4dd344d 100644 --- a/test/libsolidity/syntaxTests/parsing/address_invalid_state_mutability.sol +++ b/test/libsolidity/syntaxTests/parsing/address_invalid_state_mutability.sol @@ -1,26 +1,50 @@ contract C { - address view m_a; - address pure m_b; - address view[] m_c; - mapping(uint => address view) m_d; - function f() public pure { - address view a; - address pure b; - a; b; - } - function g(address view) public pure {} - function h(address pure) public pure {} - function i() public pure returns (address view) {} - function j() public pure returns (address pure) {} + address view m_a; + address pure m_b; + address view[] m_c; + mapping(uint => address view) m_d; + function f() public pure { + address view a; + address pure b; + a; b; + } + function g(address view) public pure {} + function h(address pure) public pure {} + function i() public pure returns (address view) {} + function j() public pure returns (address pure) {} + modifier m1(address view) {_;} + modifier m2(address pure) {_;} + event e1(address view); + event e2(address pure); + error err1(address view); + error err2(address pure); + function f2() public pure returns (address) { + try this.f2() returns (address view res) {} catch {} + } + function f3() public pure returns (address) { + try this.f3() returns (address pure res) {} catch {} + } } +address view constant f_a; +address pure constant f_b; // ---- -// TypeError 2311: (14-26): Address types can only be payable or non-payable. -// TypeError 2311: (33-45): Address types can only be payable or non-payable. -// TypeError 2311: (52-64): Address types can only be payable or non-payable. -// TypeError 2311: (89-101): Address types can only be payable or non-payable. -// TypeError 2311: (138-150): Address types can only be payable or non-payable. -// TypeError 2311: (156-168): Address types can only be payable or non-payable. -// TypeError 2311: (195-207): Address types can only be payable or non-payable. -// TypeError 2311: (236-248): Address types can only be payable or non-payable. -// TypeError 2311: (300-312): Address types can only be payable or non-payable. -// TypeError 2311: (352-364): Address types can only be payable or non-payable. +// TypeError 2311: (17-29): Address types can only be payable or non-payable. +// TypeError 2311: (39-51): Address types can only be payable or non-payable. +// TypeError 2311: (61-73): Address types can only be payable or non-payable. +// TypeError 2311: (101-113): Address types can only be payable or non-payable. +// TypeError 2311: (159-171): Address types can only be payable or non-payable. +// TypeError 2311: (183-195): Address types can only be payable or non-payable. +// TypeError 2311: (234-246): Address types can only be payable or non-payable. +// TypeError 2311: (278-290): Address types can only be payable or non-payable. +// TypeError 2311: (345-357): Address types can only be payable or non-payable. +// TypeError 2311: (400-412): Address types can only be payable or non-payable. +// TypeError 2311: (433-445): Address types can only be payable or non-payable. +// TypeError 2311: (468-480): Address types can only be payable or non-payable. +// TypeError 2311: (500-512): Address types can only be payable or non-payable. +// TypeError 2311: (528-540): Address types can only be payable or non-payable. +// TypeError 2311: (558-570): Address types can only be payable or non-payable. +// TypeError 2311: (588-600): Address types can only be payable or non-payable. +// TypeError 2311: (684-696): Address types can only be payable or non-payable. +// TypeError 2311: (801-813): Address types can only be payable or non-payable. +// TypeError 2311: (839-851): Address types can only be payable or non-payable. +// TypeError 2311: (866-878): Address types can only be payable or non-payable. diff --git a/test/libsolidity/syntaxTests/parsing/elemantary_non_address_payable_state_variable.sol b/test/libsolidity/syntaxTests/parsing/elemantary_non_address_payable_state_variable.sol deleted file mode 100644 index bc5db10bae..0000000000 --- a/test/libsolidity/syntaxTests/parsing/elemantary_non_address_payable_state_variable.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract C { - bool payable a; - string payable b; - int payable c; - int256 payable d; - uint payable e; - uint256 payable f; - bytes1 payable g; - bytes payable h; - bytes32 payable i; - fixed payable j; - fixed80x80 payable k; - ufixed payable l; - ufixed80x80 payable m; -} -// ---- -// ParserError 9106: (22-29): State mutability can only be specified for address types. -// ParserError 9106: (44-51): State mutability can only be specified for address types. -// ParserError 9106: (63-70): State mutability can only be specified for address types. -// ParserError 9106: (85-92): State mutability can only be specified for address types. -// ParserError 9106: (105-112): State mutability can only be specified for address types. -// ParserError 9106: (128-135): State mutability can only be specified for address types. -// ParserError 9106: (150-157): State mutability can only be specified for address types. -// ParserError 9106: (171-178): State mutability can only be specified for address types. -// ParserError 9106: (194-201): State mutability can only be specified for address types. -// ParserError 9106: (215-222): State mutability can only be specified for address types. -// ParserError 9106: (241-248): State mutability can only be specified for address types. -// ParserError 9106: (263-270): State mutability can only be specified for address types. -// ParserError 9106: (290-297): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_argument.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_argument.sol deleted file mode 100644 index 7d26f74c07..0000000000 --- a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_argument.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract C { - function a(bool payable) public pure {} - function b(string payable) public pure {} - function c(int payable) public pure {} - function d(int256 payable) public pure {} - function e(uint payable) public pure {} - function f(uint256 payable) public pure {} - function g(bytes1 payable) public pure {} - function h(bytes payable) public pure {} - function i(bytes32 payable) public pure {} - function j(fixed payable) public pure {} - function k(fixed80x80 payable) public pure {} - function l(ufixed payable) public pure {} - function m(ufixed80x80 payable) public pure {} -} -// ---- -// ParserError 9106: (33-40): State mutability can only be specified for address types. -// ParserError 9106: (79-86): State mutability can only be specified for address types. -// ParserError 9106: (122-129): State mutability can only be specified for address types. -// ParserError 9106: (168-175): State mutability can only be specified for address types. -// ParserError 9106: (212-219): State mutability can only be specified for address types. -// ParserError 9106: (259-266): State mutability can only be specified for address types. -// ParserError 9106: (305-312): State mutability can only be specified for address types. -// ParserError 9106: (350-357): State mutability can only be specified for address types. -// ParserError 9106: (397-404): State mutability can only be specified for address types. -// ParserError 9106: (442-449): State mutability can only be specified for address types. -// ParserError 9106: (492-499): State mutability can only be specified for address types. -// ParserError 9106: (538-545): State mutability can only be specified for address types. -// ParserError 9106: (589-596): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_local.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_local.sol deleted file mode 100644 index 2aad9cd04e..0000000000 --- a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_local.sol +++ /dev/null @@ -1,31 +0,0 @@ -contract C { - function f() public pure { - bool payable a; - string payable b; - int payable c; - int256 payable d; - uint payable e; - uint256 payable f; - bytes1 payable g; - bytes payable h; - bytes32 payable i; - fixed payable j; - fixed80x80 payable k; - ufixed payable l; - ufixed80x80 payable m; - } -} -// ---- -// ParserError 9106: (57-64): State mutability can only be specified for address types. -// ParserError 9106: (83-90): State mutability can only be specified for address types. -// ParserError 9106: (106-113): State mutability can only be specified for address types. -// ParserError 9106: (132-139): State mutability can only be specified for address types. -// ParserError 9106: (156-163): State mutability can only be specified for address types. -// ParserError 9106: (183-190): State mutability can only be specified for address types. -// ParserError 9106: (209-216): State mutability can only be specified for address types. -// ParserError 9106: (234-241): State mutability can only be specified for address types. -// ParserError 9106: (261-268): State mutability can only be specified for address types. -// ParserError 9106: (286-293): State mutability can only be specified for address types. -// ParserError 9106: (316-323): State mutability can only be specified for address types. -// ParserError 9106: (342-349): State mutability can only be specified for address types. -// ParserError 9106: (373-380): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_return.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_return.sol deleted file mode 100644 index 026138cde6..0000000000 --- a/test/libsolidity/syntaxTests/parsing/elementary_non_address_payable_return.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract C { - function a() public pure returns (bool payable) {} - function b() public pure returns (string payable) {} - function c() public pure returns (int payable) {} - function d() public pure returns (int256 payable) {} - function e() public pure returns (uint payable) {} - function f() public pure returns (uint256 payable) {} - function g() public pure returns (bytes1 payable) {} - function h() public pure returns (bytes payable) {} - function i() public pure returns (bytes32 payable) {} - function j() public pure returns (fixed payable) {} - function k() public pure returns (fixed80x80 payable) {} - function l() public pure returns (ufixed payable) {} - function m() public pure returns (ufixed80x80 payable) {} -} -// ---- -// ParserError 9106: (56-63): State mutability can only be specified for address types. -// ParserError 9106: (113-120): State mutability can only be specified for address types. -// ParserError 9106: (167-174): State mutability can only be specified for address types. -// ParserError 9106: (224-231): State mutability can only be specified for address types. -// ParserError 9106: (279-286): State mutability can only be specified for address types. -// ParserError 9106: (337-344): State mutability can only be specified for address types. -// ParserError 9106: (394-401): State mutability can only be specified for address types. -// ParserError 9106: (450-457): State mutability can only be specified for address types. -// ParserError 9106: (508-515): State mutability can only be specified for address types. -// ParserError 9106: (564-571): State mutability can only be specified for address types. -// ParserError 9106: (625-632): State mutability can only be specified for address types. -// ParserError 9106: (682-689): State mutability can only be specified for address types. -// ParserError 9106: (744-751): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_argument.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_argument.sol new file mode 100644 index 0000000000..aefb4748c1 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_argument.sol @@ -0,0 +1,85 @@ +contract C { + function a(bool payable) public pure {} + function b(string payable) public pure {} + function c(int payable) public pure {} + function d(int256 payable) public pure {} + function e(uint payable) public pure {} + function f(uint256 payable) public pure {} + function g(bytes1 payable) public pure {} + function h(bytes payable) public pure {} + function i(bytes32 payable) public pure {} + function j(fixed payable) public pure {} + function k(fixed80x80 payable) public pure {} + function l(ufixed payable) public pure {} + function m(ufixed80x80 payable) public pure {} +} +contract C1 { + function a(bool view) public pure {} + function b(string view) public pure {} + function c(int view) public pure {} + function d(int256 view) public pure {} + function e(uint view) public pure {} + function f(uint256 view) public pure {} + function g(bytes1 view) public pure {} + function h(bytes view) public pure {} + function i(bytes32 view) public pure {} + function j(fixed view) public pure {} + function k(fixed80x80 view) public pure {} + function l(ufixed view) public pure {} + function m(ufixed80x80 view) public pure {} +} +contract C2 { + function a(bool pure) public pure {} + function b(string pure) public pure {} + function c(int pure) public pure {} + function d(int256 pure) public pure {} + function e(uint pure) public pure {} + function f(uint256 pure) public pure {} + function g(bytes1 pure) public pure {} + function h(bytes pure) public pure {} + function i(bytes32 pure) public pure {} + function j(fixed pure) public pure {} + function k(fixed80x80 pure) public pure {} + function l(ufixed pure) public pure {} + function m(ufixed80x80 pure) public pure {} +} +// ---- +// ParserError 9106: (33-40): State mutability can only be specified for address types. +// ParserError 9106: (79-86): State mutability can only be specified for address types. +// ParserError 9106: (122-129): State mutability can only be specified for address types. +// ParserError 9106: (168-175): State mutability can only be specified for address types. +// ParserError 9106: (212-219): State mutability can only be specified for address types. +// ParserError 9106: (259-266): State mutability can only be specified for address types. +// ParserError 9106: (305-312): State mutability can only be specified for address types. +// ParserError 9106: (350-357): State mutability can only be specified for address types. +// ParserError 9106: (397-404): State mutability can only be specified for address types. +// ParserError 9106: (442-449): State mutability can only be specified for address types. +// ParserError 9106: (492-499): State mutability can only be specified for address types. +// ParserError 9106: (538-545): State mutability can only be specified for address types. +// ParserError 9106: (589-596): State mutability can only be specified for address types. +// ParserError 9106: (649-653): State mutability can only be specified for address types. +// ParserError 9106: (692-696): State mutability can only be specified for address types. +// ParserError 9106: (732-736): State mutability can only be specified for address types. +// ParserError 9106: (775-779): State mutability can only be specified for address types. +// ParserError 9106: (816-820): State mutability can only be specified for address types. +// ParserError 9106: (860-864): State mutability can only be specified for address types. +// ParserError 9106: (903-907): State mutability can only be specified for address types. +// ParserError 9106: (945-949): State mutability can only be specified for address types. +// ParserError 9106: (989-993): State mutability can only be specified for address types. +// ParserError 9106: (1031-1035): State mutability can only be specified for address types. +// ParserError 9106: (1078-1082): State mutability can only be specified for address types. +// ParserError 9106: (1121-1125): State mutability can only be specified for address types. +// ParserError 9106: (1169-1173): State mutability can only be specified for address types. +// ParserError 9106: (1226-1230): State mutability can only be specified for address types. +// ParserError 9106: (1269-1273): State mutability can only be specified for address types. +// ParserError 9106: (1309-1313): State mutability can only be specified for address types. +// ParserError 9106: (1352-1356): State mutability can only be specified for address types. +// ParserError 9106: (1393-1397): State mutability can only be specified for address types. +// ParserError 9106: (1437-1441): State mutability can only be specified for address types. +// ParserError 9106: (1480-1484): State mutability can only be specified for address types. +// ParserError 9106: (1522-1526): State mutability can only be specified for address types. +// ParserError 9106: (1566-1570): State mutability can only be specified for address types. +// ParserError 9106: (1608-1612): State mutability can only be specified for address types. +// ParserError 9106: (1655-1659): State mutability can only be specified for address types. +// ParserError 9106: (1698-1702): State mutability can only be specified for address types. +// ParserError 9106: (1746-1750): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_file_var.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_file_var.sol new file mode 100644 index 0000000000..25b9acc9fc --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_file_var.sol @@ -0,0 +1,81 @@ +bool payable a; +string payable b; +int payable c; +int256 payable d; +uint payable e; +uint256 payable f; +bytes1 payable g; +bytes payable h; +bytes32 payable i; +fixed payable j; +fixed80x80 payable k; +ufixed payable l; +ufixed80x80 payable m; + +bool view a2; +string view b2; +int view c2; +int256 view d2; +uint view e2; +uint256 view f2; +bytes1 view g2; +bytes view h2; +bytes32 view i2; +fixed view j2; +fixed80x80 view k2; +ufixed view l2; +ufixed80x80 view m2; + +bool pure a3; +string pure b3; +int pure c3; +int256 pure d3; +uint pure e3; +uint256 pure f3; +bytes1 pure g3; +bytes pure h3; +bytes32 pure i3; +fixed pure j3; +fixed80x80 pure k3; +ufixed pure l3; +ufixed80x80 pure m3; +// ---- +// ParserError 9106: (5-12): State mutability can only be specified for address types. +// ParserError 9106: (23-30): State mutability can only be specified for address types. +// ParserError 9106: (38-45): State mutability can only be specified for address types. +// ParserError 9106: (56-63): State mutability can only be specified for address types. +// ParserError 9106: (72-79): State mutability can only be specified for address types. +// ParserError 9106: (91-98): State mutability can only be specified for address types. +// ParserError 9106: (109-116): State mutability can only be specified for address types. +// ParserError 9106: (126-133): State mutability can only be specified for address types. +// ParserError 9106: (145-152): State mutability can only be specified for address types. +// ParserError 9106: (162-169): State mutability can only be specified for address types. +// ParserError 9106: (184-191): State mutability can only be specified for address types. +// ParserError 9106: (202-209): State mutability can only be specified for address types. +// ParserError 9106: (225-232): State mutability can only be specified for address types. +// ParserError 9106: (242-246): State mutability can only be specified for address types. +// ParserError 9106: (258-262): State mutability can only be specified for address types. +// ParserError 9106: (271-275): State mutability can only be specified for address types. +// ParserError 9106: (287-291): State mutability can only be specified for address types. +// ParserError 9106: (301-305): State mutability can only be specified for address types. +// ParserError 9106: (318-322): State mutability can only be specified for address types. +// ParserError 9106: (334-338): State mutability can only be specified for address types. +// ParserError 9106: (349-353): State mutability can only be specified for address types. +// ParserError 9106: (366-370): State mutability can only be specified for address types. +// ParserError 9106: (381-385): State mutability can only be specified for address types. +// ParserError 9106: (401-405): State mutability can only be specified for address types. +// ParserError 9106: (417-421): State mutability can only be specified for address types. +// ParserError 9106: (438-442): State mutability can only be specified for address types. +// ParserError 9106: (453-457): State mutability can only be specified for address types. +// ParserError 9106: (469-473): State mutability can only be specified for address types. +// ParserError 9106: (482-486): State mutability can only be specified for address types. +// ParserError 9106: (498-502): State mutability can only be specified for address types. +// ParserError 9106: (512-516): State mutability can only be specified for address types. +// ParserError 9106: (529-533): State mutability can only be specified for address types. +// ParserError 9106: (545-549): State mutability can only be specified for address types. +// ParserError 9106: (560-564): State mutability can only be specified for address types. +// ParserError 9106: (577-581): State mutability can only be specified for address types. +// ParserError 9106: (592-596): State mutability can only be specified for address types. +// ParserError 9106: (612-616): State mutability can only be specified for address types. +// ParserError 9106: (628-632): State mutability can only be specified for address types. +// ParserError 9106: (649-653): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_local.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_local.sol new file mode 100644 index 0000000000..d0b25a539b --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_local.sol @@ -0,0 +1,91 @@ +contract C { + function f() public pure { + bool payable a; + string payable b; + int payable c; + int256 payable d; + uint payable e; + uint256 payable f; + bytes1 payable g; + bytes payable h; + bytes32 payable i; + fixed payable j; + fixed80x80 payable k; + ufixed payable l; + ufixed80x80 payable m; + } +} +contract C2 { + function f() public pure { + bool view a; + string view b; + int view c; + int256 view d; + uint view e; + uint256 view f; + bytes1 view g; + bytes view h; + bytes32 view i; + fixed view j; + fixed80x80 view k; + ufixed view l; + ufixed80x80 view m; + } +} +contract C3 { + function f() public pure { + bool pure a; + string pure b; + int pure c; + int256 pure d; + uint pure e; + uint256 pure f; + bytes1 pure g; + bytes pure h; + bytes32 pure i; + fixed pure j; + fixed80x80 pure k; + ufixed pure l; + ufixed80x80 pure m; + } +} +// ---- +// ParserError 9106: (57-64): State mutability can only be specified for address types. +// ParserError 9106: (83-90): State mutability can only be specified for address types. +// ParserError 9106: (106-113): State mutability can only be specified for address types. +// ParserError 9106: (132-139): State mutability can only be specified for address types. +// ParserError 9106: (156-163): State mutability can only be specified for address types. +// ParserError 9106: (183-190): State mutability can only be specified for address types. +// ParserError 9106: (209-216): State mutability can only be specified for address types. +// ParserError 9106: (234-241): State mutability can only be specified for address types. +// ParserError 9106: (261-268): State mutability can only be specified for address types. +// ParserError 9106: (286-293): State mutability can only be specified for address types. +// ParserError 9106: (316-323): State mutability can only be specified for address types. +// ParserError 9106: (342-349): State mutability can only be specified for address types. +// ParserError 9106: (373-380): State mutability can only be specified for address types. +// ParserError 9106: (450-454): State mutability can only be specified for address types. +// ParserError 9106: (473-477): State mutability can only be specified for address types. +// ParserError 9106: (493-497): State mutability can only be specified for address types. +// ParserError 9106: (516-520): State mutability can only be specified for address types. +// ParserError 9106: (537-541): State mutability can only be specified for address types. +// ParserError 9106: (561-565): State mutability can only be specified for address types. +// ParserError 9106: (584-588): State mutability can only be specified for address types. +// ParserError 9106: (606-610): State mutability can only be specified for address types. +// ParserError 9106: (630-634): State mutability can only be specified for address types. +// ParserError 9106: (652-656): State mutability can only be specified for address types. +// ParserError 9106: (679-683): State mutability can only be specified for address types. +// ParserError 9106: (702-706): State mutability can only be specified for address types. +// ParserError 9106: (730-734): State mutability can only be specified for address types. +// ParserError 9106: (804-808): State mutability can only be specified for address types. +// ParserError 9106: (827-831): State mutability can only be specified for address types. +// ParserError 9106: (847-851): State mutability can only be specified for address types. +// ParserError 9106: (870-874): State mutability can only be specified for address types. +// ParserError 9106: (891-895): State mutability can only be specified for address types. +// ParserError 9106: (915-919): State mutability can only be specified for address types. +// ParserError 9106: (938-942): State mutability can only be specified for address types. +// ParserError 9106: (960-964): State mutability can only be specified for address types. +// ParserError 9106: (984-988): State mutability can only be specified for address types. +// ParserError 9106: (1006-1010): State mutability can only be specified for address types. +// ParserError 9106: (1033-1037): State mutability can only be specified for address types. +// ParserError 9106: (1056-1060): State mutability can only be specified for address types. +// ParserError 9106: (1084-1088): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_return.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_return.sol new file mode 100644 index 0000000000..9e428fa9dd --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_return.sol @@ -0,0 +1,85 @@ +contract C { + function a() public pure returns (bool payable) {} + function b() public pure returns (string payable) {} + function c() public pure returns (int payable) {} + function d() public pure returns (int256 payable) {} + function e() public pure returns (uint payable) {} + function f() public pure returns (uint256 payable) {} + function g() public pure returns (bytes1 payable) {} + function h() public pure returns (bytes payable) {} + function i() public pure returns (bytes32 payable) {} + function j() public pure returns (fixed payable) {} + function k() public pure returns (fixed80x80 payable) {} + function l() public pure returns (ufixed payable) {} + function m() public pure returns (ufixed80x80 payable) {} +} +contract C1 { + function a() public pure returns (bool view) {} + function b() public pure returns (string view) {} + function c() public pure returns (int view) {} + function d() public pure returns (int256 view) {} + function e() public pure returns (uint view) {} + function f() public pure returns (uint256 view) {} + function g() public pure returns (bytes1 view) {} + function h() public pure returns (bytes view) {} + function i() public pure returns (bytes32 view) {} + function j() public pure returns (fixed view) {} + function k() public pure returns (fixed80x80 view) {} + function l() public pure returns (ufixed view) {} + function m() public pure returns (ufixed80x80 view) {} +} +contract C2 { + function a() public pure returns (bool pure) {} + function b() public pure returns (string pure) {} + function c() public pure returns (int pure) {} + function d() public pure returns (int256 pure) {} + function e() public pure returns (uint pure) {} + function f() public pure returns (uint256 pure) {} + function g() public pure returns (bytes1 pure) {} + function h() public pure returns (bytes pure) {} + function i() public pure returns (bytes32 pure) {} + function j() public pure returns (fixed pure) {} + function k() public pure returns (fixed80x80 pure) {} + function l() public pure returns (ufixed pure) {} + function m() public pure returns (ufixed80x80 pure) {} +} +// ---- +// ParserError 9106: (56-63): State mutability can only be specified for address types. +// ParserError 9106: (113-120): State mutability can only be specified for address types. +// ParserError 9106: (167-174): State mutability can only be specified for address types. +// ParserError 9106: (224-231): State mutability can only be specified for address types. +// ParserError 9106: (279-286): State mutability can only be specified for address types. +// ParserError 9106: (337-344): State mutability can only be specified for address types. +// ParserError 9106: (394-401): State mutability can only be specified for address types. +// ParserError 9106: (450-457): State mutability can only be specified for address types. +// ParserError 9106: (508-515): State mutability can only be specified for address types. +// ParserError 9106: (564-571): State mutability can only be specified for address types. +// ParserError 9106: (625-632): State mutability can only be specified for address types. +// ParserError 9106: (682-689): State mutability can only be specified for address types. +// ParserError 9106: (744-751): State mutability can only be specified for address types. +// ParserError 9106: (815-819): State mutability can only be specified for address types. +// ParserError 9106: (869-873): State mutability can only be specified for address types. +// ParserError 9106: (920-924): State mutability can only be specified for address types. +// ParserError 9106: (974-978): State mutability can only be specified for address types. +// ParserError 9106: (1026-1030): State mutability can only be specified for address types. +// ParserError 9106: (1081-1085): State mutability can only be specified for address types. +// ParserError 9106: (1135-1139): State mutability can only be specified for address types. +// ParserError 9106: (1188-1192): State mutability can only be specified for address types. +// ParserError 9106: (1243-1247): State mutability can only be specified for address types. +// ParserError 9106: (1296-1300): State mutability can only be specified for address types. +// ParserError 9106: (1354-1358): State mutability can only be specified for address types. +// ParserError 9106: (1408-1412): State mutability can only be specified for address types. +// ParserError 9106: (1467-1471): State mutability can only be specified for address types. +// ParserError 9106: (1535-1539): State mutability can only be specified for address types. +// ParserError 9106: (1589-1593): State mutability can only be specified for address types. +// ParserError 9106: (1640-1644): State mutability can only be specified for address types. +// ParserError 9106: (1694-1698): State mutability can only be specified for address types. +// ParserError 9106: (1746-1750): State mutability can only be specified for address types. +// ParserError 9106: (1801-1805): State mutability can only be specified for address types. +// ParserError 9106: (1855-1859): State mutability can only be specified for address types. +// ParserError 9106: (1908-1912): State mutability can only be specified for address types. +// ParserError 9106: (1963-1967): State mutability can only be specified for address types. +// ParserError 9106: (2016-2020): State mutability can only be specified for address types. +// ParserError 9106: (2074-2078): State mutability can only be specified for address types. +// ParserError 9106: (2128-2132): State mutability can only be specified for address types. +// ParserError 9106: (2187-2191): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_state_variable.sol b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_state_variable.sol new file mode 100644 index 0000000000..960929f919 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/elementary_non_address_state_mutability_state_variable.sol @@ -0,0 +1,85 @@ +contract C { + bool payable a; + string payable b; + int payable c; + int256 payable d; + uint payable e; + uint256 payable f; + bytes1 payable g; + bytes payable h; + bytes32 payable i; + fixed payable j; + fixed80x80 payable k; + ufixed payable l; + ufixed80x80 payable m; +} +contract C2 { + bool view a; + string view b; + int view c; + int256 view d; + uint view e; + uint256 view f; + bytes1 view g; + bytes view h; + bytes32 view i; + fixed view j; + fixed80x80 view k; + ufixed view l; + ufixed80x80 view m; +} +contract C3 { + bool pure a; + string pure b; + int pure c; + int256 pure d; + uint pure e; + uint256 pure f; + bytes1 pure g; + bytes pure h; + bytes32 pure i; + fixed pure j; + fixed80x80 pure k; + ufixed pure l; + ufixed80x80 pure m; +} +// ---- +// ParserError 9106: (22-29): State mutability can only be specified for address types. +// ParserError 9106: (44-51): State mutability can only be specified for address types. +// ParserError 9106: (63-70): State mutability can only be specified for address types. +// ParserError 9106: (85-92): State mutability can only be specified for address types. +// ParserError 9106: (105-112): State mutability can only be specified for address types. +// ParserError 9106: (128-135): State mutability can only be specified for address types. +// ParserError 9106: (150-157): State mutability can only be specified for address types. +// ParserError 9106: (171-178): State mutability can only be specified for address types. +// ParserError 9106: (194-201): State mutability can only be specified for address types. +// ParserError 9106: (215-222): State mutability can only be specified for address types. +// ParserError 9106: (241-248): State mutability can only be specified for address types. +// ParserError 9106: (263-270): State mutability can only be specified for address types. +// ParserError 9106: (290-297): State mutability can only be specified for address types. +// ParserError 9106: (326-330): State mutability can only be specified for address types. +// ParserError 9106: (345-349): State mutability can only be specified for address types. +// ParserError 9106: (361-365): State mutability can only be specified for address types. +// ParserError 9106: (380-384): State mutability can only be specified for address types. +// ParserError 9106: (397-401): State mutability can only be specified for address types. +// ParserError 9106: (417-421): State mutability can only be specified for address types. +// ParserError 9106: (436-440): State mutability can only be specified for address types. +// ParserError 9106: (454-458): State mutability can only be specified for address types. +// ParserError 9106: (474-478): State mutability can only be specified for address types. +// ParserError 9106: (492-496): State mutability can only be specified for address types. +// ParserError 9106: (515-519): State mutability can only be specified for address types. +// ParserError 9106: (534-538): State mutability can only be specified for address types. +// ParserError 9106: (558-562): State mutability can only be specified for address types. +// ParserError 9106: (591-595): State mutability can only be specified for address types. +// ParserError 9106: (610-614): State mutability can only be specified for address types. +// ParserError 9106: (626-630): State mutability can only be specified for address types. +// ParserError 9106: (645-649): State mutability can only be specified for address types. +// ParserError 9106: (662-666): State mutability can only be specified for address types. +// ParserError 9106: (682-686): State mutability can only be specified for address types. +// ParserError 9106: (701-705): State mutability can only be specified for address types. +// ParserError 9106: (719-723): State mutability can only be specified for address types. +// ParserError 9106: (739-743): State mutability can only be specified for address types. +// ParserError 9106: (757-761): State mutability can only be specified for address types. +// ParserError 9106: (780-784): State mutability can only be specified for address types. +// ParserError 9106: (799-803): State mutability can only be specified for address types. +// ParserError 9106: (823-827): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_indexed.sol b/test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_indexed.sol new file mode 100644 index 0000000000..0dd79bae79 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_indexed.sol @@ -0,0 +1,11 @@ +==== Source: A ==== +contract test { + function f1(uint indexed a) public returns (uint) { } +} +==== Source: B ==== +contract test { + function f1(uint a) public returns (uint indexed) { } +} +// ---- +// ParserError 2314: (A:37-44): Expected ',' but got 'indexed' +// ParserError 2314: (B:61-68): Expected ',' but got 'indexed' diff --git a/test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_mutability.sol b/test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_mutability.sol new file mode 100644 index 0000000000..6024141925 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/invalid_function_parameter_and_return_var_mutability.sol @@ -0,0 +1,9 @@ +contract test { + function f1(uint immutable a) public returns (uint immutable) { } + function f2(uint constant a) public returns (uint constant) { } +} +// ---- +// DeclarationError 8297: (32-48): The "immutable" keyword can only be used for state variables. +// DeclarationError 8297: (66-80): The "immutable" keyword can only be used for state variables. +// DeclarationError 1788: (102-117): The "constant" keyword can only be used for state variables or variables at file level. +// DeclarationError 1788: (135-148): The "constant" keyword can only be used for state variables or variables at file level. diff --git a/test/libsolidity/syntaxTests/parsing/invalid_state_variable_location.sol b/test/libsolidity/syntaxTests/parsing/invalid_state_variable_location.sol new file mode 100644 index 0000000000..b5b3439f42 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/invalid_state_variable_location.sol @@ -0,0 +1,11 @@ +==== Source: A ==== +contract test { + string memory a; +} +==== Source: B ==== +contract test { + string calldata a; +} +// ---- +// ParserError 2314: (A:27-33): Expected identifier but got 'memory' +// ParserError 2314: (B:27-35): Expected identifier but got 'calldata' diff --git a/test/libsolidity/syntaxTests/parsing/invalid_variable_indexed.sol b/test/libsolidity/syntaxTests/parsing/invalid_variable_indexed.sol new file mode 100644 index 0000000000..9508e795ac --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/invalid_variable_indexed.sol @@ -0,0 +1,16 @@ +==== Source: A ==== +uint indexed a; +==== Source: B ==== +contract test { + function f(uint a) public { + uint indexed a; + } +} +==== Source: C ==== +contract test { + uint indexed a; +} +// ---- +// ParserError 2314: (A:5-12): Expected identifier but got 'indexed' +// ParserError 2314: (B:61-68): Expected ';' but got 'indexed' +// ParserError 2314: (C:25-32): Expected identifier but got 'indexed' \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol b/test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol new file mode 100644 index 0000000000..874a185123 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol @@ -0,0 +1,15 @@ +==== Source: A ==== +contract test { + function f(uint a) public { + uint constant a; + } +} +==== Source: B ==== +contract test { + function f(uint a) public { + uint immutable a; + } +} +// ---- +// ParserError 2314: (A:61-69): Expected ';' but got 'constant' +// ParserError 2314: (B:61-70): Expected ';' but got 'immutable' \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_file_level_var.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_file_level_var.sol new file mode 100644 index 0000000000..c7b1558e61 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_file_level_var.sol @@ -0,0 +1,10 @@ +==== Source: A ==== +uint[] storage a; +==== Source: B ==== +uint[] memory b; +==== Source: C ==== +uint[] calldata c; +// ---- +// ParserError 2314: (A:7-14): Expected identifier but got 'storage' +// ParserError 2314: (B:7-13): Expected identifier but got 'memory' +// ParserError 2314: (C:7-15): Expected identifier but got 'calldata' diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_fn_returns_multi.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_fn_returns_multi.sol new file mode 100644 index 0000000000..06627bd649 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_fn_returns_multi.sol @@ -0,0 +1,21 @@ +contract Foo { + function f1() returns (string calldata calldata) {} + function f2() returns (string calldata memory) {} + function f3() returns (string calldata storage) {} + function f4() returns (string memory calldata) {} + function f5() returns (string memory memory) {} + function f6() returns (string memory storage) {} + function f7() returns (string storage calldata) {} + function f8() returns (string storage memory) {} + function f9() returns (string storage storage) {} +} +// ---- +// ParserError 3548: (58-66): Location already specified. +// ParserError 3548: (114-120): Location already specified. +// ParserError 3548: (168-175): Location already specified. +// ParserError 3548: (221-229): Location already specified. +// ParserError 3548: (275-281): Location already specified. +// ParserError 3548: (327-334): Location already specified. +// ParserError 3548: (381-389): Location already specified. +// ParserError 3548: (436-442): Location already specified. +// ParserError 3548: (489-496): Location already specified. diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals_multi.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals_multi.sol index f660c0953e..f61cd9498e 100644 --- a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals_multi.sol +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_locals_multi.sol @@ -3,6 +3,14 @@ contract Foo { function f() public view { uint[] storage memory x = m_x; uint[] memory storage calldata y; + uint[] storage calldata x2; + uint[] storage storage x3; + uint[] calldata memory x4; + uint[] calldata calldata x5; + uint[] calldata storage x6; + uint[] storage memory x4; + uint[] storage calldata x5; + uint[] storage storage x6; x; y; } } @@ -10,3 +18,11 @@ contract Foo { // ParserError 3548: (85-91): Location already specified. // ParserError 3548: (123-130): Location already specified. // ParserError 3548: (131-139): Location already specified. +// ParserError 3548: (166-174): Location already specified. +// ParserError 3548: (202-209): Location already specified. +// ParserError 3548: (238-244): Location already specified. +// ParserError 3548: (273-281): Location already specified. +// ParserError 3548: (310-317): Location already specified. +// ParserError 3548: (345-351): Location already specified. +// ParserError 3548: (379-387): Location already specified. +// ParserError 3548: (415-422): Location already specified. diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params_multi.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params_multi.sol index 25d1e02d3c..8d1985cd6f 100644 --- a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params_multi.sol +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params_multi.sol @@ -1,6 +1,20 @@ contract Foo { function f(uint[] storage memory constant x, uint[] memory calldata y) internal { } + function f2(uint[] storage storage x) internal { } + function f3(uint[] storage calldata x) internal { } + function f4(uint[] memory storage x) internal { } + function f5(uint[] memory memory x) internal { } + function f6(uint[] calldata storage x) internal { } + function f7(uint[] calldata memory x) internal { } + function f8(uint[] calldata calldata x) internal { } } // ---- // ParserError 3548: (45-51): Location already specified. // ParserError 3548: (78-86): Location already specified. +// ParserError 3548: (134-141): Location already specified. +// ParserError 3548: (189-197): Location already specified. +// ParserError 3548: (244-251): Location already specified. +// ParserError 3548: (298-304): Location already specified. +// ParserError 3548: (353-360): Location already specified. +// ParserError 3548: (409-415): Location already specified. +// ParserError 3548: (464-472): Location already specified. diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_state_variables_multi.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_state_variables_multi.sol index 134397fec6..d53f247571 100644 --- a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_state_variables_multi.sol +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_state_variables_multi.sol @@ -1,5 +1,11 @@ +==== Source: A ==== contract Foo { uint[] memory storage calldata x; } +==== Source: B ==== +contract Foo { + uint[] storage storage x; +} // ---- -// ParserError 2314: (23-29): Expected identifier but got 'memory' +// ParserError 2314: (A:23-29): Expected identifier but got 'memory' +// ParserError 2314: (B:23-30): Expected identifier but got 'storage' \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/parsing/multiple_mutability_specifiers.sol b/test/libsolidity/syntaxTests/parsing/multiple_mutability_specifiers.sol new file mode 100644 index 0000000000..50579054c8 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/multiple_mutability_specifiers.sol @@ -0,0 +1,11 @@ +contract C { + uint constant constant a; + uint immutable immutable b; + uint constant immutable c; + uint immutable constant d; +} +// ---- +// ParserError 3109: (31-39): Mutability already set to "constant" +// ParserError 3109: (62-71): Mutability already set to "immutable" +// ParserError 3109: (93-102): Mutability already set to "constant" +// ParserError 3109: (125-133): Mutability already set to "immutable" diff --git a/test/libsolidity/syntaxTests/parsing/multiple_state_mutability_specifiers.sol b/test/libsolidity/syntaxTests/parsing/multiple_state_mutability_specifiers.sol new file mode 100644 index 0000000000..e9c4401054 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/multiple_state_mutability_specifiers.sol @@ -0,0 +1,103 @@ +==== Source: A ==== +contract c1 { + function f() payable payable {} +} +contract c2 { + function f() view view {} +} +contract c3 { + function f() pure pure {} +} +contract c4 { + function f() pure view {} +} +contract c5 { + function f() payable view {} +} +contract c6 { + function f() pure payable {} +} +contract c7 { + function f() view payable {} +} +contract c8 { + function f() payable pure {} +} +contract c9 { + function f() view pure {} +} +==== Source: B ==== +contract c { + address payable payable v; +} +==== Source: C ==== +contract c { + function fn(address payable payable) public { } +} +==== Source: D ==== +contract c { + function fn() public returns (address payable payable) { } +} +==== Source: E ==== +contract c { + function fn() public { + address payable payable v; + } +} +==== Source: F ==== +contract c { + function fn(address payable payable v) public { } +} +==== Source: G ==== +contract c { + function fn() public returns (address payable payable res) { } +} +==== Source: H ==== +address payable payable v; +==== Source: I ==== +contract c { + modifier m(address payable payable x) { _; } +} +==== Source: J ==== +contract c { + event e(address payable payable x); +} +==== Source: K ==== +contract c { + error e1(address payable payable x); +} +==== Source: L ==== +contract c { + function f() public returns (address payable) { + try this.f() returns (address payable payable) { } catch { } + } +} +==== Source: M ==== +contract c { + function f() public returns (address payable) { + try this.f() returns (address payable) { } catch Error(address payable payable) { } + } +} +// ---- +// ParserError 9680: (A:39-46): State mutability already specified as "payable". +// ParserError 9680: (A:88-92): State mutability already specified as "view". +// ParserError 9680: (A:134-138): State mutability already specified as "pure". +// ParserError 9680: (A:180-184): State mutability already specified as "pure". +// ParserError 9680: (A:229-233): State mutability already specified as "payable". +// ParserError 9680: (A:275-282): State mutability already specified as "pure". +// ParserError 9680: (A:324-331): State mutability already specified as "view". +// ParserError 9680: (A:376-380): State mutability already specified as "payable". +// ParserError 9680: (A:422-426): State mutability already specified as "view". +// ParserError 2314: (B:33-40): Expected identifier but got 'payable' +// ParserError 2314: (C:45-52): Expected ',' but got 'payable' +// ParserError 2314: (D:63-70): Expected ',' but got 'payable' +// ParserError 2314: (E:64-71): Expected identifier but got 'payable' +// ParserError 2314: (F:45-52): Expected ',' but got 'payable' +// ParserError 2314: (G:63-70): Expected ',' but got 'payable' +// ParserError 2314: (H:16-23): Expected identifier but got 'payable' +// ParserError 2314: (I:44-51): Expected ',' but got 'payable' +// ParserError 2314: (J:41-48): Expected ',' but got 'payable' +// ParserError 2314: (K:42-49): Expected ',' but got 'payable' +// ParserError 2314: (L:111-118): Expected ',' but got 'payable' +// ParserError 2314: (M:144-151): Expected ',' but got 'payable' + diff --git a/test/libsolidity/syntaxTests/parsing/multiple_statemutability_specifiers.sol b/test/libsolidity/syntaxTests/parsing/multiple_statemutability_specifiers.sol deleted file mode 100644 index e2c56ae577..0000000000 --- a/test/libsolidity/syntaxTests/parsing/multiple_statemutability_specifiers.sol +++ /dev/null @@ -1,29 +0,0 @@ -contract c1 { - function f() payable payable {} -} -contract c2 { - function f() view view {} -} -contract c3 { - function f() pure pure {} -} -contract c4 { - function f() pure view {} -} -contract c5 { - function f() payable view {} -} -contract c6 { - function f() pure payable {} -} -contract c7 { - function f() view payable {} -} -// ---- -// ParserError 9680: (39-46): State mutability already specified as "payable". -// ParserError 9680: (88-92): State mutability already specified as "view". -// ParserError 9680: (134-138): State mutability already specified as "pure". -// ParserError 9680: (180-184): State mutability already specified as "pure". -// ParserError 9680: (229-233): State mutability already specified as "payable". -// ParserError 9680: (275-282): State mutability already specified as "pure". -// ParserError 9680: (324-331): State mutability already specified as "view". diff --git a/test/libsolidity/syntaxTests/parsing/multiple_visibility_specifiers.sol b/test/libsolidity/syntaxTests/parsing/multiple_visibility_specifiers.sol deleted file mode 100644 index c04558171d..0000000000 --- a/test/libsolidity/syntaxTests/parsing/multiple_visibility_specifiers.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract C { - uint private internal a; - function f() private external {} -} -// ---- -// ParserError 4110: (30-38): Visibility already specified as "private". -// ParserError 9439: (67-75): Visibility already specified as "private". diff --git a/test/libsolidity/syntaxTests/parsing/payable_accessor.sol b/test/libsolidity/syntaxTests/parsing/payable_accessor.sol deleted file mode 100644 index 4df1b18df8..0000000000 --- a/test/libsolidity/syntaxTests/parsing/payable_accessor.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract test { - uint payable x; -} -// ---- -// ParserError 9106: (22-29): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol b/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol new file mode 100644 index 0000000000..49fe597ec3 --- /dev/null +++ b/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol @@ -0,0 +1,4 @@ +pragma experimental experimental __test; +// ---- +// SyntaxError 6022: (0-40): Stray arguments. + diff --git a/test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_catch.sol b/test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_catch.sol new file mode 100644 index 0000000000..edb3c5301f --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_catch.sol @@ -0,0 +1,31 @@ +contract C { + function a() public pure { + try this.a() {} catch (string payable memory) {} + } + function c() public pure { + try this.c() {} catch (bytes payable memory) {} + } +} +contract C2 { + function a() public pure { + try this.a() {} catch (string view memory) {} + } + function c() public pure { + try this.c() {} catch (bytes view memory) {} + } +} +contract C3 { + function a() public pure { + try this.a() {} catch (string pure memory) {} + } + function c() public pure { + try this.c() {} catch (bytes pure memory) {} + } +} +// ---- +// ParserError 9106: (82-89): State mutability can only be specified for address types. +// ParserError 9106: (175-182): State mutability can only be specified for address types. +// ParserError 9106: (285-289): State mutability can only be specified for address types. +// ParserError 9106: (375-379): State mutability can only be specified for address types. +// ParserError 9106: (482-486): State mutability can only be specified for address types. +// ParserError 9106: (572-576): State mutability can only be specified for address types. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_try_returns.sol b/test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_try_returns.sol new file mode 100644 index 0000000000..bc16f19c7a --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/elementary_non_address_state_mutability_try_returns.sol @@ -0,0 +1,163 @@ +contract C { + function a() public pure returns (bool) { + try this.a() returns (bool payable res) {} catch {} + } + function b() public pure returns (string) { + try this.b() returns (string payable res) {} catch {} + } + function c() public pure returns (int) { + try this.c() returns (int payable res) {} catch {} + } + function d() public pure returns (int256) { + try this.d() returns (int256 payable res) {} catch {} + } + function e() public pure returns (uint) { + try this.e() returns (uint payable res) {} catch {} + } + function f() public pure returns (uint256) { + try this.f() returns (uint256 payable res) {} catch {} + } + function g() public pure returns (bytes1) { + try this.g() returns (bytes1 payable res) {} catch {} + } + function h() public pure returns (bytes) { + try this.h() returns (bytes payable res) {} catch {} + } + function i() public pure returns (bytes32) { + try this.i() returns (bytes32 payable res) {} catch {} + } + function j() public pure returns (fixed) { + try this.j() returns (fixed payable res) {} catch {} + } + function k() public pure returns (fixed80x80) { + try this.k() returns (fixed80x80 payable res) {} catch {} + } + function l() public pure returns (ufixed) { + try this.l() returns (ufixed payable res) {} catch {} + } + function m() public pure returns (ufixed80x80) { + try this.m() returns (ufixed80x80 payable res) {} catch {} + } +} +contract C1 { + function a() public pure returns (bool) { + try this.a() returns (bool view res) {} catch {} + } + function b() public pure returns (string) { + try this.b() returns (string view res) {} catch {} + } + function c() public pure returns (int) { + try this.c() returns (int view res) {} catch {} + } + function d() public pure returns (int256) { + try this.d() returns (int256 view res) {} catch {} + } + function e() public pure returns (uint) { + try this.e() returns (uint view res) {} catch {} + } + function f() public pure returns (uint256) { + try this.f() returns (uint256 view res) {} catch {} + } + function g() public pure returns (bytes1) { + try this.g() returns (bytes1 view res) {} catch {} + } + function h() public pure returns (bytes) { + try this.h() returns (bytes view res) {} catch {} + } + function i() public pure returns (bytes32) { + try this.i() returns (bytes32 view res) {} catch {} + } + function j() public pure returns (fixed) { + try this.j() returns (fixed view res) {} catch {} + } + function k() public pure returns (fixed80x80) { + try this.k() returns (fixed80x80 view res) {} catch {} + } + function l() public pure returns (ufixed) { + try this.l() returns (ufixed view res) {} catch {} + } + function m() public pure returns (ufixed80x80) { + try this.m() returns (ufixed80x80 view res) {} catch {} + } +} +contract C2 { + function a() public pure returns (bool) { + try this.a() returns (bool pure res) {} catch {} + } + function b() public pure returns (string) { + try this.b() returns (string pure res) {} catch {} + } + function c() public pure returns (int) { + try this.c() returns (int pure res) {} catch {} + } + function d() public pure returns (int256) { + try this.d() returns (int256 pure res) {} catch {} + } + function e() public pure returns (uint) { + try this.e() returns (uint pure res) {} catch {} + } + function f() public pure returns (uint256) { + try this.f() returns (uint256 pure res) {} catch {} + } + function g() public pure returns (bytes1) { + try this.g() returns (bytes1 pure res) {} catch {} + } + function h() public pure returns (bytes) { + try this.h() returns (bytes pure res) {} catch {} + } + function i() public pure returns (bytes32) { + try this.i() returns (bytes32 pure res) {} catch {} + } + function j() public pure returns (fixed) { + try this.j() returns (fixed pure res) {} catch {} + } + function k() public pure returns (fixed80x80) { + try this.k() returns (fixed80x80 pure res) {} catch {} + } + function l() public pure returns (ufixed) { + try this.l() returns (ufixed pure res) {} catch {} + } + function m() public pure returns (ufixed80x80) { + try this.m() returns (ufixed80x80 pure res) {} catch {} + } +} +// ---- +// ParserError 9106: (94-101): State mutability can only be specified for address types. +// ParserError 9106: (210-217): State mutability can only be specified for address types. +// ParserError 9106: (320-327): State mutability can only be specified for address types. +// ParserError 9106: (436-443): State mutability can only be specified for address types. +// ParserError 9106: (548-555): State mutability can only be specified for address types. +// ParserError 9106: (666-673): State mutability can only be specified for address types. +// ParserError 9106: (782-789): State mutability can only be specified for address types. +// ParserError 9106: (896-903): State mutability can only be specified for address types. +// ParserError 9106: (1014-1021): State mutability can only be specified for address types. +// ParserError 9106: (1128-1135): State mutability can only be specified for address types. +// ParserError 9106: (1252-1259): State mutability can only be specified for address types. +// ParserError 9106: (1368-1375): State mutability can only be specified for address types. +// ParserError 9106: (1494-1501): State mutability can only be specified for address types. +// ParserError 9106: (1622-1626): State mutability can only be specified for address types. +// ParserError 9106: (1735-1739): State mutability can only be specified for address types. +// ParserError 9106: (1842-1846): State mutability can only be specified for address types. +// ParserError 9106: (1955-1959): State mutability can only be specified for address types. +// ParserError 9106: (2064-2068): State mutability can only be specified for address types. +// ParserError 9106: (2179-2183): State mutability can only be specified for address types. +// ParserError 9106: (2292-2296): State mutability can only be specified for address types. +// ParserError 9106: (2403-2407): State mutability can only be specified for address types. +// ParserError 9106: (2518-2522): State mutability can only be specified for address types. +// ParserError 9106: (2629-2633): State mutability can only be specified for address types. +// ParserError 9106: (2750-2754): State mutability can only be specified for address types. +// ParserError 9106: (2863-2867): State mutability can only be specified for address types. +// ParserError 9106: (2986-2990): State mutability can only be specified for address types. +// ParserError 9106: (3111-3115): State mutability can only be specified for address types. +// ParserError 9106: (3224-3228): State mutability can only be specified for address types. +// ParserError 9106: (3331-3335): State mutability can only be specified for address types. +// ParserError 9106: (3444-3448): State mutability can only be specified for address types. +// ParserError 9106: (3553-3557): State mutability can only be specified for address types. +// ParserError 9106: (3668-3672): State mutability can only be specified for address types. +// ParserError 9106: (3781-3785): State mutability can only be specified for address types. +// ParserError 9106: (3892-3896): State mutability can only be specified for address types. +// ParserError 9106: (4007-4011): State mutability can only be specified for address types. +// ParserError 9106: (4118-4122): State mutability can only be specified for address types. +// ParserError 9106: (4239-4243): State mutability can only be specified for address types. +// ParserError 9106: (4352-4356): State mutability can only be specified for address types. +// ParserError 9106: (4475-4479): State mutability can only be specified for address types. diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_calldata.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_calldata.sol new file mode 100644 index 0000000000..d9302ef1f0 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_calldata.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + try this.f() {} catch (string calldata a) { } + } +} +// ---- +// TypeError 6651: (70-87): Data location must be "memory" for parameter in function, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_storage.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_storage.sol new file mode 100644 index 0000000000..066b1ebfe9 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_catch_parameter_location_storage.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + try this.f() {} catch (string storage a) { } + } +} +// ---- +// TypeError 6651: (70-86): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_returns_var_location.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_var_location.sol new file mode 100644 index 0000000000..c9980026f5 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_var_location.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (string memory) { + try this.f() returns (string storage a) {} catch { } + } +} +// ---- +// TypeError 6651: (93-109): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_indexed.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_indexed.sol new file mode 100644 index 0000000000..43e04583ac --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_indexed.sol @@ -0,0 +1,27 @@ +==== Source: A ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint indexed a) { + } catch { } + } +} +==== Source: E ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch Error(string memory indexed x) { + } + } +} +==== Source: I ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch (bytes memory indexed x) { + } + } +} +// ---- +// ParserError 2314: (A:89-96): Expected ',' but got 'indexed' +// ParserError 2314: (E:128-135): Expected ',' but got 'indexed' +// ParserError 2314: (I:122-129): Expected ',' but got 'indexed' diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_mutability.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_mutability.sol new file mode 100644 index 0000000000..bbc267f899 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_mutability.sol @@ -0,0 +1,30 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() returns (uint constant a, uint immutable b) { + } catch Error(string memory immutable x) { + x; + } + + try this.f() returns (uint a, uint b) { + } catch (bytes memory immutable x) { + x; + } + + try this.f() returns (uint a, uint b) { + } catch Error(string memory constant x) { + x; + } + + try this.f() returns (uint a, uint b) { + } catch (bytes memory constant x) { + x; + } + } +} +// ---- +// DeclarationError 1788: (90-105): The "constant" keyword can only be used for state variables or variables at file level. +// DeclarationError 8297: (107-123): The "immutable" keyword can only be used for state variables. +// DeclarationError 8297: (149-174): The "immutable" keyword can only be used for state variables. +// DeclarationError 8297: (269-293): The "immutable" keyword can only be used for state variables. +// DeclarationError 1788: (393-417): The "constant" keyword can only be used for state variables or variables at file level. +// DeclarationError 1788: (512-535): The "constant" keyword can only be used for state variables or variables at file level. diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_visibility.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_visibility.sol new file mode 100644 index 0000000000..1828f25d3c --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_returns_vars_and_catch_parameter_visibility.sol @@ -0,0 +1,105 @@ +==== Source: A ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint public a) { + } catch { } + } +} +==== Source: B ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint private a) { + } catch { } + } +} +==== Source: C ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint external a) { + } catch { } + } +} +==== Source: D ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint internal a) { + } catch { } + } +} +==== Source: E ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch Error(string memory public x) { + } + } +} +==== Source: F ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch Error(string memory private x) { + } + } +} +==== Source: G ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch Error(string memory external x) { + } + } +} +==== Source: H ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch Error(string memory internal x) { + } + } +} +==== Source: I ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch (bytes memory public x) { + } + } +} +==== Source: J ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch (bytes memory private x) { + } + } +} +==== Source: K ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch (bytes memory external x) { + } + } +} +==== Source: L ==== +contract C { + function f() public returns (uint) { + try this.f() returns (uint) { + } catch (bytes memory internal x) { + } + } +} +// ---- +// ParserError 2314: (A:89-95): Expected ',' but got 'public' +// ParserError 2314: (B:89-96): Expected ',' but got 'private' +// ParserError 2314: (C:89-97): Expected ',' but got 'external' +// ParserError 2314: (D:89-97): Expected ',' but got 'internal' +// ParserError 2314: (E:128-134): Expected ',' but got 'public' +// ParserError 2314: (F:128-135): Expected ',' but got 'private' +// ParserError 2314: (G:128-136): Expected ',' but got 'external' +// ParserError 2314: (H:128-136): Expected ',' but got 'internal' +// ParserError 2314: (I:122-128): Expected ',' but got 'public' +// ParserError 2314: (J:122-129): Expected ',' but got 'private' +// ParserError 2314: (K:122-130): Expected ',' but got 'external' +// ParserError 2314: (L:122-130): Expected ',' but got 'internal' \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/multiple_returns_vars_and_catch_parameter_location.sol b/test/libsolidity/syntaxTests/tryCatch/multiple_returns_vars_and_catch_parameter_location.sol new file mode 100644 index 0000000000..88df3f5bad --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/multiple_returns_vars_and_catch_parameter_location.sol @@ -0,0 +1,132 @@ +==== Source: A1 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string memory memory a) { } catch { } + } +} +==== Source: A2 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string memory storage a) { } catch { } + } +} +==== Source: A3 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string memory calldata a) { } catch { } + } +} + +==== Source: B1 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string calldata memory a) { } catch { } + } +} +==== Source: B2 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string calldata storage a) { } catch { } + } +} +==== Source: B3 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string calldata calldata a) { } catch { } + } +} + +==== Source: C1 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string storage memory a) { } catch { } + } +} +==== Source: C2 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string storage storage a) { } catch { } + } +} +==== Source: C3 ==== +contract C { + function f() public returns (string memory) { + try this.f() returns (string storage calldata a) { } catch { } + } +} + +==== Source: D1 ==== +contract C { + function f() public { + try this.f() {} catch (string memory memory x) { } + } +} +==== Source: D2 ==== +contract C { + function f() public { + try this.f() {} catch (string memory calldata x) { } + } +} +==== Source: D3 ==== +contract C { + function f() public { + try this.f() {} catch (string memory storage x) { } + } +} + +==== Source: E1 ==== +contract C { + function f() public { + try this.f() {} catch (string calldata memory x) { } + } +} +==== Source: E2 ==== +contract C { + function f() public { + try this.f() {} catch (string calldata calldata x) { } + } +} +==== Source: E3 ==== +contract C { + function f() public { + try this.f() {} catch (string calldata storage x) { } + } +} + +==== Source: G1 ==== +contract C { + function f() public { + try this.f() {} catch (string storage memory x) { } + } +} +==== Source: G2 ==== +contract C { + function f() public { + try this.f() {} catch (string storage calldata x) { } + } +} +==== Source: G3 ==== +contract C { + function f() public { + try this.f() {} catch (string storage storage x) { } + } +} +// ---- +// ParserError 3548: (A1:107-113): Location already specified. +// ParserError 3548: (A2:107-114): Location already specified. +// ParserError 3548: (A3:107-115): Location already specified. +// ParserError 3548: (B1:109-115): Location already specified. +// ParserError 3548: (B2:109-116): Location already specified. +// ParserError 3548: (B3:109-117): Location already specified. +// ParserError 3548: (C1:108-114): Location already specified. +// ParserError 3548: (C2:108-115): Location already specified. +// ParserError 3548: (C3:108-116): Location already specified. +// ParserError 3548: (D1:85-91): Location already specified. +// ParserError 3548: (D2:85-93): Location already specified. +// ParserError 3548: (D3:85-92): Location already specified. +// ParserError 3548: (E1:87-93): Location already specified. +// ParserError 3548: (E2:87-95): Location already specified. +// ParserError 3548: (E3:87-94): Location already specified. +// ParserError 3548: (G1:86-92): Location already specified. +// ParserError 3548: (G2:86-94): Location already specified. +// ParserError 3548: (G3:86-93): Location already specified. diff --git a/test/libsolidity/syntaxTests/using/global_multiple_global_keywords.sol b/test/libsolidity/syntaxTests/using/global_multiple_global_keywords.sol new file mode 100644 index 0000000000..48ce7f1119 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/global_multiple_global_keywords.sol @@ -0,0 +1,5 @@ +using {f} for S global global; +struct S { uint x; } +function f(S memory _x) pure returns (uint) { return _x.x; } +// ---- +// ParserError 2314: (23-29): Expected ';' but got identifier diff --git a/test/libsolidity/syntaxTests/visibility/file_level_variable_visibility.sol b/test/libsolidity/syntaxTests/visibility/file_level_variable_visibility.sol new file mode 100644 index 0000000000..3de9f3ae23 --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/file_level_variable_visibility.sol @@ -0,0 +1,13 @@ +==== Source: A ==== +uint external a; +==== Source: B ==== +uint internal a; +==== Source: C ==== +uint public a; +==== Source: D ==== +uint private a; +// ---- +// ParserError 2314: (A:5-13): Expected identifier but got 'external' +// ParserError 2314: (B:5-13): Expected identifier but got 'internal' +// ParserError 2314: (C:5-11): Expected identifier but got 'public' +// ParserError 2314: (D:5-12): Expected identifier but got 'private' diff --git a/test/libsolidity/syntaxTests/visibility/invalid_function_parameter_and_return_var_visibility.sol b/test/libsolidity/syntaxTests/visibility/invalid_function_parameter_and_return_var_visibility.sol new file mode 100644 index 0000000000..4f73e884d9 --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/invalid_function_parameter_and_return_var_visibility.sol @@ -0,0 +1,41 @@ +==== Source: A ==== +contract test { + function f(uint external a) public returns (uint) { } +} +==== Source: B ==== +contract test { + function f(uint internal a) public returns (uint) { } +} +==== Source: C ==== +contract test { + function f(uint public a) public returns (uint) { } +} +==== Source: D ==== +contract test { + function f(uint private a) public returns (uint) { } +} +==== Source: E ==== +contract test { + function f(uint a) public returns (uint external) { } +} +==== Source: F ==== +contract test { + function f(uint a) public returns (uint internal) { } +} +==== Source: G ==== +contract test { + function f(uint a) public returns (uint public) { } +} +==== Source: H ==== +contract test { + function f(uint a) public returns (uint private) { } +} +// ---- +// ParserError 2314: (A:36-44): Expected ',' but got 'external' +// ParserError 2314: (B:36-44): Expected ',' but got 'internal' +// ParserError 2314: (C:36-42): Expected ',' but got 'public' +// ParserError 2314: (D:36-43): Expected ',' but got 'private' +// ParserError 2314: (E:60-68): Expected ',' but got 'external' +// ParserError 2314: (F:60-68): Expected ',' but got 'internal' +// ParserError 2314: (G:60-66): Expected ',' but got 'public' +// ParserError 2314: (H:60-67): Expected ',' but got 'private' diff --git a/test/libsolidity/syntaxTests/visibility/invalid_variable_visibility.sol b/test/libsolidity/syntaxTests/visibility/invalid_variable_visibility.sol new file mode 100644 index 0000000000..4fc73dfbe1 --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/invalid_variable_visibility.sol @@ -0,0 +1,29 @@ +==== Source: A ==== +contract test { + function f(uint a) public { + uint public a; + } +} +==== Source: B ==== +contract test { + function f(uint a) public { + uint private a; + } +} +==== Source: C ==== +contract test { + function f(uint a) public { + uint external a; + } +} +==== Source: D ==== +contract test { + function f(uint a) public { + uint internal a; + } +} +// ---- +// ParserError 2314: (A:61-67): Expected ';' but got 'public' +// ParserError 2314: (B:61-68): Expected ';' but got 'private' +// ParserError 2314: (C:61-69): Expected ';' but got 'external' +// ParserError 2314: (D:61-69): Expected ';' but got 'internal' diff --git a/test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers.sol b/test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers.sol new file mode 100644 index 0000000000..5f3d6d6876 --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers.sol @@ -0,0 +1,53 @@ +contract C { + uint private internal a; + uint private public b; + uint private private c; + uint internal internal e; + uint internal public f; + uint internal private g; + uint public internal h; + uint public public i; + uint public private j; + function f1() private external {} + function f2() private internal {} + function f3() private public {} + function f4() private private {} + function f5() external external {} + function f6() external internal {} + function f7() external public {} + function f8() external private {} + function f9() internal external {} + function f10() internal internal {} + function f11() internal public {} + function f12() internal private {} + function f13() public external {} + function f14() public internal {} + function f15() public public {} + function f16() public private {} +} +// ---- +// ParserError 4110: (30-38): Visibility already specified as "private". +// ParserError 4110: (59-65): Visibility already specified as "private". +// ParserError 4110: (86-93): Visibility already specified as "private". +// ParserError 4110: (115-123): Visibility already specified as "internal". +// ParserError 4110: (145-151): Visibility already specified as "internal". +// ParserError 4110: (173-180): Visibility already specified as "internal". +// ParserError 4110: (200-208): Visibility already specified as "public". +// ParserError 4110: (228-234): Visibility already specified as "public". +// ParserError 4110: (254-261): Visibility already specified as "public". +// ParserError 9439: (291-299): Visibility already specified as "private". +// ParserError 9439: (329-337): Visibility already specified as "private". +// ParserError 9439: (367-373): Visibility already specified as "private". +// ParserError 9439: (403-410): Visibility already specified as "private". +// ParserError 9439: (441-449): Visibility already specified as "external". +// ParserError 9439: (480-488): Visibility already specified as "external". +// ParserError 9439: (519-525): Visibility already specified as "external". +// ParserError 9439: (556-563): Visibility already specified as "external". +// ParserError 9439: (594-602): Visibility already specified as "internal". +// ParserError 9439: (634-642): Visibility already specified as "internal". +// ParserError 9439: (674-680): Visibility already specified as "internal". +// ParserError 9439: (712-719): Visibility already specified as "internal". +// ParserError 9439: (749-757): Visibility already specified as "public". +// ParserError 9439: (787-795): Visibility already specified as "public". +// ParserError 9439: (825-831): Visibility already specified as "public". +// ParserError 9439: (861-868): Visibility already specified as "public". diff --git a/test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers_external.sol b/test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers_external.sol new file mode 100644 index 0000000000..b543e10a4f --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/multiple_visibility_specifiers_external.sol @@ -0,0 +1,16 @@ +==== Source: A ==== +contract C { + uint external external x; +} +==== Source: B ==== +contract C { + uint internal external x; +} +==== Source: C ==== +contract C { + uint external internal x; +} +// ---- +// ParserError 2314: (A:22-30): Expected identifier but got 'external' +// ParserError 2314: (B:31-39): Expected identifier but got 'external' +// ParserError 2314: (C:22-30): Expected identifier but got 'external' From ef6ff2f05550e4386f2fec7753a44fe39a124488 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 23 Nov 2022 11:51:34 +0100 Subject: [PATCH 0040/1140] Adds support for the EVM version "Paris". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deprecates `block.difficulty` and disallow `difficulty()` in inline assembly for EVM versions >= paris. The change is due to the renaming introduced by EIP-4399 (see: https://eips.ethereum.org/EIPS/eip-4399). Introduces `block.prevrandao` in Solidity and `prevrandao()` in inline assembly for EVM versions >= paris. Co-authored-by: Alex Beregszaszi Co-authored-by: Daniel Co-authored-by: matheusaaguiar <95899911+matheusaaguiar@users.noreply.github.com> Co-authored-by: Nikola Matić --- Changelog.md | 4 +- docs/cheatsheet.rst | 5 +- docs/grammar/SolidityLexer.g4 | 4 +- docs/units-and-global-variables.rst | 7 +- docs/yul.rst | 12 ++- libevmasm/Assembly.cpp | 2 +- libevmasm/Assembly.h | 5 +- libevmasm/AssemblyItem.cpp | 17 +++-- libevmasm/AssemblyItem.h | 3 +- libevmasm/CommonSubexpressionEliminator.cpp | 4 +- libevmasm/ConstantOptimiser.cpp | 12 +-- libevmasm/ConstantOptimiser.h | 2 +- libevmasm/Disassemble.cpp | 9 ++- libevmasm/Disassemble.h | 4 +- libevmasm/GasMeter.cpp | 24 +++--- libevmasm/GasMeter.h | 3 +- libevmasm/Instruction.cpp | 10 ++- libevmasm/Instruction.h | 5 +- libevmasm/KnownState.cpp | 4 +- libevmasm/PeepholeOptimiser.cpp | 73 +++++++++++++------ libevmasm/SemanticInformation.cpp | 10 +-- libevmasm/SimplificationRule.h | 2 +- libevmasm/SimplificationRules.cpp | 3 +- liblangutil/EVMVersion.h | 1 + libsolidity/analysis/TypeChecker.cpp | 39 +++++++--- libsolidity/ast/Types.cpp | 1 + libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 4 +- .../codegen/ir/IRGeneratorForStatements.cpp | 9 ++- libsolidity/interface/StandardCompiler.cpp | 6 +- libyul/AsmAnalysis.cpp | 4 +- libyul/CompilabilityChecker.cpp | 2 +- libyul/YulStack.cpp | 2 +- libyul/backends/evm/AbstractAssembly.h | 1 + libyul/backends/evm/EVMDialect.cpp | 25 ++++++- libyul/backends/evm/EVMMetrics.cpp | 6 +- libyul/backends/evm/EthAssemblyAdapter.cpp | 2 +- libyul/backends/evm/NoOutputAssembly.cpp | 2 +- libyul/backends/evm/NoOutputAssembly.h | 3 +- libyul/backends/evm/StackLayoutGenerator.cpp | 8 +- libyul/optimiser/ExpressionSimplifier.cpp | 2 +- libyul/optimiser/KnowledgeBase.cpp | 2 +- libyul/optimiser/Metrics.cpp | 3 +- libyul/optimiser/OptimizerUtilities.cpp | 7 ++ libyul/optimiser/OptimizerUtilities.h | 5 ++ libyul/optimiser/SimplificationRules.cpp | 6 +- libyul/optimiser/SimplificationRules.h | 2 +- scripts/check_style.sh | 3 +- scripts/test_antlr_grammar.sh | 3 + solc/CommandLineInterface.cpp | 6 +- .../evmasm_difficulty_post_paris/args | 1 + .../evmasm_difficulty_post_paris/err | 5 ++ .../evmasm_difficulty_post_paris/input.sol | 18 +++++ .../evmasm_difficulty_post_paris/output | 13 ++++ .../evmasm_difficulty_pre_paris/args | 1 + .../evmasm_difficulty_pre_paris/input.sol | 18 +++++ .../evmasm_difficulty_pre_paris/output | 13 ++++ .../evmasm_prevrandao_post_paris/args | 1 + .../evmasm_prevrandao_post_paris/input.sol | 18 +++++ .../evmasm_prevrandao_post_paris/output | 13 ++++ .../evmasm_prevrandao_pre_paris/args | 1 + .../evmasm_prevrandao_pre_paris/err | 5 ++ .../evmasm_prevrandao_pre_paris/input.sol | 18 +++++ .../evmasm_prevrandao_pre_paris/output | 13 ++++ test/libevmasm/Assembler.cpp | 27 ++++--- test/libevmasm/Optimiser.cpp | 24 +++--- test/libsolidity/SolidityOptimizer.cpp | 6 +- .../analysis/FunctionCallGraph.cpp | 1 + .../inlineAssembly/difficulty.sol | 12 +++ .../inlineAssembly/prevrandao.sol | 12 +++ .../semanticTests/state/block_prevrandao.sol | 10 +++ .../state/block_prevrandao_pre_paris.sol | 10 +++ .../difficulty_builtin_pre_paris.sol | 14 ++++ ...fficulty_disallowed_function_pre_paris.sol | 21 ++++++ ...difficulty_magic_block_warn_post_paris.sol | 9 +++ .../difficulty_nobuiltin_post_paris.sol | 12 +++ .../difficulty_reserved_post_paris.sol | 22 ++++++ .../prevrandao_allowed_function_pre_paris.sol | 20 +++++ .../prevrandao_builtin_post_paris.sol | 14 ++++ ...vrandao_disallowed_function_post_paris.sol | 21 ++++++ .../prevrandao_magic_block_warn_pre_paris.sol | 9 +++ .../prevrandao_nobuitin_pre_paris.sol | 12 +++ ...-byzantium.sol => low_level_homestead.sol} | 2 +- .../tryCatch/low_level_spuriousDragon.sol | 13 ++++ .../tryCatch/low_level_tangerineWhistle.sol | 13 ++++ ...byzantium.sol => structured_homestead.sol} | 2 +- .../tryCatch/structured_spuriousDragon.sol | 13 ++++ .../tryCatch/structured_tangerineWhistle.sol | 13 ++++ .../types/magic_block_istanbul.sol | 7 +- .../syntaxTests/types/magic_block_paris.sol | 13 ++++ .../inline_assembly_instructions_allowed.sol | 4 +- ...e_assembly_instructions_allowed_london.sol | 11 +++ ...ine_assembly_instructions_allowed_pure.sol | 1 - ...ine_assembly_instructions_allowed_view.sol | 4 +- ...embly_instructions_allowed_view_london.sol | 10 +++ ..._assembly_instructions_disallowed_pure.sol | 60 ++++++--------- ...instructions_disallowed_pure_byzantium.sol | 11 +++ ...uctions_disallowed_pure_constantinople.sol | 13 ++++ ..._instructions_disallowed_pure_istanbul.sol | 13 ++++ ...ly_instructions_disallowed_pure_london.sol | 11 +++ ...bly_instructions_disallowed_pure_paris.sol | 11 +++ ...instructions_disallowed_pure_pre_paris.sol | 11 +++ test/libyul/EVMCodeTransformTest.cpp | 4 +- test/libyul/ObjectCompilerTest.cpp | 4 +- test/libyul/YulInterpreterTest.cpp | 2 +- .../ewasmTranslationTests/difficulty.yul | 2 + .../libyul/yulInterpreterTests/difficulty.yul | 10 +++ .../libyul/yulInterpreterTests/prevrandao.yul | 10 +++ test/tools/fuzzer_common.cpp | 2 +- .../EVMInstructionInterpreter.cpp | 8 +- .../EVMInstructionInterpreter.h | 6 +- .../EwasmBuiltinInterpreter.cpp | 2 +- test/tools/yulInterpreter/Interpreter.cpp | 2 +- test/tools/yulInterpreter/Interpreter.h | 1 + 114 files changed, 842 insertions(+), 221 deletions(-) create mode 100644 test/cmdlineTests/evmasm_difficulty_post_paris/args create mode 100644 test/cmdlineTests/evmasm_difficulty_post_paris/err create mode 100644 test/cmdlineTests/evmasm_difficulty_post_paris/input.sol create mode 100644 test/cmdlineTests/evmasm_difficulty_post_paris/output create mode 100644 test/cmdlineTests/evmasm_difficulty_pre_paris/args create mode 100644 test/cmdlineTests/evmasm_difficulty_pre_paris/input.sol create mode 100644 test/cmdlineTests/evmasm_difficulty_pre_paris/output create mode 100644 test/cmdlineTests/evmasm_prevrandao_post_paris/args create mode 100644 test/cmdlineTests/evmasm_prevrandao_post_paris/input.sol create mode 100644 test/cmdlineTests/evmasm_prevrandao_post_paris/output create mode 100644 test/cmdlineTests/evmasm_prevrandao_pre_paris/args create mode 100644 test/cmdlineTests/evmasm_prevrandao_pre_paris/err create mode 100644 test/cmdlineTests/evmasm_prevrandao_pre_paris/input.sol create mode 100644 test/cmdlineTests/evmasm_prevrandao_pre_paris/output create mode 100644 test/libsolidity/semanticTests/inlineAssembly/difficulty.sol create mode 100644 test/libsolidity/semanticTests/inlineAssembly/prevrandao.sol create mode 100644 test/libsolidity/semanticTests/state/block_prevrandao.sol create mode 100644 test/libsolidity/semanticTests/state/block_prevrandao_pre_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_builtin_pre_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_magic_block_warn_post_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_nobuiltin_post_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_reserved_post_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_builtin_post_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_magic_block_warn_pre_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_nobuitin_pre_paris.sol rename test/libsolidity/syntaxTests/tryCatch/{low_level_pre-byzantium.sol => low_level_homestead.sol} (92%) create mode 100644 test/libsolidity/syntaxTests/tryCatch/low_level_spuriousDragon.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/low_level_tangerineWhistle.sol rename test/libsolidity/syntaxTests/tryCatch/{structured_pre_byzantium.sol => structured_homestead.sol} (92%) create mode 100644 test/libsolidity/syntaxTests/tryCatch/structured_spuriousDragon.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/structured_tangerineWhistle.sol create mode 100644 test/libsolidity/syntaxTests/types/magic_block_paris.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_london.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_istanbul.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_paris.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_pre_paris.sol create mode 100644 test/libyul/yulInterpreterTests/difficulty.yul create mode 100644 test/libyul/yulInterpreterTests/prevrandao.yul diff --git a/Changelog.md b/Changelog.md index 2877bbf8c5..251144b378 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,7 +7,9 @@ Language Features: Compiler Features: * Commandline Interface: Return exit code ``2`` on uncaught exceptions. * Commandline Interface: Add `--no-cbor-metadata` that skips CBOR metadata from getting appended at the end of the bytecode. - * EVM: Basic support for the EVM version "Paris". + * EVM: Deprecate ``block.difficulty`` and disallow ``difficulty()`` in inline assembly for EVM versions >= paris. The change is due to the renaming introduced by [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399). + * EVM: Introduce ``block.prevrandao`` in Solidity and ``prevrandao()`` in inline assembly for EVM versions >= paris. + * EVM: Support for the EVM version "Paris". * Natspec: Add event Natspec inheritance for devdoc. * Standard JSON: Add a boolean field `settings.metadata.appendCBOR` that skips CBOR metadata from getting appended at the end of the bytecode. * Yul EVM Code Transform: Generate more optimal code for user-defined functions that always terminate a transaction. No return labels will be pushed for calls to functions that always terminate. diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 412678953e..5d8e6ede76 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -8,7 +8,7 @@ Order of Precedence of Operators ================================ .. include:: types/operator-precedence-table.rst -.. index:: assert, block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, codehash, send +.. index:: assert, block, coinbase, difficulty, prevrandao, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, codehash, send Global Variables ================ @@ -32,9 +32,10 @@ Global Variables - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.chainid`` (``uint``): current chain id - ``block.coinbase`` (``address payable``): current block miner's address -- ``block.difficulty`` (``uint``): current block difficulty +- ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` that will be removed in the next breaking release - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number +- ``block.prevrandao`` (``uint``): random number provided by the beacon chain (``EVM >= Paris``) (see `EIP-4399 `_ ) - ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch - ``gasleft() returns (uint256)``: remaining gas - ``msg.data`` (``bytes``): complete calldata diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index c47dc411cd..b0dfca0c47 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -291,8 +291,8 @@ YulEVMBuiltin: | 'returndatacopy' | 'extcodehash' | 'create' | 'create2' | 'call' | 'callcode' | 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid' | 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice' - | 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'gaslimit' - | 'basefee'; + | 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'prevrandao' + | 'gaslimit' | 'basefee'; YulLBrace: '{' -> pushMode(YulMode); YulRBrace: '}' -> popMode; diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index cf4fb2bd7c..6e49665907 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -65,7 +65,7 @@ There are special variables and functions which always exist in the global namespace and are mainly used to provide information about the blockchain or are general-use utility functions. -.. index:: abi, block, coinbase, difficulty, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin +.. index:: abi, block, coinbase, difficulty, prevrandao, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin Block and Transaction Properties @@ -75,9 +75,10 @@ Block and Transaction Properties - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.chainid`` (``uint``): current chain id - ``block.coinbase`` (``address payable``): current block miner's address -- ``block.difficulty`` (``uint``): current block difficulty +- ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` (`EIP-4399 `_ ) - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number +- ``block.prevrandao`` (``uint``): random number provided by the beacon chain (``EVM >= Paris``) - ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch - ``gasleft() returns (uint256)``: remaining gas - ``msg.data`` (``bytes calldata``): complete calldata @@ -394,4 +395,4 @@ These keywords are reserved in Solidity. They might become part of the syntax in ``define``, ``final``, ``implements``, ``in``, ``inline``, ``let``, ``macro``, ``match``, ``mutable``, ``null``, ``of``, ``partial``, ``promise``, ``reference``, ``relocatable``, ``sealed``, ``sizeof``, ``static``, ``supports``, ``switch``, ``typedef``, ``typeof``, -``var``. \ No newline at end of file +``var``. diff --git a/docs/yul.rst b/docs/yul.rst index 8ae454b2e0..206f80cace 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -751,8 +751,8 @@ This document does not want to be a full description of the Ethereum virtual mac Please refer to a different document if you are interested in the precise semantics. Opcodes marked with ``-`` do not return a result and all others return exactly one value. -Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I`` and ``L`` are present since Frontier, Homestead, -Byzantium, Constantinople, Istanbul or London respectively. +Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L`` and ``P`` are present since Frontier, +Homestead, Byzantium, Constantinople, Istanbul, London or Paris respectively. In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to but not including position ``b`` and ``storage[p]`` signifies the storage contents at slot ``p``. @@ -931,6 +931,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | difficulty() | | F | difficulty of the current block (see note below) | +-------------------------+-----+---+-----------------------------------------------------------------+ +| prevrandao() | | P | randomness provided by the beacon chain (see note below) | ++-------------------------+-----+---+-----------------------------------------------------------------+ | gaslimit() | | F | block gas limit of the current block | +-------------------------+-----+---+-----------------------------------------------------------------+ @@ -945,8 +947,10 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a The remaining bytes will retain their values as of before the call. .. note:: - With the Paris network upgrade the semantics of ``difficulty`` have been changed. - It returns the value of ``prevrandao``, which is a 256-bit value, whereas the highest recorded + The `difficulty()` instruction is disallowed in EVM version >= Paris. + With the Paris network upgrade the semantics of the instruction that was previously called + ``difficulty`` have been changed and the instruction was renamed to ``prevrandao``. + It can now return arbitrary values in the full 256-bit range, whereas the highest recorded difficulty value within Ethash was ~54 bits. This change is described in `EIP-4399 `_. Please note that irrelevant to which EVM version is selected in the compiler, the semantics of diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 5b6e2a86f3..f596f63038 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -237,7 +237,7 @@ Json::Value Assembly::assemblyJSON(map const& _sourceIndices, sourceIndex = static_cast(iter->second); } - auto [name, data] = item.nameAndData(); + auto [name, data] = item.nameAndData(m_evmVersion); Json::Value jsonItem; jsonItem["name"] = name; jsonItem["begin"] = item.location().start; diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 7b8b4509d8..bd37b3a7fd 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -49,7 +49,7 @@ using AssemblyPointer = std::shared_ptr; class Assembly { public: - Assembly(bool _creation, std::string _name): m_creation(_creation), m_name(std::move(_name)) { } + Assembly(langutil::EVMVersion _evmVersion, bool _creation, std::string _name): m_evmVersion(_evmVersion), m_creation(_creation), m_name(std::move(_name)) { } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } @@ -112,6 +112,7 @@ class Assembly /// Changes the source location used for each appended item. void setSourceLocation(langutil::SourceLocation const& _location) { m_currentSourceLocation = _location; } langutil::SourceLocation const& currentSourceLocation() const { return m_currentSourceLocation; } + langutil::EVMVersion const& evmVersion() const { return m_evmVersion; } /// Assembles the assembly into bytecode. The assembly should not be modified after this call, since the assembled version is cached. LinkerObject const& assemble() const; @@ -208,6 +209,8 @@ class Assembly mutable LinkerObject m_assembledObject; mutable std::vector m_tagPositionsInBytecode; + langutil::EVMVersion m_evmVersion; + int m_deposit = 0; /// True, if the assembly contains contract creation code. bool const m_creation = false; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index a36e0ddb1d..ce60c25161 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -69,12 +69,12 @@ pair AssemblyItem::splitForeignPushTag() const return make_pair(subId, tag); } -pair AssemblyItem::nameAndData() const +pair AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const { switch (type()) { case Operation: - return {instructionInfo(instruction()).name, m_data != nullptr ? toStringInHex(*m_data) : ""}; + return {instructionInfo(instruction(), _evmVersion).name, m_data != nullptr ? toStringInHex(*m_data) : ""}; case Push: return {"PUSH", toStringInHex(data())}; case PushTag: @@ -168,7 +168,9 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision) size_t AssemblyItem::arguments() const { if (type() == Operation) - return static_cast(instructionInfo(instruction()).args); + // The latest EVMVersion is used here, since the InstructionInfo is assumed to be + // the same across all EVM versions except for the instruction name. + return static_cast(instructionInfo(instruction(), EVMVersion()).args); else if (type() == VerbatimBytecode) return get<0>(*m_verbatimBytecode); else if (type() == AssignImmutable) @@ -182,7 +184,9 @@ size_t AssemblyItem::returnValues() const switch (m_type) { case Operation: - return static_cast(instructionInfo(instruction()).ret); + // The latest EVMVersion is used here, since the InstructionInfo is assumed to be + // the same across all EVM versions except for the instruction name. + return static_cast(instructionInfo(instruction(), EVMVersion()).ret); case Push: case PushTag: case PushData: @@ -251,7 +255,7 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case Operation: { assertThrow(isValidInstruction(instruction()), AssemblyException, "Invalid instruction."); - text = util::toLower(instructionInfo(instruction()).name); + text = util::toLower(instructionInfo(instruction(), _assembly.evmVersion()).name); break; } case Push: @@ -323,12 +327,13 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const return text; } +// Note: This method is exclusively used for debugging. ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item) { switch (_item.type()) { case Operation: - _out << " " << instructionInfo(_item.instruction()).name; + _out << " " << instructionInfo(_item.instruction(), EVMVersion()).name; if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI) _out << "\t" << _item.getJumpTypeAsString(); break; diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 4aef82d8b2..077c1912d2 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -108,10 +108,11 @@ class AssemblyItem /// This function is used in `Assembly::assemblyJSON`. /// It returns the name & data of the current assembly item. + /// @param _evmVersion the EVM version. /// @returns a pair, where the first element is the json-assembly /// item name, where second element is the string representation /// of it's data. - std::pair nameAndData() const; + std::pair nameAndData(langutil::EVMVersion _evmVersion) const; bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); } diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 19b275cb6f..d097f3c725 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -406,7 +406,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) m_stack.erase(m_stackHeight - static_cast(i)); } appendItem(*expr.item); - if (expr.item->type() != Operation || instructionInfo(expr.item->instruction()).ret == 1) + if (expr.item->type() != Operation || instructionInfo(expr.item->instruction(), EVMVersion()).ret == 1) { m_stack[m_stackHeight] = _c; m_classPositions[_c].insert(m_stackHeight); @@ -414,7 +414,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) else { assertThrow( - instructionInfo(expr.item->instruction()).ret == 0, + instructionInfo(expr.item->instruction(), EVMVersion()).ret == 0, OptimizerException, "Invalid number of return values." ); diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 37ac4c18bd..5bce21cf1e 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -79,18 +79,18 @@ unsigned ConstantOptimisationMethod::optimiseConstants( return optimisations; } -bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items) +bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items, langutil::EVMVersion _evmVersion) { bigint gas = 0; for (AssemblyItem const& item: _items) if (item.type() == Push) - gas += GasMeter::runGas(Instruction::PUSH1); + gas += GasMeter::runGas(Instruction::PUSH1, _evmVersion); else if (item.type() == Operation) { if (item.instruction() == Instruction::EXP) gas += GasCosts::expGas; else - gas += GasMeter::runGas(item.instruction()); + gas += GasMeter::runGas(item.instruction(), _evmVersion); } return gas; } @@ -131,7 +131,7 @@ void ConstantOptimisationMethod::replaceConstants( bigint LiteralMethod::gasNeeded() const { return combineGas( - simpleRunGas({Instruction::PUSH1}), + simpleRunGas({Instruction::PUSH1}, m_params.evmVersion), // PUSHX plus data (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas) + dataGas(toCompactBigEndian(m_value, 1)), 0 @@ -142,7 +142,7 @@ bigint CodeCopyMethod::gasNeeded() const { return combineGas( // Run gas: we ignore memory increase costs - simpleRunGas(copyRoutine()) + GasCosts::copyGas, + simpleRunGas(copyRoutine(), m_params.evmVersion) + GasCosts::copyGas, // Data gas for copy routines: Some bytes are zero, but we ignore them. bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas), // Data gas for data itself @@ -322,7 +322,7 @@ bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const { auto numExps = static_cast(count(_routine.begin(), _routine.end(), Instruction::EXP)); return combineGas( - simpleRunGas(_routine) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)), + simpleRunGas(_routine, m_params.evmVersion) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)), // Data gas for routine: Some bytes are zero, but we ignore them. bytesRequired(_routine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas), 0 diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index ece28d2496..b491fb0042 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -76,7 +76,7 @@ class ConstantOptimisationMethod protected: /// @returns the run gas for the given items ignoring special gas costs - static bigint simpleRunGas(AssemblyItems const& _items); + static bigint simpleRunGas(AssemblyItems const& _items, langutil::EVMVersion _evmVersion); /// @returns the gas needed to store the given data literally bigint dataGas(bytes const& _data) const; static size_t bytesRequired(AssemblyItems const& _items); diff --git a/libevmasm/Disassemble.cpp b/libevmasm/Disassemble.cpp index aa5b2820c4..f1c904b699 100644 --- a/libevmasm/Disassemble.cpp +++ b/libevmasm/Disassemble.cpp @@ -30,6 +30,7 @@ using namespace solidity::evmasm; void solidity::evmasm::eachInstruction( bytes const& _mem, + langutil::EVMVersion _evmVersion, function const& _onInstruction ) { @@ -38,7 +39,7 @@ void solidity::evmasm::eachInstruction( Instruction const instr{*it}; int additional = 0; if (isValidInstruction(instr)) - additional = instructionInfo(instr).additional; + additional = instructionInfo(instr, _evmVersion).additional; u256 data{}; @@ -57,15 +58,15 @@ void solidity::evmasm::eachInstruction( } } -string solidity::evmasm::disassemble(bytes const& _mem, string const& _delimiter) +string solidity::evmasm::disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, string const& _delimiter) { stringstream ret; - eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) { + eachInstruction(_mem, _evmVersion, [&](Instruction _instr, u256 const& _data) { if (!isValidInstruction(_instr)) ret << "0x" << std::uppercase << std::hex << static_cast(_instr) << _delimiter; else { - InstructionInfo info = instructionInfo(_instr); + InstructionInfo info = instructionInfo(_instr, _evmVersion); ret << info.name; if (info.additional) ret << " 0x" << std::uppercase << std::hex << _data; diff --git a/libevmasm/Disassemble.h b/libevmasm/Disassemble.h index cf194e24b7..2e03a5d35c 100644 --- a/libevmasm/Disassemble.h +++ b/libevmasm/Disassemble.h @@ -30,9 +30,9 @@ namespace solidity::evmasm { /// Iterate through EVM code and call a function on each instruction. -void eachInstruction(bytes const& _mem, std::function const& _onInstruction); +void eachInstruction(bytes const& _mem, langutil::EVMVersion _evmVersion, std::function const& _onInstruction); /// Convert from EVM code to simple EVM assembly language. -std::string disassemble(bytes const& _mem, std::string const& _delimiter = " "); +std::string disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, std::string const& _delimiter = " "); } diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index d49ee98919..258f68b31f 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -52,10 +52,10 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _ case PushProgramSize: case PushLibraryAddress: case PushDeployTimeAddress: - gas = runGas(Instruction::PUSH1); + gas = runGas(Instruction::PUSH1, m_evmVersion); break; case Tag: - gas = runGas(Instruction::JUMPDEST); + gas = runGas(Instruction::JUMPDEST, m_evmVersion); break; case Operation: { @@ -80,19 +80,19 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _ break; case Instruction::RETURN: case Instruction::REVERT: - gas = runGas(_item.instruction()); + gas = runGas(_item.instruction(), m_evmVersion); gas += memoryGas(0, -1); break; case Instruction::MLOAD: case Instruction::MSTORE: - gas = runGas(_item.instruction()); + gas = runGas(_item.instruction(), m_evmVersion); gas += memoryGas(classes.find(Instruction::ADD, { m_state->relativeStackElement(0), classes.find(AssemblyItem(32)) })); break; case Instruction::MSTORE8: - gas = runGas(_item.instruction()); + gas = runGas(_item.instruction(), m_evmVersion); gas += memoryGas(classes.find(Instruction::ADD, { m_state->relativeStackElement(0), classes.find(AssemblyItem(1)) @@ -106,7 +106,7 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _ case Instruction::CALLDATACOPY: case Instruction::CODECOPY: case Instruction::RETURNDATACOPY: - gas = runGas(_item.instruction()); + gas = runGas(_item.instruction(), m_evmVersion); gas += memoryGas(0, -2); gas += wordGas(GasCosts::copyGas, m_state->relativeStackElement(-2)); break; @@ -195,13 +195,13 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _ gas = GasCosts::balanceGas(m_evmVersion); break; case Instruction::CHAINID: - gas = runGas(Instruction::CHAINID); + gas = runGas(Instruction::CHAINID, m_evmVersion); break; case Instruction::SELFBALANCE: - gas = runGas(Instruction::SELFBALANCE); + gas = runGas(Instruction::SELFBALANCE, m_evmVersion); break; default: - gas = runGas(_item.instruction()); + gas = runGas(_item.instruction(), m_evmVersion); break; } break; @@ -252,12 +252,12 @@ GasMeter::GasConsumption GasMeter::memoryGas(int _stackPosOffset, int _stackPosS })); } -unsigned GasMeter::runGas(Instruction _instruction) +unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVersion) { if (_instruction == Instruction::JUMPDEST) return 1; - switch (instructionInfo(_instruction).gasPriceTier) + switch (instructionInfo(_instruction, _evmVersion).gasPriceTier) { case Tier::Zero: return GasCosts::tier0Gas; case Tier::Base: return GasCosts::tier1Gas; @@ -268,7 +268,7 @@ unsigned GasMeter::runGas(Instruction _instruction) case Tier::Ext: return GasCosts::tier6Gas; default: break; } - assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction).name); + assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); return 0; } diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index 306fc02088..ec19466447 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -221,7 +221,7 @@ class GasMeter /// @returns gas costs for simple instructions with constant gas costs (that do not /// change with EVM versions) - static unsigned runGas(Instruction _instruction); + static unsigned runGas(Instruction _instruction, langutil::EVMVersion _evmVersion); /// @returns the gas cost of the supplied data, depending whether it is in creation code, or not. /// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas @@ -257,5 +257,4 @@ inline std::ostream& operator<<(std::ostream& _str, GasMeter::GasConsumption con return _str << std::dec << _consumption.value; } - } diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index e2ce48b7f1..418a6e1856 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -76,7 +76,8 @@ std::map const solidity::evmasm::c_instructions = { "COINBASE", Instruction::COINBASE }, { "TIMESTAMP", Instruction::TIMESTAMP }, { "NUMBER", Instruction::NUMBER }, - { "DIFFICULTY", Instruction::DIFFICULTY }, + { "DIFFICULTY", Instruction::PREVRANDAO }, + { "PREVRANDAO", Instruction::PREVRANDAO }, { "GASLIMIT", Instruction::GASLIMIT }, { "CHAINID", Instruction::CHAINID }, { "SELFBALANCE", Instruction::SELFBALANCE }, @@ -174,6 +175,7 @@ std::map const solidity::evmasm::c_instructions = { "SELFDESTRUCT", Instruction::SELFDESTRUCT } }; +/// @note InstructionInfo is assumed to be the same across all EVM versions except for the instruction name. static std::map const c_instructionInfo = { // Add, Args, Ret, SideEffects, GasPriceTier { Instruction::STOP, { "STOP", 0, 0, 0, true, Tier::Zero } }, @@ -223,7 +225,7 @@ static std::map const c_instructionInfo = { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } }, { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } }, { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false, Tier::Base } }, - { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, Tier::Base } }, + { Instruction::PREVRANDAO, { "PREVRANDAO", 0, 0, 1, false, Tier::Base } }, { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } }, { Instruction::CHAINID, { "CHAINID", 0, 0, 1, false, Tier::Base } }, { Instruction::SELFBALANCE, { "SELFBALANCE", 0, 0, 1, false, Tier::Low } }, @@ -321,10 +323,12 @@ static std::map const c_instructionInfo = { Instruction::SELFDESTRUCT, { "SELFDESTRUCT", 0, 1, 0, true, Tier::Special } } }; -InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst) +InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst, langutil::EVMVersion _evmVersion) { try { + if (_inst == Instruction::PREVRANDAO && _evmVersion < langutil::EVMVersion::paris()) + return InstructionInfo({ "DIFFICULTY", 0, 0, 1, false, Tier::Base }); return c_instructionInfo.at(_inst); } catch (...) diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 5d4432ca58..48ee37b5c7 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace solidity::evmasm { @@ -83,7 +84,7 @@ enum class Instruction: uint8_t COINBASE, ///< get the block's coinbase address TIMESTAMP, ///< get the block's timestamp NUMBER, ///< get the block's number - DIFFICULTY, ///< get the block's difficulty + PREVRANDAO, ///< get randomness provided by the beacon chain GASLIMIT, ///< get the block's gas limit CHAINID, ///< get the config's chainid param SELFBALANCE, ///< get balance of the current account @@ -306,7 +307,7 @@ struct InstructionInfo }; /// Information on all the instructions. -InstructionInfo instructionInfo(Instruction _inst); +InstructionInfo instructionInfo(Instruction _inst, langutil::EVMVersion _evmVersion); /// check whether instructions exists. bool isValidInstruction(Instruction _inst); diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 1e886f7ab0..a2bda5af71 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -130,7 +130,9 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool else { Instruction instruction = _item.instruction(); - InstructionInfo info = instructionInfo(instruction); + // The latest EVMVersion is used here, since the InstructionInfo is assumed to be + // the same across all EVM versions except for the instruction name. + InstructionInfo info = instructionInfo(instruction, EVMVersion()); if (SemanticInformation::isDupInstruction(_item)) setStackElement( m_stackHeight + 1, diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 334903c92b..22d40c8ea1 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -38,7 +38,7 @@ struct OptimiserState { AssemblyItems const& items; size_t i; - std::back_insert_iterator out; + back_insert_iterator out; }; template @@ -53,7 +53,11 @@ template struct SimplePeepholeOptimizerMethod { template - static bool applyRule(AssemblyItems::const_iterator _in, back_insert_iterator _out, index_sequence) + static bool applyRule( + AssemblyItems::const_iterator _in, + back_insert_iterator _out, + index_sequence + ) { return Method::applySimple(_in[Indices]..., _out); } @@ -75,7 +79,10 @@ struct SimplePeepholeOptimizerMethod struct Identity: SimplePeepholeOptimizerMethod { - static bool applySimple(AssemblyItem const& _item, std::back_insert_iterator _out) + static bool applySimple( + AssemblyItem const& _item, + back_insert_iterator _out + ) { *_out = _item; return true; @@ -84,7 +91,11 @@ struct Identity: SimplePeepholeOptimizerMethod struct PushPop: SimplePeepholeOptimizerMethod { - static bool applySimple(AssemblyItem const& _push, AssemblyItem const& _pop, std::back_insert_iterator) + static bool applySimple( + AssemblyItem const& _push, + AssemblyItem const& _pop, + back_insert_iterator + ) { auto t = _push.type(); return _pop == Instruction::POP && ( @@ -100,15 +111,15 @@ struct OpPop: SimplePeepholeOptimizerMethod static bool applySimple( AssemblyItem const& _op, AssemblyItem const& _pop, - std::back_insert_iterator _out + back_insert_iterator _out ) { if (_pop == Instruction::POP && _op.type() == Operation) { Instruction instr = _op.instruction(); - if (instructionInfo(instr).ret == 1 && !instructionInfo(instr).sideEffects) + if (instructionInfo(instr, langutil::EVMVersion()).ret == 1 && !instructionInfo(instr, langutil::EVMVersion()).sideEffects) { - for (int j = 0; j < instructionInfo(instr).args; j++) + for (int j = 0; j < instructionInfo(instr, langutil::EVMVersion()).args; j++) *_out = {Instruction::POP, _op.location()}; return true; } @@ -122,7 +133,7 @@ struct OpStop: SimplePeepholeOptimizerMethod static bool applySimple( AssemblyItem const& _op, AssemblyItem const& _stop, - std::back_insert_iterator _out + back_insert_iterator _out ) { if (_stop == Instruction::STOP) @@ -130,7 +141,7 @@ struct OpStop: SimplePeepholeOptimizerMethod if (_op.type() == Operation) { Instruction instr = _op.instruction(); - if (!instructionInfo(instr).sideEffects) + if (!instructionInfo(instr, langutil::EVMVersion()).sideEffects) { *_out = {Instruction::STOP, _op.location()}; return true; @@ -153,7 +164,7 @@ struct OpReturnRevert: SimplePeepholeOptimizerMethod AssemblyItem const& _push, AssemblyItem const& _pushOrDup, AssemblyItem const& _returnRevert, - std::back_insert_iterator _out + back_insert_iterator _out ) { if ( @@ -162,7 +173,7 @@ struct OpReturnRevert: SimplePeepholeOptimizerMethod (_pushOrDup.type() == Push || _pushOrDup == dupInstruction(1)) ) if ( - (_op.type() == Operation && !instructionInfo(_op.instruction()).sideEffects) || + (_op.type() == Operation && !instructionInfo(_op.instruction(), langutil::EVMVersion()).sideEffects) || _op.type() == Push ) { @@ -177,7 +188,11 @@ struct OpReturnRevert: SimplePeepholeOptimizerMethod struct DoubleSwap: SimplePeepholeOptimizerMethod { - static size_t applySimple(AssemblyItem const& _s1, AssemblyItem const& _s2, std::back_insert_iterator) + static size_t applySimple( + AssemblyItem const& _s1, + AssemblyItem const& _s2, + back_insert_iterator + ) { return _s1 == _s2 && SemanticInformation::isSwapInstruction(_s1); } @@ -185,7 +200,11 @@ struct DoubleSwap: SimplePeepholeOptimizerMethod struct DoublePush: SimplePeepholeOptimizerMethod { - static bool applySimple(AssemblyItem const& _push1, AssemblyItem const& _push2, std::back_insert_iterator _out) + static bool applySimple( + AssemblyItem const& _push1, + AssemblyItem const& _push2, + back_insert_iterator _out + ) { if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data()) { @@ -200,7 +219,11 @@ struct DoublePush: SimplePeepholeOptimizerMethod struct CommutativeSwap: SimplePeepholeOptimizerMethod { - static bool applySimple(AssemblyItem const& _swap, AssemblyItem const& _op, std::back_insert_iterator _out) + static bool applySimple( + AssemblyItem const& _swap, + AssemblyItem const& _op, + back_insert_iterator _out + ) { // Remove SWAP1 if following instruction is commutative if ( @@ -218,7 +241,11 @@ struct CommutativeSwap: SimplePeepholeOptimizerMethod struct SwapComparison: SimplePeepholeOptimizerMethod { - static bool applySimple(AssemblyItem const& _swap, AssemblyItem const& _op, std::back_insert_iterator _out) + static bool applySimple( + AssemblyItem const& _swap, + AssemblyItem const& _op, + back_insert_iterator _out + ) { static map const swappableOps{ { Instruction::LT, Instruction::GT }, @@ -247,7 +274,7 @@ struct DupSwap: SimplePeepholeOptimizerMethod static size_t applySimple( AssemblyItem const& _dupN, AssemblyItem const& _swapN, - std::back_insert_iterator _out + back_insert_iterator _out ) { if ( @@ -272,7 +299,7 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod AssemblyItem const& _iszero2, AssemblyItem const& _pushTag, AssemblyItem const& _jumpi, - std::back_insert_iterator _out + back_insert_iterator _out ) { if ( @@ -298,7 +325,7 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod AssemblyItem const& _iszero, AssemblyItem const& _pushTag, AssemblyItem const& _jumpi, - std::back_insert_iterator _out + back_insert_iterator _out ) { if ( @@ -327,7 +354,7 @@ struct DoubleJump: SimplePeepholeOptimizerMethod AssemblyItem const& _pushTag2, AssemblyItem const& _jump, AssemblyItem const& _tag1, - std::back_insert_iterator _out + back_insert_iterator _out ) { if ( @@ -356,7 +383,7 @@ struct JumpToNext: SimplePeepholeOptimizerMethod AssemblyItem const& _pushTag, AssemblyItem const& _jump, AssemblyItem const& _tag, - std::back_insert_iterator _out + back_insert_iterator _out ) { if ( @@ -382,7 +409,7 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod AssemblyItem const& _pushTag, AssemblyItem const& _pushConstant, AssemblyItem const& _and, - std::back_insert_iterator _out + back_insert_iterator _out ) { if (_and != Instruction::AND) @@ -417,7 +444,7 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod AssemblyItem const& _push, AssemblyItem const& _not, AssemblyItem const& _and, - std::back_insert_iterator + back_insert_iterator ) { return ( @@ -484,7 +511,7 @@ bool PeepholeOptimiser::optimise() { // Avoid referencing immutables too early by using approx. counting in bytesRequired() auto const approx = evmasm::Precision::Approximate; - OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)}; + OptimiserState state {m_items, 0, back_inserter(m_optimisedItems)}; while (state.i < m_items.size()) applyMethods( state, diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index acbcaa5c0f..b6bcc82802 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -110,7 +110,7 @@ vector SemanticInformation::readWriteOperations( case Instruction::CALLCODE: case Instruction::DELEGATECALL: { - size_t paramCount = static_cast(instructionInfo(_instruction).args); + size_t paramCount = static_cast(instructionInfo(_instruction, langutil::EVMVersion()).args); vector operations{ Operation{Location::Memory, Effect::Read, paramCount - 4, paramCount - 3, {}}, Operation{Location::Storage, Effect::Read, {}, {}, {}} @@ -178,7 +178,7 @@ bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item, bool return true; // GAS and PC assume a specific order of opcodes if (_item.instruction() == Instruction::MSIZE) return true; // msize is modified already by memory access, avoid that for now - InstructionInfo info = instructionInfo(_item.instruction()); + InstructionInfo info = instructionInfo(_item.instruction(), langutil::EVMVersion()); if (_item.instruction() == Instruction::SSTORE) return false; if (_item.instruction() == Instruction::MSTORE) @@ -318,7 +318,7 @@ bool SemanticInformation::movable(Instruction _instruction) // These are not really functional. if (isDupInstruction(_instruction) || isSwapInstruction(_instruction)) return false; - InstructionInfo info = instructionInfo(_instruction); + InstructionInfo info = instructionInfo(_instruction, langutil::EVMVersion()); if (info.sideEffects) return false; switch (_instruction) @@ -345,7 +345,7 @@ bool SemanticInformation::canBeRemoved(Instruction _instruction) // These are not really functional. assertThrow(!isDupInstruction(_instruction) && !isSwapInstruction(_instruction), AssemblyException, ""); - return !instructionInfo(_instruction).sideEffects; + return !instructionInfo(_instruction, langutil::EVMVersion()).sideEffects; } bool SemanticInformation::canBeRemovedIfNoMSize(Instruction _instruction) @@ -483,7 +483,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) case Instruction::COINBASE: case Instruction::TIMESTAMP: case Instruction::NUMBER: - case Instruction::DIFFICULTY: + case Instruction::PREVRANDAO: case Instruction::GASLIMIT: case Instruction::STATICCALL: case Instruction::SLOAD: diff --git a/libevmasm/SimplificationRule.h b/libevmasm/SimplificationRule.h index d548a00dfb..e970068fbd 100644 --- a/libevmasm/SimplificationRule.h +++ b/libevmasm/SimplificationRule.h @@ -122,7 +122,7 @@ struct EVMBuiltins static auto constexpr COINBASE = PatternGenerator{}; static auto constexpr TIMESTAMP = PatternGenerator{}; static auto constexpr NUMBER = PatternGenerator{}; - static auto constexpr DIFFICULTY = PatternGenerator{}; + static auto constexpr PREVRANDAO = PatternGenerator{}; static auto constexpr GASLIMIT = PatternGenerator{}; static auto constexpr CHAINID = PatternGenerator{}; static auto constexpr SELFBALANCE = PatternGenerator{}; diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index a21ed41951..bcb8da3882 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -141,7 +141,8 @@ string Pattern::toString() const switch (m_type) { case Operation: - s << instructionInfo(m_instruction).name; + // Note: This function is exclusively used for debugging. + s << instructionInfo(m_instruction, EVMVersion()).name; break; case Push: if (m_data) diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index d366338451..f985b4aff8 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -96,6 +96,7 @@ class EVMVersion: bool hasChainID() const { return *this >= istanbul(); } bool hasSelfBalance() const { return *this >= istanbul(); } bool hasBaseFee() const { return *this >= london(); } + bool hasPrevRandao() const { return *this >= paris(); } bool hasOpcode(evmasm::Instruction _opcode) const; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 00c763a90b..ac00ab7fe5 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3296,18 +3296,33 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) (memberName == "min" || memberName == "max") ) annotation.isPure = true; - else if (magicType->kind() == MagicType::Kind::Block && memberName == "chainid" && !m_evmVersion.hasChainID()) - m_errorReporter.typeError( - 3081_error, - _memberAccess.location(), - "\"chainid\" is not supported by the VM version." - ); - else if (magicType->kind() == MagicType::Kind::Block && memberName == "basefee" && !m_evmVersion.hasBaseFee()) - m_errorReporter.typeError( - 5921_error, - _memberAccess.location(), - "\"basefee\" is not supported by the VM version." - ); + else if (magicType->kind() == MagicType::Kind::Block) + { + if (memberName == "chainid" && !m_evmVersion.hasChainID()) + m_errorReporter.typeError( + 3081_error, + _memberAccess.location(), + "\"chainid\" is not supported by the VM version." + ); + else if (memberName == "basefee" && !m_evmVersion.hasBaseFee()) + m_errorReporter.typeError( + 5921_error, + _memberAccess.location(), + "\"basefee\" is not supported by the VM version." + ); + else if (memberName == "prevrandao" && !m_evmVersion.hasPrevRandao()) + m_errorReporter.warning( + 9432_error, + _memberAccess.location(), + "\"prevrandao\" is not supported by the VM version and will be treated as \"difficulty\"." + ); + else if (memberName == "difficulty" && m_evmVersion.hasPrevRandao()) + m_errorReporter.warning( + 8417_error, + _memberAccess.location(), + "Since the VM version paris, \"difficulty\" was replaced by \"prevrandao\", which now returns a random number based on the beacon chain." + ); + } } if ( diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 9bbd70a675..0a148f2fb2 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -4067,6 +4067,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const {"timestamp", TypeProvider::uint256()}, {"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)}, {"difficulty", TypeProvider::uint256()}, + {"prevrandao", TypeProvider::uint256()}, {"number", TypeProvider::uint256()}, {"gaslimit", TypeProvider::uint256()}, {"chainid", TypeProvider::uint256()}, diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 4f7fd3abd1..8eba084eba 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -65,7 +65,7 @@ class CompilerContext RevertStrings _revertStrings, CompilerContext* _runtimeContext = nullptr ): - m_asm(std::make_shared(_runtimeContext != nullptr, std::string{})), + m_asm(std::make_shared(_evmVersion, _runtimeContext != nullptr, std::string{})), m_evmVersion(_evmVersion), m_revertStrings(_revertStrings), m_reservedMemory{0}, diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index b26825c778..2aa2315f91 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1808,8 +1808,8 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) m_context << Instruction::COINBASE; else if (member == "timestamp") m_context << Instruction::TIMESTAMP; - else if (member == "difficulty") - m_context << Instruction::DIFFICULTY; + else if (member == "difficulty" || member == "prevrandao") + m_context << Instruction::PREVRANDAO; else if (member == "number") m_context << Instruction::NUMBER; else if (member == "gaslimit") diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 1ec64b548d..3e3041bc10 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1822,8 +1822,13 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) define(_memberAccess) << "coinbase()\n"; else if (member == "timestamp") define(_memberAccess) << "timestamp()\n"; - else if (member == "difficulty") - define(_memberAccess) << "difficulty()\n"; + else if (member == "difficulty" || member == "prevrandao") + { + if (m_context.evmVersion().hasPrevRandao()) + define(_memberAccess) << "prevrandao()\n"; + else + define(_memberAccess) << "difficulty()\n"; + } else if (member == "number") define(_memberAccess) << "number()\n"; else if (member == "gaslimit") diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 823c7c2f21..27fa1c9896 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -381,6 +381,7 @@ Json::Value formatImmutableReferences(map>> co } Json::Value collectEVMObject( + langutil::EVMVersion _evmVersion, evmasm::LinkerObject const& _object, string const* _sourceMap, Json::Value _generatedSources, @@ -392,7 +393,7 @@ Json::Value collectEVMObject( if (_artifactRequested("object")) output["object"] = _object.toHex(); if (_artifactRequested("opcodes")) - output["opcodes"] = evmasm::disassemble(_object.bytecode); + output["opcodes"] = evmasm::disassemble(_object.bytecode, _evmVersion); if (_artifactRequested("sourceMap")) output["sourceMap"] = _sourceMap ? *_sourceMap : ""; if (_artifactRequested("functionDebugData")) @@ -1328,6 +1329,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting wildcardMatchesExperimental )) evmData["bytecode"] = collectEVMObject( + _inputsAndSettings.evmVersion, compilerStack.object(contractName), compilerStack.sourceMapping(contractName), compilerStack.generatedSources(contractName), @@ -1349,6 +1351,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting wildcardMatchesExperimental )) evmData["deployedBytecode"] = collectEVMObject( + _inputsAndSettings.evmVersion, compilerStack.runtimeObject(contractName), compilerStack.runtimeSourceMapping(contractName), compilerStack.generatedSources(contractName, true), @@ -1491,6 +1494,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (o.bytecode) output["contracts"][sourceName][contractName]["evm"][kind] = collectEVMObject( + _inputsAndSettings.evmVersion, *o.bytecode, o.sourceMappings.get(), Json::arrayValue, diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 2e9f8f1d3e..4c9abdaddf 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -119,7 +119,6 @@ vector AsmAnalyzer::operator()(Literal const& _literal) "Invalid type \"" + _literal.type.str() + "\" for literal \"" + _literal.value.str() + "\"." ); - return {_literal.type}; } @@ -619,7 +618,6 @@ Scope& AsmAnalyzer::scope(Block const* _block) void AsmAnalyzer::expectValidIdentifier(YulString _identifier, SourceLocation const& _location) { // NOTE: the leading dot case is handled by the parser not allowing it. - if (boost::ends_with(_identifier.str(), ".")) m_errorReporter.syntaxError( 3384_error, @@ -692,7 +690,7 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio _location, fmt::format( "The \"{instruction}\" instruction is {kind} VMs (you are currently compiling for \"{version}\").", - fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr).name)), + fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)), fmt::arg("kind", vmKindMessage), fmt::arg("version", m_evmVersion.name()) ) diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 270773cbcc..acb48cfa54 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -50,7 +50,7 @@ CompilabilityChecker::CompilabilityChecker( builtinContext.subIDs[_object.name] = 1; for (auto const& subNode: _object.subObjects) builtinContext.subIDs[subNode->name] = 1; - NoOutputAssembly assembly; + NoOutputAssembly assembly{evmDialect->evmVersion()}; CodeTransform transform( assembly, analysisInfo, diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index b330269499..f258de6a84 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -264,7 +264,7 @@ YulStack::assembleEVMWithDeployed(optional _deployName) const yulAssert(m_parserResult->code, ""); yulAssert(m_parserResult->analysisInfo, ""); - evmasm::Assembly assembly(true, {}); + evmasm::Assembly assembly(m_evmVersion, true, {}); EthAssemblyAdapter adapter(assembly); compileEVM(adapter, m_optimiserSettings.optimizeStackAllocation); diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 2d7be90019..c64669abea 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 71b9dba4ce..b66738b9db 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -47,11 +47,12 @@ namespace { pair createEVMFunction( + langutil::EVMVersion _evmVersion, string const& _name, evmasm::Instruction _instruction ) { - evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction); + evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); BuiltinFunctionForEVM f; f.name = YulString{_name}; f.parameters.resize(static_cast(info.args)); @@ -119,11 +120,19 @@ set createReservedIdentifiers(langutil::EVMVersion _evmVersion) return _instr == evmasm::Instruction::BASEFEE && _evmVersion < langutil::EVMVersion::london(); }; + // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name + // prevrandao for VMs before paris. + auto prevRandaoException = [&](string const& _instrName) -> bool + { + // Using string comparison as the opcode is the same as for "difficulty" + return _instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris(); + }; + set reserved; for (auto const& instr: evmasm::c_instructions) { string name = toLower(instr.first); - if (!baseFeeException(instr.second)) + if (!baseFeeException(instr.second) && !prevRandaoException(name)) reserved.emplace(name); } reserved += vector{ @@ -139,6 +148,13 @@ set createReservedIdentifiers(langutil::EVMVersion _evmVersion) map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) { + + // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. + auto prevRandaoException = [&](string const& _instrName) -> bool + { + return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); + }; + map builtins; for (auto const& instr: evmasm::c_instructions) { @@ -152,9 +168,10 @@ map createBuiltins(langutil::EVMVersion _evmVe opcode != evmasm::Instruction::JUMP && opcode != evmasm::Instruction::JUMPI && opcode != evmasm::Instruction::JUMPDEST && - _evmVersion.hasOpcode(opcode) + _evmVersion.hasOpcode(opcode) && + !prevRandaoException(name) ) - builtins.emplace(createEVMFunction(name, opcode)); + builtins.emplace(createEVMFunction(_evmVersion, name, opcode)); } if (_objectAccess) diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index bd39f966f5..0959698389 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -88,7 +88,7 @@ void GasMeterVisitor::operator()(FunctionCall const& _funCall) void GasMeterVisitor::operator()(Literal const& _lit) { - m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1); + m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1, m_dialect.evmVersion()); m_dataGas += singleByteDataGas() + evmasm::GasMeter::dataGas( @@ -100,7 +100,7 @@ void GasMeterVisitor::operator()(Literal const& _lit) void GasMeterVisitor::operator()(Identifier const&) { - m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::DUP1); + m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::DUP1, m_dialect.evmVersion()); m_dataGas += singleByteDataGas(); } @@ -120,6 +120,6 @@ void GasMeterVisitor::instructionCostsInternal(evmasm::Instruction _instruction) // Assumes that Keccak-256 is computed on a single word (rounded up). m_runGas += evmasm::GasCosts::keccak256Gas + evmasm::GasCosts::keccak256WordGas; else - m_runGas += evmasm::GasMeter::runGas(_instruction); + m_runGas += evmasm::GasMeter::runGas(_instruction, m_dialect.evmVersion()); m_dataGas += singleByteDataGas(); } diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index 685f56cbc0..28a4e4ae29 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -124,7 +124,7 @@ void EthAssemblyAdapter::appendAssemblySize() pair, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name) { - shared_ptr assembly{make_shared(_creation, std::move(_name))}; + shared_ptr assembly{make_shared(m_assembly.evmVersion(), _creation, std::move(_name))}; auto sub = m_assembly.newSub(assembly); return {make_shared(*assembly), static_cast(sub.data())}; } diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index e262042014..ac64418ad8 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -37,7 +37,7 @@ using namespace solidity::langutil; void NoOutputAssembly::appendInstruction(evmasm::Instruction _instr) { - m_stackHeight += instructionInfo(_instr).ret - instructionInfo(_instr).args; + m_stackHeight += instructionInfo(_instr, m_evmVersion).ret - instructionInfo(_instr, m_evmVersion).args; } void NoOutputAssembly::appendConstant(u256 const&) diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 1103392ef9..eeb00039c5 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -45,7 +45,7 @@ namespace solidity::yul class NoOutputAssembly: public AbstractAssembly { public: - explicit NoOutputAssembly() { } + explicit NoOutputAssembly(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) { } ~NoOutputAssembly() override = default; void setSourceLocation(langutil::SourceLocation const&) override {} @@ -79,6 +79,7 @@ class NoOutputAssembly: public AbstractAssembly private: int m_stackHeight = 0; + langutil::EVMVersion m_evmVersion; }; diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 95c840733d..ddb1b63793 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -747,23 +747,23 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi if (_swapDepth > 16) opGas += 1000; else - opGas += evmasm::GasMeter::runGas(evmasm::swapInstruction(_swapDepth)); + opGas += evmasm::GasMeter::runGas(evmasm::swapInstruction(_swapDepth), langutil::EVMVersion()); }; auto dupOrPush = [&](StackSlot const& _slot) { if (canBeFreelyGenerated(_slot)) - opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32)); + opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32), langutil::EVMVersion()); else { auto depth = util::findOffset(_source | ranges::views::reverse, _slot); yulAssert(depth); if (*depth < 16) - opGas += evmasm::GasMeter::runGas(evmasm::dupInstruction(static_cast(*depth + 1))); + opGas += evmasm::GasMeter::runGas(evmasm::dupInstruction(static_cast(*depth + 1)), langutil::EVMVersion()); else opGas += 1000; } }; - auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP); }; + auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP,langutil::EVMVersion()); }; createStackLayout(_source, _target, swap, dupOrPush, pop); return opGas; }; diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index caf74cfb7a..4a423fe465 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -47,7 +47,7 @@ void ExpressionSimplifier::visit(Expression& _expression) m_dialect, [this](YulString _var) { return variableValue(_var); } )) - _expression = match->action().toExpression(debugDataOf(_expression)); + _expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_dialect)); if (auto* functionCall = get_if(&_expression)) if (optional instruction = toEVMInstruction(m_dialect, functionCall->functionName.name)) diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 77848cce04..c706d529b6 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -102,7 +102,7 @@ Expression KnowledgeBase::simplifyRecursively(Expression _expression) arg = simplifyRecursively(arg); if (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_variableValues)) - return simplifyRecursively(match->action().toExpression(debugDataOf(_expression))); + return simplifyRecursively(match->action().toExpression(debugDataOf(_expression), langutil::EVMVersion())); return _expression; } diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 298dfe9c15..2eac515956 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -180,7 +181,7 @@ void CodeCost::visit(Expression const& _expression) void CodeCost::addInstructionCost(evmasm::Instruction _instruction) { - evmasm::Tier gasPriceTier = evmasm::instructionInfo(_instruction).gasPriceTier; + evmasm::Tier gasPriceTier = evmasm::instructionInfo(_instruction, evmVersionFromDialect(m_dialect)).gasPriceTier; if (gasPriceTier < evmasm::Tier::VeryLow) m_cost -= 1; else if (gasPriceTier < evmasm::Tier::High) diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index ba06b2180b..bd474f7482 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -58,6 +58,13 @@ optional yul::toEVMInstruction(Dialect const& _dialect, Yul return nullopt; } +langutil::EVMVersion const yul::evmVersionFromDialect(Dialect const& _dialect) +{ + if (auto const* dialect = dynamic_cast(&_dialect)) + return dialect->evmVersion(); + return langutil::EVMVersion(); +} + void StatementRemover::operator()(Block& _block) { util::iterateReplacing( diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index b491e57e1f..cb07f7a530 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -49,6 +50,10 @@ bool isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifie /// Helper function that returns the instruction, if the `_name` is a BuiltinFunction std::optional toEVMInstruction(Dialect const& _dialect, YulString const& _name); +/// Helper function that returns the EVM version from a dialect. +/// It returns the default EVM version if dialect is not an EVMDialect. +langutil::EVMVersion const evmVersionFromDialect(Dialect const& _dialect); + class StatementRemover: public ASTModifier { public: diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 9d0144750d..c3c4d5a533 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -235,7 +235,7 @@ evmasm::Instruction Pattern::instruction() const return m_instruction; } -Expression Pattern::toExpression(shared_ptr const& _debugData) const +Expression Pattern::toExpression(shared_ptr const& _debugData, langutil::EVMVersion _evmVersion) const { if (matchGroup()) return ASTCopier().translate(matchGroupValue()); @@ -248,9 +248,9 @@ Expression Pattern::toExpression(shared_ptr const& _debugData) { vector arguments; for (auto const& arg: m_arguments) - arguments.emplace_back(arg.toExpression(_debugData)); + arguments.emplace_back(arg.toExpression(_debugData, _evmVersion)); - string name = util::toLower(instructionInfo(m_instruction).name); + string name = util::toLower(instructionInfo(m_instruction, _evmVersion).name); return FunctionCall{_debugData, Identifier{_debugData, YulString{name}}, diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 7444c47fb8..e36730f054 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -131,7 +131,7 @@ class Pattern /// Turns this pattern into an actual expression. Should only be called /// for patterns resulting from an action, i.e. with match groups assigned. - Expression toExpression(std::shared_ptr const& _debugData) const; + Expression toExpression(std::shared_ptr const& _debugData, langutil::EVMVersion _evmVersion) const; private: Expression const& matchGroupValue() const; diff --git a/scripts/check_style.sh b/scripts/check_style.sh index d1ad6bb9e9..e3dbe6cb6a 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -5,9 +5,10 @@ set -eu ERROR_LOG="$(mktemp -t check_style_XXXXXX.log)" EXCLUDE_FILES=( + # The line below is left unquoted to allow the shell globbing path expansion + test/cmdlineTests/*/{err,output} "libsolutil/picosha2.h" "test/cmdlineTests/strict_asm_only_cr/input.yul" - "test/cmdlineTests/strict_asm_only_cr/err" "test/libsolutil/UTF8.cpp" "test/libsolidity/syntaxTests/license/license_cr_endings.sol" "test/libsolidity/syntaxTests/license/license_crlf_endings.sol" diff --git a/scripts/test_antlr_grammar.sh b/scripts/test_antlr_grammar.sh index 5745f01be3..3394534f8d 100755 --- a/scripts/test_antlr_grammar.sh +++ b/scripts/test_antlr_grammar.sh @@ -121,6 +121,9 @@ done < <( grep -v -E 'revertStatement/non_called.sol' | # Skipping a test with "let basefee := ..." grep -v -E 'inlineAssembly/basefee_berlin_function.sol' | + # Skipping tests with "let prevrandao := ..." + grep -v -E 'inlineAssembly/prevrandao_allowed_function_pre_paris.sol' | + grep -v -E 'inlineAssembly/prevrandao_disallowed_function_post_paris.sol' | # Skipping license error, unrelated to the grammar grep -v -E 'license/license_double5.sol' | grep -v -E 'license/license_hidden_unicode.sol' | diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 1d64fa4946..e9688cda3f 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -198,11 +198,11 @@ void CommandLineInterface::handleOpcode(string const& _contract) solAssert(CompilerInputModes.count(m_options.input.mode) == 1); if (!m_options.output.dir.empty()) - createFile(m_compiler->filesystemFriendlyName(_contract) + ".opcode", evmasm::disassemble(m_compiler->object(_contract).bytecode)); + createFile(m_compiler->filesystemFriendlyName(_contract) + ".opcode", evmasm::disassemble(m_compiler->object(_contract).bytecode, m_options.output.evmVersion)); else { sout() << "Opcodes:" << endl; - sout() << std::uppercase << evmasm::disassemble(m_compiler->object(_contract).bytecode); + sout() << std::uppercase << evmasm::disassemble(m_compiler->object(_contract).bytecode, m_options.output.evmVersion); sout() << endl; } } @@ -825,7 +825,7 @@ void CommandLineInterface::handleCombinedJSON() if (m_options.compiler.combinedJsonRequests->binaryRuntime && m_compiler->compilationSuccessful()) contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex(); if (m_options.compiler.combinedJsonRequests->opcodes && m_compiler->compilationSuccessful()) - contractData[g_strOpcodes] = evmasm::disassemble(m_compiler->object(contractName).bytecode); + contractData[g_strOpcodes] = evmasm::disassemble(m_compiler->object(contractName).bytecode, m_options.output.evmVersion); if (m_options.compiler.combinedJsonRequests->asm_ && m_compiler->compilationSuccessful()) contractData[g_strAsm] = m_compiler->assemblyJSON(contractName); if (m_options.compiler.combinedJsonRequests->storageLayout && m_compiler->compilationSuccessful()) diff --git a/test/cmdlineTests/evmasm_difficulty_post_paris/args b/test/cmdlineTests/evmasm_difficulty_post_paris/args new file mode 100644 index 0000000000..a0588fcfc2 --- /dev/null +++ b/test/cmdlineTests/evmasm_difficulty_post_paris/args @@ -0,0 +1 @@ +--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version paris diff --git a/test/cmdlineTests/evmasm_difficulty_post_paris/err b/test/cmdlineTests/evmasm_difficulty_post_paris/err new file mode 100644 index 0000000000..d8210184e1 --- /dev/null +++ b/test/cmdlineTests/evmasm_difficulty_post_paris/err @@ -0,0 +1,5 @@ +Warning: Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. + --> evmasm_difficulty_post_paris/input.sol:6:21: + | +6 | uint256 x = block.difficulty; + | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/evmasm_difficulty_post_paris/input.sol b/test/cmdlineTests/evmasm_difficulty_post_paris/input.sol new file mode 100644 index 0000000000..e81c034e78 --- /dev/null +++ b/test/cmdlineTests/evmasm_difficulty_post_paris/input.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + constructor() payable { + uint256 x = block.difficulty; + assembly { + sstore(0, x) + stop() + } + } + + fallback() external payable { + assembly { + stop() + } + } +} diff --git a/test/cmdlineTests/evmasm_difficulty_post_paris/output b/test/cmdlineTests/evmasm_difficulty_post_paris/output new file mode 100644 index 0000000000..f8c1611e02 --- /dev/null +++ b/test/cmdlineTests/evmasm_difficulty_post_paris/output @@ -0,0 +1,13 @@ + +======= evmasm_difficulty_post_paris/input.sol:C ======= +EVM assembly: + sstore(0x00, prevrandao) + stop +stop + +sub_0: assembly { + stop +} + +Opcodes: +PREVRANDAO PUSH1 0x0 SSTORE STOP INVALID diff --git a/test/cmdlineTests/evmasm_difficulty_pre_paris/args b/test/cmdlineTests/evmasm_difficulty_pre_paris/args new file mode 100644 index 0000000000..67d6f9a650 --- /dev/null +++ b/test/cmdlineTests/evmasm_difficulty_pre_paris/args @@ -0,0 +1 @@ +--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version london diff --git a/test/cmdlineTests/evmasm_difficulty_pre_paris/input.sol b/test/cmdlineTests/evmasm_difficulty_pre_paris/input.sol new file mode 100644 index 0000000000..e81c034e78 --- /dev/null +++ b/test/cmdlineTests/evmasm_difficulty_pre_paris/input.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + constructor() payable { + uint256 x = block.difficulty; + assembly { + sstore(0, x) + stop() + } + } + + fallback() external payable { + assembly { + stop() + } + } +} diff --git a/test/cmdlineTests/evmasm_difficulty_pre_paris/output b/test/cmdlineTests/evmasm_difficulty_pre_paris/output new file mode 100644 index 0000000000..ad75355f5b --- /dev/null +++ b/test/cmdlineTests/evmasm_difficulty_pre_paris/output @@ -0,0 +1,13 @@ + +======= evmasm_difficulty_pre_paris/input.sol:C ======= +EVM assembly: + sstore(0x00, difficulty) + stop +stop + +sub_0: assembly { + stop +} + +Opcodes: +DIFFICULTY PUSH1 0x0 SSTORE STOP INVALID diff --git a/test/cmdlineTests/evmasm_prevrandao_post_paris/args b/test/cmdlineTests/evmasm_prevrandao_post_paris/args new file mode 100644 index 0000000000..a0588fcfc2 --- /dev/null +++ b/test/cmdlineTests/evmasm_prevrandao_post_paris/args @@ -0,0 +1 @@ +--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version paris diff --git a/test/cmdlineTests/evmasm_prevrandao_post_paris/input.sol b/test/cmdlineTests/evmasm_prevrandao_post_paris/input.sol new file mode 100644 index 0000000000..707d12d745 --- /dev/null +++ b/test/cmdlineTests/evmasm_prevrandao_post_paris/input.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + constructor() payable { + uint256 x = block.prevrandao; + assembly { + sstore(0, x) + stop() + } + } + + fallback() external payable { + assembly { + stop() + } + } +} diff --git a/test/cmdlineTests/evmasm_prevrandao_post_paris/output b/test/cmdlineTests/evmasm_prevrandao_post_paris/output new file mode 100644 index 0000000000..47c85bb50f --- /dev/null +++ b/test/cmdlineTests/evmasm_prevrandao_post_paris/output @@ -0,0 +1,13 @@ + +======= evmasm_prevrandao_post_paris/input.sol:C ======= +EVM assembly: + sstore(0x00, prevrandao) + stop +stop + +sub_0: assembly { + stop +} + +Opcodes: +PREVRANDAO PUSH1 0x0 SSTORE STOP INVALID diff --git a/test/cmdlineTests/evmasm_prevrandao_pre_paris/args b/test/cmdlineTests/evmasm_prevrandao_pre_paris/args new file mode 100644 index 0000000000..67d6f9a650 --- /dev/null +++ b/test/cmdlineTests/evmasm_prevrandao_pre_paris/args @@ -0,0 +1 @@ +--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version london diff --git a/test/cmdlineTests/evmasm_prevrandao_pre_paris/err b/test/cmdlineTests/evmasm_prevrandao_pre_paris/err new file mode 100644 index 0000000000..5970ec2020 --- /dev/null +++ b/test/cmdlineTests/evmasm_prevrandao_pre_paris/err @@ -0,0 +1,5 @@ +Warning: "prevrandao" is not supported by the VM version and will be treated as "difficulty". + --> evmasm_prevrandao_pre_paris/input.sol:6:21: + | +6 | uint256 x = block.prevrandao; + | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/evmasm_prevrandao_pre_paris/input.sol b/test/cmdlineTests/evmasm_prevrandao_pre_paris/input.sol new file mode 100644 index 0000000000..707d12d745 --- /dev/null +++ b/test/cmdlineTests/evmasm_prevrandao_pre_paris/input.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + constructor() payable { + uint256 x = block.prevrandao; + assembly { + sstore(0, x) + stop() + } + } + + fallback() external payable { + assembly { + stop() + } + } +} diff --git a/test/cmdlineTests/evmasm_prevrandao_pre_paris/output b/test/cmdlineTests/evmasm_prevrandao_pre_paris/output new file mode 100644 index 0000000000..e41148a833 --- /dev/null +++ b/test/cmdlineTests/evmasm_prevrandao_pre_paris/output @@ -0,0 +1,13 @@ + +======= evmasm_prevrandao_pre_paris/input.sol:C ======= +EVM assembly: + sstore(0x00, difficulty) + stop +stop + +sub_0: assembly { + stop +} + +Opcodes: +DIFFICULTY PUSH1 0x0 SSTORE STOP INVALID diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 680531799d..12c3be67d6 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -20,6 +20,7 @@ * @date 2018 * Tests for the assembler. */ +#include #include #include @@ -59,15 +60,16 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) { "sub.asm", 1 }, { "verbatim.asm", 2 } }; - Assembly _assembly{false, {}}; + EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); + Assembly _assembly{evmVersion, false, {}}; auto root_asm = make_shared("root.asm"); _assembly.setSourceLocation({1, 3, root_asm}); - Assembly _subAsm{false, {}}; + Assembly _subAsm{evmVersion, false, {}}; auto sub_asm = make_shared("sub.asm"); _subAsm.setSourceLocation({6, 8, sub_asm}); - Assembly _verbatimAsm(true, ""); + Assembly _verbatimAsm(evmVersion, true, ""); auto verbatim_asm = make_shared("verbatim.asm"); _verbatimAsm.setSourceLocation({8, 18, verbatim_asm}); @@ -215,6 +217,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) { + EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); // Tests for 1, 2, 3 number of immutables. for (int numImmutables = 1; numImmutables <= 3; ++numImmutables) { @@ -243,7 +246,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) { *subName, 1 } }; - auto subAsm = make_shared(false, string{}); + auto subAsm = make_shared(evmVersion, false, string{}); for (char i = 0; i < numImmutables; ++i) { for (int r = 0; r < numActualRefs; ++r) @@ -253,7 +256,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) } } - Assembly assembly{true, {}}; + Assembly assembly{evmVersion, true, {}}; for (char i = 1; i <= numImmutables; ++i) { assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName}); @@ -270,7 +273,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) auto const numberOfMappings = std::count(sourceMappings.begin(), sourceMappings.end(), ';'); LinkerObject const& obj = assembly.assemble(); - string const disassembly = disassemble(obj.bytecode, "\n"); + string const disassembly = disassemble(obj.bytecode, evmVersion, "\n"); auto const numberOfOpcodes = std::count(disassembly.begin(), disassembly.end(), '\n'); #if 0 // {{{ debug prints @@ -302,11 +305,12 @@ BOOST_AUTO_TEST_CASE(immutable) { "root.asm", 0 }, { "sub.asm", 1 } }; - Assembly _assembly{true, {}}; + EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); + Assembly _assembly{evmVersion, true, {}}; auto root_asm = make_shared("root.asm"); _assembly.setSourceLocation({1, 3, root_asm}); - Assembly _subAsm{false, {}}; + Assembly _subAsm{evmVersion, false, {}}; auto sub_asm = make_shared("sub.asm"); _subAsm.setSourceLocation({6, 8, sub_asm}); _subAsm.appendImmutable("someImmutable"); @@ -395,10 +399,11 @@ BOOST_AUTO_TEST_CASE(immutable) BOOST_AUTO_TEST_CASE(subobject_encode_decode) { - Assembly assembly{true, {}}; + EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); + Assembly assembly{evmVersion, true, {}}; - shared_ptr subAsmPtr = make_shared(false, string{}); - shared_ptr subSubAsmPtr = make_shared(false, string{}); + shared_ptr subAsmPtr = make_shared(evmVersion, false, string{}); + shared_ptr subSubAsmPtr = make_shared(evmVersion, false, string{}); assembly.appendSubroutine(subAsmPtr); subAsmPtr->appendSubroutine(subSubAsmPtr); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 6fc3c5a743..6f1a137599 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1250,8 +1250,18 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) // tag unifications (due to block deduplication) is also // visible at the super-assembly. - Assembly main{false, {}}; - AssemblyPointer sub = make_shared(true, string{}); + Assembly::OptimiserSettings settings; + settings.runInliner = false; + settings.runJumpdestRemover = true; + settings.runPeephole = true; + settings.runDeduplicate = true; + settings.runCSE = true; + settings.runConstantOptimiser = true; + settings.evmVersion = solidity::test::CommonOptions::get().evmVersion(); + settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; + + Assembly main{settings.evmVersion, false, {}}; + AssemblyPointer sub = make_shared(settings.evmVersion, true, string{}); sub->append(u256(1)); auto t1 = sub->newTag(); @@ -1277,16 +1287,6 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) main.append(t1.toSubAssemblyTag(subId)); main.append(u256(8)); - Assembly::OptimiserSettings settings; - settings.runInliner = false; - settings.runJumpdestRemover = true; - settings.runPeephole = true; - settings.runDeduplicate = true; - settings.runCSE = true; - settings.runConstantOptimiser = true; - settings.evmVersion = solidity::test::CommonOptions::get().evmVersion(); - settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; - main.optimise(settings); AssemblyItems expectationMain{ diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index a1580fb539..e775bb6d0e 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -109,7 +109,7 @@ class OptimizerTestFramework: public SolidityExecutionFramework bytes realCode = bytecodeSansMetadata(_bytecode); BOOST_REQUIRE_MESSAGE(!realCode.empty(), "Invalid or missing metadata in bytecode."); size_t instructions = 0; - evmasm::eachInstruction(realCode, [&](Instruction _instr, u256 const&) { + evmasm::eachInstruction(realCode, m_evmVersion, [&](Instruction _instr, u256 const&) { if (!_which || *_which == _instr) instructions++; }); @@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches) bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true); size_t numSHA3s = 0; - eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { + eachInstruction(optimizedBytecode, m_evmVersion, [&](Instruction _instr, u256 const&) { if (_instr == Instruction::KECCAK256) numSHA3s++; }); @@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions) bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "test", true); size_t numSHA3s = 0; - eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { + eachInstruction(optimizedBytecode, m_evmVersion, [&](Instruction _instr, u256 const&) { if (_instr == Instruction::KECCAK256) numSHA3s++; }); diff --git a/test/libsolidity/analysis/FunctionCallGraph.cpp b/test/libsolidity/analysis/FunctionCallGraph.cpp index 8c10ca72a2..fcc8d14239 100644 --- a/test/libsolidity/analysis/FunctionCallGraph.cpp +++ b/test/libsolidity/analysis/FunctionCallGraph.cpp @@ -1860,6 +1860,7 @@ BOOST_AUTO_TEST_CASE(builtins) block.chainid; block.coinbase; block.difficulty; + block.prevrandao; block.gaslimit; block.number; block.timestamp; diff --git a/test/libsolidity/semanticTests/inlineAssembly/difficulty.sol b/test/libsolidity/semanticTests/inlineAssembly/difficulty.sol new file mode 100644 index 0000000000..7ae286110c --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/difficulty.sol @@ -0,0 +1,12 @@ +contract C { + function f() public view returns (uint ret) { + assembly { + ret := difficulty() + } + } +} +// ==== +// compileToEwasm: also +// EVMVersion: 200000000 diff --git a/test/libsolidity/semanticTests/inlineAssembly/prevrandao.sol b/test/libsolidity/semanticTests/inlineAssembly/prevrandao.sol new file mode 100644 index 0000000000..5a3b791feb --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/prevrandao.sol @@ -0,0 +1,12 @@ +contract C { + function f() public view returns (uint ret) { + assembly { + ret := prevrandao() + } + } +} +// ==== +// compileToEwasm: also +// EVMVersion: >=paris +// ---- +// f() -> 0xa86c2e601b6c44eb4848f7d23d9df3113fbcac42041c49cbed5000cb4f118777 diff --git a/test/libsolidity/semanticTests/state/block_prevrandao.sol b/test/libsolidity/semanticTests/state/block_prevrandao.sol new file mode 100644 index 0000000000..24d5f2af63 --- /dev/null +++ b/test/libsolidity/semanticTests/state/block_prevrandao.sol @@ -0,0 +1,10 @@ +contract C { + function f() public view returns (uint) { + return block.prevrandao; + } +} +// ==== +// compileToEwasm: also +// EVMVersion: >=paris +// ---- +// f() -> 0xa86c2e601b6c44eb4848f7d23d9df3113fbcac42041c49cbed5000cb4f118777 diff --git a/test/libsolidity/semanticTests/state/block_prevrandao_pre_paris.sol b/test/libsolidity/semanticTests/state/block_prevrandao_pre_paris.sol new file mode 100644 index 0000000000..efc4d226f5 --- /dev/null +++ b/test/libsolidity/semanticTests/state/block_prevrandao_pre_paris.sol @@ -0,0 +1,10 @@ +contract C { + function f() public view returns (uint) { + return block.prevrandao; + } +} +// ==== +// compileToEwasm: also +// EVMVersion: 200000000 diff --git a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_builtin_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_builtin_pre_paris.sol new file mode 100644 index 0000000000..13ea92c526 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_builtin_pre_paris.sol @@ -0,0 +1,14 @@ +contract C { + function f() public view returns (uint256) { + return block.difficulty; + } + + function g() public view returns (uint256 ret) { + assembly { + ret := difficulty() + } + } +} +// ==== +// EVMVersion: r { + r := 1000 + } + ret := difficulty() + } + } +} +// ==== +// EVMVersion: =paris +// ---- +// Warning 8417: (77-93): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_nobuiltin_post_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_nobuiltin_post_paris.sol new file mode 100644 index 0000000000..65fe4c15c1 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_nobuiltin_post_paris.sol @@ -0,0 +1,12 @@ +contract C { + function f() public { + assembly { + pop(difficulty()) + } + } +} +// ==== +// EVMVersion: >=paris +// ---- +// DeclarationError 4619: (74-84): Function "difficulty" not found. +// TypeError 3950: (74-86): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_reserved_post_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_reserved_post_paris.sol new file mode 100644 index 0000000000..5121a110ba --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_reserved_post_paris.sol @@ -0,0 +1,22 @@ +contract C { + function f() public view returns (uint256 ret) { + assembly { + let difficulty := sload(0) + ret := difficulty + } + } + + function g() public pure returns (uint256 ret) { + assembly { + function difficulty() -> r { + r := 1000 + } + ret := difficulty() + } + } +} +// ==== +// EVMVersion: >=paris +// ---- +// DeclarationError 5017: (101-111): The identifier "difficulty" is reserved and can not be used. +// DeclarationError 5017: (255-323): The identifier "difficulty" is reserved and can not be used. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol new file mode 100644 index 0000000000..d85e77a45e --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol @@ -0,0 +1,20 @@ +contract C { + function f() public view returns (uint256 ret) { + assembly { + let prevrandao := sload(0) + ret := prevrandao + } + } + + function g() public pure returns (uint256 ret) { + assembly { + function prevrandao() -> r { + r := 1000 + } + ret := prevrandao() + } + } +} +// ==== +// EVMVersion: =paris +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol new file mode 100644 index 0000000000..6c284a0059 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol @@ -0,0 +1,21 @@ +contract C { + function f() public view returns (uint256 ret) { + assembly { + let prevrandao := sload(0) + ret := prevrandao + } + } + + function g() public pure returns (uint256 ret) { + assembly { + function prevrandao() -> r { + r := 1000 + } + ret := prevrandao() + } + } +} +// ==== +// EVMVersion: >=paris +// ---- +// ParserError 5568: (101-111): Cannot use builtin function name "prevrandao" as identifier name. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_magic_block_warn_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_magic_block_warn_pre_paris.sol new file mode 100644 index 0000000000..2086892b1c --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_magic_block_warn_pre_paris.sol @@ -0,0 +1,9 @@ +contract C { + function f() public view returns (uint256) { + return block.prevrandao; + } +} +// ==== +// EVMVersion: =paris +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol index 8b634c2195..2b9e5ae5fb 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol @@ -73,7 +73,7 @@ contract C { pop(coinbase()) pop(timestamp()) pop(number()) - pop(difficulty()) + pop(prevrandao()) pop(gaslimit()) // NOTE: msize() is allowed only with optimizer disabled @@ -83,7 +83,7 @@ contract C { } } // ==== -// EVMVersion: >=london +// EVMVersion: >=paris // ---- // Warning 5740: (89-1716): Unreachable code. // Warning 5740: (1729-1741): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_london.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_london.sol new file mode 100644 index 0000000000..be9f7281f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_london.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + assembly { + pop(difficulty()) + } + } +} +// ==== +// EVMVersion: <=london +// ---- +// Warning 2018: (17-103): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol index 85d7b63008..16c75d6f72 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol @@ -73,7 +73,6 @@ contract C { //pop(coinbase()) //pop(timestamp()) //pop(number()) - //pop(difficulty()) //pop(gaslimit()) // NOTE: msize() is allowed only with optimizer disabled diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol index af30bc21ae..0bb92c1fd2 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol @@ -73,7 +73,7 @@ contract C { pop(coinbase()) pop(timestamp()) pop(number()) - pop(difficulty()) + pop(prevrandao()) pop(gaslimit()) // NOTE: msize() is allowed only with optimizer disabled @@ -83,7 +83,7 @@ contract C { } } // ==== -// EVMVersion: >=london +// EVMVersion: >=paris // ---- // Warning 5740: (94-1733): Unreachable code. // Warning 5740: (1746-1758): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol new file mode 100644 index 0000000000..ffc757a19f --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol @@ -0,0 +1,10 @@ +contract C { + function f() public view { + assembly { + pop(difficulty()) + } + } +} +// ==== +// EVMVersion: <=london +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol index f9a652fdbd..9b3806f4d6 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol @@ -6,33 +6,26 @@ contract C { pop(gas()) pop(address()) pop(balance(0)) - pop(selfbalance()) pop(caller()) pop(callvalue()) pop(extcodesize(0)) extcodecopy(0, 1, 2, 3) - pop(extcodehash(0)) pop(create(0, 1, 2)) - pop(create2(0, 1, 2, 3)) pop(call(0, 1, 2, 3, 4, 5, 6)) pop(callcode(0, 1, 2, 3, 4, 5, 6)) pop(delegatecall(0, 1, 2, 3, 4, 5)) - pop(staticcall(0, 1, 2, 3, 4, 5)) selfdestruct(0) log0(0, 1) log1(0, 1, 2) log2(0, 1, 2, 3) log3(0, 1, 2, 3, 4) log4(0, 1, 2, 3, 4, 5) - pop(chainid()) - pop(basefee()) pop(origin()) pop(gasprice()) pop(blockhash(0)) pop(coinbase()) pop(timestamp()) pop(number()) - pop(difficulty()) pop(gaslimit()) // These two are disallowed too but the error suppresses other errors. @@ -41,40 +34,31 @@ contract C { } } } -// ==== -// EVMVersion: >=london // ---- -// Warning 5740: (672-1083): Unreachable code. +// Warning 5740: (526-853): Unreachable code. // TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". // TypeError 8961: (101-113): Function cannot be declared as pure because this expression (potentially) modifies the state. // TypeError 2527: (130-135): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". // TypeError 2527: (153-162): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". // TypeError 2527: (180-190): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (208-221): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (239-247): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (265-276): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (294-308): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (322-345): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (362-376): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 8961: (394-409): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (427-446): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (464-489): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (507-536): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (554-584): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 2527: (602-630): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 8961: (644-659): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (672-682): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (695-708): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (721-737): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (750-769): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 8961: (782-804): Function cannot be declared as pure because this expression (potentially) modifies the state. -// TypeError 2527: (821-830): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (848-857): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (875-883): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (901-911): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (929-941): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (959-969): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (987-998): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (1016-1024): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (1042-1054): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". -// TypeError 2527: (1072-1082): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (208-216): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (234-245): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (263-277): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (291-314): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (331-346): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (364-389): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (407-436): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (454-484): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (498-513): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (526-536): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (549-562): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (575-591): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (604-623): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (636-658): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (675-683): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (701-711): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (729-741): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (759-769): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (787-798): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (816-824): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (842-852): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol new file mode 100644 index 0000000000..f0320d8b08 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + pop(staticcall(0, 1, 2, 3, 4, 5)) + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// TypeError 2527: (79-107): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol new file mode 100644 index 0000000000..30210efc32 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + assembly { + pop(extcodehash(0)) + pop(create2(0, 1, 2, 3)) + } + } +} +// ==== +// EVMVersion: >=constantinople +// ---- +// TypeError 2527: (79-93): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (111-130): Function cannot be declared as pure because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_istanbul.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_istanbul.sol new file mode 100644 index 0000000000..b4e0224834 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_istanbul.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + assembly { + pop(selfbalance()) + pop(chainid()) + } + } +} +// ==== +// EVMVersion: >=istanbul +// ---- +// TypeError 2527: (79-92): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (110-119): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol new file mode 100644 index 0000000000..ba47d44472 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + pop(basefee()) + } + } +} +// ==== +// EVMVersion: >=london +// ---- +// TypeError 2527: (79-88): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_paris.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_paris.sol new file mode 100644 index 0000000000..e374522a1f --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_paris.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + pop(prevrandao()) + } + } +} +// ==== +// EVMVersion: >=paris +// ---- +// TypeError 2527: (79-91): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_pre_paris.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_pre_paris.sol new file mode 100644 index 0000000000..e348fd98be --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_pre_paris.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + pop(difficulty()) + } + } +} +// ==== +// EVMVersion: <=london +// ---- +// TypeError 2527: (79-91): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 744fa8c033..73042b18b6 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include #include #include @@ -66,7 +68,7 @@ TestCase::TestResult EVMCodeTransformTest::run(ostream& _stream, string const& _ return TestResult::FatalError; } - evmasm::Assembly assembly{false, {}}; + evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( *stack.parserResult(), diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 190001a57a..3a8d966922 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -20,6 +20,8 @@ #include +#include + #include #include @@ -101,7 +103,7 @@ TestCase::TestResult ObjectCompilerTest::run(ostream& _stream, string const& _li "Bytecode: " + util::toHex(obj.bytecode->bytecode) + "\nOpcodes: " + - boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode)) + + boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode, solidity::test::CommonOptions::get().evmVersion())) + "\nSourceMappings:" + (obj.sourceMappings->empty() ? "" : " " + *obj.sourceMappings) + "\n"; diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 3d1974e968..a1ada928b8 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -98,7 +98,7 @@ string YulInterpreterTest::interpret() { Interpreter::run( state, - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}), + EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion()), *m_ast, /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false diff --git a/test/libyul/ewasmTranslationTests/difficulty.yul b/test/libyul/ewasmTranslationTests/difficulty.yul index c467d51a7b..52e4275b43 100644 --- a/test/libyul/ewasmTranslationTests/difficulty.yul +++ b/test/libyul/ewasmTranslationTests/difficulty.yul @@ -1,6 +1,8 @@ { sstore(0, difficulty()) } +// ==== +// EVMVersion: =paris +// ---- +// Trace: +// Memory dump: +// Storage dump: +// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000010000000000000001 diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 25ad6986cb..895957f4d2 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -189,7 +189,7 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet) for (bool isCreation: {false, true}) { - Assembly assembly{isCreation, {}}; + Assembly assembly{langutil::EVMVersion{}, isCreation, {}}; for (u256 const& n: numbers) { if (!_quiet) diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index f0691a8369..db0e648286 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -98,7 +98,7 @@ u256 EVMInstructionInterpreter::eval( using namespace solidity::evmasm; using evmasm::Instruction; - auto info = instructionInfo(_instruction); + auto info = instructionInfo(_instruction, m_evmVersion); yulAssert(static_cast(info.args) == _arguments.size(), ""); auto const& arg = _arguments; @@ -268,8 +268,8 @@ u256 EVMInstructionInterpreter::eval( return m_state.timestamp; case Instruction::NUMBER: return m_state.blockNumber; - case Instruction::DIFFICULTY: - return m_state.difficulty; + case Instruction::PREVRANDAO: + return (m_evmVersion < langutil::EVMVersion::paris()) ? m_state.difficulty : m_state.prevrandao; case Instruction::GASLIMIT: return m_state.gaslimit; // --------------- memory / storage / logs --------------- @@ -543,7 +543,7 @@ void EVMInstructionInterpreter::logTrace( ) { logTrace( - evmasm::instructionInfo(_instruction).name, + evmasm::instructionInfo(_instruction, m_evmVersion).name, SemanticInformation::memory(_instruction) == SemanticInformation::Effect::Write, _arguments, _data diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.h b/test/tools/yulInterpreter/EVMInstructionInterpreter.h index c60e4b4e7e..9f0f473f14 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.h +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.h @@ -26,6 +26,8 @@ #include #include +#include + #include namespace solidity::evmasm @@ -74,7 +76,8 @@ struct InterpreterState; class EVMInstructionInterpreter { public: - explicit EVMInstructionInterpreter(InterpreterState& _state, bool _disableMemWriteTrace): + explicit EVMInstructionInterpreter(langutil::EVMVersion _evmVersion, InterpreterState& _state, bool _disableMemWriteTrace): + m_evmVersion(_evmVersion), m_state(_state), m_disableMemoryWriteInstructions(_disableMemWriteTrace) {} @@ -128,6 +131,7 @@ class EVMInstructionInterpreter return m_disableMemoryWriteInstructions; } + langutil::EVMVersion m_evmVersion; InterpreterState& m_state; /// Flag to disable trace of instructions that write to memory. bool m_disableMemoryWriteInstructions; diff --git a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp index 36f51b11c8..fdba09aa46 100644 --- a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp +++ b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp @@ -597,7 +597,7 @@ u256 EwasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo) void EwasmBuiltinInterpreter::logTrace(evmasm::Instruction _instruction, std::vector const& _arguments, bytes const& _data) { - logTrace(evmasm::instructionInfo(_instruction).name, _arguments, _data); + logTrace(evmasm::instructionInfo(_instruction, langutil::EVMVersion()).name, _arguments, _data); } void EwasmBuiltinInterpreter::logTrace(std::string const& _pseudoInstruction, std::vector const& _arguments, bytes const& _data) diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index e10f6a9e57..b66967e26f 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -314,7 +314,7 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall) { if (BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) { - EVMInstructionInterpreter interpreter(m_state, m_disableMemoryTrace); + EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace); u256 const value = interpreter.evalBuiltin(*fun, _funCall.arguments, values()); diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index 949d0ce4ec..26a8b27012 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -94,6 +94,7 @@ struct InterpreterState u256 timestamp = 0x88888888; u256 blockNumber = 1024; u256 difficulty = 0x9999999; + u256 prevrandao = (u256(1) << 64) + 1; u256 gaslimit = 4000000; u256 chainid = 0x01; /// The minimum value of basefee: 7 wei. From e7543d487d8dd813ca37765d5d8b1c011641a6eb Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 19 Jan 2023 09:34:14 +0100 Subject: [PATCH 0041/1140] Issue warning when using deprecated SELFDESTRUCT --- Changelog.md | 1 + docs/contracts/function-modifiers.rst | 1 + docs/contracts/inheritance.rst | 4 +++- docs/examples/micropayment.rst | 2 ++ libsolidity/analysis/TypeChecker.cpp | 8 ++++++++ libyul/AsmAnalysis.cpp | 8 ++++++++ .../nameAndTypeResolution/430_bare_selfdestruct.sol | 1 + .../types/address/address_nonpayable_selfdestruct.sol | 1 + .../types/address/address_payable_selfdestruct.sol | 1 + .../syntaxTests/viewPureChecker/builtin_functions.sol | 1 + .../viewPureChecker/builtin_functions_view_fail.sol | 1 + .../inline_assembly_instructions_allowed.sol | 1 + .../inline_assembly_instructions_disallowed_pure.sol | 1 + .../inline_assembly_instructions_disallowed_view.sol | 1 + test/libyul/yulSyntaxTests/selfdestruct.yul | 1 + 15 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 251144b378..362be6d1fc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,6 +21,7 @@ Compiler Features: * SMTChecker: Make ``z3`` the default solver for the BMC and CHC engines instead of all solvers. * Parser: More detailed error messages about invalid version pragmas. * Removed support for the ``solidity-upgrade`` tool. + * TypeChecker: Warn when using deprecated builtin ``selfdestruct``. Bugfixes: diff --git a/docs/contracts/function-modifiers.rst b/docs/contracts/function-modifiers.rst index f231195448..bbdec1e488 100644 --- a/docs/contracts/function-modifiers.rst +++ b/docs/contracts/function-modifiers.rst @@ -19,6 +19,7 @@ if they are marked ``virtual``. For details, please see // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1 <0.9.0; + // This will report a warning due to deprecated selfdestruct contract owned { constructor() { owner = payable(msg.sender); } diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index a33a36d27b..4f310bd406 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -40,7 +40,7 @@ Details are given in the following example. // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - + // This will report a warning due to deprecated selfdestruct contract Owned { constructor() { owner = payable(msg.sender); } @@ -130,6 +130,7 @@ seen in the following example: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; + // This will report a warning due to deprecated selfdestruct contract owned { constructor() { owner = payable(msg.sender); } @@ -162,6 +163,7 @@ explicitly in the final override, but this function will bypass // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; + // This will report a warning due to deprecated selfdestruct contract owned { constructor() { owner = payable(msg.sender); } diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index 7ade926572..f5037e6f76 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -144,6 +144,7 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; + // This will report a warning due to deprecated selfdestruct contract ReceiverPays { address owner = msg.sender; @@ -341,6 +342,7 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; + // This will report a warning due to deprecated selfdestruct contract SimplePaymentChannel { address payable public sender; // The account sending payments. address payable public recipient; // The account receiving the payments. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index ac00ab7fe5..4e390931fc 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3657,6 +3657,14 @@ bool TypeChecker::visit(Identifier const& _identifier) _identifier.location(), "\"suicide\" has been deprecated in favour of \"selfdestruct\"." ); + else if (_identifier.name() == "selfdestruct" && fType->kind() == FunctionType::Kind::Selfdestruct) + m_errorReporter.warning( + 5159_error, + _identifier.location(), + "\"selfdestruct\" has been deprecated. " + "The underlying opcode will eventually undergo breaking changes, " + "and its use is not recommended." + ); } if ( diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 4c9abdaddf..3ca84da714 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -311,6 +311,14 @@ vector AsmAnalyzer::operator()(FunctionCall const& _funCall) if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name)) { + if (_funCall.functionName.name.str() == "selfdestruct") + m_errorReporter.warning( + 1699_error, + nativeLocationOf(_funCall.functionName), + "\"selfdestruct\" has been deprecated. " + "The underlying opcode will eventually undergo breaking changes, " + "and its use is not recommended." + ); parameterTypes = &f->parameters; returnTypes = &f->returns; if (!f->literalArguments.empty()) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/430_bare_selfdestruct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/430_bare_selfdestruct.sol index b770b60447..6662d7b299 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/430_bare_selfdestruct.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/430_bare_selfdestruct.sol @@ -2,4 +2,5 @@ contract C { function f() pure public { selfdestruct; } } // ---- +// Warning 5159: (44-56): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. // Warning 6133: (44-56): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/types/address/address_nonpayable_selfdestruct.sol b/test/libsolidity/syntaxTests/types/address/address_nonpayable_selfdestruct.sol index 8122587115..9122d2a894 100644 --- a/test/libsolidity/syntaxTests/types/address/address_nonpayable_selfdestruct.sol +++ b/test/libsolidity/syntaxTests/types/address/address_nonpayable_selfdestruct.sol @@ -4,4 +4,5 @@ contract C { } } // ---- +// Warning 5159: (56-68): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. // TypeError 9553: (69-70): Invalid type for argument in function call. Invalid implicit conversion from address to address payable requested. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol index 62eadeca58..bd1aff7952 100644 --- a/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol +++ b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol @@ -4,3 +4,4 @@ contract C { } } // ---- +// Warning 5159: (64-76): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol index b381b31300..3ee9406798 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -19,3 +19,4 @@ contract C { receive() payable external {} } // ---- +// Warning 5159: (122-134): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol index 76a05d8beb..f458aaad5d 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol @@ -20,6 +20,7 @@ contract C { } } // ---- +// Warning 5159: (201-213): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. // TypeError 8961: (52-77): Function cannot be declared as view because this expression (potentially) modifies the state. // TypeError 8961: (132-153): Function cannot be declared as view because this expression (potentially) modifies the state. // TypeError 8961: (201-228): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol index 2b9e5ae5fb..b3753706cf 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol @@ -85,6 +85,7 @@ contract C { // ==== // EVMVersion: >=paris // ---- +// Warning 1699: (1754-1766): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. // Warning 5740: (89-1716): Unreachable code. // Warning 5740: (1729-1741): Unreachable code. // Warning 5740: (1754-1769): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol index 9b3806f4d6..be84b801f2 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol @@ -35,6 +35,7 @@ contract C { } } // ---- +// Warning 1699: (498-510): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. // Warning 5740: (526-853): Unreachable code. // TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". // TypeError 8961: (101-113): Function cannot be declared as pure because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol index 5daf917420..cd69bed793 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol @@ -23,6 +23,7 @@ contract C { // ==== // EVMVersion: >=london // ---- +// Warning 1699: (308-320): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. // Warning 5740: (336-468): Unreachable code. // TypeError 8961: (75-87): Function cannot be declared as view because this expression (potentially) modifies the state. // TypeError 8961: (104-119): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libyul/yulSyntaxTests/selfdestruct.yul b/test/libyul/yulSyntaxTests/selfdestruct.yul index 70d76c73b2..745fdc5c5a 100644 --- a/test/libyul/yulSyntaxTests/selfdestruct.yul +++ b/test/libyul/yulSyntaxTests/selfdestruct.yul @@ -2,3 +2,4 @@ selfdestruct(0x02) } // ---- +// Warning 1699: (3-15): "selfdestruct" has been deprecated. The underlying opcode will eventually undergo breaking changes, and its use is not recommended. From 83a937423f2d486a4e92004ad02acf21599239e9 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 24 Jan 2023 11:43:34 +0100 Subject: [PATCH 0042/1140] Update docs to reflect deprecation warning --- docs/introduction-to-smart-contracts.rst | 5 +++++ docs/units-and-global-variables.rst | 8 +++++--- docs/yul.rst | 6 ++++++ libyul/AsmAnalysis.cpp | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 875e5ebc86..4e370a461b 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -562,6 +562,11 @@ is removed from the state. Removing the contract in theory sounds like a good idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost. +.. warning:: + From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a + deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behaviour + as stated in `EIP-6049 `_. + .. warning:: Even if a contract is removed by ``selfdestruct``, it is still part of the history of the blockchain and probably retained by most Ethereum nodes. diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 6e49665907..80162a3b4a 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -327,11 +327,13 @@ Contract Related - the receiving contract's receive function is not executed. - the contract is only really destroyed at the end of the transaction and ``revert`` s might "undo" the destruction. - - - Furthermore, all functions of the current contract are callable directly including the current function. +.. warning:: + From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a + deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behaviour + as stated in `EIP-6049 `_. + .. note:: Prior to version 0.5.0, there was a function called ``suicide`` with the same semantics as ``selfdestruct``. diff --git a/docs/yul.rst b/docs/yul.rst index 206f80cace..bbe72a5320 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -899,6 +899,7 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a | revert(p, s) | `-` | B | end execution, revert state changes, return data mem[p...(p+s)) | +-------------------------+-----+---+-----------------------------------------------------------------+ | selfdestruct(a) | `-` | F | end execution, destroy current contract and send funds to a | +| | | | (deprecated) | +-------------------------+-----+---+-----------------------------------------------------------------+ | invalid() | `-` | F | end execution with invalid instruction | +-------------------------+-----+---+-----------------------------------------------------------------+ @@ -956,6 +957,11 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a Please note that irrelevant to which EVM version is selected in the compiler, the semantics of instructions depend on the final chain of deployment. +.. warning:: + From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a + deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behaviour + as stated in `EIP-6049 `_. + In some internal dialects, there are additional functions: datasize, dataoffset, datacopy diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 3ca84da714..b8baec9988 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -311,7 +311,7 @@ vector AsmAnalyzer::operator()(FunctionCall const& _funCall) if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name)) { - if (_funCall.functionName.name.str() == "selfdestruct") + if (_funCall.functionName.name == "selfdestruct"_yulstring) m_errorReporter.warning( 1699_error, nativeLocationOf(_funCall.functionName), From 206e7cf5db48b13085b943436764c41f169c6c3b Mon Sep 17 00:00:00 2001 From: r0qs Date: Thu, 26 Jan 2023 13:40:38 +0000 Subject: [PATCH 0043/1140] Disable stale action debug mode (#13756) --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c1a7bd45a6..18046d107c 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/stale@v6 with: - debug-only: true + debug-only: false days-before-issue-stale: ${{ env.BEFORE_ISSUE_STALE }} days-before-issue-close: ${{ env.BEFORE_ISSUE_CLOSE }} stale-issue-message: | From 564cf85725639f47558fcc1dc2d02366aeb6a391 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Mon, 30 Jan 2023 09:19:33 +0100 Subject: [PATCH 0044/1140] Yul proto converter: Output prevrandao for evm versions >= paris --- test/tools/ossfuzz/protoToYul.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index cd2898e128..991b25e752 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -715,7 +715,10 @@ void ProtoConverter::visit(NullaryOp const& _x) m_output << "number()"; break; case NullaryOp::DIFFICULTY: - m_output << "difficulty()"; + if (m_evmVersion >= EVMVersion::paris()) + m_output << "prevrandao()"; + else + m_output << "difficulty()"; break; case NullaryOp::GASLIMIT: m_output << "gaslimit()"; From 21f95c45369fa84f78b374dee8d4b8e98ef22c45 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Mon, 30 Jan 2023 13:22:58 +0100 Subject: [PATCH 0045/1140] Suppress libcln from asan tests --- .circleci/cln-asan.supp | 1 + .circleci/config.yml | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 .circleci/cln-asan.supp diff --git a/.circleci/cln-asan.supp b/.circleci/cln-asan.supp new file mode 100644 index 0000000000..b16becf29b --- /dev/null +++ b/.circleci/cln-asan.supp @@ -0,0 +1 @@ +leak:*libcln* diff --git a/.circleci/config.yml b/.circleci/config.yml index b2c1ab9209..81b757a66e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1094,6 +1094,9 @@ jobs: environment: TERM: xterm ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 + # Suppress CLN memory leak. + # See: https://github.com/ethereum/solidity/issues/13891 for details. + LSAN_OPTIONS: suppressions=.circleci/cln-asan.supp <<: *steps_cmdline_tests t_ubu_asan_soltest: @@ -1104,6 +1107,9 @@ jobs: OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 + # Suppress CLN memory leak. + # See: https://github.com/ethereum/solidity/issues/13891 for details. + LSAN_OPTIONS: suppressions=.circleci/cln-asan.supp <<: *steps_soltest t_ubu_asan_clang_soltest: From d9d9ab30a231601441c60ceb98d636977e54b26a Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 18 Jan 2023 16:34:48 +0000 Subject: [PATCH 0046/1140] Update default evm version to paris --- .circleci/soltest_all.sh | 2 +- Changelog.md | 1 + docs/using-the-compiler.rst | 6 +++--- liblangutil/EVMVersion.h | 2 +- scripts/tests.sh | 4 ++-- test/externalTests/common.sh | 2 +- test/libsolidity/StandardCompiler.cpp | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 5a5449a948..b3544a08c5 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -32,7 +32,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" source "${REPODIR}/scripts/common.sh" EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london paris) -DEFAULT_EVM=london +DEFAULT_EVM=paris [[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]] OPTIMIZE_VALUES=(0 1) diff --git a/Changelog.md b/Changelog.md index 362be6d1fc..a1ff633eac 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: * Commandline Interface: Add `--no-cbor-metadata` that skips CBOR metadata from getting appended at the end of the bytecode. * EVM: Deprecate ``block.difficulty`` and disallow ``difficulty()`` in inline assembly for EVM versions >= paris. The change is due to the renaming introduced by [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399). * EVM: Introduce ``block.prevrandao`` in Solidity and ``prevrandao()`` in inline assembly for EVM versions >= paris. + * EVM: Set the default EVM version to "Paris". * EVM: Support for the EVM version "Paris". * Natspec: Add event Natspec inheritance for devdoc. * Standard JSON: Add a boolean field `settings.metadata.appendCBOR` that skips CBOR metadata from getting appended at the end of the bytecode. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index fca81760c4..c186fa25eb 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -170,10 +170,10 @@ at each version. Backward compatibility is not guaranteed between each version. - Gas costs for ``SLOAD``, ``*CALL``, ``BALANCE``, ``EXT*`` and ``SELFDESTRUCT`` increased. The compiler assumes cold gas costs for such operations. This is relevant for gas estimation and the optimizer. -- ``london`` (**default**) +- ``london`` - The block's base fee (`EIP-3198 `_ and `EIP-1559 `_) can be accessed via the global ``block.basefee`` or ``basefee()`` in inline assembly. -- ``paris`` - - No changes, however the semantics of the ``difficulty`` value have changed (see `EIP-4399 `_). +- ``paris`` (**default**) + - Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_). .. index:: ! standard JSON, ! --standard-json .. _compiler-api: diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index f985b4aff8..aa23ea6eef 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -109,7 +109,7 @@ class EVMVersion: EVMVersion(Version _version): m_version(_version) {} - Version m_version = Version::London; + Version m_version = Version::Paris; }; } diff --git a/scripts/tests.sh b/scripts/tests.sh index c9a7471343..2be31eec03 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -115,9 +115,9 @@ do for vm in $EVM_VERSIONS do FORCE_ABIV1_RUNS="no" - if [[ "$vm" == "london" ]] + if [[ "$vm" == "paris" ]] then - FORCE_ABIV1_RUNS="no yes" # run both in london + FORCE_ABIV1_RUNS="no yes" # run both in paris fi for abiv1 in $FORCE_ABIV1_RUNS do diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 144c68a890..b6a85c1e3b 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -22,7 +22,7 @@ set -e # Requires $REPO_ROOT to be defined and "${REPO_ROOT}/scripts/common.sh" to be included before. -CURRENT_EVM_VERSION=london +CURRENT_EVM_VERSION=paris AVAILABLE_PRESETS=( legacy-no-optimize diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 61b28b11e7..d2eeedd910 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1086,7 +1086,7 @@ BOOST_AUTO_TEST_CASE(evm_version) BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"paris\"") != string::npos); // test default result = compile(inputForVersion("")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"london\"") != string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"paris\"") != string::npos); // test invalid result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); BOOST_CHECK(result["errors"][0]["message"].asString() == "Invalid EVM version requested."); From a68501cebda6fa1ac6affe020496d4c7575deda6 Mon Sep 17 00:00:00 2001 From: Mio Date: Tue, 31 Jan 2023 13:23:47 +0800 Subject: [PATCH 0047/1140] fix redundant typo --- docs/internals/optimizer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 11f55e0e3a..99589db992 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -1162,7 +1162,7 @@ will be transformed into the code below after the Unused Store Eliminator step i For memory store operations, things are generally simpler, at least in the outermost yul block as all such statements will be removed if they are never read from in any code path. At function analysis level, however, the approach is similar to ``sstore``, as we do not know whether the memory location will -be read once we leave the function's scope, so the statement will be removed only if all code code paths lead to a memory overwrite. +be read once we leave the function's scope, so the statement will be removed only if all code paths lead to a memory overwrite. Best run in SSA form. From feba4de50994de90531236b9f7734d27c7b6af2d Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Thu, 19 Jan 2023 13:06:23 +0000 Subject: [PATCH 0048/1140] Add paris constraints to SMTChecker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel Co-authored-by: Kamil Śliwak Co-authored-by: Leo --- docs/using-the-compiler.rst | 2 +- libsolidity/formal/Predicate.cpp | 10 ++- libsolidity/formal/SMTEncoder.cpp | 8 ++- libsolidity/formal/SymbolicState.cpp | 9 ++- libsolidity/formal/SymbolicState.h | 5 +- .../output.json | 64 +++++++++---------- .../abi/abi_encode_with_selector_vs_sig.sol | 7 +- .../abi/abi_encode_with_sig_array_slice_2.sol | 2 +- .../bmc_coverage/range_check.sol | 8 +++ .../external_calls/external_safe.sol | 2 +- .../invariants/state_machine_1.sol | 3 +- ...r_loop_array_assignment_memory_storage.sol | 2 +- .../operators/index_access_for_bytesNN.sol | 1 + .../smtCheckerTests/out_of_bounds/array_1.sol | 2 +- .../special/block_vars_bmc_internal.sol | 18 ++++-- .../special/block_vars_chc_internal.sol | 8 ++- .../smtCheckerTests/special/difficulty.sol | 11 ---- .../smtCheckerTests/special/many.sol | 15 +++-- .../smtCheckerTests/special/many_internal.sol | 15 +++-- .../smtCheckerTests/special/prevrandao.sol | 16 +++++ .../smtCheckerTests/special/range_check.sol | 8 +++ .../special/tx_data_immutable.sol | 7 ++ .../special/tx_data_immutable_fail.sol | 57 ++++++++++------- .../types/fixed_bytes_access_3.sol | 2 +- .../userTypes/user_type_as_array_elem_1.sol | 2 + .../user_type_as_struct_member_1.sol | 1 + 26 files changed, 183 insertions(+), 102 deletions(-) delete mode 100644 test/libsolidity/smtCheckerTests/special/difficulty.sol create mode 100644 test/libsolidity/smtCheckerTests/special/prevrandao.sol diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index c186fa25eb..6d6264e1aa 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -173,7 +173,7 @@ at each version. Backward compatibility is not guaranteed between each version. - ``london`` - The block's base fee (`EIP-3198 `_ and `EIP-1559 `_) can be accessed via the global ``block.basefee`` or ``basefee()`` in inline assembly. - ``paris`` (**default**) - - Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_). + - Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the now deprecated ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_). .. index:: ! standard JSON, ! --standard-json .. _compiler-api: diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index d4b6994cf5..918728d86d 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -255,8 +255,14 @@ string Predicate::formatSummaryCall( if (auto const* identifier = dynamic_cast(memberExpr)) { ASTString const& name = identifier->name(); + auto memberName = _memberAccess.memberName(); + + // TODO remove this for 0.9.0 + if (name == "block" && memberName == "difficulty") + memberName = "prevrandao"; + if (name == "block" || name == "msg" || name == "tx") - txVars.insert(name + "." + _memberAccess.memberName()); + txVars.insert(name + "." + memberName); } return true; @@ -642,7 +648,7 @@ map> Predicate::readTxVars(smtutil::Expression const& _ {"block.basefee", TypeProvider::uint256()}, {"block.chainid", TypeProvider::uint256()}, {"block.coinbase", TypeProvider::address()}, - {"block.difficulty", TypeProvider::uint256()}, + {"block.prevrandao", TypeProvider::uint256()}, {"block.gaslimit", TypeProvider::uint256()}, {"block.number", TypeProvider::uint256()}, {"block.timestamp", TypeProvider::uint256()}, diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 25789a3b69..810b533512 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -1337,7 +1337,13 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) { auto const& name = identifier->name(); solAssert(name == "block" || name == "msg" || name == "tx", ""); - defineExpr(_memberAccess, state().txMember(name + "." + _memberAccess.memberName())); + auto memberName = _memberAccess.memberName(); + + // TODO remove this for 0.9.0 + if (name == "block" && memberName == "difficulty") + memberName = "prevrandao"; + + defineExpr(_memberAccess, state().txMember(name + "." + memberName)); } else if (auto magicType = dynamic_cast(exprType)) { diff --git a/libsolidity/formal/SymbolicState.cpp b/libsolidity/formal/SymbolicState.cpp index 0679cee8ab..3afde0dcf5 100644 --- a/libsolidity/formal/SymbolicState.cpp +++ b/libsolidity/formal/SymbolicState.cpp @@ -142,13 +142,20 @@ smtutil::Expression SymbolicState::txMember(string const& _member) const return m_tx.member(_member); } +smtutil::Expression SymbolicState::evmParisConstraints() const +{ + // Ensure prevrandao range as defined by EIP-4399. + return txMember("block.prevrandao") > (u256(1) << 64); +} + smtutil::Expression SymbolicState::txTypeConstraints() const { return + evmParisConstraints() && smt::symbolicUnknownConstraints(m_tx.member("block.basefee"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.chainid"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.coinbase"), TypeProvider::address()) && - smt::symbolicUnknownConstraints(m_tx.member("block.difficulty"), TypeProvider::uint256()) && + smt::symbolicUnknownConstraints(m_tx.member("block.prevrandao"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.gaslimit"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.number"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.timestamp"), TypeProvider::uint256()) && diff --git a/libsolidity/formal/SymbolicState.h b/libsolidity/formal/SymbolicState.h index 309d545b80..45c129c1b1 100644 --- a/libsolidity/formal/SymbolicState.h +++ b/libsolidity/formal/SymbolicState.h @@ -68,9 +68,9 @@ class BlockchainVariable * - block basefee * - block chainid * - block coinbase - * - block difficulty * - block gaslimit * - block number + * - block prevrandao * - block timestamp * - TODO gasleft * - msg data @@ -136,6 +136,7 @@ class SymbolicState smtutil::Expression txTypeConstraints() const; smtutil::Expression txNonPayableConstraint() const; smtutil::Expression blockhash(smtutil::Expression _blockNumber) const; + smtutil::Expression evmParisConstraints() const; //@} /// Crypto functions. @@ -197,7 +198,7 @@ class SymbolicState {"block.basefee", smtutil::SortProvider::uintSort}, {"block.chainid", smtutil::SortProvider::uintSort}, {"block.coinbase", smt::smtSort(*TypeProvider::address())}, - {"block.difficulty", smtutil::SortProvider::uintSort}, + {"block.prevrandao", smtutil::SortProvider::uintSort}, {"block.gaslimit", smtutil::SortProvider::uintSort}, {"block.number", smtutil::SortProvider::uintSort}, {"block.timestamp", smtutil::SortProvider::uintSort}, diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index 41ef018d92..fa8726d55e 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -3,38 +3,11 @@ { "smtlib2queries": { - "0x2bcd3328dc8d31e869efd5e0dfdb16a6fa26f0a9c2829ea55670262be485e401": "(set-option :produce-models true) -(set-logic ALL) -(declare-fun |x_3_3| () Int) -(declare-fun |error_0| () Int) -(declare-fun |this_0| () Int) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |state_0| () |state_type|) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.difficulty| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |tx_0| () |tx_type|) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-fun |crypto_0| () |crypto_type|) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-fun |abi_0| () |abi_type|) -(declare-fun |x_3_4| () Int) -(declare-fun |x_3_0| () Int) -(declare-fun |expr_7_0| () Int) -(declare-fun |expr_8_0| () Int) -(declare-fun |expr_9_1| () Bool) - -(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) -(declare-const |EVALEXPR_0| Int) -(assert (= |EVALEXPR_0| x_3_0)) -(check-sat) -(get-value (|EVALEXPR_0| )) -", - "0x4e70784a8a93c7429a716aa8b778f3de5d1f63b30158452534da5d44e5967d2b": "(set-logic HORN) + "0x0ebc730de380833af1e52ed063befb32994bc637929c942b7fd089b7cd3ba64e": "(set-logic HORN) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.difficulty| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) @@ -95,7 +68,7 @@ (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (block_9_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2)))) +(=> (and (and (block_9_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2)))) (assert @@ -139,7 +112,7 @@ (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (summary_constructor_2_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14_0 this_0 abi_0 crypto_0 state_1)))) (declare-fun |error_target_3_0| () Bool) @@ -151,7 +124,34 @@ (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) (=> error_target_3_0 false))) -(check-sat)" +(check-sat)", + "0xcb822e6220a39244d26887a0fa6f62b06718359056555679fb06dd7dff18bb86": "(set-option :produce-models true) +(set-logic ALL) +(declare-fun |x_3_3| () Int) +(declare-fun |error_0| () Int) +(declare-fun |this_0| () Int) +(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) +(declare-fun |state_0| () |state_type|) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |tx_0| () |tx_type|) +(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) +(declare-fun |crypto_0| () |crypto_type|) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) +(declare-fun |abi_0| () |abi_type|) +(declare-fun |x_3_4| () Int) +(declare-fun |x_3_0| () Int) +(declare-fun |expr_7_0| () Int) +(declare-fun |expr_8_0| () Int) +(declare-fun |expr_9_1| () Bool) + +(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) +(declare-const |EVALEXPR_0| Int) +(assert (= |EVALEXPR_0| x_3_0)) +(check-sat) +(get-value (|EVALEXPR_0| )) +" } }, "errors": diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol index 2e64613668..4b4f7a3ace 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol @@ -3,12 +3,13 @@ contract C { bytes memory b1 = abi.encodeWithSignature(sig, x, a); bytes memory b2 = abi.encodeWithSelector(bytes4(keccak256(bytes(sig))), x, a); // should hold but we do not evaluate keccak256 in an interpreted way - assert(b1.length == b2.length); + //assert(b1.length == b2.length); + assert(b1.length != b2.length); // should fail } } // ==== // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6328: (294-324): CHC: Assertion violation might happen here. -// Warning 7812: (294-324): BMC: Assertion violation might happen here. +// Warning 6328: (330-360): CHC: Assertion violation might happen here. +// Warning 7812: (330-360): BMC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol index e015679581..6451a932b5 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol @@ -26,7 +26,7 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6328: (335-365): CHC: Assertion violation happens here.\nCounterexample:\n\ndata = [69]\nb2 = [0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43]\nb3 = []\nb4 = []\nx = 0\ny = 0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeSlice(sig, [69]) +// Warning 6328: (335-365): CHC: Assertion violation happens here. // Warning 6328: (589-619): CHC: Assertion violation happens here. // Warning 6328: (1087-1117): CHC: Assertion violation might happen here. // Warning 4661: (1087-1117): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/range_check.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/range_check.sol index ad31bafb5d..cfedc8fd69 100644 --- a/test/libsolidity/smtCheckerTests/bmc_coverage/range_check.sol +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/range_check.sol @@ -17,6 +17,8 @@ contract C { assert(block.chainid <= 2**256 - 1); assert(block.difficulty >= 0); assert(block.difficulty <= 2**256 - 1); + assert(block.prevrandao > 2**64); + assert(block.prevrandao <= 2**256 - 1); assert(block.gaslimit >= 0); assert(block.gaslimit <= 2**256 - 1); assert(block.number >= 0); @@ -44,6 +46,8 @@ contract D { assert(block.chainid <= 2**256 - 1); assert(block.difficulty >= 0); assert(block.difficulty <= 2**256 - 1); + assert(block.prevrandao > 2**64); + assert(block.prevrandao <= 2**256 - 1); assert(block.gaslimit >= 0); assert(block.gaslimit <= 2**256 - 1); assert(block.number >= 0); @@ -54,3 +58,7 @@ contract D { // ==== // SMTEngine: bmc // ---- +// Warning 8417: (565-581): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (598-614): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1447-1463): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1481-1497): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol index 5921189b7a..b50185449b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol @@ -16,5 +16,5 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- -// Info 1180: Contract invariant(s) for :C:\n!(x >= 11)\nReentrancy property(ies) for :C:\n!( = 1)\n((!(x <= 10) || !( >= 3)) && (!(x <= 10) || !(x' >= 11)))\n = 0 -> no errors\n = 1 -> Overflow at ++x\n = 3 -> Assertion failed at assert(x < 11)\n diff --git a/test/libsolidity/smtCheckerTests/invariants/state_machine_1.sol b/test/libsolidity/smtCheckerTests/invariants/state_machine_1.sol index a4910e5d36..4e74d4ea68 100644 --- a/test/libsolidity/smtCheckerTests/invariants/state_machine_1.sol +++ b/test/libsolidity/smtCheckerTests/invariants/state_machine_1.sol @@ -30,7 +30,6 @@ contract C { } // ==== // SMTEngine: all -// SMTSolvers: z3 // SMTIgnoreOS: macos +// SMTSolvers: z3 // ---- -// Info 1180: Contract invariant(s) for :C:\n!(x >= 7)\n diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_array_assignment_memory_storage.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_array_assignment_memory_storage.sol index 28f2028c6e..c5fa1f288d 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_array_assignment_memory_storage.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_array_assignment_memory_storage.sol @@ -24,6 +24,6 @@ contract LoopFor2 { } // ==== // SMTEngine: all -// SMTSolvers: z3 // SMTIgnoreOS: macos +// SMTSolvers: z3 // ---- diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol index 2fee40f40a..e73554c1e9 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol @@ -6,5 +6,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6368: (76-90): CHC: Out of bounds access might happen here. diff --git a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol index ee57f069d4..0f5a63b07c 100644 --- a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol +++ b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol @@ -22,6 +22,6 @@ contract C { // ---- // Warning 4984: (112-115): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 3944: (181-184): CHC: Underflow (resulting value less than 0) might happen here. -// Warning 6368: (259-263): CHC: Out of bounds access happens here.\nCounterexample:\na = [0], l = 1\n = 0\n\nTransaction trace:\nC.constructor()\nState: a = [], l = 0\nC.p()\nState: a = [0], l = 1\nC.r() +// Warning 6368: (259-263): CHC: Out of bounds access happens here. // Warning 2661: (112-115): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. // Warning 4144: (181-184): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/special/block_vars_bmc_internal.sol b/test/libsolidity/smtCheckerTests/special/block_vars_bmc_internal.sol index 51a330d8ea..273590f65a 100644 --- a/test/libsolidity/smtCheckerTests/special/block_vars_bmc_internal.sol +++ b/test/libsolidity/smtCheckerTests/special/block_vars_bmc_internal.sol @@ -1,12 +1,14 @@ contract C { address coin; uint dif; + uint prevrandao; uint gas; uint number; uint timestamp; function f() public { coin = block.coinbase; dif = block.difficulty; + prevrandao = block.prevrandao; gas = block.gaslimit; number = block.number; timestamp = block.timestamp; @@ -16,12 +18,14 @@ contract C { function g() internal view { assert(uint160(coin) >= 0); // should hold assert(dif >= 0); // should hold + assert(prevrandao > 2**64); // should hold assert(gas >= 0); // should hold assert(number >= 0); // should hold assert(timestamp >= 0); // should hold assert(coin == block.coinbase); // should fail with BMC assert(dif == block.difficulty); // should fail with BMC + assert(prevrandao == block.prevrandao); // should fail with BMC assert(gas == block.gaslimit); // should fail with BMC assert(number == block.number); // should fail with BMC assert(timestamp == block.timestamp); // should fail with BMC @@ -30,8 +34,12 @@ contract C { // ==== // SMTEngine: bmc // ---- -// Warning 4661: (473-503): BMC: Assertion violation happens here. -// Warning 4661: (531-562): BMC: Assertion violation happens here. -// Warning 4661: (590-619): BMC: Assertion violation happens here. -// Warning 4661: (647-677): BMC: Assertion violation happens here. -// Warning 4661: (705-741): BMC: Assertion violation happens here. +// Warning 8417: (155-171): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (641-657): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 4661: (409-435): BMC: Assertion violation happens here. +// Warning 4661: (569-599): BMC: Assertion violation happens here. +// Warning 4661: (627-658): BMC: Assertion violation happens here. +// Warning 4661: (686-724): BMC: Assertion violation happens here. +// Warning 4661: (752-781): BMC: Assertion violation happens here. +// Warning 4661: (809-839): BMC: Assertion violation happens here. +// Warning 4661: (867-903): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/special/block_vars_chc_internal.sol b/test/libsolidity/smtCheckerTests/special/block_vars_chc_internal.sol index ab355dbd25..3e06779a0f 100644 --- a/test/libsolidity/smtCheckerTests/special/block_vars_chc_internal.sol +++ b/test/libsolidity/smtCheckerTests/special/block_vars_chc_internal.sol @@ -1,12 +1,14 @@ contract C { address coin; uint dif; + uint prevrandao; uint gas; uint number; uint timestamp; function f() public { coin = block.coinbase; dif = block.difficulty; + prevrandao = block.prevrandao; gas = block.gaslimit; number = block.number; timestamp = block.timestamp; @@ -16,12 +18,14 @@ contract C { function g() internal view { assert(uint160(coin) >= 0); // should hold assert(dif >= 0); // should hold + assert(prevrandao > 2**64); // should hold assert(gas >= 0); // should hold assert(number >= 0); // should hold assert(timestamp >= 0); // should hold assert(coin == block.coinbase); // should hold with CHC assert(dif == block.difficulty); // should hold with CHC + assert(prevrandao == block.prevrandao); // should hold with CHC assert(gas == block.gaslimit); // should hold with CHC assert(number == block.number); // should hold with CHC assert(timestamp == block.timestamp); // should hold with CHC @@ -33,4 +37,6 @@ contract C { // SMTEngine: chc // SMTIgnoreOS: macos // ---- -// Warning 6328: (770-799): CHC: Assertion violation happens here.\nCounterexample:\ncoin = 0x0, dif = 0, gas = 0, number = 0, timestamp = 0\n\nTransaction trace:\nC.constructor()\nState: coin = 0x0, dif = 0, gas = 0, number = 0, timestamp = 0\nC.f(){ block.coinbase: 0x0, block.difficulty: 0, block.gaslimit: 0, block.number: 0, block.timestamp: 0 }\n C.g() -- internal call +// Warning 8417: (155-171): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (641-657): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 6328: (932-961): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/special/difficulty.sol b/test/libsolidity/smtCheckerTests/special/difficulty.sol deleted file mode 100644 index faf44ddd76..0000000000 --- a/test/libsolidity/smtCheckerTests/special/difficulty.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C -{ - function f(uint difficulty) public view { - assert(block.difficulty == difficulty); - } -} -// ==== -// SMTEngine: all -// SMTIgnoreCex: yes -// ---- -// Warning 6328: (58-96): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/special/many.sol b/test/libsolidity/smtCheckerTests/special/many.sol index e9c100014c..247eec98e2 100644 --- a/test/libsolidity/smtCheckerTests/special/many.sol +++ b/test/libsolidity/smtCheckerTests/special/many.sol @@ -3,6 +3,7 @@ contract C function f() public payable { assert(msg.sender == block.coinbase); assert(block.difficulty == block.gaslimit); + assert(block.prevrandao == block.gaslimit); assert(block.number == block.timestamp); assert(tx.gasprice == msg.value); assert(tx.origin == msg.sender); @@ -17,11 +18,13 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- +// Warning 8417: (93-109): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. // Warning 6328: (46-82): CHC: Assertion violation happens here. // Warning 6328: (86-128): CHC: Assertion violation happens here. -// Warning 6328: (132-171): CHC: Assertion violation happens here. -// Warning 6328: (175-207): CHC: Assertion violation happens here. -// Warning 6328: (211-242): CHC: Assertion violation happens here. -// Warning 6328: (295-319): CHC: Assertion violation happens here. -// Warning 6328: (323-351): CHC: Assertion violation happens here. -// Warning 6328: (355-378): CHC: Assertion violation happens here. +// Warning 6328: (132-174): CHC: Assertion violation happens here. +// Warning 6328: (178-217): CHC: Assertion violation happens here. +// Warning 6328: (221-253): CHC: Assertion violation happens here. +// Warning 6328: (257-288): CHC: Assertion violation happens here. +// Warning 6328: (341-365): CHC: Assertion violation happens here. +// Warning 6328: (369-397): CHC: Assertion violation happens here. +// Warning 6328: (401-424): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/special/many_internal.sol b/test/libsolidity/smtCheckerTests/special/many_internal.sol index eb68fd9ac2..cf9c61ae66 100644 --- a/test/libsolidity/smtCheckerTests/special/many_internal.sol +++ b/test/libsolidity/smtCheckerTests/special/many_internal.sol @@ -6,6 +6,7 @@ contract C function g() internal { assert(msg.sender == block.coinbase); assert(block.difficulty == block.gaslimit); + assert(block.prevrandao == block.gaslimit); assert(block.number == block.timestamp); assert(tx.gasprice == msg.value); assert(tx.origin == msg.sender); @@ -20,11 +21,13 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- +// Warning 8417: (128-144): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. // Warning 6328: (81-117): CHC: Assertion violation happens here. // Warning 6328: (121-163): CHC: Assertion violation happens here. -// Warning 6328: (167-206): CHC: Assertion violation happens here. -// Warning 6328: (210-242): CHC: Assertion violation happens here. -// Warning 6328: (246-277): CHC: Assertion violation happens here. -// Warning 6328: (330-354): CHC: Assertion violation happens here. -// Warning 6328: (358-386): CHC: Assertion violation happens here. -// Warning 6328: (390-413): CHC: Assertion violation happens here. +// Warning 6328: (167-209): CHC: Assertion violation happens here. +// Warning 6328: (213-252): CHC: Assertion violation happens here. +// Warning 6328: (256-288): CHC: Assertion violation happens here. +// Warning 6328: (292-323): CHC: Assertion violation happens here. +// Warning 6328: (376-400): CHC: Assertion violation happens here. +// Warning 6328: (404-432): CHC: Assertion violation happens here. +// Warning 6328: (436-459): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/special/prevrandao.sol b/test/libsolidity/smtCheckerTests/special/prevrandao.sol new file mode 100644 index 0000000000..0237c75505 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/prevrandao.sol @@ -0,0 +1,16 @@ +contract C +{ + function f(uint prevrandao) public view { + assert(block.prevrandao == prevrandao); // should fail + assert(block.difficulty == prevrandao); // should fail + assert(block.difficulty == block.prevrandao); // should hold + } +} +// ==== +// SMTEngine: all +// SMTIgnoreCex: yes +// ---- +// Warning 8417: (122-138): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (179-195): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 6328: (58-96): CHC: Assertion violation happens here. +// Warning 6328: (115-153): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/special/range_check.sol b/test/libsolidity/smtCheckerTests/special/range_check.sol index 9373adfd5e..62187f46a6 100644 --- a/test/libsolidity/smtCheckerTests/special/range_check.sol +++ b/test/libsolidity/smtCheckerTests/special/range_check.sol @@ -17,6 +17,8 @@ contract C { assert(block.chainid <= 2**256 - 1); assert(block.difficulty >= 0); assert(block.difficulty <= 2**256 - 1); + assert(block.prevrandao > 2**64); + assert(block.prevrandao <= 2**256 - 1); assert(block.gaslimit >= 0); assert(block.gaslimit <= 2**256 - 1); assert(block.number >= 0); @@ -44,6 +46,8 @@ contract D { assert(block.chainid <= 2**256 - 1); assert(block.difficulty >= 0); assert(block.difficulty <= 2**256 - 1); + assert(block.prevrandao > 2**64); + assert(block.prevrandao <= 2**256 - 1); assert(block.gaslimit >= 0); assert(block.gaslimit <= 2**256 - 1); assert(block.number >= 0); @@ -55,3 +59,7 @@ contract D { // ==== // SMTEngine: all // ---- +// Warning 8417: (565-581): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (598-614): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1447-1463): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1481-1497): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. diff --git a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol index 25fc02ef88..c15dfb1cfe 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol @@ -2,6 +2,7 @@ contract C { bytes32 bhash; address coin; uint dif; + uint prevrandao; uint glimit; uint number; uint tstamp; @@ -16,6 +17,7 @@ contract C { bhash = blockhash(12); coin = block.coinbase; dif = block.difficulty; + prevrandao = block.prevrandao; glimit = block.gaslimit; number = block.number; tstamp = block.timestamp; @@ -31,6 +33,7 @@ contract C { assert(bhash == blockhash(12)); assert(coin == block.coinbase); assert(dif == block.difficulty); + assert(prevrandao == block.prevrandao); assert(glimit == block.gaslimit); assert(number == block.number); assert(tstamp == block.timestamp); @@ -46,6 +49,7 @@ contract C { assert(bhash == blockhash(12)); assert(coin == block.coinbase); assert(dif == block.difficulty); + assert(prevrandao == block.prevrandao); assert(glimit == block.gaslimit); assert(number == block.number); assert(tstamp == block.timestamp); @@ -60,3 +64,6 @@ contract C { // ==== // SMTEngine: all // ---- +// Warning 8417: (293-309): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (645-661): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1127-1143): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. diff --git a/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol b/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol index 82d3529e0e..2b16f2d1aa 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol @@ -2,6 +2,7 @@ contract C { bytes32 bhash; address coin; uint dif; + uint prevrandao; uint glimit; uint number; uint tstamp; @@ -16,6 +17,7 @@ contract C { bhash = blockhash(12); coin = block.coinbase; dif = block.difficulty; + prevrandao = block.prevrandao; glimit = block.gaslimit; number = block.number; tstamp = block.timestamp; @@ -31,6 +33,7 @@ contract C { assert(bhash == blockhash(122)); assert(coin != block.coinbase); assert(dif != block.difficulty); + assert(prevrandao != block.prevrandao); assert(glimit != block.gaslimit); assert(number != block.number); assert(tstamp != block.timestamp); @@ -46,6 +49,7 @@ contract C { assert(bhash == blockhash(122)); assert(coin != block.coinbase); assert(dif != block.difficulty); + assert(prevrandao != block.prevrandao); assert(glimit != block.gaslimit); assert(number != block.number); assert(tstamp != block.timestamp); @@ -61,27 +65,32 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (512-543): CHC: Assertion violation happens here. -// Warning 6328: (547-577): CHC: Assertion violation happens here. -// Warning 6328: (581-612): CHC: Assertion violation happens here. -// Warning 6328: (616-648): CHC: Assertion violation happens here. -// Warning 6328: (652-682): CHC: Assertion violation happens here. -// Warning 6328: (686-719): CHC: Assertion violation happens here. -// Warning 6328: (723-762): CHC: Assertion violation happens here. -// Warning 6328: (766-794): CHC: Assertion violation happens here. -// Warning 6328: (798-820): CHC: Assertion violation happens here. -// Warning 6328: (824-850): CHC: Assertion violation happens here. -// Warning 6328: (854-883): CHC: Assertion violation happens here. -// Warning 6328: (887-914): CHC: Assertion violation happens here. -// Warning 6328: (953-984): CHC: Assertion violation happens here. -// Warning 6328: (988-1018): CHC: Assertion violation happens here. -// Warning 6328: (1022-1053): CHC: Assertion violation happens here. -// Warning 6328: (1057-1089): CHC: Assertion violation happens here. -// Warning 6328: (1093-1123): CHC: Assertion violation happens here. -// Warning 6328: (1127-1160): CHC: Assertion violation happens here. -// Warning 6328: (1164-1203): CHC: Assertion violation happens here. -// Warning 6328: (1207-1235): CHC: Assertion violation happens here. -// Warning 6328: (1239-1261): CHC: Assertion violation happens here. -// Warning 6328: (1265-1291): CHC: Assertion violation happens here. -// Warning 6328: (1295-1324): CHC: Assertion violation happens here. -// Warning 6328: (1328-1355): CHC: Assertion violation happens here. +// Warning 8417: (293-309): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (646-662): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1129-1145): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 6328: (563-594): CHC: Assertion violation happens here. +// Warning 6328: (598-628): CHC: Assertion violation happens here. +// Warning 6328: (632-663): CHC: Assertion violation happens here. +// Warning 6328: (667-705): CHC: Assertion violation happens here. +// Warning 6328: (709-741): CHC: Assertion violation happens here. +// Warning 6328: (745-775): CHC: Assertion violation happens here. +// Warning 6328: (779-812): CHC: Assertion violation happens here. +// Warning 6328: (816-855): CHC: Assertion violation happens here. +// Warning 6328: (859-887): CHC: Assertion violation happens here. +// Warning 6328: (891-913): CHC: Assertion violation happens here. +// Warning 6328: (917-943): CHC: Assertion violation happens here. +// Warning 6328: (947-976): CHC: Assertion violation happens here. +// Warning 6328: (980-1007): CHC: Assertion violation happens here. +// Warning 6328: (1046-1077): CHC: Assertion violation happens here. +// Warning 6328: (1081-1111): CHC: Assertion violation happens here. +// Warning 6328: (1115-1146): CHC: Assertion violation happens here. +// Warning 6328: (1150-1188): CHC: Assertion violation happens here. +// Warning 6328: (1192-1224): CHC: Assertion violation happens here. +// Warning 6328: (1228-1258): CHC: Assertion violation happens here. +// Warning 6328: (1262-1295): CHC: Assertion violation happens here. +// Warning 6328: (1299-1338): CHC: Assertion violation happens here. +// Warning 6328: (1342-1370): CHC: Assertion violation happens here. +// Warning 6328: (1374-1396): CHC: Assertion violation happens here. +// Warning 6328: (1400-1426): CHC: Assertion violation happens here. +// Warning 6328: (1430-1459): CHC: Assertion violation happens here. +// Warning 6328: (1463-1490): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol index 320d7dd10e..305c00a62f 100644 --- a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol +++ b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol @@ -32,5 +32,5 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- +// Warning 6368: (374-381): CHC: Out of bounds access might happen here. // Warning 6368: (456-462): CHC: Out of bounds access happens here. -// Info 1180: Contract invariant(s) for :C:\n!(a.length <= 4)\n!(a[2].length <= 2)\n diff --git a/test/libsolidity/smtCheckerTests/userTypes/user_type_as_array_elem_1.sol b/test/libsolidity/smtCheckerTests/userTypes/user_type_as_array_elem_1.sol index 55a88fd7e2..8856ebd43a 100644 --- a/test/libsolidity/smtCheckerTests/userTypes/user_type_as_array_elem_1.sol +++ b/test/libsolidity/smtCheckerTests/userTypes/user_type_as_array_elem_1.sol @@ -11,6 +11,8 @@ contract C { assert(T.unwrap(arr[i]) == address(42)); // should hold } } +// ==== +// SMTIgnoreOS: macos // ---- // Warning 6328: (204-243): CHC: Assertion violation might happen here. // Warning 4661: (204-243): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol b/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol index 1a72cad3da..5cb307385b 100644 --- a/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol +++ b/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol @@ -23,3 +23,4 @@ contract C { ); } } +// ---- From 4f84112650cab6701bcfa7e6c86e43069615819c Mon Sep 17 00:00:00 2001 From: Lokesh Kumar Date: Wed, 1 Feb 2023 03:12:03 +0530 Subject: [PATCH 0049/1140] updated abi-spec.rst --- docs/abi-spec.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 7906d75ffe..35123a30a2 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -311,7 +311,7 @@ Use of Dynamic Types A call to a function with the signature ``f(uint256,uint32[],bytes10,bytes)`` with values ``(0x123, [0x456, 0x789], "1234567890", "Hello, world!")`` is encoded in the following way: -We take the first four bytes of ``sha3("f(uint256,uint32[],bytes10,bytes)")``, i.e. ``0x8be65246``. +We take the first four bytes of ``keccak("f(uint256,uint32[],bytes10,bytes)")``, i.e. ``0x8be65246``. Then we encode the head parts of all four arguments. For the static types ``uint256`` and ``bytes10``, these are directly the values we want to pass, whereas for the dynamic types ``uint32[]`` and ``bytes``, we use the offset in bytes to the start of their data area, measured from the start of the value From 6cad055d97c5e9abaccd971598a40e8a0ea91d34 Mon Sep 17 00:00:00 2001 From: franzihei <41991517+franzihei@users.noreply.github.com> Date: Wed, 1 Feb 2023 11:47:08 +0100 Subject: [PATCH 0050/1140] [DOCS] Update copyright year and description (#13894) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nuno Santos Co-authored-by: Kamil Śliwak --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 61df2b53ec..daa5e99132 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -63,7 +63,7 @@ def setup(sphinx): # General information about the project. project = 'Solidity' -project_copyright = '2016-2021, Ethereum' +project_copyright = '2016-2023, The Solidity Authors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the From 986bc361b15f0f89bc4cad97807e69a36378fc36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 1 Feb 2023 12:26:44 +0100 Subject: [PATCH 0051/1140] docs: Replace some links with redirects found by linkcheck --- docs/contracts/creating-contracts.rst | 2 +- docs/contracts/events.rst | 2 +- docs/contributing.rst | 4 ++-- docs/examples/micropayment.rst | 2 +- docs/introduction-to-smart-contracts.rst | 2 +- docs/layout-of-source-files.rst | 2 +- docs/natspec-format.rst | 2 +- docs/resources.rst | 6 +++--- docs/style-guide.rst | 4 ++-- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/contracts/creating-contracts.rst b/docs/contracts/creating-contracts.rst index f574a5a6aa..8eb4e5f56c 100644 --- a/docs/contracts/creating-contracts.rst +++ b/docs/contracts/creating-contracts.rst @@ -8,7 +8,7 @@ Contracts can be created "from outside" via Ethereum transactions or from within IDEs, such as `Remix `_, make the creation process seamless using UI elements. -One way to create contracts programmatically on Ethereum is via the JavaScript API `web3.js `_. +One way to create contracts programmatically on Ethereum is via the JavaScript API `web3.js `_. It has a function called `web3.eth.Contract `_ to facilitate contract creation. diff --git a/docs/contracts/events.rst b/docs/contracts/events.rst index 8618e7524b..a7c7bc13f6 100644 --- a/docs/contracts/events.rst +++ b/docs/contracts/events.rst @@ -151,6 +151,6 @@ The output of the above looks like the following (trimmed): Additional Resources for Understanding Events ============================================= -- `Javascript documentation `_ +- `Javascript documentation `_ - `Example usage of events `_ - `How to access them in js `_ diff --git a/docs/contributing.rst b/docs/contributing.rst index da949c1369..c174e3f606 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -102,9 +102,9 @@ This can be easiest accomplished using Homebrew: ``brew install coreutils``. On Windows systems, make sure that you have a privilege to create symlinks, otherwise several tests may fail. Administrators should have that privilege, but you may also -`grant it to other users `_ +`grant it to other users `_ or -`enable Developer Mode `_. +`enable Developer Mode `_. Running the Tests ----------------- diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index f5037e6f76..6ce049457b 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -36,7 +36,7 @@ Creating the signature Alice does not need to interact with the Ethereum network to sign the transaction, the process is completely offline. In this tutorial, we will sign messages in the browser -using `web3.js `_ and +using `web3.js `_ and `MetaMask `_, using the method described in `EIP-712 `_, as it provides a number of other security benefits. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 4e370a461b..5a278ecfb1 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -185,7 +185,7 @@ arguments ``from``, ``to`` and ``amount``, which makes it possible to track transactions. To listen for this event, you could use the following -JavaScript code, which uses `web3.js `_ to create the ``Coin`` contract object, +JavaScript code, which uses `web3.js `_ to create the ``Coin`` contract object, and any user interface calls the automatically generated ``balances`` function from above: .. code-block:: javascript diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 9a58478586..a5c7164bcc 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -182,7 +182,7 @@ Syntax and Semantics Solidity supports import statements to help modularise your code that are similar to those available in JavaScript (from ES6 on). However, Solidity does not support the concept of -a `default export `_. +a `default export `_. At a global level, you can use import statements of the following form: diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index 01726fe860..b23a46090d 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -46,7 +46,7 @@ for the purposes of NatSpec. - For Vyper, use ``"""`` indented to the inner contents with bare comments. See the `Vyper - documentation `__. + documentation `__. The following example shows a contract and a function using all available tags. diff --git a/docs/resources.rst b/docs/resources.rst index 9084037d9d..df0e450197 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -28,7 +28,7 @@ Integrated (Ethereum) Development Environments * `Embark `_ Developer platform for building and deploying decentralized applications. - * `Foundry `_ + * `Foundry `_ Fast, portable and modular toolkit for Ethereum application development written in Rust. * `Hardhat `_ @@ -37,7 +37,7 @@ Integrated (Ethereum) Development Environments * `Remix `_ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. - * `Truffle `_ + * `Truffle `_ Ethereum development framework. Editor Integrations @@ -50,7 +50,7 @@ Editor Integrations * IntelliJ - * `IntelliJ IDEA plugin `_ + * `IntelliJ IDEA plugin `_ Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs). * Sublime Text diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 08050c7511..35e7324c99 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -17,11 +17,11 @@ conflicts, project specific style guides take precedence. The structure and many of the recommendations within this style guide were taken from python's -`pep8 style guide `_. +`pep8 style guide `_. The goal of this guide is *not* to be the right way or the best way to write Solidity code. The goal of this guide is *consistency*. A quote from python's -`pep8 `_ +`pep8 `_ captures this concept well. .. note:: From 57b01db57b3c7bb6110ec3c39e4336d85528c86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 1 Feb 2023 12:27:23 +0100 Subject: [PATCH 0052/1140] docs: Replace broken link to Oxford Dictionary British spelling page with an archive.org copy --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index c174e3f606..e6925a4896 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -408,7 +408,7 @@ local slang and references, making your language as clear to all readers as poss * `Simplified technical English `_ * `International English `_ -* `British English spelling `_ +* `British English spelling `_ .. note:: From 8447baec4db9537dfe2d22bddb726a0938a0aa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 1 Feb 2023 12:27:56 +0100 Subject: [PATCH 0053/1140] docs; Link to published versions of translated docs for languages that already have them --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 3cb27eaeda..ba216ec3a9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -95,7 +95,7 @@ version stands as a reference. You can switch between languages by clicking on the flyout menu in the bottom-left corner and selecting the preferred language. -* `Chinese `_ +* `Chinese `_ * `French `_ * `Indonesian `_ * `Japanese `_ @@ -103,7 +103,7 @@ and selecting the preferred language. * `Persian `_ * `Russian `_ * `Spanish `_ -* `Turkish `_ +* `Turkish `_ .. note:: From 828f95ad9ecce5dacf7d3b37340803e1c17708fd Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 1 Feb 2023 13:22:08 +0100 Subject: [PATCH 0054/1140] Fix pylint 2.16 warnings --- scripts/bytecodecompare/prepare_report.py | 2 +- scripts/gas_diff_stats.py | 2 +- scripts/pylintrc | 1 + test/lsp.py | 8 ++++---- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/bytecodecompare/prepare_report.py b/scripts/bytecodecompare/prepare_report.py index dd317735fe..90901e8b79 100755 --- a/scripts/bytecodecompare/prepare_report.py +++ b/scripts/bytecodecompare/prepare_report.py @@ -251,7 +251,7 @@ def detect_metadata_cli_option_support(compiler_path: Path): f"Compiler output:\n{process.stderr}\n", file=sys.stderr ) - raise Exception("Failed to determine if the compiler supports the --metadata option.") + raise RuntimeError("Failed to determine if the compiler supports the --metadata option.") return process.returncode == 0 diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 56cd0cd430..234d42df0c 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -75,7 +75,7 @@ def collect_statistics(lines) -> (int, int, int, int, int, int): """ if not lines: - raise Exception("Empty list") + raise RuntimeError("Empty list") def try_parse(line): try: diff --git a/scripts/pylintrc b/scripts/pylintrc index 3a2b852930..735810ad52 100644 --- a/scripts/pylintrc +++ b/scripts/pylintrc @@ -23,6 +23,7 @@ disable= no-else-return, pointless-string-statement, redefined-outer-name, + superfluous-parens, too-few-public-methods, too-many-arguments, too-many-branches, diff --git a/test/lsp.py b/test/lsp.py index 2e097dab0a..669951ca4c 100755 --- a/test/lsp.py +++ b/test/lsp.py @@ -591,7 +591,7 @@ def test_diagnostics(self): for diagnostics in published_diagnostics: if not diagnostics["uri"].startswith(self.suite.project_root_uri + "/"): - raise Exception( + raise RuntimeError( f"'{self.test_name}.sol' imported file outside of test directory: '{diagnostics['uri']}'" ) self.open_tests.append(self.suite.normalizeUri(diagnostics["uri"])) @@ -804,9 +804,9 @@ def findMarker(desired_tag): if tag == desired_tag: return tagRange elif tag.lower() == desired_tag.lower(): - raise Exception(f"Detected lower/upper case mismatch: Requested {desired_tag} but only found {tag}") + raise RuntimeError(f"Detected lower/upper case mismatch: Requested {desired_tag} but only found {tag}") - raise Exception(f"Marker {desired_tag} not found in file") + raise RuntimeError(f"Marker {desired_tag} not found in file") # Check if we need markers from a specific file @@ -1032,7 +1032,7 @@ def fetch_and_format_diagnostics(self, solc: JsonRpcProcess, test, sub_dir=None) tag = self.find_tag_with_range(testname, local_sub_dir, diagnostic['range']) if tag is None: - raise Exception(f"No tag found for diagnostic range {diagnostic['range']}") + raise RuntimeError(f"No tag found for diagnostic range {diagnostic['range']}") expectations += f" {tag} {diagnostic['code']}" expectations += "\n" From a186e607827ce7ce5578d671d3d1b580626a6525 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 1 Feb 2023 12:56:23 +0100 Subject: [PATCH 0055/1140] Sort changelog for 0.8.18 alphabetically --- Changelog.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Changelog.md b/Changelog.md index a1ff633eac..9b0661a90d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,43 +1,42 @@ ### 0.8.18 (unreleased) Language Features: -* Allow named parameters in mapping types. + * Allow named parameters in mapping types. Compiler Features: + * Commandline Interface: Add ``--no-cbor-metadata`` that skips CBOR metadata from getting appended at the end of the bytecode. * Commandline Interface: Return exit code ``2`` on uncaught exceptions. - * Commandline Interface: Add `--no-cbor-metadata` that skips CBOR metadata from getting appended at the end of the bytecode. * EVM: Deprecate ``block.difficulty`` and disallow ``difficulty()`` in inline assembly for EVM versions >= paris. The change is due to the renaming introduced by [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399). * EVM: Introduce ``block.prevrandao`` in Solidity and ``prevrandao()`` in inline assembly for EVM versions >= paris. * EVM: Set the default EVM version to "Paris". * EVM: Support for the EVM version "Paris". - * Natspec: Add event Natspec inheritance for devdoc. - * Standard JSON: Add a boolean field `settings.metadata.appendCBOR` that skips CBOR metadata from getting appended at the end of the bytecode. - * Yul EVM Code Transform: Generate more optimal code for user-defined functions that always terminate a transaction. No return labels will be pushed for calls to functions that always terminate. - * Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string. - * Yul Optimizer: Eliminate ``keccak256`` calls if the value was already calculated by a previous call and can be reused. * Language Server: Add basic document hover support. + * Natspec: Add event Natspec inheritance for devdoc. * Optimizer: Added optimization rule ``and(shl(X, Y), shl(X, Z)) => shl(X, and(Y, Z))``. - * SMTChecker: Support Eldarica as a Horn solver for the CHC engine when using the CLI option ``--model-checker-solvers eld``. The binary `eld` must be available in the system. - * SMTChecker: Make ``z3`` the default solver for the BMC and CHC engines instead of all solvers. * Parser: More detailed error messages about invalid version pragmas. - * Removed support for the ``solidity-upgrade`` tool. + * SMTChecker: Make ``z3`` the default solver for the BMC and CHC engines instead of all solvers. + * SMTChecker: Support Eldarica as a Horn solver for the CHC engine when using the CLI option ``--model-checker-solvers eld``. The binary ``eld`` must be available in the system. + * Solidity Upgrade Tool: Remove ``solidity-upgrade`` tool. + * Standard JSON: Add a boolean field ``settings.metadata.appendCBOR`` that skips CBOR metadata from getting appended at the end of the bytecode. * TypeChecker: Warn when using deprecated builtin ``selfdestruct``. + * Yul EVM Code Transform: Generate more optimal code for user-defined functions that always terminate a transaction. No return labels will be pushed for calls to functions that always terminate. + * Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string. + * Yul Optimizer: Eliminate ``keccak256`` calls if the value was already calculated by a previous call and can be reused. Bugfixes: * Parser: Disallow several ``indexed`` attributes for the same event parameter. * Parser: Disallow usage of the ``indexed`` attribute for modifier parameters. - * Yul Optimizer: Hash hex and decimal literals according to their value instead of their representation, improving the detection of equivalent functions. - * Solidity Upgrade Tool ``solidity-upgrade``: Fix the tool returning success code on uncaught exceptions. * SMTChecker: Fix display error for negative integers that are one more than powers of two. - * SMTChecker: Improved readability for large integers that are powers of two or almost powers of two in error messages. - * SMTChecker: Fix internal error when a public library function is called internally. - * SMTChecker: Fix internal error on multiple wrong SMTChecker natspec entries. * SMTChecker: Fix internal error on chain assignments using static fully specified state variables. - * SMTChecker: Fix internal error when using user defined types as mapping indices or struct members. + * SMTChecker: Fix internal error on multiple wrong SMTChecker natspec entries. + * SMTChecker: Fix internal error when a public library function is called internally. * SMTChecker: Fix internal error when deleting struct member of function type. + * SMTChecker: Fix internal error when using user-defined types as mapping indices or struct members. + * SMTChecker: Improved readability for large integers that are powers of two or almost powers of two in error messages. * TypeChecker: Fix bug where private library functions could be attached with ``using for`` outside of their declaration scope. + * Yul Optimizer: Hash hex and decimal literals according to their value instead of their representation, improving the detection of equivalent functions. ### 0.8.17 (2022-09-08) From 66007f500195bdca41dea0ab80dddf86a14a0df8 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 1 Feb 2023 14:08:57 +0100 Subject: [PATCH 0056/1140] Add release date and bugs by version entry for 0.8.18 --- Changelog.md | 2 +- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 9b0661a90d..6b804fbd6c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.8.18 (unreleased) +### 0.8.18 (2023-02-01) Language Features: * Allow named parameters in mapping types. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 4e7bca56b3..1541a4655d 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1772,6 +1772,10 @@ "bugs": [], "released": "2022-09-08" }, + "0.8.18": { + "bugs": [], + "released": "2023-02-01" + }, "0.8.2": { "bugs": [ "AbiReencodingHeadOverflowWithStaticArrayCleanup", From e89efe89a68cd27a2b75258c54405d74ae16ac45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:49:34 -0300 Subject: [PATCH 0057/1140] style(mapping-types): fix mapping style --- docs/types/mapping-types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/types/mapping-types.rst b/docs/types/mapping-types.rst index 68f963753e..454caaf05d 100644 --- a/docs/types/mapping-types.rst +++ b/docs/types/mapping-types.rst @@ -95,8 +95,8 @@ The example below uses ``_allowances`` to record the amount someone else is allo contract MappingExample { - mapping (address => uint256) private _balances; - mapping (address => mapping (address => uint256)) private _allowances; + mapping(address => uint256) private _balances; + mapping(address => mapping(address => uint256)) private _allowances; event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); From 4ff310cc625c4406884d63999b691da0e554e9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:50:48 -0300 Subject: [PATCH 0058/1140] style(common-patterns): fix mapping style --- docs/common-patterns.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index 1793ebd2f2..766f8f35ed 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -34,7 +34,7 @@ you receive the funds of the person who is now the richest. address public richest; uint public mostSent; - mapping (address => uint) pendingWithdrawals; + mapping(address => uint) pendingWithdrawals; /// The amount of Ether sent was not higher than /// the currently highest amount. From 7b8478a81b86f2f8ccae4219d5542d529227fd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:51:26 -0300 Subject: [PATCH 0059/1140] style(intro-sc): fix mapping style --- docs/introduction-to-smart-contracts.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 5a278ecfb1..146f2224be 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -91,7 +91,7 @@ registering with a username and password, all you need is an Ethereum keypair. // The keyword "public" makes variables // accessible from other contracts address public minter; - mapping (address => uint) public balances; + mapping(address => uint) public balances; // Events allow clients to react to specific // contract changes you declare @@ -151,7 +151,7 @@ You do not need to do this, the compiler figures it out for you. .. index:: mapping -The next line, ``mapping (address => uint) public balances;`` also +The next line, ``mapping(address => uint) public balances;`` also creates a public state variable, but it is a more complex datatype. The :ref:`mapping ` type maps addresses to :ref:`unsigned integers `. From 1edfd73b377040bfd0aef0292624652e6f0c8862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:51:56 -0300 Subject: [PATCH 0060/1140] style(security-considerations): fix mapping style --- docs/security-considerations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 0375484316..0a86a8d598 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -336,7 +336,7 @@ field of a ``struct`` that is the base type of a dynamic storage array. The pragma solidity >=0.6.0 <0.9.0; contract Map { - mapping (uint => uint)[] array; + mapping(uint => uint)[] array; function allocate(uint newMaps) public { for (uint i = 0; i < newMaps; i++) From 72a17ceb71a8eed590578b6f788a8cbe67136bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:52:34 -0300 Subject: [PATCH 0061/1140] style(function-modifiers): fix mapping style --- docs/contracts/function-modifiers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contracts/function-modifiers.rst b/docs/contracts/function-modifiers.rst index bbdec1e488..b6b83bf3cc 100644 --- a/docs/contracts/function-modifiers.rst +++ b/docs/contracts/function-modifiers.rst @@ -61,7 +61,7 @@ if they are marked ``virtual``. For details, please see } contract Register is priced, destructible { - mapping (address => bool) registeredAddresses; + mapping(address => bool) registeredAddresses; uint price; constructor(uint initialPrice) { price = initialPrice; } From 5b149adfcd9bfba59f2adcf6f1160558b4694005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:53:04 -0300 Subject: [PATCH 0062/1140] style(visibility-and-getters): fix mapping style --- docs/contracts/visibility-and-getters.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index 8932c5079b..5bf46dea55 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -200,12 +200,12 @@ The next example is more complex: struct Data { uint a; bytes3 b; - mapping (uint => uint) map; + mapping(uint => uint) map; uint[3] c; uint[] d; bytes e; } - mapping (uint => mapping(bool => Data[])) public data; + mapping(uint => mapping(bool => Data[])) public data; } It generates a function of the following form. The mapping and arrays (with the From 9b0556caa4d5476d92262eae5ae01df4f8afcff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:53:33 -0300 Subject: [PATCH 0063/1140] style(modular): fix mapping style --- docs/examples/modular.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/modular.rst b/docs/examples/modular.rst index 697699ae6e..f96b296df7 100644 --- a/docs/examples/modular.rst +++ b/docs/examples/modular.rst @@ -34,7 +34,7 @@ and the sum of all balances is an invariant across the lifetime of the contract. contract Token { mapping(address => uint256) balances; using Balances for *; - mapping(address => mapping (address => uint256)) allowed; + mapping(address => mapping(address => uint256)) allowed; event Transfer(address from, address to, uint amount); event Approval(address owner, address spender, uint amount); From b403085fa15c5d35ed94b33d44c2b5abeabfb575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:54:08 -0300 Subject: [PATCH 0064/1140] style(layout_in_storage): fix mapping style --- docs/internals/layout_in_storage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index 53670eeb85..a492dea14c 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -232,7 +232,7 @@ value and reference types, types that are encoded packed, and nested types. uint y; S s; address addr; - mapping (uint => mapping (address => bool)) map; + mapping(uint => mapping(address => bool)) map; uint[] array; string s1; bytes b1; From da7dfeb0c52e706859fdbe520c5d2a2506ca9cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Acosta?= Date: Wed, 1 Feb 2023 15:54:32 -0300 Subject: [PATCH 0065/1140] style(reference-types): fix mapping style --- docs/types/reference-types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 6a7667b6b9..771fdecee8 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -686,11 +686,11 @@ shown in the following example: uint fundingGoal; uint numFunders; uint amount; - mapping (uint => Funder) funders; + mapping(uint => Funder) funders; } uint numCampaigns; - mapping (uint => Campaign) campaigns; + mapping(uint => Campaign) campaigns; function newCampaign(address payable beneficiary, uint goal) public returns (uint campaignID) { campaignID = numCampaigns++; // campaignID is return variable From e735ff1a95497160840afa772dab2a32181db8bc Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 1 Feb 2023 20:24:50 +0100 Subject: [PATCH 0066/1140] Set version to 0.8.19 --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d04d708ae2..cefaeeb656 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.18") +set(PROJECT_VERSION "0.8.19") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 6b804fbd6c..8a3bfae6a8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.19 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.18 (2023-02-01) Language Features: From f8880cad820f741a5288ed42a6719ab6aef6424b Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 30 Mar 2022 11:15:04 +0200 Subject: [PATCH 0067/1140] Yul grammar generator: Bound memory accesses. --- .../libyul/yulInterpreterTests/and_create.yul | 2 - .../yulInterpreterTests/and_create2.yul | 2 - .../external_call_to_self.yul | 1 - .../infinite_recursion_tracelimit.yul | 34 +---- .../yulInterpreterTests/pop_byte_shr_call.yul | 1 - .../libyul/yulInterpreterTests/zero_range.yul | 1 - test/tools/ossfuzz/protoToYul.cpp | 99 +++++++++--- test/tools/ossfuzz/protoToYul.h | 5 + .../EVMInstructionInterpreter.cpp | 142 +++++++++++++++--- .../EVMInstructionInterpreter.h | 13 ++ 10 files changed, 215 insertions(+), 85 deletions(-) diff --git a/test/libyul/yulInterpreterTests/and_create.yul b/test/libyul/yulInterpreterTests/and_create.yul index 8907081506..cbc68ca623 100644 --- a/test/libyul/yulInterpreterTests/and_create.yul +++ b/test/libyul/yulInterpreterTests/and_create.yul @@ -6,8 +6,6 @@ } // ---- // Trace: -// CREATE(0, 0xffffffffffffffffffffffffffffffffffffffff, 0) -// CREATE(0, 0xffffffffffffffffffffffffffffffffffffffff, 0) // Memory dump: // 0: 0000000000000000000000000000000000000000000000000000000000000001 // Storage dump: diff --git a/test/libyul/yulInterpreterTests/and_create2.yul b/test/libyul/yulInterpreterTests/and_create2.yul index 46df2a9cae..0c0135500d 100644 --- a/test/libyul/yulInterpreterTests/and_create2.yul +++ b/test/libyul/yulInterpreterTests/and_create2.yul @@ -8,8 +8,6 @@ // EVMVersion: >=constantinople // ---- // Trace: -// CREATE2(0, 0xffffffffffffffffffffffffffffffffffffffff, 0, 0) -// CREATE2(0, 0xffffffffffffffffffffffffffffffffffffffff, 0, 0) // Memory dump: // 0: 0000000000000000000000000000000000000000000000000000000000000001 // Storage dump: diff --git a/test/libyul/yulInterpreterTests/external_call_to_self.yul b/test/libyul/yulInterpreterTests/external_call_to_self.yul index ad2d2bb77f..711159a9fc 100644 --- a/test/libyul/yulInterpreterTests/external_call_to_self.yul +++ b/test/libyul/yulInterpreterTests/external_call_to_self.yul @@ -14,7 +14,6 @@ // ---- // Trace: // CALL(153, 0x11111111, 0, 64, 32, 256, 32) -// RETURN(0, 0) // Memory dump: // 40: 0000000000000000000000000000000000000000000000000000000000000042 // 100: 0000000000000000000000000000000000000000000000000000000000000042 diff --git a/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul b/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul index 45d3cc781c..65c28ed5e7 100644 --- a/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul +++ b/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul @@ -7,38 +7,6 @@ } // ---- // Trace: -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// LOG0(0, 0) -// Trace size limit reached. +// Interpreter execution step limit reached. // Memory dump: // Storage dump: diff --git a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul index 4e431a6b18..51e0602a3b 100644 --- a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul +++ b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul @@ -5,6 +5,5 @@ // EVMVersion: >=constantinople // ---- // Trace: -// CALL(0, 0, 0, 0, 0, 0, 0) // Memory dump: // Storage dump: diff --git a/test/libyul/yulInterpreterTests/zero_range.yul b/test/libyul/yulInterpreterTests/zero_range.yul index b39a10feb3..5e1042dfbc 100644 --- a/test/libyul/yulInterpreterTests/zero_range.yul +++ b/test/libyul/yulInterpreterTests/zero_range.yul @@ -5,6 +5,5 @@ } // ---- // Trace: -// CALLDATACOPY(32, 0, 0) // Memory dump: // Storage dump: diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 991b25e752..25b5a977df 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -351,9 +351,22 @@ void ProtoConverter::visit(BinaryOp const& _x) break; } m_output << "("; - visit(_x.left()); - m_output << ","; - visit(_x.right()); + if (op == BinaryOp::KECCAK) + { + m_output << "mod("; + visit(_x.left()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ","; + m_output << "mod("; + visit(_x.right()); + m_output << ", " << to_string(s_maxSize) << ")"; + } + else + { + visit(_x.left()); + m_output << ","; + visit(_x.right()); + } m_output << ")"; } @@ -623,7 +636,14 @@ void ProtoConverter::visit(UnaryOp const& _x) break; } m_output << "("; - visit(_x.operand()); + if (op == UnaryOp::MLOAD) + { + m_output << "mod("; + visit(_x.operand()); + m_output << ", " << to_string(s_maxMemory) << ")"; + } + else + visit(_x.operand()); m_output << ")"; } @@ -778,11 +798,15 @@ void ProtoConverter::visit(CopyFunc const& _x) break; } m_output << "("; + m_output << "mod("; visit(_x.target()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; visit(_x.source()); m_output << ", "; + m_output << "mod("; visit(_x.size()); + m_output << ", " << to_string(s_maxSize) << ")"; m_output << ")\n"; } @@ -792,32 +816,42 @@ void ProtoConverter::visit(ExtCodeCopy const& _x) m_output << "("; visit(_x.addr()); m_output << ", "; + m_output << "mod("; visit(_x.target()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; visit(_x.source()); m_output << ", "; + m_output << "mod("; visit(_x.size()); + m_output << ", " << to_string(s_maxSize) << ")"; m_output << ")\n"; } void ProtoConverter::visit(LogFunc const& _x) { + auto visitPosAndSize = [&](LogFunc const& _y) { + m_output << "mod("; + visit(_y.pos()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", "; + m_output << "mod("; + visit(_y.size()); + m_output << ", " << to_string(s_maxSize) << ")"; + }; + switch (_x.num_topics()) { case LogFunc::ZERO: m_output << "log0"; m_output << "("; - visit(_x.pos()); - m_output << ", "; - visit(_x.size()); + visitPosAndSize(_x); m_output << ")\n"; break; case LogFunc::ONE: m_output << "log1"; m_output << "("; - visit(_x.pos()); - m_output << ", "; - visit(_x.size()); + visitPosAndSize(_x); m_output << ", "; visit(_x.t1()); m_output << ")\n"; @@ -825,9 +859,7 @@ void ProtoConverter::visit(LogFunc const& _x) case LogFunc::TWO: m_output << "log2"; m_output << "("; - visit(_x.pos()); - m_output << ", "; - visit(_x.size()); + visitPosAndSize(_x); m_output << ", "; visit(_x.t1()); m_output << ", "; @@ -837,9 +869,7 @@ void ProtoConverter::visit(LogFunc const& _x) case LogFunc::THREE: m_output << "log3"; m_output << "("; - visit(_x.pos()); - m_output << ", "; - visit(_x.size()); + visitPosAndSize(_x); m_output << ", "; visit(_x.t1()); m_output << ", "; @@ -851,9 +881,7 @@ void ProtoConverter::visit(LogFunc const& _x) case LogFunc::FOUR: m_output << "log4"; m_output << "("; - visit(_x.pos()); - m_output << ", "; - visit(_x.size()); + visitPosAndSize(_x); m_output << ", "; visit(_x.t1()); m_output << ", "; @@ -1015,13 +1043,21 @@ void ProtoConverter::visit(LowLevelCall const& _x) visit(_x.wei()); m_output << ", "; } + m_output << "mod("; visit(_x.in()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; + m_output << "mod("; visit(_x.insize()); + m_output << ", " << to_string(s_maxSize) << ")"; m_output << ", "; + m_output << "mod("; visit(_x.out()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; + m_output << "mod("; visit(_x.outsize()); + m_output << ", " << to_string(s_maxSize) << ")"; m_output << ")"; } @@ -1048,9 +1084,13 @@ void ProtoConverter::visit(Create const& _x) } visit(_x.wei()); m_output << ", "; + m_output << "mod("; visit(_x.position()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; + m_output << "mod("; visit(_x.size()); + m_output << ", " << to_string(s_maxSize) << ")"; if (type == Create::CREATE2) { m_output << ", "; @@ -1069,7 +1109,8 @@ void ProtoConverter::visit(IfStmt const& _x) void ProtoConverter::visit(StoreFunc const& _x) { - switch (_x.st()) + auto storeType = _x.st(); + switch (storeType) { case StoreFunc::MSTORE: m_output << "mstore("; @@ -1081,7 +1122,15 @@ void ProtoConverter::visit(StoreFunc const& _x) m_output << "mstore8("; break; } - visit(_x.loc()); + // Write to memory within bounds, storage is unbounded + if (storeType == StoreFunc::SSTORE) + visit(_x.loc()); + else + { + m_output << "mod("; + visit(_x.loc()); + m_output << ", " << to_string(s_maxMemory) << ")"; + } m_output << ", "; visit(_x.val()); m_output << ")\n"; @@ -1262,9 +1311,13 @@ void ProtoConverter::visit(RetRevStmt const& _x) break; } m_output << "("; + m_output << "mod("; visit(_x.pos()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; + m_output << "mod("; visit(_x.size()); + m_output << ", " << to_string(s_maxSize) << ")"; m_output << ")\n"; } @@ -1651,8 +1704,12 @@ void ProtoConverter::fillFunctionCallInput(unsigned _numInParams) m_output << "calldataload(" << slot << ")"; break; case 1: + { + // Access memory within stipulated bounds + slot = "mod(" + dictionaryToken() + ", " + to_string(s_maxMemory) + ")"; m_output << "mload(" << slot << ")"; break; + } case 2: m_output << "sload(" << slot << ")"; break; diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index 9100b490ce..00559fa93a 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -344,6 +344,11 @@ class ProtoConverter static unsigned constexpr s_modOutputParams = 5; /// Hard-coded identifier for a Yul object's data block static auto constexpr s_dataIdentifier = "datablock"; + /// Upper bound on memory writes = 2**32 - 1 + /// See: https://eips.ethereum.org/EIPS/eip-1985#memory-size + static unsigned constexpr s_maxMemory = 4294967295; + /// Upper bound on size for range copy functions + static unsigned constexpr s_maxSize = 65536; /// Predicate to keep track of for body scope. If false, break/continue /// statements can not be created. bool m_inForBodyScope; diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index db0e648286..ed73a43813 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -211,22 +211,24 @@ u256 EVMInstructionInterpreter::eval( case Instruction::CALLDATASIZE: return m_state.calldata.size(); case Instruction::CALLDATACOPY: - logTrace(_instruction, arg); if (accessMemory(arg[0], arg[2])) copyZeroExtended( m_state.memory, m_state.calldata, size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) ); + if (arg[2] != 0) + logTrace(_instruction, arg); return 0; case Instruction::CODESIZE: return m_state.code.size(); case Instruction::CODECOPY: - logTrace(_instruction, arg); if (accessMemory(arg[0], arg[2])) copyZeroExtended( m_state.memory, m_state.code, size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) ); + if (arg[2] != 0) + logTrace(_instruction, arg); return 0; case Instruction::GASPRICE: return m_state.gasprice; @@ -239,23 +241,25 @@ u256 EVMInstructionInterpreter::eval( case Instruction::EXTCODEHASH: return u256(keccak256(h256(arg[0] + 1))); case Instruction::EXTCODECOPY: - logTrace(_instruction, arg); if (accessMemory(arg[1], arg[3])) // TODO this way extcodecopy and codecopy do the same thing. copyZeroExtended( m_state.memory, m_state.code, size_t(arg[1]), size_t(arg[2]), size_t(arg[3]) ); + if (arg[3] != 0) + logTrace(_instruction, arg); return 0; case Instruction::RETURNDATASIZE: return m_state.returndata.size(); case Instruction::RETURNDATACOPY: - logTrace(_instruction, arg); if (accessMemory(arg[0], arg[2])) copyZeroExtended( m_state.memory, m_state.returndata, size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) ); + if (arg[2] != 0) + logTrace(_instruction, arg); return 0; case Instruction::BLOCKHASH: if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber) @@ -297,38 +301,54 @@ u256 EVMInstructionInterpreter::eval( return 0x99; case Instruction::LOG0: accessMemory(arg[0], arg[1]); - logTrace(_instruction, arg); + if (arg[1] != 0) + logTrace(_instruction, arg); return 0; case Instruction::LOG1: accessMemory(arg[0], arg[1]); - logTrace(_instruction, arg); + if (arg[1] != 0) + logTrace(_instruction, arg); return 0; case Instruction::LOG2: accessMemory(arg[0], arg[1]); - logTrace(_instruction, arg); + if (arg[1] != 0) + logTrace(_instruction, arg); return 0; case Instruction::LOG3: accessMemory(arg[0], arg[1]); - logTrace(_instruction, arg); + if (arg[1] != 0) + logTrace(_instruction, arg); return 0; case Instruction::LOG4: accessMemory(arg[0], arg[1]); - logTrace(_instruction, arg); + if (arg[1] != 0) + logTrace(_instruction, arg); return 0; // --------------- calls --------------- case Instruction::CREATE: accessMemory(arg[1], arg[2]); - logTrace(_instruction, arg); - return (0xcccccc + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); + if (arg[2] != 0) + { + logTrace(_instruction, arg); + return (0xcccccc + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); + } + return 0xcccccc; case Instruction::CREATE2: accessMemory(arg[1], arg[2]); - logTrace(_instruction, arg); - return (0xdddddd + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); + if (arg[2] != 0) + { + logTrace(_instruction, arg); + return (0xdddddd + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); + } + return 0xdddddd; case Instruction::CALL: case Instruction::CALLCODE: - accessMemory(arg[3], arg[4]); - accessMemory(arg[5], arg[6]); - logTrace(_instruction, arg); + if (arg[4] != 0) + accessMemory(arg[3], arg[4]); + if (arg[6] != 0) + accessMemory(arg[5], arg[6]); + if (arg[4] != 0 && arg[6] != 0) + logTrace(_instruction, arg); // Randomly fail based on the called address if it isn't a call to self. // Used for fuzzing. return ( @@ -337,10 +357,12 @@ u256 EVMInstructionInterpreter::eval( ) ? 1 : 0; case Instruction::DELEGATECALL: case Instruction::STATICCALL: - accessMemory(arg[2], arg[3]); - accessMemory(arg[4], arg[5]); - logTrace(_instruction, arg); - + if (arg[3] != 0) + accessMemory(arg[2], arg[3]); + if (arg[5] != 0) + accessMemory(arg[4], arg[5]); + if (arg[3] != 0 && arg[5] != 0) + logTrace(_instruction, arg); // Randomly fail based on the called address if it isn't a call to self. // Used for fuzzing. return ( @@ -352,12 +374,14 @@ u256 EVMInstructionInterpreter::eval( m_state.returndata = {}; if (accessMemory(arg[0], arg[1])) m_state.returndata = m_state.readMemory(arg[0], arg[1]); - logTrace(_instruction, arg, m_state.returndata); + if (arg[1] != 0) + logTrace(_instruction, arg, m_state.returndata); BOOST_THROW_EXCEPTION(ExplicitlyTerminatedWithReturn()); } case Instruction::REVERT: accessMemory(arg[0], arg[1]); - logTrace(_instruction, arg); + if (arg[1] != 0) + logTrace(_instruction, arg); m_state.storage.clear(); m_state.trace.clear(); BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); @@ -479,7 +503,10 @@ u256 EVMInstructionInterpreter::evalBuiltin( else if (fun == "datacopy") { // This is identical to codecopy. - if (accessMemory(_evaluatedArguments.at(0), _evaluatedArguments.at(2))) + if ( + _evaluatedArguments.at(2) != 0 && + accessMemory(_evaluatedArguments.at(0), _evaluatedArguments.at(2)) + ) copyZeroExtended( m_state.memory, m_state.code, @@ -560,8 +587,13 @@ void EVMInstructionInterpreter::logTrace( if (!(_writesToMemory && memWriteTracingDisabled())) { string message = _pseudoInstruction + "("; + std::pair inputMemoryPtrModified = isInputMemoryPtrModified(_pseudoInstruction, _arguments); for (size_t i = 0; i < _arguments.size(); ++i) - message += (i > 0 ? ", " : "") + formatNumber(_arguments[i]); + { + bool printZero = inputMemoryPtrModified.first && inputMemoryPtrModified.second == i; + u256 arg = printZero ? 0 : _arguments[i]; + message += (i > 0 ? ", " : "") + formatNumber(arg); + } message += ")"; if (!_data.empty()) message += " [" + util::toHex(_data) + "]"; @@ -573,3 +605,65 @@ void EVMInstructionInterpreter::logTrace( } } } + +std::pair EVMInstructionInterpreter::isInputMemoryPtrModified( + std::string const& _pseudoInstruction, + std::vector const& _arguments +) +{ + if (_pseudoInstruction == "return" || _pseudoInstruction == "revert") + { + if (_arguments[1] == 0) + return {true, 0}; + else + return {false, 0}; + } + else if ( + _pseudoInstruction == "returndatacopy" || _pseudoInstruction == "calldatacopy" + || _pseudoInstruction == "codecopy") + { + if (_arguments[2] == 0) + return {true, 0}; + else + return {false, 0}; + } + else if (_pseudoInstruction == "extcodedatacopy") + { + if (_arguments[3] == 0) + return {true, 1}; + else + return {false, 0}; + } + else if ( + _pseudoInstruction == "log0" || _pseudoInstruction == "log1" || _pseudoInstruction == "log2" + || _pseudoInstruction == "log3" || _pseudoInstruction == "log4") + { + if (_arguments[1] == 0) + return {true, 0}; + else + return {false, 0}; + } + if (_pseudoInstruction == "create" || _pseudoInstruction == "create2") + { + if (_arguments[2] == 0) + return {true, 1}; + else + return {false, 0}; + } + if (_pseudoInstruction == "call" || _pseudoInstruction == "callcode") + { + if (_arguments[4] == 0) + return {true, 3}; + else + return {false, 0}; + } + else if (_pseudoInstruction == "delegatecall" || _pseudoInstruction == "staticcall") + { + if (_arguments[3] == 0) + return {true, 2}; + else + return {false, 0}; + } + else + return {false, 0}; +} diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.h b/test/tools/yulInterpreter/EVMInstructionInterpreter.h index 9f0f473f14..d37cae542f 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.h +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.h @@ -125,6 +125,19 @@ class EVMInstructionInterpreter std::vector const& _arguments = {}, bytes const& _data = {} ); + + /// @returns a pair of boolean and size_t whose first value is true if @param _pseudoInstruction + /// is a Yul instruction that the Yul optimizer's loadResolver step rewrites the input + /// memory pointer value to zero if that instruction's read length (contained within @param + // _arguments) is zero, and whose second value is the positional index of the input memory + // pointer argument. + /// If the Yul instruction is unaffected or affected but read length is non-zero, the first + /// value is false. + std::pair isInputMemoryPtrModified( + std::string const& _pseudoInstruction, + std::vector const& _arguments + ); + /// @returns disable trace flag. bool memWriteTracingDisabled() { From bc00063b2ecdfb37afadc6231f511e4836fcfa0d Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Wed, 1 Feb 2023 10:25:39 +0100 Subject: [PATCH 0068/1140] Do not print suppressions statistics for cli tests --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 81b757a66e..0f5d0da8f8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1096,7 +1096,7 @@ jobs: ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. # See: https://github.com/ethereum/solidity/issues/13891 for details. - LSAN_OPTIONS: suppressions=.circleci/cln-asan.supp + LSAN_OPTIONS: suppressions=.circleci/cln-asan.supp:print_suppressions=0 <<: *steps_cmdline_tests t_ubu_asan_soltest: From 7ddb5e0c6621eaf61ceaef593471753db808e1be Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Thu, 2 Feb 2023 09:48:43 +0100 Subject: [PATCH 0069/1140] Change relative to absolute path for LSAN_OPTIONS --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0f5d0da8f8..8a2361492c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1096,7 +1096,7 @@ jobs: ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. # See: https://github.com/ethereum/solidity/issues/13891 for details. - LSAN_OPTIONS: suppressions=.circleci/cln-asan.supp:print_suppressions=0 + LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0 <<: *steps_cmdline_tests t_ubu_asan_soltest: @@ -1109,7 +1109,7 @@ jobs: ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. # See: https://github.com/ethereum/solidity/issues/13891 for details. - LSAN_OPTIONS: suppressions=.circleci/cln-asan.supp + LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp <<: *steps_soltest t_ubu_asan_clang_soltest: From 5c6e12b2c020d1b8b2981a8a81ae670a990d14b8 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 1 Feb 2023 08:28:05 +0100 Subject: [PATCH 0070/1140] Update existing and add new test cases. --- .../libyul/yulInterpreterTests/and_create.yul | 2 + .../yulInterpreterTests/and_create2.yul | 2 + .../external_call_to_self.yul | 1 + .../infinite_recursion_tracelimit.yul | 34 +++++++- .../yulInterpreterTests/pop_byte_shr_call.yul | 1 + .../yulInterpreterTests/zero_length_reads.yul | 40 +++++++++ .../zero_length_reads_and_revert.yul | 40 +++++++++ .../libyul/yulInterpreterTests/zero_range.yul | 1 + .../loadResolver/zero_length_reads.yul | 45 ++++++++++ .../EVMInstructionInterpreter.cpp | 84 +++++++------------ 10 files changed, 197 insertions(+), 53 deletions(-) create mode 100644 test/libyul/yulInterpreterTests/zero_length_reads.yul create mode 100644 test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul diff --git a/test/libyul/yulInterpreterTests/and_create.yul b/test/libyul/yulInterpreterTests/and_create.yul index cbc68ca623..cf32c4658e 100644 --- a/test/libyul/yulInterpreterTests/and_create.yul +++ b/test/libyul/yulInterpreterTests/and_create.yul @@ -6,6 +6,8 @@ } // ---- // Trace: +// CREATE(0, 0, 0) +// CREATE(0, 0, 0) // Memory dump: // 0: 0000000000000000000000000000000000000000000000000000000000000001 // Storage dump: diff --git a/test/libyul/yulInterpreterTests/and_create2.yul b/test/libyul/yulInterpreterTests/and_create2.yul index 0c0135500d..5201b0188a 100644 --- a/test/libyul/yulInterpreterTests/and_create2.yul +++ b/test/libyul/yulInterpreterTests/and_create2.yul @@ -8,6 +8,8 @@ // EVMVersion: >=constantinople // ---- // Trace: +// CREATE2(0, 0, 0, 0) +// CREATE2(0, 0, 0, 0) // Memory dump: // 0: 0000000000000000000000000000000000000000000000000000000000000001 // Storage dump: diff --git a/test/libyul/yulInterpreterTests/external_call_to_self.yul b/test/libyul/yulInterpreterTests/external_call_to_self.yul index 711159a9fc..ad2d2bb77f 100644 --- a/test/libyul/yulInterpreterTests/external_call_to_self.yul +++ b/test/libyul/yulInterpreterTests/external_call_to_self.yul @@ -14,6 +14,7 @@ // ---- // Trace: // CALL(153, 0x11111111, 0, 64, 32, 256, 32) +// RETURN(0, 0) // Memory dump: // 40: 0000000000000000000000000000000000000000000000000000000000000042 // 100: 0000000000000000000000000000000000000000000000000000000000000042 diff --git a/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul b/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul index 65c28ed5e7..45d3cc781c 100644 --- a/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul +++ b/test/libyul/yulInterpreterTests/infinite_recursion_tracelimit.yul @@ -7,6 +7,38 @@ } // ---- // Trace: -// Interpreter execution step limit reached. +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// LOG0(0, 0) +// Trace size limit reached. // Memory dump: // Storage dump: diff --git a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul index 51e0602a3b..4e431a6b18 100644 --- a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul +++ b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul @@ -5,5 +5,6 @@ // EVMVersion: >=constantinople // ---- // Trace: +// CALL(0, 0, 0, 0, 0, 0, 0) // Memory dump: // Storage dump: diff --git a/test/libyul/yulInterpreterTests/zero_length_reads.yul b/test/libyul/yulInterpreterTests/zero_length_reads.yul new file mode 100644 index 0000000000..6c1f38d1e9 --- /dev/null +++ b/test/libyul/yulInterpreterTests/zero_length_reads.yul @@ -0,0 +1,40 @@ +{ + returndatacopy(1, 1, 0) + calldatacopy(1, 1, 0) + extcodecopy(1, 1, 1, 0) + codecopy(1, 1, 0) + log0(1, 0) + log1(1, 0, 1) + log2(1, 0, 1, 1) + log3(1, 0, 1, 1, 1) + log4(1, 0, 1, 1, 1, 1) + pop(create(1, 1, 0)) + pop(create2(1, 1, 0, 1)) + pop(call(1, 1, 1, 1, 0, 1, 0)) + pop(callcode(1, 1, 1, 1, 0, 1, 0)) + pop(delegatecall(1, 1, 1, 0, 1, 0)) + pop(staticcall(1, 1, 1, 0, 1, 0)) + return(1, 0) +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Trace: +// RETURNDATACOPY(0, 1, 0) +// CALLDATACOPY(0, 1, 0) +// EXTCODECOPY(1, 0, 1, 0) +// CODECOPY(0, 1, 0) +// LOG0(0, 0) +// LOG1(0, 0, 1) +// LOG2(0, 0, 1, 1) +// LOG3(0, 0, 1, 1, 1) +// LOG4(0, 0, 1, 1, 1, 1) +// CREATE(1, 0, 0) +// CREATE2(1, 0, 0, 1) +// CALL(1, 1, 1, 0, 0, 1, 0) +// CALLCODE(1, 1, 1, 0, 0, 1, 0) +// DELEGATECALL(1, 1, 0, 0, 1, 0) +// STATICCALL(1, 1, 0, 0, 1, 0) +// RETURN(0, 0) +// Memory dump: +// Storage dump: diff --git a/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul b/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul new file mode 100644 index 0000000000..4be49eeb09 --- /dev/null +++ b/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul @@ -0,0 +1,40 @@ +{ + returndatacopy(1, 1, 0) + calldatacopy(1, 1, 0) + extcodecopy(1, 1, 1, 0) + codecopy(1, 1, 0) + log0(1, 0) + log1(1, 0, 1) + log2(1, 0, 1, 1) + log3(1, 0, 1, 1, 1) + log4(1, 0, 1, 1, 1, 1) + pop(create(1, 1, 0)) + pop(create2(1, 1, 0, 1)) + pop(call(1, 1, 1, 1, 0, 1, 0)) + pop(callcode(1, 1, 1, 1, 0, 1, 0)) + pop(delegatecall(1, 1, 1, 0, 1, 0)) + pop(staticcall(1, 1, 1, 0, 1, 0)) + revert(1, 0) +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Trace: +// RETURNDATACOPY(0, 1, 0) +// CALLDATACOPY(0, 1, 0) +// EXTCODECOPY(1, 0, 1, 0) +// CODECOPY(0, 1, 0) +// LOG0(0, 0) +// LOG1(0, 0, 1) +// LOG2(0, 0, 1, 1) +// LOG3(0, 0, 1, 1, 1) +// LOG4(0, 0, 1, 1, 1, 1) +// CREATE(1, 0, 0) +// CREATE2(1, 0, 0, 1) +// CALL(1, 1, 1, 0, 0, 1, 0) +// CALLCODE(1, 1, 1, 0, 0, 1, 0) +// DELEGATECALL(1, 1, 0, 0, 1, 0) +// STATICCALL(1, 1, 0, 0, 1, 0) +// REVERT(0, 0) +// Memory dump: +// Storage dump: diff --git a/test/libyul/yulInterpreterTests/zero_range.yul b/test/libyul/yulInterpreterTests/zero_range.yul index 5e1042dfbc..1ad25ed37b 100644 --- a/test/libyul/yulInterpreterTests/zero_range.yul +++ b/test/libyul/yulInterpreterTests/zero_range.yul @@ -5,5 +5,6 @@ } // ---- // Trace: +// CALLDATACOPY(0, 0, 0) // Memory dump: // Storage dump: diff --git a/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul new file mode 100644 index 0000000000..418221a938 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul @@ -0,0 +1,45 @@ +{ + returndatacopy(1, 1, 0) + calldatacopy(1, 1, 0) + extcodecopy(1, 1, 1, 0) + codecopy(1, 1, 0) + log0(1, 0) + log1(1, 0, 1) + log2(1, 0, 1, 1) + log3(1, 0, 1, 1, 1) + log4(1, 0, 1, 1, 1, 1) + pop(create(1, 1, 0)) + pop(create2(1, 1, 0, 1)) + pop(call(1, 1, 1, 1, 0, 1, 0)) + pop(callcode(1, 1, 1, 1, 0, 1, 0)) + pop(delegatecall(1, 1, 1, 0, 1, 0)) + pop(staticcall(1, 1, 1, 0, 1, 0)) + return(1, 0) +} +// ==== +// EVMVersion: >=constantinople +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 0 +// let _2 := 1 +// returndatacopy(0, _2, _1) +// calldatacopy(0, _2, _1) +// extcodecopy(_2, 0, _2, _1) +// codecopy(0, _2, _1) +// log0(0, _1) +// log1(0, _1, _2) +// log2(0, _1, _2, _2) +// log3(0, _1, _2, _2, _2) +// log4(0, _1, _2, _2, _2, _2) +// pop(create(_2, 0, _1)) +// pop(create2(_2, 0, _1, _2)) +// pop(call(_2, _2, _2, 0, _1, _2, _1)) +// pop(callcode(_2, _2, _2, 0, _1, _2, _1)) +// pop(delegatecall(_2, _2, 0, _1, _2, _1)) +// pop(staticcall(_2, _2, 0, _1, _2, _1)) +// return(0, _1) +// } +// } diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index ed73a43813..b049ee6c4f 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -216,8 +216,7 @@ u256 EVMInstructionInterpreter::eval( m_state.memory, m_state.calldata, size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) ); - if (arg[2] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::CODESIZE: return m_state.code.size(); @@ -227,8 +226,7 @@ u256 EVMInstructionInterpreter::eval( m_state.memory, m_state.code, size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) ); - if (arg[2] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::GASPRICE: return m_state.gasprice; @@ -247,8 +245,7 @@ u256 EVMInstructionInterpreter::eval( m_state.memory, m_state.code, size_t(arg[1]), size_t(arg[2]), size_t(arg[3]) ); - if (arg[3] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::RETURNDATASIZE: return m_state.returndata.size(); @@ -258,8 +255,7 @@ u256 EVMInstructionInterpreter::eval( m_state.memory, m_state.returndata, size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) ); - if (arg[2] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::BLOCKHASH: if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber) @@ -301,54 +297,44 @@ u256 EVMInstructionInterpreter::eval( return 0x99; case Instruction::LOG0: accessMemory(arg[0], arg[1]); - if (arg[1] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::LOG1: accessMemory(arg[0], arg[1]); - if (arg[1] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::LOG2: accessMemory(arg[0], arg[1]); - if (arg[1] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::LOG3: accessMemory(arg[0], arg[1]); - if (arg[1] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; case Instruction::LOG4: accessMemory(arg[0], arg[1]); - if (arg[1] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); return 0; // --------------- calls --------------- case Instruction::CREATE: accessMemory(arg[1], arg[2]); + logTrace(_instruction, arg); if (arg[2] != 0) - { - logTrace(_instruction, arg); return (0xcccccc + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); - } - return 0xcccccc; + else + return 0xcccccc; case Instruction::CREATE2: accessMemory(arg[1], arg[2]); + logTrace(_instruction, arg); if (arg[2] != 0) - { - logTrace(_instruction, arg); return (0xdddddd + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); - } - return 0xdddddd; + else + return 0xdddddd; case Instruction::CALL: case Instruction::CALLCODE: - if (arg[4] != 0) - accessMemory(arg[3], arg[4]); - if (arg[6] != 0) - accessMemory(arg[5], arg[6]); - if (arg[4] != 0 && arg[6] != 0) - logTrace(_instruction, arg); + accessMemory(arg[3], arg[4]); + accessMemory(arg[5], arg[6]); + logTrace(_instruction, arg); // Randomly fail based on the called address if it isn't a call to self. // Used for fuzzing. return ( @@ -357,12 +343,9 @@ u256 EVMInstructionInterpreter::eval( ) ? 1 : 0; case Instruction::DELEGATECALL: case Instruction::STATICCALL: - if (arg[3] != 0) - accessMemory(arg[2], arg[3]); - if (arg[5] != 0) - accessMemory(arg[4], arg[5]); - if (arg[3] != 0 && arg[5] != 0) - logTrace(_instruction, arg); + accessMemory(arg[2], arg[3]); + accessMemory(arg[4], arg[5]); + logTrace(_instruction, arg); // Randomly fail based on the called address if it isn't a call to self. // Used for fuzzing. return ( @@ -374,16 +357,13 @@ u256 EVMInstructionInterpreter::eval( m_state.returndata = {}; if (accessMemory(arg[0], arg[1])) m_state.returndata = m_state.readMemory(arg[0], arg[1]); - if (arg[1] != 0) - logTrace(_instruction, arg, m_state.returndata); + logTrace(_instruction, arg, m_state.returndata); BOOST_THROW_EXCEPTION(ExplicitlyTerminatedWithReturn()); } case Instruction::REVERT: accessMemory(arg[0], arg[1]); - if (arg[1] != 0) - logTrace(_instruction, arg); + logTrace(_instruction, arg); m_state.storage.clear(); - m_state.trace.clear(); BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); case Instruction::INVALID: logTrace(_instruction); @@ -611,7 +591,7 @@ std::pair EVMInstructionInterpreter::isInputMemoryPtrModified( std::vector const& _arguments ) { - if (_pseudoInstruction == "return" || _pseudoInstruction == "revert") + if (_pseudoInstruction == "RETURN" || _pseudoInstruction == "REVERT") { if (_arguments[1] == 0) return {true, 0}; @@ -619,15 +599,15 @@ std::pair EVMInstructionInterpreter::isInputMemoryPtrModified( return {false, 0}; } else if ( - _pseudoInstruction == "returndatacopy" || _pseudoInstruction == "calldatacopy" - || _pseudoInstruction == "codecopy") + _pseudoInstruction == "RETURNDATACOPY" || _pseudoInstruction == "CALLDATACOPY" + || _pseudoInstruction == "CODECOPY") { if (_arguments[2] == 0) return {true, 0}; else return {false, 0}; } - else if (_pseudoInstruction == "extcodedatacopy") + else if (_pseudoInstruction == "EXTCODECOPY") { if (_arguments[3] == 0) return {true, 1}; @@ -635,29 +615,29 @@ std::pair EVMInstructionInterpreter::isInputMemoryPtrModified( return {false, 0}; } else if ( - _pseudoInstruction == "log0" || _pseudoInstruction == "log1" || _pseudoInstruction == "log2" - || _pseudoInstruction == "log3" || _pseudoInstruction == "log4") + _pseudoInstruction == "LOG0" || _pseudoInstruction == "LOG1" || _pseudoInstruction == "LOG2" + || _pseudoInstruction == "LOG3" || _pseudoInstruction == "LOG4") { if (_arguments[1] == 0) return {true, 0}; else return {false, 0}; } - if (_pseudoInstruction == "create" || _pseudoInstruction == "create2") + if (_pseudoInstruction == "CREATE" || _pseudoInstruction == "CREATE2") { if (_arguments[2] == 0) return {true, 1}; else return {false, 0}; } - if (_pseudoInstruction == "call" || _pseudoInstruction == "callcode") + if (_pseudoInstruction == "CALL" || _pseudoInstruction == "CALLCODE") { if (_arguments[4] == 0) return {true, 3}; else return {false, 0}; } - else if (_pseudoInstruction == "delegatecall" || _pseudoInstruction == "staticcall") + else if (_pseudoInstruction == "DELEGATECALL" || _pseudoInstruction == "STATICCALL") { if (_arguments[3] == 0) return {true, 2}; From 2b70b08d5f637f2252e84c26d2fbda96385aaf7e Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sun, 8 Jan 2023 23:14:17 -0300 Subject: [PATCH 0071/1140] Allow library external functions to be bound with using for --- Changelog.md | 1 + libsolidity/analysis/NameAndTypeResolver.cpp | 15 ++++++--- libsolidity/analysis/NameAndTypeResolver.h | 2 +- libsolidity/analysis/ReferencesResolver.cpp | 33 +++++++++++++++++++ libsolidity/analysis/ReferencesResolver.h | 1 + libsolidity/analysis/TypeChecker.cpp | 20 ++++++++--- .../library_functions_inside_contract.sol | 31 +++++++++++++++++ ...external_library_function_inside_scope.sol | 9 +++++ .../external_function_qualified_with_this.sol | 7 ++++ .../using/free_functions_non_unique_err.sol | 2 +- .../syntaxTests/using/free_overloads.sol | 2 +- .../using/free_overloads_array.sol | 2 +- ...rom_base_contract_qualified_with_super.sol | 9 +++++ ..._name_without_braces_at_file_level_err.sol | 11 +++++++ ...ame_without_braces_inside_contract_err.sol | 10 ++++++ .../interface_function_at_file_level.sol | 7 ++++ .../interface_function_inside_contract.sol | 9 +++++ .../using/library_at_file_level.sol | 17 ++++++++++ .../using/library_functions_at_file_level.sol | 19 +++++++++++ ...ched_at_file_level_used_inside_library.sol | 17 ++++++++++ ...ched_in_single_directive_at_file_level.sol | 17 ++++++++++ ...ed_in_single_directive_inside_contract.sol | 17 ++++++++++ .../library_functions_inside_contract.sol | 19 +++++++++++ .../using/library_inside_contract.sol | 17 ++++++++++ ...library_non_free_external_function_err.sol | 2 +- .../using/module_identifier_not_found.sol | 2 +- .../using/public_state_variable_getter.sol | 11 +++++++ .../syntaxTests/using/undeclared_library.sol | 3 ++ ...hed_in_single_directive_inside_library.sol | 19 +++++++++++ 29 files changed, 316 insertions(+), 15 deletions(-) create mode 100644 test/libsolidity/semanticTests/using/library_functions_inside_contract.sol create mode 100644 test/libsolidity/syntaxTests/scoping/external_library_function_inside_scope.sol create mode 100644 test/libsolidity/syntaxTests/using/external_function_qualified_with_this.sol create mode 100644 test/libsolidity/syntaxTests/using/function_from_base_contract_qualified_with_super.sol create mode 100644 test/libsolidity/syntaxTests/using/function_name_without_braces_at_file_level_err.sol create mode 100644 test/libsolidity/syntaxTests/using/function_name_without_braces_inside_contract_err.sol create mode 100644 test/libsolidity/syntaxTests/using/interface_function_at_file_level.sol create mode 100644 test/libsolidity/syntaxTests/using/interface_function_inside_contract.sol create mode 100644 test/libsolidity/syntaxTests/using/library_at_file_level.sol create mode 100644 test/libsolidity/syntaxTests/using/library_functions_at_file_level.sol create mode 100644 test/libsolidity/syntaxTests/using/library_functions_attached_at_file_level_used_inside_library.sol create mode 100644 test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_at_file_level.sol create mode 100644 test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_inside_contract.sol create mode 100644 test/libsolidity/syntaxTests/using/library_functions_inside_contract.sol create mode 100644 test/libsolidity/syntaxTests/using/library_inside_contract.sol create mode 100644 test/libsolidity/syntaxTests/using/public_state_variable_getter.sol create mode 100644 test/libsolidity/syntaxTests/using/undeclared_library.sol create mode 100644 test/libsolidity/syntaxTests/using/unqualified_library_functions_attached_in_single_directive_inside_library.sol diff --git a/Changelog.md b/Changelog.md index 8a3bfae6a8..7619fbd40d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: + * TypeChecker: Also allow external library functions in ``using for``. ### 0.8.18 (2023-02-01) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 1b58d3c9ab..641f022804 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -195,16 +195,23 @@ Declaration const* NameAndTypeResolver::pathFromCurrentScope(vector c return nullptr; } -std::vector NameAndTypeResolver::pathFromCurrentScopeWithAllDeclarations(std::vector const& _path) const +std::vector NameAndTypeResolver::pathFromCurrentScopeWithAllDeclarations( + std::vector const& _path, + bool _includeInvisibles +) const { solAssert(!_path.empty(), ""); vector pathDeclarations; ResolvingSettings settings; settings.recursive = true; - settings.alsoInvisible = false; + settings.alsoInvisible = _includeInvisibles; settings.onlyVisibleAsUnqualifiedNames = true; - vector candidates = m_currentScope->resolveName(_path.front(), std::move(settings)); + vector candidates = m_currentScope->resolveName(_path.front(), settings); + + // inside the loop, use default settings, except for alsoInvisible + settings.recursive = false; + settings.onlyVisibleAsUnqualifiedNames = false; for (size_t i = 1; i < _path.size() && candidates.size() == 1; i++) { @@ -213,7 +220,7 @@ std::vector NameAndTypeResolver::pathFromCurrentScopeWithAll pathDeclarations.push_back(candidates.front()); - candidates = m_scopes.at(candidates.front())->resolveName(_path[i]); + candidates = m_scopes.at(candidates.front())->resolveName(_path[i], settings); } if (candidates.size() == 1) { diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index 2bf238a00e..6ba591e8ad 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -96,7 +96,7 @@ class NameAndTypeResolver /// Resolves a path starting from the "current" scope, but also searches parent scopes. /// Should only be called during the initial resolving phase. /// @note Returns an empty vector if any component in the path was non-unique or not found. Otherwise, all declarations along the path are returned. - std::vector pathFromCurrentScopeWithAllDeclarations(std::vector const& _path) const; + std::vector pathFromCurrentScopeWithAllDeclarations(std::vector const& _path, bool _includeInvisibles = false) const; /// Generate and store warnings about declarations with the same name. void warnHomonymDeclarations() const; diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 50b1656ef8..399c15b56e 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -173,6 +173,7 @@ void ReferencesResolver::endVisit(ModifierDefinition const&) void ReferencesResolver::endVisit(IdentifierPath const& _path) { + // Note that library/functions names in "using {} for" directive are resolved separately in visit(UsingForDirective) std::vector declarations = m_resolver.pathFromCurrentScopeWithAllDeclarations(_path.path()); if (declarations.empty()) { @@ -184,6 +185,38 @@ void ReferencesResolver::endVisit(IdentifierPath const& _path) _path.annotation().pathDeclarations = std::move(declarations); } +bool ReferencesResolver::visit(UsingForDirective const& _usingFor) +{ + for (ASTPointer const& path: _usingFor.functionsOrLibrary()) + { + // _includeInvisibles is enabled here because external library functions are marked invisible. + // As unintended side-effects other invisible names (eg.: super, this) may be returned as well. + // DeclarationTypeChecker should detect and report such situations. + vector declarations = m_resolver.pathFromCurrentScopeWithAllDeclarations(path->path(), true /* _includeInvisibles */); + if (declarations.empty()) + { + string libraryOrFunctionNameErrorMessage = + _usingFor.usesBraces() ? + "Identifier is not a function name or not unique." : + "Identifier is not a library name."; + m_errorReporter.fatalDeclarationError( + 9589_error, + path->location(), + libraryOrFunctionNameErrorMessage + ); + break; + } + + path->annotation().referencedDeclaration = declarations.back(); + path->annotation().pathDeclarations = std::move(declarations); + } + + if (_usingFor.typeName()) + _usingFor.typeName()->accept(*this); + + return false; +} + bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) { m_yulAnnotation = &_inlineAssembly.annotation(); diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 530100a245..512a681b45 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -84,6 +84,7 @@ class ReferencesResolver: private ASTConstVisitor, private yul::ASTWalker void endVisit(IdentifierPath const& _path) override; bool visit(InlineAssembly const& _inlineAssembly) override; bool visit(Return const& _return) override; + bool visit(UsingForDirective const& _usingFor) override; void operator()(yul::FunctionDefinition const& _function) override; void operator()(yul::Identifier const& _identifier) override; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4e390931fc..074b644b77 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3826,7 +3826,13 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) FunctionDefinition const& functionDefinition = dynamic_cast(*path->annotation().referencedDeclaration); - solAssert(functionDefinition.type()); + FunctionType const* functionType = dynamic_cast( + functionDefinition.libraryFunction() ? + functionDefinition.typeViaContractName() : + functionDefinition.type() + ); + + solAssert(functionType); if (functionDefinition.parameters().empty()) m_errorReporter.fatalTypeError( @@ -3864,21 +3870,25 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) ); } - FunctionType const* functionType = dynamic_cast(*functionDefinition.type()).withBoundFirstArgument(); - solAssert(functionType && functionType->selfType(), ""); + FunctionType const* functionTypeWithBoundFirstArgument = functionType->withBoundFirstArgument(); + solAssert(functionTypeWithBoundFirstArgument && functionTypeWithBoundFirstArgument->selfType(), ""); BoolResult result = normalizedType->isImplicitlyConvertibleTo( - *TypeProvider::withLocationIfReference(DataLocation::Storage, functionType->selfType()) + *TypeProvider::withLocationIfReference(DataLocation::Storage, functionTypeWithBoundFirstArgument->selfType()) ); if (!result) m_errorReporter.typeError( 3100_error, path->location(), + SecondarySourceLocation().append( + "Function defined here:", + functionDefinition.location() + ), fmt::format( "The function \"{}\" cannot be attached to the type \"{}\" because the type cannot " "be implicitly converted to the first argument of the function (\"{}\"){}", joinHumanReadable(path->path(), "."), usingForType->toString(true /* withoutDataLocation */), - functionType->selfType()->humanReadableName(), + functionTypeWithBoundFirstArgument->selfType()->humanReadableName(), result.message().empty() ? "." : ": " + result.message() ) ); diff --git a/test/libsolidity/semanticTests/using/library_functions_inside_contract.sol b/test/libsolidity/semanticTests/using/library_functions_inside_contract.sol new file mode 100644 index 0000000000..170bc78536 --- /dev/null +++ b/test/libsolidity/semanticTests/using/library_functions_inside_contract.sol @@ -0,0 +1,31 @@ +library L { + function externalFunction(uint a) external pure returns (uint) { return a * 1; } + function publicFunction(uint b) public pure returns (uint) { return b * 2; } + function internalFunction(uint c) internal pure returns (uint) { return c * 3; } +} + +contract C { + using {L.externalFunction} for uint; + using {L.publicFunction} for uint; + using {L.internalFunction} for uint; + + function f() public pure returns (uint) { + uint x = 1; + return x.externalFunction(); + } + + function g() public pure returns (uint) { + uint x = 1; + return x.publicFunction(); + } + + function h() public pure returns (uint) { + uint x = 1; + return x.internalFunction(); + } +} +// ---- +// library: L +// f() -> 1 +// g() -> 2 +// h() -> 3 diff --git a/test/libsolidity/syntaxTests/scoping/external_library_function_inside_scope.sol b/test/libsolidity/syntaxTests/scoping/external_library_function_inside_scope.sol new file mode 100644 index 0000000000..647e5b416e --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/external_library_function_inside_scope.sol @@ -0,0 +1,9 @@ +library L { + function externalFunction(uint) external pure {} + function f() public pure { + uint x; + externalFunction(x); + } +} +// ---- +// DeclarationError 7576: (120-136): Undeclared identifier. "externalFunction" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/using/external_function_qualified_with_this.sol b/test/libsolidity/syntaxTests/using/external_function_qualified_with_this.sol new file mode 100644 index 0000000000..2f4007605b --- /dev/null +++ b/test/libsolidity/syntaxTests/using/external_function_qualified_with_this.sol @@ -0,0 +1,7 @@ +contract C { + using {this.contractFunction} for uint; + + function contractFunction(uint) external view {} +} +// ---- +// DeclarationError 9589: (24-45): Identifier is not a function name or not unique. diff --git a/test/libsolidity/syntaxTests/using/free_functions_non_unique_err.sol b/test/libsolidity/syntaxTests/using/free_functions_non_unique_err.sol index 7536dff07f..7404b0d9be 100644 --- a/test/libsolidity/syntaxTests/using/free_functions_non_unique_err.sol +++ b/test/libsolidity/syntaxTests/using/free_functions_non_unique_err.sol @@ -9,4 +9,4 @@ contract C { using {id} for uint256; } // ---- -// DeclarationError 7920: (145-147): Identifier not found or not unique. +// DeclarationError 9589: (145-147): Identifier is not a function name or not unique. diff --git a/test/libsolidity/syntaxTests/using/free_overloads.sol b/test/libsolidity/syntaxTests/using/free_overloads.sol index 28a8e69ed1..e05580d5fb 100644 --- a/test/libsolidity/syntaxTests/using/free_overloads.sol +++ b/test/libsolidity/syntaxTests/using/free_overloads.sol @@ -7,4 +7,4 @@ function f(int8 storage x) pure returns (int) { using {f} for uint8; using {f} for int; // ---- -// DeclarationError 7920: (132-133): Identifier not found or not unique. +// DeclarationError 9589: (132-133): Identifier is not a function name or not unique. diff --git a/test/libsolidity/syntaxTests/using/free_overloads_array.sol b/test/libsolidity/syntaxTests/using/free_overloads_array.sol index 91b8073971..cab3eccf24 100644 --- a/test/libsolidity/syntaxTests/using/free_overloads_array.sol +++ b/test/libsolidity/syntaxTests/using/free_overloads_array.sol @@ -6,4 +6,4 @@ function f(uint x, uint y) pure returns (int) { } using {f} for uint; // ---- -// DeclarationError 7920: (138-139): Identifier not found or not unique. +// DeclarationError 9589: (138-139): Identifier is not a function name or not unique. diff --git a/test/libsolidity/syntaxTests/using/function_from_base_contract_qualified_with_super.sol b/test/libsolidity/syntaxTests/using/function_from_base_contract_qualified_with_super.sol new file mode 100644 index 0000000000..a162912cad --- /dev/null +++ b/test/libsolidity/syntaxTests/using/function_from_base_contract_qualified_with_super.sol @@ -0,0 +1,9 @@ +contract C { + function baseFunction(uint) public pure {} +} + +contract D is C { + using {super.baseFunction} for uint; +} +// ---- +// DeclarationError 9589: (92-110): Identifier is not a function name or not unique. diff --git a/test/libsolidity/syntaxTests/using/function_name_without_braces_at_file_level_err.sol b/test/libsolidity/syntaxTests/using/function_name_without_braces_at_file_level_err.sol new file mode 100644 index 0000000000..85d591fd47 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/function_name_without_braces_at_file_level_err.sol @@ -0,0 +1,11 @@ +function f(uint x) pure { } + +using f for uint; + +contract C { + function g(uint x) public pure { + x.f(); + } +} +// ---- +// TypeError 4357: (35-36): Library name expected. If you want to attach a function, use '{...}'. diff --git a/test/libsolidity/syntaxTests/using/function_name_without_braces_inside_contract_err.sol b/test/libsolidity/syntaxTests/using/function_name_without_braces_inside_contract_err.sol new file mode 100644 index 0000000000..0031373817 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/function_name_without_braces_inside_contract_err.sol @@ -0,0 +1,10 @@ +function f(uint x) pure { } + +contract C { + using f for uint; + function g(uint x) public pure { + x.f(); + } +} +// ---- +// TypeError 4357: (52-53): Library name expected. If you want to attach a function, use '{...}'. diff --git a/test/libsolidity/syntaxTests/using/interface_function_at_file_level.sol b/test/libsolidity/syntaxTests/using/interface_function_at_file_level.sol new file mode 100644 index 0000000000..9a9ee26f61 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/interface_function_at_file_level.sol @@ -0,0 +1,7 @@ +interface I { + function g() external pure; +} + +using {I.g} for uint; +// ---- +// TypeError 4167: (56-59): Only file-level functions and library functions can be attached to a type in a "using" statement diff --git a/test/libsolidity/syntaxTests/using/interface_function_inside_contract.sol b/test/libsolidity/syntaxTests/using/interface_function_inside_contract.sol new file mode 100644 index 0000000000..f01788ff51 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/interface_function_inside_contract.sol @@ -0,0 +1,9 @@ +interface I { + function g() external pure; +} + +contract C { + using {I.g} for uint; +} +// ---- +// TypeError 4167: (73-76): Only file-level functions and library functions can be attached to a type in a "using" statement diff --git a/test/libsolidity/syntaxTests/using/library_at_file_level.sol b/test/libsolidity/syntaxTests/using/library_at_file_level.sol new file mode 100644 index 0000000000..9cb1965a08 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/library_at_file_level.sol @@ -0,0 +1,17 @@ +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} +} + +using L for uint; + +contract C { + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/library_functions_at_file_level.sol b/test/libsolidity/syntaxTests/using/library_functions_at_file_level.sol new file mode 100644 index 0000000000..2876f591a0 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/library_functions_at_file_level.sol @@ -0,0 +1,19 @@ +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} +} + +using {L.externalFunction} for uint; +using {L.publicFunction} for uint; +using {L.internalFunction} for uint; + +contract C { + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/library_functions_attached_at_file_level_used_inside_library.sol b/test/libsolidity/syntaxTests/using/library_functions_attached_at_file_level_used_inside_library.sol new file mode 100644 index 0000000000..21d30f5572 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/library_functions_attached_at_file_level_used_inside_library.sol @@ -0,0 +1,17 @@ +using {L.externalFunction, L.publicFunction, L.internalFunction} for uint; + +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} + + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + } +} +// ---- +// TypeError 6700: (299-319): Libraries cannot call their own functions externally. +// TypeError 6700: (329-347): Libraries cannot call their own functions externally. diff --git a/test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_at_file_level.sol b/test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_at_file_level.sol new file mode 100644 index 0000000000..bb191faa64 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_at_file_level.sol @@ -0,0 +1,17 @@ +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} +} + +using {L.externalFunction, L.publicFunction, L.internalFunction} for uint; + +contract C { + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_inside_contract.sol b/test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_inside_contract.sol new file mode 100644 index 0000000000..300a3480d3 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/library_functions_attached_in_single_directive_inside_contract.sol @@ -0,0 +1,17 @@ +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} +} + +contract C { + using {L.externalFunction, L.publicFunction, L.internalFunction} for uint; + + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/library_functions_inside_contract.sol b/test/libsolidity/syntaxTests/using/library_functions_inside_contract.sol new file mode 100644 index 0000000000..46d4c571d6 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/library_functions_inside_contract.sol @@ -0,0 +1,19 @@ +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} +} + +contract C { + using {L.externalFunction} for uint; + using {L.publicFunction} for uint; + using {L.internalFunction} for uint; + + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/library_inside_contract.sol b/test/libsolidity/syntaxTests/using/library_inside_contract.sol new file mode 100644 index 0000000000..cd7f8fd193 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/library_inside_contract.sol @@ -0,0 +1,17 @@ +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} +} + +contract C { + using L for uint; + + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/library_non_free_external_function_err.sol b/test/libsolidity/syntaxTests/using/library_non_free_external_function_err.sol index 76d53cf90c..0a51043db2 100644 --- a/test/libsolidity/syntaxTests/using/library_non_free_external_function_err.sol +++ b/test/libsolidity/syntaxTests/using/library_non_free_external_function_err.sol @@ -11,4 +11,4 @@ contract C { } } // ---- -// DeclarationError 7920: (115-123): Identifier not found or not unique. +// TypeError 4357: (115-123): Library name expected. If you want to attach a function, use '{...}'. diff --git a/test/libsolidity/syntaxTests/using/module_identifier_not_found.sol b/test/libsolidity/syntaxTests/using/module_identifier_not_found.sol index ef1688b229..2526d216f2 100644 --- a/test/libsolidity/syntaxTests/using/module_identifier_not_found.sol +++ b/test/libsolidity/syntaxTests/using/module_identifier_not_found.sol @@ -10,4 +10,4 @@ contract C { using { id } for uint; } // ---- -// DeclarationError 7920: (B:43-45): Identifier not found or not unique. +// DeclarationError 9589: (B:43-45): Identifier is not a function name or not unique. diff --git a/test/libsolidity/syntaxTests/using/public_state_variable_getter.sol b/test/libsolidity/syntaxTests/using/public_state_variable_getter.sol new file mode 100644 index 0000000000..9223a92a5d --- /dev/null +++ b/test/libsolidity/syntaxTests/using/public_state_variable_getter.sol @@ -0,0 +1,11 @@ +contract A { + uint public data; +} + +contract C { + A a = new A(); + + using {a.data} for uint; +} +// ---- +// DeclarationError 9589: (82-88): Identifier is not a function name or not unique. diff --git a/test/libsolidity/syntaxTests/using/undeclared_library.sol b/test/libsolidity/syntaxTests/using/undeclared_library.sol new file mode 100644 index 0000000000..c2174cc6c1 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/undeclared_library.sol @@ -0,0 +1,3 @@ +using L for uint; +// ---- +// DeclarationError 9589: (6-7): Identifier is not a library name. diff --git a/test/libsolidity/syntaxTests/using/unqualified_library_functions_attached_in_single_directive_inside_library.sol b/test/libsolidity/syntaxTests/using/unqualified_library_functions_attached_in_single_directive_inside_library.sol new file mode 100644 index 0000000000..7403dcf282 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/unqualified_library_functions_attached_in_single_directive_inside_library.sol @@ -0,0 +1,19 @@ +library L { + function externalFunction(uint) external pure {} + function publicFunction(uint) public pure {} + function internalFunction(uint) internal pure {} + function privateFunction(uint) private pure {} + + using {externalFunction, publicFunction, internalFunction, privateFunction} for uint; + + function f() public pure { + uint x; + x.externalFunction(); + x.publicFunction(); + x.internalFunction(); + x.privateFunction(); + } +} +// ---- +// TypeError 6700: (365-385): Libraries cannot call their own functions externally. +// TypeError 6700: (395-413): Libraries cannot call their own functions externally. From 6f285ad19758b0f8bfb20183c1b8d6b48fdd4a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 4 Dec 2022 23:20:48 +0100 Subject: [PATCH 0072/1140] Update debian/compat to version 13 Compat version 13 is currently the recommended one. An important change introduced in 10 was change of default to target parallel builds https://github.com/Debian/debhelper/blob/5d1bb29841043d8e47ebbdd043e6cd086cad508e/debhelper.pod#compatibility-levels --- scripts/deps-ppa/static_z3.sh | 6 +++--- scripts/release_ppa.sh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index fa237ba08f..35fff526f9 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -73,16 +73,16 @@ cp "/tmp/${packagename}_${debversion}.orig.tar.gz" ../ # Create debian package information mkdir debian -echo 9 > debian/compat +echo 13 > debian/compat # TODO: the Z3 packages have different build dependencies cat < debian/control Source: z3-static Section: science Priority: extra Maintainer: Daniel Kirchner -Build-Depends: debhelper (>= 9.0.0), +Build-Depends: debhelper (>= 13.0.0), cmake, - g++ (>= 5.0), + g++ (>= 9.0), git, libgmp-dev, dh-python, diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 2acd62cd36..cf3e4b3356 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -156,15 +156,15 @@ cp "/tmp/${packagename}_${debversion}.orig.tar.gz" ../ # Create debian package information mkdir debian -echo 9 > debian/compat +echo 13 > debian/compat cat < debian/control Source: solc Section: science Priority: extra Maintainer: Christian (Buildserver key) -Build-Depends: ${SMTDEPENDENCY}debhelper (>= 9.0.0), +Build-Depends: ${SMTDEPENDENCY}debhelper (>= 13.0.0), cmake, - g++ (>= 5.0), + g++ (>= 9.0), git, libgmp-dev, libboost-all-dev, From 43431eb427c6086701353aeda94b8ae9b401b1e9 Mon Sep 17 00:00:00 2001 From: Jacob Heider Date: Fri, 3 Feb 2023 21:37:50 -0500 Subject: [PATCH 0073/1140] Fixes compilation errors with some clangs resolves https://github.com/ethereum/solidity/issues/13854 --- libsolidity/lsp/DocumentHoverHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/lsp/DocumentHoverHandler.cpp b/libsolidity/lsp/DocumentHoverHandler.cpp index 628b62fa1f..7700022289 100644 --- a/libsolidity/lsp/DocumentHoverHandler.cpp +++ b/libsolidity/lsp/DocumentHoverHandler.cpp @@ -63,7 +63,7 @@ void DocumentHoverHandler::operator()(MessageID _id, Json::Value const& _args) auto const [sourceUnitName, lineColumn] = HandlerBase(*this).extractSourceUnitNameAndLineColumn(_args); auto const [sourceNode, sourceOffset] = m_server.astNodeAndOffsetAtSourceLocation(sourceUnitName, lineColumn); - MarkdownBuilder markdown{}; + MarkdownBuilder markdown; auto rangeToHighlight = toRange(sourceNode->location()); // Try getting the type definition of the underlying AST node, if available. From 8f1668ffb8ca21fa8bc95674bc366a6069a586d8 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Wed, 1 Feb 2023 20:00:20 +0100 Subject: [PATCH 0074/1140] libsolutil: Add missing include This helps suppressing the following message during compilation: ``` /builddir/build/BUILD/solidity-0.8.18/libsolutil/Common.h:55:27: error: 'uint8_t' was not declared in this scope 55 | using bytes = std::vector; | ^~~~~~~ /builddir/build/BUILD/solidity-0.8.18/libsolutil/Common.h:49:1: note: 'uint8_t' is defined in header ''; did you forget to '#include '? 48 | #include +++ |+#include 49 | #include ``` Signed-off-by: Peter Lemenkov --- libsolutil/Common.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsolutil/Common.h b/libsolutil/Common.h index eea9dacd54..c908c13ae2 100644 --- a/libsolutil/Common.h +++ b/libsolutil/Common.h @@ -42,11 +42,12 @@ #include +#include +#include #include +#include #include #include -#include -#include namespace solidity { From 6a6bf303b5ef7a000e56d4b0e87d882e7287e1ea Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Wed, 1 Feb 2023 20:00:20 +0100 Subject: [PATCH 0075/1140] libsolutil: Add missing include This one is more obscure. It helps suppressing the following error while compiling: ``` /builddir/build/BUILD/solidity-0.8.18/liblangutil/EVMVersion.h:33:6: error: elaborated-type-specifier for a scoped enum must not use the 'class' keyword [-Werror] 33 | enum class Instruction: uint8_t; | ~~~~ ^~~~~ | ----- /builddir/build/BUILD/solidity-0.8.18/liblangutil/EVMVersion.h:33:23: error: found ':' in nested-name-specifier, expected '::' 33 | enum class Instruction: uint8_t; | ^ | :: /builddir/build/BUILD/solidity-0.8.18/liblangutil/EVMVersion.h:33:12: error: 'Instruction' has not been declared 33 | enum class Instruction: uint8_t; | ^~~~~~~~~~~ /builddir/build/BUILD/solidity-0.8.18/liblangutil/EVMVersion.h:101:24: error: 'solidity::evmasm::Instruction' has not been declared 101 | bool hasOpcode(evmasm::Instruction _opcode) const; | ^~~~~~ /builddir/build/BUILD/solidity-0.8.18/liblangutil/EVMVersion.cpp:29:6: error: no declaration matches 'bool solidity::langutil::EVMVersion::hasOpcode(solidity::evmasm::Instruction) const' 29 | bool EVMVersion::hasOpcode(Instruction _opcode) const | ^~~~~~~~~~ /builddir/build/BUILD/solidity-0.8.18/liblangutil/EVMVersion.h:101:14: note: candidate is: 'bool solidity::langutil::EVMVersion::hasOpcode(int) const' 101 | bool hasOpcode(evmasm::Instruction _opcode) const; | ^~~~~~~~~ /builddir/build/BUILD/solidity-0.8.18/liblangutil/EVMVersion.h:43:7: note: 'class solidity::langutil::EVMVersion' defined here 43 | class EVMVersion: | ^~~~~~~~~~ cc1plus: all warnings being treated as errors ``` Signed-off-by: Peter Lemenkov --- liblangutil/EVMVersion.h | 1 + 1 file changed, 1 insertion(+) diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index aa23ea6eef..22f85c8af6 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include From b3f35f703aa5d2f55cff36b9a6f16c0ac7d44849 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Sat, 4 Feb 2023 16:16:54 +0100 Subject: [PATCH 0076/1140] libsolidity: Redundant std::move This patch suppresses warnings like this one: ``` /builddir/build/BUILD/solidity-0.8.18/libsolidity/ast/AST.h: In constructor 'solidity::frontend::FunctionDefinition::FunctionDefinition(int64_t, const solidity::frontend::ASTNode::SourceLocation&, solidity::frontend::ASTPointer >&, const solidity::frontend::ASTNode::SourceLocation&, solidity::frontend::Visibility, solidity::frontend::StateMutability, bool, solidity::langutil::Token, bool, solidity::frontend::ASTPointer&, solidity::frontend::ASTPointer&, solidity::frontend::ASTPointer&, std::vector >, solidity::frontend::ASTPointer&, solidity::frontend::ASTPointer&)': /builddir/build/BUILD/solidity-0.8.18/libsolidity/ast/AST.h:926:69: error: redundant move in initialization [-Werror=redundant-move] 926 | CallableDeclaration(_id, _location, _name, std::move(_nameLocation), _visibility, _parameters, _isVirtual, _overrides, _returnParameters), | ~~~~~~~~~^~~~~~~~~~~~~~~ /builddir/build/BUILD/solidity-0.8.18/libsolidity/ast/AST.h:926:69: note: remove 'std::move' call ``` Signed-off-by: Peter Lemenkov --- libsolidity/ast/AST.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 06575beece..f0f43945bf 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -923,7 +923,7 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen ASTPointer const& _returnParameters, ASTPointer const& _body ): - CallableDeclaration(_id, _location, _name, std::move(_nameLocation), _visibility, _parameters, _isVirtual, _overrides, _returnParameters), + CallableDeclaration(_id, _location, _name, _nameLocation, _visibility, _parameters, _isVirtual, _overrides, _returnParameters), StructurallyDocumented(_documentation), ImplementationOptional(_body != nullptr), m_stateMutability(_stateMutability), From 821da895ea81167ded6d7f879b8793f9a3ba251e Mon Sep 17 00:00:00 2001 From: Evan Saulpaugh Date: Sun, 5 Feb 2023 16:13:23 -0600 Subject: [PATCH 0077/1140] specify "receive" as having no "name" --- docs/abi-spec.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 35123a30a2..44988c8dc1 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -563,7 +563,7 @@ A function description is a JSON object with the fields: blockchain state `), ``view`` (:ref:`specified to not modify the blockchain state `), ``nonpayable`` (function does not accept Ether - the default) and ``payable`` (function accepts Ether). -Constructor and fallback function never have ``name`` or ``outputs``. Fallback function doesn't have ``inputs`` either. +Constructor, receive, and fallback never have ``name`` or ``outputs``. Receive and fallback don't have ``inputs`` either. .. note:: Sending non-zero Ether to non-payable function will revert the transaction. From 8d91ccf0284b4baa00f4438ad099f9f44a5ff8f1 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Tue, 12 Oct 2021 11:12:18 +0200 Subject: [PATCH 0078/1140] [SMTChecker] Add a new trusted mode which assumes that code that is available at compile time is trusted. --- Changelog.md | 1 + docs/smtchecker.rst | 182 +++++++ docs/using-the-compiler.rst | 4 + libsolidity/formal/BMC.cpp | 6 +- libsolidity/formal/CHC.cpp | 486 ++++++++++++++---- libsolidity/formal/CHC.h | 23 + libsolidity/formal/ModelCheckerSettings.cpp | 9 + libsolidity/formal/ModelCheckerSettings.h | 17 + libsolidity/formal/Predicate.cpp | 10 + libsolidity/formal/Predicate.h | 4 + libsolidity/formal/PredicateInstance.cpp | 11 +- libsolidity/formal/PredicateInstance.h | 12 +- libsolidity/formal/SMTEncoder.cpp | 47 +- libsolidity/formal/SMTEncoder.h | 15 +- libsolidity/formal/SymbolicState.cpp | 200 ++++++- libsolidity/formal/SymbolicState.h | 57 +- libsolidity/formal/SymbolicTypes.cpp | 22 + libsolidity/formal/SymbolicTypes.h | 4 + libsolidity/interface/StandardCompiler.cpp | 12 +- solc/CommandLineParser.cpp | 17 + .../err | 26 + .../model_checker_contracts_only_one/err | 2 +- .../model_checker_ext_calls_empty_arg/args | 1 + .../model_checker_ext_calls_empty_arg/err | 1 + .../model_checker_ext_calls_empty_arg/exit | 1 + .../input.sol | 15 + .../model_checker_ext_calls_trusted_chc/args | 1 + .../model_checker_ext_calls_trusted_chc/err | 5 + .../input.sol | 15 + .../args | 1 + .../model_checker_ext_calls_untrusted_chc/err | 14 + .../input.sol | 13 + .../model_checker_ext_calls_wrong_arg/args | 1 + .../model_checker_ext_calls_wrong_arg/err | 1 + .../model_checker_ext_calls_wrong_arg/exit | 1 + .../input.sol | 15 + .../output.json | 68 +++ .../output.json | 4 +- .../output.json | 4 +- .../input.json | 30 ++ .../output.json | 12 + .../input.json | 30 ++ .../output.json | 32 ++ .../input.json | 28 + .../output.json | 50 ++ .../input.json | 30 ++ .../output.json | 12 + .../input.json | 30 ++ .../output.json | 12 + .../output.json | 62 +-- test/libsolidity/SMTCheckerTest.cpp | 15 +- .../length_1d_struct_array_2d_1.sol | 2 +- .../length_same_after_assignment_3_fail.sol | 2 +- .../array_members/push_as_lhs_1d.sol | 1 + .../array_members/push_as_lhs_2d.sol | 1 + .../complex/slither/external_function.sol | 4 +- .../deployment/deploy_bmc_trusted.sol | 18 + .../deployment/deploy_bmc_untrusted.sol | 17 + .../deployment/deploy_trusted.sol | 16 + .../deployment/deploy_trusted_addresses.sol | 19 + .../deployment/deploy_trusted_flow.sol | 32 ++ ...eploy_trusted_keep_storage_constraints.sol | 17 + .../deployment/deploy_trusted_state_flow.sol | 24 + .../deploy_trusted_state_flow_2.sol | 20 + .../deploy_trusted_state_flow_3.sol | 21 + .../deploy_trusted_state_flow_4.sol | 20 + .../deployment/deploy_untrusted.sol | 17 + .../deployment/deploy_untrusted_addresses.sol | 22 + ...oy_untrusted_erase_storage_constraints.sol | 17 + .../deployment_trusted_with_value_1.sol | 20 + .../call_abstract_constructor_trusted_1.sol | 28 + .../call_abstract_constructor_trusted_2.sol | 25 + .../call_abstract_trusted_1.sol | 28 + .../call_abstract_trusted_2.sol | 25 + .../call_abstract_trusted_3.sol | 29 ++ .../external_calls/call_reentrancy_view.sol | 2 +- ...ternal_call_from_constructor_1_trusted.sol | 21 + ...ternal_call_from_constructor_2_trusted.sol | 17 + ...ternal_call_from_constructor_3_trusted.sol | 25 + .../external_call_indirect_1.sol | 41 ++ .../external_call_indirect_2.sol | 52 ++ .../external_call_indirect_3.sol | 45 ++ .../external_call_indirect_4.sol | 48 ++ .../external_call_indirect_5.sol | 50 ++ .../external_call_semantic_this_1.sol | 17 + .../external_call_semantic_this_2.sol | 16 + .../external_call_semantic_this_3.sol | 17 + ..._address_inside_array_struct_trusted_1.sol | 23 + ..._address_inside_array_struct_trusted_2.sol | 24 + ...ate_var_address_inside_array_trusted_1.sol | 21 + ...ate_var_address_inside_array_trusted_2.sol | 20 + ...te_var_address_inside_struct_trusted_1.sol | 24 + ...te_var_address_inside_struct_trusted_2.sol | 23 + ...te_var_address_inside_struct_trusted_3.sol | 26 + ...te_var_address_inside_struct_trusted_4.sol | 27 + ...contract_inside_array_struct_trusted_1.sol | 23 + ...contract_inside_array_struct_trusted_2.sol | 24 + ...te_var_contract_inside_array_trusted_1.sol | 21 + ...te_var_contract_inside_array_trusted_2.sol | 21 + ...e_var_contract_inside_struct_trusted_1.sol | 24 + ...e_var_contract_inside_struct_trusted_2.sol | 24 + ...e_var_contract_inside_struct_trusted_3.sol | 27 + ...e_var_contract_inside_struct_trusted_4.sol | 27 + .../external_call_this_with_value_1.sol | 2 +- .../external_call_this_with_value_2.sol | 6 +- .../external_hash_known_code_pure_trusted.sol | 33 ++ ..._known_code_state_reentrancy_2_trusted.sol | 47 ++ ...code_state_reentrancy_indirect_trusted.sol | 56 ++ ...sh_known_code_state_reentrancy_trusted.sol | 38 ++ ...n_code_state_reentrancy_unsafe_trusted.sol | 44 ++ ...external_hash_known_code_state_trusted.sol | 36 ++ ...l_hash_known_code_state_unsafe_trusted.sol | 40 ++ .../external_calls/external_reentrancy_2.sol | 2 +- .../external_calls/external_safe.sol | 2 + .../token_trusted_transfer_correct.sol | 64 +++ .../token_trusted_transfer_wrong.sol | 68 +++ .../file_level/new_operator.sol | 2 +- .../functions/functions_external_2.sol | 2 +- .../functions/getters/external_getter_1.sol | 22 + .../functions/getters/external_getter_2.sol | 33 ++ .../getters/external_getter_this_1.sol | 18 + .../getters/external_getter_this_2.sol | 19 + ...virtual_function_called_by_constructor.sol | 2 +- .../smtCheckerTests/imports/ExtCall.sol | 2 +- .../imports/import_as_module_2.sol | 1 + .../operators/compound_mul_mapping.sol | 3 +- .../operators/conditional_assignment_6.sol | 2 +- .../special/tx_vars_reentrancy_1.sol | 1 + .../smtCheckerTests/try_catch/try_new.sol | 4 +- .../typecast/bytes_to_fixed_bytes_1.sol | 3 + .../typecast/string_to_bytes_push_1.sol | 2 +- .../smtCheckerTests/types/bool_simple_2.sol | 1 + .../user_type_as_struct_member_1.sol | 1 - test/solc/CommandLineParser.cpp | 2 + test/tools/fuzzer_common.cpp | 1 + 135 files changed, 3153 insertions(+), 232 deletions(-) create mode 100644 test/cmdlineTests/model_checker_ext_calls_empty_arg/args create mode 100644 test/cmdlineTests/model_checker_ext_calls_empty_arg/err create mode 100644 test/cmdlineTests/model_checker_ext_calls_empty_arg/exit create mode 100644 test/cmdlineTests/model_checker_ext_calls_empty_arg/input.sol create mode 100644 test/cmdlineTests/model_checker_ext_calls_trusted_chc/args create mode 100644 test/cmdlineTests/model_checker_ext_calls_trusted_chc/err create mode 100644 test/cmdlineTests/model_checker_ext_calls_trusted_chc/input.sol create mode 100644 test/cmdlineTests/model_checker_ext_calls_untrusted_chc/args create mode 100644 test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err create mode 100644 test/cmdlineTests/model_checker_ext_calls_untrusted_chc/input.sol create mode 100644 test/cmdlineTests/model_checker_ext_calls_wrong_arg/args create mode 100644 test/cmdlineTests/model_checker_ext_calls_wrong_arg/err create mode 100644 test/cmdlineTests/model_checker_ext_calls_wrong_arg/exit create mode 100644 test/cmdlineTests/model_checker_ext_calls_wrong_arg/input.sol create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/input.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/input.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/input.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/input.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/input.json create mode 100644 test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_bmc_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_bmc_untrusted.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted_keep_storage_constraints.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_2.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_3.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_4.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_untrusted.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_erase_storage_constraints.sol create mode 100644 test/libsolidity/smtCheckerTests/deployment/deployment_trusted_with_value_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_3.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_2_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_3.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_3.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_4.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_2.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_3.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_4.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_pure_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_2_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_unsafe_trusted.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_correct.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_wrong.sol create mode 100644 test/libsolidity/smtCheckerTests/functions/getters/external_getter_1.sol create mode 100644 test/libsolidity/smtCheckerTests/functions/getters/external_getter_2.sol create mode 100644 test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_1.sol create mode 100644 test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_2.sol diff --git a/Changelog.md b/Changelog.md index 7619fbd40d..5ce4057a48 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * SMTChecker: New trusted mode that assumes that any compile-time available code is the actual used code even in external calls. This can be used via the CLI option ``--model-checker-ext-calls trusted`` or the JSON field ``settings.modelChecker.extCalls: "trusted"``. Bugfixes: diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index c16a3e5d71..276f9c33a0 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -518,6 +518,188 @@ which has the following form: "source2.sol": ["contract2", "contract3"] } +Trusted External Calls +====================== + +By default, the SMTChecker does not assume that compile-time available code +is the same as the runtime code for external calls. Take the following contracts +as an example: + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.8.0; + + contract Ext { + uint public x; + function setX(uint _x) public { x = _x; } + } + contract MyContract { + function callExt(Ext _e) public { + _e.setX(42); + assert(_e.x() == 42); + } + } + +When ``MyContract.callExt`` is called, an address is given as the argument. +At deployment time, we cannot know for sure that address ``_e`` actually +contains a deployment of contract ``Ext``. +Therefore, the SMTChecker will warn that the assertion above can be violated, +which is true, if ``_e`` contains another contract than ``Ext``. + +However, it can be useful to treat these external calls as trusted, for example, +to test that different implementations of an interface conform to the same property. +This means assuming that address ``_e`` indeed was deployed as contract ``Ext``. +This mode can be enabled via the CLI option ``--model-checker-ext-calls=trusted`` +or the JSON field ``settings.modelChecker.extCalls: "trusted"``. + +Please be aware that enabling this mode can make the SMTChecker analysis much more +computationally costly. + +An important part of this mode is that it is applied to contract types and high +level external calls to contracts, and not low level calls such as ``call`` and +``delegatecall``. The storage of an address is stored per contract type, and +the SMTChecker assumes that an externally called contract has the type of the +caller expression. Therefore, casting an ``address`` or a contract to +different contract types will yield different storage values and can give +unsound results if the assumptions are inconsistent, such as the example below: + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.8.0; + + contract D { + constructor(uint _x) { x = _x; } + uint public x; + function setX(uint _x) public { x = _x; } + } + + contract E { + constructor() { x = 2; } + uint public x; + function setX(uint _x) public { x = _x; } + } + + contract C { + function f() public { + address d = address(new D(42)); + + // `d` was deployed as `D`, so its `x` should be 42 now. + assert(D(d).x() == 42); // should hold + assert(D(d).x() == 43); // should fail + + // E and D have the same interface, so the following + // call would also work at runtime. + // However, the change to `E(d)` is not reflected in `D(d)`. + E(d).setX(1024); + + // Reading from `D(d)` now will show old values. + // The assertion below should fail at runtime, + // but succeeds in this mode's analysis (unsound). + assert(D(d).x() == 42); + // The assertion below should succeed at runtime, + // but fails in this mode's analysis (false positive). + assert(D(d).x() == 1024); + } + } + +Due to the above, make sure that the trusted external calls to a certain +variable of ``address`` or ``contract`` type always have the same caller +expression type. + +It is also helpful to cast the called contract's variable as the type of the +most derived type in case of inheritance. + + .. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.8.0; + + interface Token { + function balanceOf(address _a) external view returns (uint); + function transfer(address _to, uint _amt) external; + } + + contract TokenCorrect is Token { + mapping (address => uint) balance; + constructor(address _a, uint _b) { + balance[_a] = _b; + } + function balanceOf(address _a) public view override returns (uint) { + return balance[_a]; + } + function transfer(address _to, uint _amt) public override { + require(balance[msg.sender] >= _amt); + balance[msg.sender] -= _amt; + balance[_to] += _amt; + } + } + + contract Test { + function property_transfer(address _token, address _to, uint _amt) public { + require(_to != address(this)); + + TokenCorrect t = TokenCorrect(_token); + + uint xPre = t.balanceOf(address(this)); + require(xPre >= _amt); + uint yPre = t.balanceOf(_to); + + t.transfer(_to, _amt); + uint xPost = t.balanceOf(address(this)); + uint yPost = t.balanceOf(_to); + + assert(xPost == xPre - _amt); + assert(yPost == yPre + _amt); + } + } + +Note that in function ``property_transfer``, the external calls are +performed on variable ``t`` + +Another caveat of this mode are calls to state variables of contract type +outside the analyzed contract. In the code below, even though ``B`` deploys +``A``, it is also possible for the address stored in ``B.a`` to be called by +anyone outside of ``B`` in between transactions to ``B`` itself. To reflect the +possible changes to ``B.a``, the encoding allows an unbounded number of calls +to be made to ``B.a`` externally. The encoding will keep track of ``B.a``'s +storage, therefore assertion (2) should hold. However, currently the encoding +allows such calls to be made from ``B`` conceptually, therefore assertion (3) +fails. Making the encoding stronger logically is an extension of the trusted +mode and is under development. Note that the encoding does not keep track of +storage for ``address`` variables, therefore if ``B.a`` had type ``address`` +the encoding would assume that its storage does not change in between +transactions to ``B``. + + .. code-block:: solidity + + pragma solidity >=0.8.0; + + contract A { + uint public x; + address immutable public owner; + constructor() { + owner = msg.sender; + } + function setX(uint _x) public { + require(msg.sender == owner); + x = _x; + } + } + + contract B { + A a; + constructor() { + a = new A(); + assert(a.x() == 0); // (1) should hold + } + function g() public view { + assert(a.owner() == address(this)); // (2) should hold + assert(a.x() == 0); // (3) should hold, but fails due to a false positive + } + } + Reported Inferred Inductive Invariants ====================================== diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 6d6264e1aa..251a2c0536 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -433,6 +433,10 @@ Input Description "divModNoSlacks": false, // Choose which model checker engine to use: all (default), bmc, chc, none. "engine": "chc", + // Choose whether external calls should be considered trusted in case the + // code of the called function is available at compile-time. + // For details see the SMTChecker section. + "extCalls": "trusted", // Choose which types of invariants should be reported to the user: contract, reentrancy. "invariants": ["contract", "reentrancy"], // Choose whether to output all unproved targets. The default is `false`. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 0b4f347816..d17b5c93a9 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -82,7 +82,7 @@ void BMC::analyze(SourceUnit const& _source, map(*_funCall.expression().annotation().type); if (funType.kind() == FunctionType::Kind::External) - return isTrustedExternalCall(&_funCall.expression()); + return isExternalCallToThis(&_funCall.expression()); else if (funType.kind() != FunctionType::Kind::Internal) return false; @@ -567,7 +567,7 @@ void BMC::internalOrExternalFunctionCall(FunctionCall const& _funCall) auto const& funType = dynamic_cast(*_funCall.expression().annotation().type); if (shouldInlineFunctionCall(_funCall, currentScopeContract(), m_currentContract)) inlineFunctionCall(_funCall); - else if (isPublicGetter(_funCall.expression())) + else if (publicGetter(_funCall.expression())) { // Do nothing here. // The processing happens in SMT Encoder, but we need to prevent the resetting of the state variables. diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 83602ace34..db67426259 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -104,7 +104,7 @@ void CHC::analyze(SourceUnit const& _source) auto sources = sourceDependencies(_source); collectFreeFunctions(sources); createFreeConstants(sources); - state().prepareForSourceUnit(_source); + state().prepareForSourceUnit(_source, encodeExternalCallsAsTrusted()); for (auto const* source: sources) defineInterfacesAndSummaries(*source); @@ -175,15 +175,30 @@ void CHC::endVisit(ContractDefinition const& _contract) smtutil::Expression zeroes(true); for (auto var: stateVariablesIncludingInheritedAndPrivate(_contract)) zeroes = zeroes && currentValue(*var) == smt::zeroValue(var->type()); + + smtutil::Expression newAddress = encodeExternalCallsAsTrusted() ? + !state().addressActive(state().thisAddress()) : + smtutil::Expression(true); + // The contract's address might already have funds before deployment, // so the balance must be at least `msg.value`, but not equals. auto initialBalanceConstraint = state().balance(state().thisAddress()) >= state().txMember("msg.value"); addRule(smtutil::Expression::implies( - initialConstraints(_contract) && zeroes && initialBalanceConstraint, + initialConstraints(_contract) && zeroes && newAddress && initialBalanceConstraint, predicate(entry) ), entry.functor().name); + setCurrentBlock(entry); + if (encodeExternalCallsAsTrusted()) + { + auto const& entryAfterAddress = *createConstructorBlock(_contract, "implicit_constructor_entry_after_address"); + state().setAddressActive(state().thisAddress(), true); + + connectBlocks(m_currentBlock, predicate(entryAfterAddress)); + setCurrentBlock(entryAfterAddress); + } + solAssert(!m_errorDest, ""); m_errorDest = m_constructorSummaries.at(&_contract); // We need to evaluate the base constructor calls (arguments) from derived -> base @@ -220,6 +235,9 @@ void CHC::endVisit(ContractDefinition const& _contract) m_context.addAssertion(errorFlag().currentValue() == 0); } + if (encodeExternalCallsAsTrusted()) + state().writeStateVars(_contract, state().thisAddress()); + connectBlocks(m_currentBlock, summary(_contract)); setCurrentBlock(*m_constructorSummaries.at(&_contract)); @@ -550,10 +568,12 @@ void CHC::endVisit(FunctionCall const& _funCall) externalFunctionCall(_funCall); SMTEncoder::endVisit(_funCall); break; + case FunctionType::Kind::Creation: + visitDeployment(_funCall); + break; case FunctionType::Kind::DelegateCall: case FunctionType::Kind::BareCallCode: case FunctionType::Kind::BareDelegateCall: - case FunctionType::Kind::Creation: SMTEncoder::endVisit(_funCall); unknownFunctionCall(_funCall); break; @@ -717,6 +737,19 @@ void CHC::visitAssert(FunctionCall const& _funCall) verificationTargetEncountered(&_funCall, VerificationTargetType::Assert, errorCondition); } +void CHC::visitPublicGetter(FunctionCall const& _funCall) +{ + createExpr(_funCall); + if (encodeExternalCallsAsTrusted()) + { + auto const& access = dynamic_cast(_funCall.expression()); + auto const& contractType = dynamic_cast(*access.expression().annotation().type); + state().writeStateVars(*m_currentContract, state().thisAddress()); + state().readStateVars(contractType.contractDefinition(), expr(access.expression())); + } + SMTEncoder::visitPublicGetter(_funCall); +} + void CHC::visitAddMulMod(FunctionCall const& _funCall) { solAssert(_funCall.arguments().at(2), ""); @@ -726,6 +759,66 @@ void CHC::visitAddMulMod(FunctionCall const& _funCall) SMTEncoder::visitAddMulMod(_funCall); } +void CHC::visitDeployment(FunctionCall const& _funCall) +{ + if (!encodeExternalCallsAsTrusted()) + { + SMTEncoder::endVisit(_funCall); + unknownFunctionCall(_funCall); + return; + } + + auto [callExpr, callOptions] = functionCallExpression(_funCall); + auto funType = dynamic_cast(callExpr->annotation().type); + ContractDefinition const* contract = + &dynamic_cast(*funType->returnParameterTypes().front()).contractDefinition(); + + // copy state variables from m_currentContract to state.storage. + state().writeStateVars(*m_currentContract, state().thisAddress()); + errorFlag().increaseIndex(); + + Expression const* value = valueOption(callOptions); + if (value) + decreaseBalanceFromOptionsValue(*value); + + auto originalTx = state().tx(); + newTxConstraints(value); + + auto prevThisAddr = state().thisAddress(); + auto newAddr = state().newThisAddress(); + + if (auto constructor = contract->constructor()) + { + auto const& args = _funCall.sortedArguments(); + auto const& params = constructor->parameters(); + solAssert(args.size() == params.size(), ""); + for (auto [arg, param]: ranges::zip_view(args, params)) + m_context.addAssertion(expr(*arg) == m_context.variable(*param)->currentValue()); + } + for (auto var: stateVariablesIncludingInheritedAndPrivate(*contract)) + m_context.variable(*var)->increaseIndex(); + Predicate const& constructorSummary = *m_constructorSummaries.at(contract); + m_context.addAssertion(smt::constructorCall(constructorSummary, m_context, false)); + + solAssert(m_errorDest, ""); + connectBlocks( + m_currentBlock, + predicate(*m_errorDest), + errorFlag().currentValue() > 0 + ); + m_context.addAssertion(errorFlag().currentValue() == 0); + + m_context.addAssertion(state().newThisAddress() == prevThisAddr); + + // copy state variables from state.storage to m_currentContract. + state().readStateVars(*m_currentContract, state().thisAddress()); + + state().newTx(); + m_context.addAssertion(originalTx == state().tx()); + + defineExpr(_funCall, newAddr); +} + void CHC::internalFunctionCall(FunctionCall const& _funCall) { solAssert(m_currentContract, ""); @@ -750,6 +843,53 @@ void CHC::internalFunctionCall(FunctionCall const& _funCall) m_context.addAssertion(errorFlag().currentValue() == 0); } +void CHC::addNondetCalls(ContractDefinition const& _contract) +{ + for (auto var: _contract.stateVariables()) + if (auto contractType = dynamic_cast(var->type())) + { + auto const& symbVar = m_context.variable(*var); + m_context.addAssertion(symbVar->currentValue() == symbVar->valueAtIndex(0)); + nondetCall(contractType->contractDefinition(), *var); + } +} + +void CHC::nondetCall(ContractDefinition const& _contract, VariableDeclaration const& _var) +{ + auto address = m_context.variable(_var)->currentValue(); + // Load the called contract's state variables from the global state. + state().readStateVars(_contract, address); + + m_context.addAssertion(state().state() == state().state(0)); + auto preCallState = vector{state().state()} + currentStateVariables(_contract); + + state().newState(); + for (auto const* var: _contract.stateVariables()) + m_context.variable(*var)->increaseIndex(); + + auto error = errorFlag().increaseIndex(); + + Predicate const& callPredicate = *createSymbolicBlock( + nondetInterfaceSort(_contract, state()), + "nondet_call_" + uniquePrefix(), + PredicateType::FunctionSummary, + &_var, + m_currentContract + ); + auto postCallState = vector{state().state()} + currentStateVariables(_contract); + vector stateExprs{error, address, state().abi(), state().crypto()}; + + auto nondet = (*m_nondetInterfaces.at(&_contract))(stateExprs + preCallState + postCallState); + auto nondetCall = callPredicate(stateExprs + preCallState + postCallState); + + addRule(smtutil::Expression::implies(nondet, nondetCall), nondetCall.name); + + m_context.addAssertion(nondetCall); + + // Load the called contract's state variables into the global state. + state().writeStateVars(_contract, address); +} + void CHC::externalFunctionCall(FunctionCall const& _funCall) { /// In external function calls we do not add a "predicate call" @@ -757,15 +897,10 @@ void CHC::externalFunctionCall(FunctionCall const& _funCall) /// so we just add the nondet_interface predicate. solAssert(m_currentContract, ""); - auto [callExpr, callOptions] = functionCallExpression(_funCall); - - if (isTrustedExternalCall(callExpr)) - { - externalFunctionCallToTrustedCode(_funCall); - return; - } + auto [callExpr, callOptions] = functionCallExpression(_funCall); FunctionType const& funType = dynamic_cast(*callExpr->annotation().type); + auto kind = funType.kind(); solAssert( kind == FunctionType::Kind::External || @@ -774,37 +909,42 @@ void CHC::externalFunctionCall(FunctionCall const& _funCall) "" ); - bool usesStaticCall = kind == FunctionType::Kind::BareStaticCall; - solAssert(m_currentContract, ""); + // Only consider high level external calls in trusted mode. + if ( + kind == FunctionType::Kind::External && + (encodeExternalCallsAsTrusted() || isExternalCallToThis(callExpr)) + ) + { + externalFunctionCallToTrustedCode(_funCall); + return; + } + + // Low level calls are still encoded nondeterministically. + auto function = functionCallToDefinition(_funCall, currentScopeContract(), m_currentContract); if (function) - { - usesStaticCall |= function->stateMutability() == StateMutability::Pure || - function->stateMutability() == StateMutability::View; for (auto var: function->returnParameters()) m_context.variable(*var)->increaseIndex(); - } + // If we see a low level call in trusted mode, + // we need to havoc the global state. + if ( + kind == FunctionType::Kind::BareCall && + encodeExternalCallsAsTrusted() + ) + state().newStorage(); + + // No reentrancy from constructor calls. if (!m_currentFunction || m_currentFunction->isConstructor()) return; - if (callOptions) - { - optional valueIndex; - for (auto&& [i, name]: callOptions->names() | ranges::views::enumerate) - if (name && *name == "value") - { - valueIndex = i; - break; - } - if (valueIndex) - state().addBalance(state().thisAddress(), 0 - expr(*callOptions->options().at(*valueIndex))); - } + if (Expression const* value = valueOption(callOptions)) + decreaseBalanceFromOptionsValue(*value); auto preCallState = vector{state().state()} + currentStateVariables(); - if (!usesStaticCall) + if (!usesStaticCall(_funCall)) { state().newState(); for (auto const* var: m_stateVariables) @@ -843,8 +983,14 @@ void CHC::externalFunctionCall(FunctionCall const& _funCall) void CHC::externalFunctionCallToTrustedCode(FunctionCall const& _funCall) { + if (publicGetter(_funCall.expression())) + visitPublicGetter(_funCall); + solAssert(m_currentContract, ""); - FunctionType const& funType = dynamic_cast(*_funCall.expression().annotation().type); + + auto [callExpr, callOptions] = functionCallExpression(_funCall); + FunctionType const& funType = dynamic_cast(*callExpr->annotation().type); + auto kind = funType.kind(); solAssert(kind == FunctionType::Kind::External || kind == FunctionType::Kind::BareStaticCall, ""); @@ -854,14 +1000,25 @@ void CHC::externalFunctionCallToTrustedCode(FunctionCall const& _funCall) // External call creates a new transaction. auto originalTx = state().tx(); - auto txOrigin = state().txMember("tx.origin"); - state().newTx(); - // set the transaction sender as this contract - m_context.addAssertion(state().txMember("msg.sender") == state().thisAddress()); - // set the transaction value as 0 - m_context.addAssertion(state().txMember("msg.value") == 0); - // set the origin to be the current transaction origin - m_context.addAssertion(state().txMember("tx.origin") == txOrigin); + Expression const* value = valueOption(callOptions); + newTxConstraints(value); + + auto calledAddress = contractAddressValue(_funCall); + if (value) + { + decreaseBalanceFromOptionsValue(*value); + state().addBalance(calledAddress, expr(*value)); + } + + if (encodeExternalCallsAsTrusted()) + { + // The order here is important!! Write should go first. + + // Load the caller contract's state variables into the global state. + state().writeStateVars(*m_currentContract, state().thisAddress()); + // Load the called contract's state variables from the global state. + state().readStateVars(*function->annotation().contract, contractAddressValue(_funCall)); + } smtutil::Expression pred = predicate(_funCall); @@ -878,6 +1035,17 @@ void CHC::externalFunctionCallToTrustedCode(FunctionCall const& _funCall) (errorFlag().currentValue() > 0) ); m_context.addAssertion(errorFlag().currentValue() == 0); + + if (!usesStaticCall(_funCall)) + if (encodeExternalCallsAsTrusted()) + { + // The order here is important!! Write should go first. + + // Load the called contract's state variables into the global state. + state().writeStateVars(*function->annotation().contract, contractAddressValue(_funCall)); + // Load the caller contract's state variables from the global state. + state().readStateVars(*m_currentContract, state().thisAddress()); + } } void CHC::unknownFunctionCall(FunctionCall const&) @@ -1088,6 +1256,14 @@ set CHC::transactionVerificationTargetsIds(ASTNode const* _txRoot) return verificationTargetsIds; } +bool CHC::usesStaticCall(FunctionCall const& _funCall) +{ + FunctionType const& funType = dynamic_cast(*_funCall.expression().annotation().type); + auto kind = funType.kind(); + auto function = functionCallToDefinition(_funCall, currentScopeContract(), m_currentContract); + return (function && (function->stateMutability() == StateMutability::Pure || function->stateMutability() == StateMutability::View)) || kind == FunctionType::Kind::BareStaticCall; +} + optional CHC::natspecOptionFromString(string const& _option) { static map options{ @@ -1128,6 +1304,11 @@ SortPointer CHC::sort(FunctionDefinition const& _function) return functionBodySort(_function, m_currentContract, state()); } +bool CHC::encodeExternalCallsAsTrusted() +{ + return m_settings.externalCalls.isTrusted(); +} + SortPointer CHC::sort(ASTNode const* _node) { if (auto funDef = dynamic_cast(_node)) @@ -1232,6 +1413,62 @@ void CHC::defineExternalFunctionInterface(FunctionDefinition const& _function, C m_context.addAssertion(smt::symbolicUnknownConstraints(state().balance(state().thisAddress()) + k.currentValue(), TypeProvider::uint256())); state().addBalance(state().thisAddress(), k.currentValue()); + if (encodeExternalCallsAsTrusted()) + { + // If the contract has state variables that are addresses to other contracts, + // we need to encode the fact that those contracts may have been called in between + // transactions to _contract. + // + // We do that by adding nondet_interface constraints for those contracts, + // in the last line of this if block. + // + // If there are state variables of container types like structs or arrays + // that indirectly contain contract types, we havoc the state for simplicity, + // in the first part of this block. + // TODO: This could actually be supported. + // For structs: simply collect the SMT expressions of all the indirect contract type members. + // For arrays: more involved, needs to traverse the array symbolically and do the same for each contract. + // For mappings: way more complicated if the element type is a contract. + auto hasContractOrAddressSubType = [&](VariableDeclaration const* _var) -> bool { + bool foundContract = false; + solidity::util::BreadthFirstSearch bfs{{_var->type()}}; + bfs.run([&](auto _type, auto&& _addChild) { + if ( + _type->category() == Type::Category::Address || + _type->category() == Type::Category::Contract + ) + { + foundContract = true; + bfs.abort(); + } + if (auto const* mapType = dynamic_cast(_type)) + _addChild(mapType->valueType()); + else if (auto const* arrayType = dynamic_cast(_type)) + _addChild(arrayType->baseType()); + else if (auto const* structType = dynamic_cast(_type)) + for (auto const& member: structType->nativeMembers(nullptr)) + _addChild(member.type); + }); + return foundContract; + }; + bool found = false; + for (auto var: m_currentContract->stateVariables()) + if ( + var->type()->category() != Type::Category::Address && + var->type()->category() != Type::Category::Contract && + hasContractOrAddressSubType(var) + ) + { + found = true; + break; + } + + if (found) + state().newStorage(); + else + addNondetCalls(*m_currentContract); + } + errorFlag().increaseIndex(); m_context.addAssertion(summaryCall(_function)); @@ -1308,26 +1545,26 @@ smtutil::Expression CHC::summary(FunctionDefinition const& _function, ContractDe return smt::function(*m_summaries.at(&_contract).at(&_function), &_contract, m_context); } -smtutil::Expression CHC::summaryCall(FunctionDefinition const& _function, ContractDefinition const& _contract) +smtutil::Expression CHC::summary(FunctionDefinition const& _function) { - return smt::functionCall(*m_summaries.at(&_contract).at(&_function), &_contract, m_context); + solAssert(m_currentContract, ""); + return summary(_function, *m_currentContract); } -smtutil::Expression CHC::externalSummary(FunctionDefinition const& _function, ContractDefinition const& _contract) +smtutil::Expression CHC::summaryCall(FunctionDefinition const& _function, ContractDefinition const& _contract) { - return smt::function(*m_externalSummaries.at(&_contract).at(&_function), &_contract, m_context); + return smt::functionCall(*m_summaries.at(&_contract).at(&_function), &_contract, m_context); } -smtutil::Expression CHC::summary(FunctionDefinition const& _function) +smtutil::Expression CHC::summaryCall(FunctionDefinition const& _function) { solAssert(m_currentContract, ""); - return summary(_function, *m_currentContract); + return summaryCall(_function, *m_currentContract); } -smtutil::Expression CHC::summaryCall(FunctionDefinition const& _function) +smtutil::Expression CHC::externalSummary(FunctionDefinition const& _function, ContractDefinition const& _contract) { - solAssert(m_currentContract, ""); - return summaryCall(_function, *m_currentContract); + return smt::function(*m_externalSummaries.at(&_contract).at(&_function), &_contract, m_context); } smtutil::Expression CHC::externalSummary(FunctionDefinition const& _function) @@ -1516,18 +1753,19 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall) auto const& hierarchy = m_currentContract->annotation().linearizedBaseContracts; solAssert(kind != FunctionType::Kind::Internal || function->isFree() || (contract && contract->isLibrary()) || util::contains(hierarchy, contract), ""); - bool usesStaticCall = function->stateMutability() == StateMutability::Pure || function->stateMutability() == StateMutability::View; + if (kind == FunctionType::Kind::Internal) + contract = m_currentContract; - args += currentStateVariables(*m_currentContract); - args += symbolicArguments(_funCall, m_currentContract); - if (!m_currentContract->isLibrary() && !usesStaticCall) + args += currentStateVariables(*contract); + args += symbolicArguments(_funCall, contract); + if (!usesStaticCall(_funCall)) { state().newState(); - for (auto const& var: m_stateVariables) + for (auto const& var: stateVariablesIncludingInheritedAndPrivate(*contract)) m_context.variable(*var)->increaseIndex(); } args += vector{state().state()}; - args += currentStateVariables(*m_currentContract); + args += currentStateVariables(*contract); for (auto var: function->parameters() + function->returnParameters()) { @@ -1538,14 +1776,14 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall) args.push_back(currentValue(*var)); } - Predicate const& summary = *m_summaries.at(m_currentContract).at(function); - auto from = smt::function(summary, m_currentContract, m_context); + Predicate const& summary = *m_summaries.at(contract).at(function); + auto from = smt::function(summary, contract, m_context); Predicate const& callPredicate = *createSummaryBlock( *function, - *m_currentContract, + *contract, kind == FunctionType::Kind::Internal ? PredicateType::InternalCall : PredicateType::ExternalCallTrusted ); - auto to = smt::function(callPredicate, m_currentContract, m_context); + auto to = smt::function(callPredicate, contract, m_context); addRule(smtutil::Expression::implies(from, to), to.name); return callPredicate(args); @@ -1910,60 +2148,63 @@ optional CHC::generateCounterexample(CHCSolverInterface::CexGraph const& Predicate const* summaryPredicate = Predicate::predicate(summaryNode.name); auto const& summaryArgs = summaryNode.arguments; - auto stateVars = summaryPredicate->stateVariables(); - solAssert(stateVars.has_value(), ""); - auto stateValues = summaryPredicate->summaryStateValues(summaryArgs); - solAssert(stateValues.size() == stateVars->size(), ""); - - if (first) + if (!summaryPredicate->programVariable()) { - first = false; - /// Generate counterexample message local to the failed target. - localState = formatVariableModel(*stateVars, stateValues, ", ") + "\n"; + auto stateVars = summaryPredicate->stateVariables(); + solAssert(stateVars.has_value(), ""); + auto stateValues = summaryPredicate->summaryStateValues(summaryArgs); + solAssert(stateValues.size() == stateVars->size(), ""); - if (auto calledFun = summaryPredicate->programFunction()) + if (first) { - auto inValues = summaryPredicate->summaryPostInputValues(summaryArgs); - auto const& inParams = calledFun->parameters(); - if (auto inStr = formatVariableModel(inParams, inValues, "\n"); !inStr.empty()) - localState += inStr + "\n"; - auto outValues = summaryPredicate->summaryPostOutputValues(summaryArgs); - auto const& outParams = calledFun->returnParameters(); - if (auto outStr = formatVariableModel(outParams, outValues, "\n"); !outStr.empty()) - localState += outStr + "\n"; - - optional localErrorId; - solidity::util::BreadthFirstSearch bfs{{summaryId}}; - bfs.run([&](auto _nodeId, auto&& _addChild) { - auto const& children = _graph.edges.at(_nodeId); - if ( - children.size() == 1 && - nodePred(children.front())->isFunctionErrorBlock() - ) - { - localErrorId = children.front(); - bfs.abort(); - } - ranges::for_each(children, _addChild); - }); + first = false; + /// Generate counterexample message local to the failed target. + localState = formatVariableModel(*stateVars, stateValues, ", ") + "\n"; - if (localErrorId.has_value()) + if (auto calledFun = summaryPredicate->programFunction()) { - auto const* localError = nodePred(*localErrorId); - solAssert(localError && localError->isFunctionErrorBlock(), ""); - auto const [localValues, localVars] = localError->localVariableValues(nodeArgs(*localErrorId)); - if (auto localStr = formatVariableModel(localVars, localValues, "\n"); !localStr.empty()) - localState += localStr + "\n"; + auto inValues = summaryPredicate->summaryPostInputValues(summaryArgs); + auto const& inParams = calledFun->parameters(); + if (auto inStr = formatVariableModel(inParams, inValues, "\n"); !inStr.empty()) + localState += inStr + "\n"; + auto outValues = summaryPredicate->summaryPostOutputValues(summaryArgs); + auto const& outParams = calledFun->returnParameters(); + if (auto outStr = formatVariableModel(outParams, outValues, "\n"); !outStr.empty()) + localState += outStr + "\n"; + + optional localErrorId; + solidity::util::BreadthFirstSearch bfs{{summaryId}}; + bfs.run([&](auto _nodeId, auto&& _addChild) { + auto const& children = _graph.edges.at(_nodeId); + if ( + children.size() == 1 && + nodePred(children.front())->isFunctionErrorBlock() + ) + { + localErrorId = children.front(); + bfs.abort(); + } + ranges::for_each(children, _addChild); + }); + + if (localErrorId.has_value()) + { + auto const* localError = nodePred(*localErrorId); + solAssert(localError && localError->isFunctionErrorBlock(), ""); + auto const [localValues, localVars] = localError->localVariableValues(nodeArgs(*localErrorId)); + if (auto localStr = formatVariableModel(localVars, localValues, "\n"); !localStr.empty()) + localState += localStr + "\n"; + } } } - } - else - { - auto modelMsg = formatVariableModel(*stateVars, stateValues, ", "); - /// We report the state after every tx in the trace except for the last, which is reported - /// first in the code above. - if (!modelMsg.empty()) - path.emplace_back("State: " + modelMsg); + else + { + auto modelMsg = formatVariableModel(*stateVars, stateValues, ", "); + /// We report the state after every tx in the trace except for the last, which is reported + /// first in the code above. + if (!modelMsg.empty()) + path.emplace_back("State: " + modelMsg); + } } string txCex = summaryPredicate->formatSummaryCall(summaryArgs, m_charStreamProvider); @@ -1992,6 +2233,12 @@ optional CHC::generateCounterexample(CHCSolverInterface::CexGraph const& if (calls.size() > callTraceSize + 1) calls.front() += ", synthesized as:"; } + else if (pred->programVariable()) + { + calls.front() += "-- action on external contract in state variable \"" + pred->programVariable()->name() + "\""; + if (calls.size() > callTraceSize + 1) + calls.front() += ", synthesized as:"; + } else if (pred->isFunctionSummary() && parentPred->isExternalCallUntrusted()) calls.front() += " -- reentrant call"; }; @@ -2047,7 +2294,8 @@ map> CHC::summaryCalls(CHCSolverInterface::CexGraph c nodePred->isInternalCall() || nodePred->isExternalCallTrusted() || nodePred->isExternalCallUntrusted() || - rootPred->isExternalCallUntrusted() + rootPred->isExternalCallUntrusted() || + rootPred->programVariable() )) { calls[root].push_back(node); @@ -2105,3 +2353,31 @@ SymbolicIntVariable& CHC::errorFlag() { return state().errorFlag(); } + +void CHC::newTxConstraints(Expression const* _value) +{ + auto txOrigin = state().txMember("tx.origin"); + state().newTx(); + // set the transaction sender as this contract + m_context.addAssertion(state().txMember("msg.sender") == state().thisAddress()); + // set the origin to be the current transaction origin + m_context.addAssertion(state().txMember("tx.origin") == txOrigin); + + if (_value) + // set the msg value + m_context.addAssertion(state().txMember("msg.value") == expr(*_value)); +} + +frontend::Expression const* CHC::valueOption(FunctionCallOptions const* _options) +{ + if (_options) + for (auto&& [i, name]: _options->names() | ranges::views::enumerate) + if (name && *name == "value") + return _options->options().at(i).get(); + return nullptr; +} + +void CHC::decreaseBalanceFromOptionsValue(Expression const& _value) +{ + state().addBalance(state().thisAddress(), 0 - expr(_value)); +} diff --git a/libsolidity/formal/CHC.h b/libsolidity/formal/CHC.h index 8b81ffb59a..c113f85831 100644 --- a/libsolidity/formal/CHC.h +++ b/libsolidity/formal/CHC.h @@ -110,10 +110,14 @@ class CHC: public SMTEncoder void popInlineFrame(CallableDeclaration const& _callable) override; void visitAssert(FunctionCall const& _funCall); + void visitPublicGetter(FunctionCall const& _funCall) override; void visitAddMulMod(FunctionCall const& _funCall) override; + void visitDeployment(FunctionCall const& _funCall); void internalFunctionCall(FunctionCall const& _funCall); void externalFunctionCall(FunctionCall const& _funCall); void externalFunctionCallToTrustedCode(FunctionCall const& _funCall); + void addNondetCalls(ContractDefinition const& _contract); + void nondetCall(ContractDefinition const& _contract, VariableDeclaration const& _var); void unknownFunctionCall(FunctionCall const& _funCall); void makeArrayPopVerificationTarget(FunctionCall const& _arrayPop) override; void makeOutOfBoundsVerificationTarget(IndexAccess const& _access) override; @@ -135,6 +139,7 @@ class CHC: public SMTEncoder void clearIndices(ContractDefinition const* _contract, FunctionDefinition const* _function = nullptr) override; void setCurrentBlock(Predicate const& _block); std::set transactionVerificationTargetsIds(ASTNode const* _txRoot); + bool usesStaticCall(FunctionCall const& _funCall); //@} /// SMT Natspec and abstraction helpers. @@ -148,6 +153,10 @@ class CHC: public SMTEncoder /// @returns true if _function is Natspec annotated to be abstracted by /// nondeterministic values. bool abstractAsNondet(FunctionDefinition const& _function); + + /// @returns true if external calls should be considered trusted. + /// If that's the case, their code is used if available at compile time. + bool encodeExternalCallsAsTrusted(); //@} /// Sort helpers. @@ -310,6 +319,20 @@ class CHC: public SMTEncoder unsigned newErrorId(); smt::SymbolicIntVariable& errorFlag(); + + /// Adds to the solver constraints that + /// - propagate tx.origin + /// - set the current contract as msg.sender + /// - set the msg.value as _value, if not nullptr + void newTxConstraints(Expression const* _value); + + /// @returns the expression representing the value sent in + /// an external call if present, + /// and nullptr otherwise. + frontend::Expression const* valueOption(FunctionCallOptions const* _options); + + /// Adds constraints that decrease the balance of the caller by _value. + void decreaseBalanceFromOptionsValue(Expression const& _value); //@} /// Predicates. diff --git a/libsolidity/formal/ModelCheckerSettings.cpp b/libsolidity/formal/ModelCheckerSettings.cpp index 274571a154..d1e383d63f 100644 --- a/libsolidity/formal/ModelCheckerSettings.cpp +++ b/libsolidity/formal/ModelCheckerSettings.cpp @@ -130,3 +130,12 @@ std::optional ModelCheckerContracts::fromString(string co return ModelCheckerContracts{chosen}; } + +std::optional ModelCheckerExtCalls::fromString(string const& _mode) +{ + if (_mode == "untrusted") + return ModelCheckerExtCalls{Mode::UNTRUSTED}; + if (_mode == "trusted") + return ModelCheckerExtCalls{Mode::TRUSTED}; + return {}; +} diff --git a/libsolidity/formal/ModelCheckerSettings.h b/libsolidity/formal/ModelCheckerSettings.h index 2c86993b9d..3c1f623a07 100644 --- a/libsolidity/formal/ModelCheckerSettings.h +++ b/libsolidity/formal/ModelCheckerSettings.h @@ -140,6 +140,21 @@ struct ModelCheckerTargets std::set targets; }; +struct ModelCheckerExtCalls +{ + enum class Mode + { + UNTRUSTED, + TRUSTED + }; + + Mode mode = Mode::UNTRUSTED; + + static std::optional fromString(std::string const& _mode); + + bool isTrusted() const { return mode == Mode::TRUSTED; } +}; + struct ModelCheckerSettings { ModelCheckerContracts contracts = ModelCheckerContracts::Default(); @@ -151,6 +166,7 @@ struct ModelCheckerSettings /// might prefer the precise encoding. bool divModNoSlacks = false; ModelCheckerEngine engine = ModelCheckerEngine::None(); + ModelCheckerExtCalls externalCalls = {}; ModelCheckerInvariants invariants = ModelCheckerInvariants::Default(); bool showUnproved = false; smtutil::SMTSolverChoice solvers = smtutil::SMTSolverChoice::Z3(); @@ -164,6 +180,7 @@ struct ModelCheckerSettings contracts == _other.contracts && divModNoSlacks == _other.divModNoSlacks && engine == _other.engine && + externalCalls.mode == _other.externalCalls.mode && invariants == _other.invariants && showUnproved == _other.showUnproved && solvers == _other.solvers && diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 918728d86d..7119a59e8b 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -144,6 +144,11 @@ FunctionCall const* Predicate::programFunctionCall() const return dynamic_cast(m_node); } +VariableDeclaration const* Predicate::programVariable() const +{ + return dynamic_cast(m_node); +} + optional> Predicate::stateVariables() const { if (m_contractContext) @@ -214,6 +219,9 @@ string Predicate::formatSummaryCall( { solAssert(isSummary(), ""); + if (programVariable()) + return {}; + if (auto funCall = programFunctionCall()) { if (funCall->location().hasText()) @@ -348,6 +356,8 @@ vector> Predicate::summaryStateValues(vector(stateVars->size()); stateLast = stateFirst + static_cast(stateVars->size()); } + else if (programVariable()) + return {}; else solAssert(false, ""); diff --git a/libsolidity/formal/Predicate.h b/libsolidity/formal/Predicate.h index 16af42f45f..d7ac0da352 100644 --- a/libsolidity/formal/Predicate.h +++ b/libsolidity/formal/Predicate.h @@ -115,6 +115,10 @@ class Predicate /// or nullptr otherwise. FunctionCall const* programFunctionCall() const; + /// @returns the VariableDeclaration that this predicate represents + /// or nullptr otherwise. + VariableDeclaration const* programVariable() const; + /// @returns the program state variables in the scope of this predicate. std::optional> stateVariables() const; diff --git a/libsolidity/formal/PredicateInstance.cpp b/libsolidity/formal/PredicateInstance.cpp index aff6aa19b4..5e057efe37 100644 --- a/libsolidity/formal/PredicateInstance.cpp +++ b/libsolidity/formal/PredicateInstance.cpp @@ -70,14 +70,14 @@ smtutil::Expression constructor(Predicate const& _pred, EncodingContext& _contex return _pred(stateExprs + initialStateVariables(contract, _context) + currentStateVariables(contract, _context)); } -smtutil::Expression constructorCall(Predicate const& _pred, EncodingContext& _context) +smtutil::Expression constructorCall(Predicate const& _pred, EncodingContext& _context, bool _internal) { auto const& contract = dynamic_cast(*_pred.programNode()); if (auto const* constructor = contract.constructor()) - return _pred(currentFunctionVariablesForCall(*constructor, &contract, _context)); + return _pred(currentFunctionVariablesForCall(*constructor, &contract, _context, _internal)); auto& state = _context.state(); - vector stateExprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state()}; + vector stateExprs{state.errorFlag().currentValue(), _internal ? state.thisAddress(0) : state.thisAddress(), state.abi(0), state.crypto(0), _internal ? state.tx(0) : state.tx(), state.state()}; state.newState(); stateExprs += vector{state.state()}; stateExprs += currentStateVariables(contract, _context); @@ -166,11 +166,12 @@ vector currentFunctionVariablesForDefinition( vector currentFunctionVariablesForCall( FunctionDefinition const& _function, ContractDefinition const* _contract, - EncodingContext& _context + EncodingContext& _context, + bool _internal ) { auto& state = _context.state(); - vector exprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state()}; + vector exprs{state.errorFlag().currentValue(), _internal ? state.thisAddress(0) : state.thisAddress(), state.abi(0), state.crypto(0), _internal ? state.tx(0) : state.tx(), state.state()}; exprs += _contract ? currentStateVariables(*_contract, _context) : vector{}; exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); diff --git a/libsolidity/formal/PredicateInstance.h b/libsolidity/formal/PredicateInstance.h index 2f6c773813..42a9e2040b 100644 --- a/libsolidity/formal/PredicateInstance.h +++ b/libsolidity/formal/PredicateInstance.h @@ -37,7 +37,14 @@ smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& smtutil::Expression nondetInterface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context, unsigned _preIdx, unsigned _postIdx); smtutil::Expression constructor(Predicate const& _pred, EncodingContext& _context); -smtutil::Expression constructorCall(Predicate const& _pred, EncodingContext& _context); +/// The encoding of the deployment procedure includes adding constraints +/// for base constructors if inheritance is used. +/// From the predicate point of view this is not different, +/// but some of the arguments are different. +/// @param _internal = true means that this constructor call is used in the +/// deployment procedure, whereas false means it is used in the deployment +/// of a contract. +smtutil::Expression constructorCall(Predicate const& _pred, EncodingContext& _context, bool _internal = true); smtutil::Expression function( Predicate const& _pred, @@ -77,7 +84,8 @@ std::vector currentFunctionVariablesForDefinition( std::vector currentFunctionVariablesForCall( FunctionDefinition const& _function, ContractDefinition const* _contract, - EncodingContext& _context + EncodingContext& _context, + bool _internal = true ); std::vector currentBlockVariables( diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 810b533512..c3286fa041 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -637,7 +637,7 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall) visitGasLeft(_funCall); break; case FunctionType::Kind::External: - if (isPublicGetter(_funCall.expression())) + if (publicGetter(_funCall.expression())) visitPublicGetter(_funCall); break; case FunctionType::Kind::ABIDecode: @@ -696,10 +696,18 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::ObjectCreation: visitObjectCreation(_funCall); return; + case FunctionType::Kind::Creation: + if (!m_settings.engine.chc || !m_settings.externalCalls.isTrusted()) + m_errorReporter.warning( + 8729_error, + _funCall.location(), + "Contract deployment is only supported in the trusted mode for external calls" + " with the CHC engine." + ); + break; case FunctionType::Kind::DelegateCall: case FunctionType::Kind::BareCallCode: case FunctionType::Kind::BareDelegateCall: - case FunctionType::Kind::Creation: default: m_errorReporter.warning( 4588_error, @@ -978,9 +986,8 @@ vector structGetterReturnedMembers(StructType const& _structType) void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall) { - MemberAccess const& access = dynamic_cast(_funCall.expression()); - auto var = dynamic_cast(access.annotation().referencedDeclaration); - solAssert(var, ""); + auto var = publicGetter(_funCall.expression()); + solAssert(var && var->isStateVariable(), ""); solAssert(m_context.knownExpression(_funCall), ""); auto paramExpectedTypes = replaceUserTypes(FunctionType(*var).parameterTypes()); auto actualArguments = _funCall.arguments(); @@ -1054,7 +1061,7 @@ bool SMTEncoder::shouldAnalyze(ContractDefinition const& _contract) const return false; return m_settings.contracts.isDefault() || - m_settings.contracts.has(_contract.sourceUnitName(), _contract.name()); + m_settings.contracts.has(_contract.sourceUnitName()); } void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall) @@ -2789,16 +2796,24 @@ MemberAccess const* SMTEncoder::isEmptyPush(Expression const& _expr) const return nullptr; } -bool SMTEncoder::isPublicGetter(Expression const& _expr) { - if (!isTrustedExternalCall(&_expr)) - return false; - auto varDecl = dynamic_cast( - dynamic_cast(_expr).annotation().referencedDeclaration - ); - return varDecl != nullptr; +smtutil::Expression SMTEncoder::contractAddressValue(FunctionCall const& _f) +{ + FunctionType const& funType = dynamic_cast(*_f.expression().annotation().type); + if (funType.kind() == FunctionType::Kind::Internal) + return state().thisAddress(); + auto [funExpr, funOptions] = functionCallExpression(_f); + if (MemberAccess const* callBase = dynamic_cast(funExpr)) + return expr(callBase->expression()); + solAssert(false, "Unreachable!"); +} + +VariableDeclaration const* SMTEncoder::publicGetter(Expression const& _expr) const { + if (auto memberAccess = dynamic_cast(&_expr)) + return dynamic_cast(memberAccess->annotation().referencedDeclaration); + return nullptr; } -bool SMTEncoder::isTrustedExternalCall(Expression const* _expr) { +bool SMTEncoder::isExternalCallToThis(Expression const* _expr) { auto memberAccess = dynamic_cast(_expr); if (!memberAccess) return false; @@ -3060,7 +3075,7 @@ RationalNumberType const* SMTEncoder::isConstant(Expression const& _expr) return nullptr; } -set SMTEncoder::collectABICalls(ASTNode const* _node) +set> SMTEncoder::collectABICalls(ASTNode const* _node) { struct ABIFunctions: public ASTConstVisitor { @@ -3082,7 +3097,7 @@ set SMTEncoder::collectABICalls(ASTNode const* _node) } } - set abiCalls; + set> abiCalls; }; return ABIFunctions(_node).abiCalls; diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index 2ba491a0b0..06b03a7eb8 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -123,7 +123,7 @@ class SMTEncoder: public ASTConstVisitor /// RationalNumberType or can be const evaluated, and nullptr otherwise. static RationalNumberType const* isConstant(Expression const& _expr); - static std::set collectABICalls(ASTNode const* _node); + static std::set> collectABICalls(ASTNode const* _node); /// @returns all the sources that @param _source depends on, /// including itself. @@ -219,7 +219,7 @@ class SMTEncoder: public ASTConstVisitor void visitTypeConversion(FunctionCall const& _funCall); void visitStructConstructorCall(FunctionCall const& _funCall); void visitFunctionIdentifier(Identifier const& _identifier); - void visitPublicGetter(FunctionCall const& _funCall); + virtual void visitPublicGetter(FunctionCall const& _funCall); /// @returns true if @param _contract is set for analysis in the settings /// and it is not abstract. @@ -227,7 +227,12 @@ class SMTEncoder: public ASTConstVisitor /// @returns true if @param _source is set for analysis in the settings. bool shouldAnalyze(SourceUnit const& _source) const; - bool isPublicGetter(Expression const& _expr); + /// @returns the state variable returned by a public getter if + /// @a _expr is a call to a public getter, + /// otherwise nullptr. + VariableDeclaration const* publicGetter(Expression const& _expr) const; + + smtutil::Expression contractAddressValue(FunctionCall const& _f); /// Encodes a modifier or function body according to the modifier /// visit depth. @@ -392,9 +397,9 @@ class SMTEncoder: public ASTConstVisitor /// otherwise nullptr. MemberAccess const* isEmptyPush(Expression const& _expr) const; - /// @returns true if the given identifier is a contract which is known and trusted. + /// @returns true if the given expression is `this`. /// This means we don't have to abstract away effects of external function calls to this contract. - static bool isTrustedExternalCall(Expression const* _expr); + static bool isExternalCallToThis(Expression const* _expr); /// Creates symbolic expressions for the returned values /// and set them as the components of the symbolic tuple. diff --git a/libsolidity/formal/SymbolicState.cpp b/libsolidity/formal/SymbolicState.cpp index 3afde0dcf5..68bd9b6462 100644 --- a/libsolidity/formal/SymbolicState.cpp +++ b/libsolidity/formal/SymbolicState.cpp @@ -22,8 +22,13 @@ #include #include +#include + +#include + using namespace std; using namespace solidity; +using namespace solidity::util; using namespace solidity::smtutil; using namespace solidity::frontend::smt; @@ -58,16 +63,8 @@ smtutil::Expression BlockchainVariable::member(string const& _member) const smtutil::Expression BlockchainVariable::assignMember(string const& _member, smtutil::Expression const& _value) { - vector args; - for (auto const& m: m_members) - if (m.first == _member) - args.emplace_back(_value); - else - args.emplace_back(member(m.first)); - m_tuple->increaseIndex(); - auto tuple = m_tuple->currentValue(); - auto sortExpr = smtutil::Expression(make_shared(tuple.sort), tuple.name); - m_context.addAssertion(tuple == smtutil::Expression::tuple_constructor(sortExpr, args)); + smtutil::Expression newTuple = smt::assignMember(m_tuple->currentValue(), {{_member, _value}}); + m_context.addAssertion(m_tuple->increaseIndex() == newTuple); return m_tuple->currentValue(); } @@ -75,16 +72,19 @@ void SymbolicState::reset() { m_error.resetIndex(); m_thisAddress.resetIndex(); - m_state.reset(); m_tx.reset(); m_crypto.reset(); if (m_abi) m_abi->reset(); + /// We don't reset nor clear these pointers on purpose, + /// since it only helps to keep the already generated types. + if (m_state) + m_state->reset(); } smtutil::Expression SymbolicState::balances() const { - return m_state.member("balances"); + return m_state->member("balances"); } smtutil::Expression SymbolicState::balance() const @@ -107,24 +107,94 @@ void SymbolicState::newBalances() auto tupleSort = dynamic_pointer_cast(stateSort()); auto balanceSort = tupleSort->components.at(tupleSort->memberToIndex.at("balances")); SymbolicVariable newBalances(balanceSort, "fresh_balances_" + to_string(m_context.newUniqueId()), m_context); - m_state.assignMember("balances", newBalances.currentValue()); + m_state->assignMember("balances", newBalances.currentValue()); } void SymbolicState::transfer(smtutil::Expression _from, smtutil::Expression _to, smtutil::Expression _value) { - unsigned indexBefore = m_state.index(); + unsigned indexBefore = m_state->index(); addBalance(_from, 0 - _value); addBalance(_to, std::move(_value)); - unsigned indexAfter = m_state.index(); + unsigned indexAfter = m_state->index(); solAssert(indexAfter > indexBefore, ""); - m_state.newVar(); + m_state->newVar(); /// Do not apply the transfer operation if _from == _to. auto newState = smtutil::Expression::ite( std::move(_from) == std::move(_to), - m_state.value(indexBefore), - m_state.value(indexAfter) + m_state->value(indexBefore), + m_state->value(indexAfter) + ); + m_context.addAssertion(m_state->value() == newState); +} + +smtutil::Expression SymbolicState::storage(ContractDefinition const& _contract) const +{ + return smt::member(m_state->member("storage"), contractStorageKey(_contract)); +} + +smtutil::Expression SymbolicState::storage(ContractDefinition const& _contract, smtutil::Expression _address) const +{ + return smtutil::Expression::select(storage(_contract), std::move(_address)); +} + +smtutil::Expression SymbolicState::addressActive(smtutil::Expression _address) const +{ + return smtutil::Expression::select(m_state->member("isActive"), std::move(_address)); +} + +void SymbolicState::setAddressActive( + smtutil::Expression _address, + bool _active +) +{ + m_state->assignMember("isActive", smtutil::Expression::store( + m_state->member("isActive"), + std::move(_address), + smtutil::Expression(_active)) + ); +} + +void SymbolicState::newStorage() +{ + auto newStorageVar = SymbolicTupleVariable( + m_state->member("storage").sort, + "havoc_storage_" + to_string(m_context.newUniqueId()), + m_context ); - m_context.addAssertion(m_state.value() == newState); + m_state->assignMember("storage", newStorageVar.currentValue()); +} + +void SymbolicState::writeStateVars(ContractDefinition const& _contract, smtutil::Expression _address) +{ + auto stateVars = SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract); + if (stateVars.empty()) + return; + + map values; + for (auto var: stateVars) + values.emplace(stateVarStorageKey(*var, _contract), m_context.variable(*var)->currentValue()); + + smtutil::Expression thisStorage = storage(_contract, _address); + smtutil::Expression newStorage = smt::assignMember(thisStorage, values); + auto newContractStorage = smtutil::Expression::store( + storage(_contract), std::move(_address), newStorage + ); + smtutil::Expression newAllStorage = smt::assignMember(m_state->member("storage"), {{contractStorageKey(_contract), newContractStorage}}); + m_state->assignMember("storage", newAllStorage); +} + +void SymbolicState::readStateVars(ContractDefinition const& _contract, smtutil::Expression _address) +{ + auto stateVars = SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract); + if (stateVars.empty()) + return; + + auto contractStorage = storage(_contract, std::move(_address)); + for (auto var: stateVars) + m_context.addAssertion( + m_context.variable(*var)->increaseIndex() == + smt::member(contractStorage, stateVarStorageKey(*var, _contract)) + ); } void SymbolicState::addBalance(smtutil::Expression _address, smtutil::Expression _value) @@ -134,7 +204,7 @@ void SymbolicState::addBalance(smtutil::Expression _address, smtutil::Expression _address, balance(_address) + std::move(_value) ); - m_state.assignMember("balances", newBalances); + m_state->assignMember("balances", newBalances); } smtutil::Expression SymbolicState::txMember(string const& _member) const @@ -194,17 +264,99 @@ smtutil::Expression SymbolicState::txFunctionConstraints(FunctionDefinition cons return conj; } -void SymbolicState::prepareForSourceUnit(SourceUnit const& _source) +void SymbolicState::prepareForSourceUnit(SourceUnit const& _source, bool _storage) { - set abiCalls = SMTEncoder::collectABICalls(&_source); - for (auto const& source: _source.referencedSourceUnits(true)) + auto allSources = _source.referencedSourceUnits(true); + allSources.insert(&_source); + set> abiCalls; + set> contracts; + for (auto const& source: allSources) + { abiCalls += SMTEncoder::collectABICalls(source); + for (auto node: source->nodes()) + if (auto contract = dynamic_cast(node.get())) + contracts.insert(contract); + } + buildState(contracts, _storage); buildABIFunctions(abiCalls); } /// Private helpers. -void SymbolicState::buildABIFunctions(set const& _abiFunctions) +string SymbolicState::contractSuffix(ContractDefinition const& _contract) const +{ + return "_" + _contract.name() + "_" + to_string(_contract.id()); +} + +string SymbolicState::contractStorageKey(ContractDefinition const& _contract) const +{ + return "storage" + contractSuffix(_contract); +} + +string SymbolicState::stateVarStorageKey(VariableDeclaration const& _var, ContractDefinition const& _contract) const +{ + return _var.name() + "_" + to_string(_var.id()) + contractSuffix(_contract); +} + +void SymbolicState::buildState(set> const& _contracts, bool _allStorages) +{ + map stateMembers{ + {"balances", make_shared(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)} + }; + + if (_allStorages) + { + vector memberNames; + vector memberSorts; + for (auto contract: _contracts) + { + string suffix = contractSuffix(*contract); + + // z3 doesn't like empty tuples, so if the contract has 0 + // state vars we can't put it there. + auto stateVars = SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*contract); + if (stateVars.empty()) + continue; + + auto names = applyMap(stateVars, [&](auto var) { + return var->name() + "_" + to_string(var->id()) + suffix; + }); + auto sorts = applyMap(stateVars, [](auto var) { return smtSortAbstractFunction(*var->type()); }); + + string name = "storage" + suffix; + auto storageTuple = make_shared( + name + "_type", names, sorts + ); + + auto storageSort = make_shared( + smtSort(*TypeProvider::address()), + storageTuple + ); + + memberNames.emplace_back(name); + memberSorts.emplace_back(storageSort); + } + + stateMembers.emplace( + "isActive", + make_shared(smtSort(*TypeProvider::address()), smtutil::SortProvider::boolSort) + ); + stateMembers.emplace( + "storage", + make_shared( + "storage_type", memberNames, memberSorts + ) + ); + } + + m_state = make_unique( + "state", + std::move(stateMembers), + m_context + ); +} + +void SymbolicState::buildABIFunctions(set> const& _abiFunctions) { map functions; diff --git a/libsolidity/formal/SymbolicState.h b/libsolidity/formal/SymbolicState.h index 45c129c1b1..7fe5b028d6 100644 --- a/libsolidity/formal/SymbolicState.h +++ b/libsolidity/formal/SymbolicState.h @@ -62,7 +62,8 @@ class BlockchainVariable * - this (the address of the currently executing contract) * - state, represented as a tuple of: * - balances - * - TODO: potentially storage of contracts + * - array of address => bool representing whether an address is used by a contract + * - storage of contracts * - block and transaction properties, represented as a tuple of: * - blockhash * - block basefee @@ -99,29 +100,41 @@ class SymbolicState /// @returns the symbolic value of the currently executing contract's address. smtutil::Expression thisAddress() const { return m_thisAddress.currentValue(); } smtutil::Expression thisAddress(unsigned _idx) const { return m_thisAddress.valueAtIndex(_idx); } + smtutil::Expression newThisAddress() { return m_thisAddress.increaseIndex(); } smtutil::SortPointer const& thisAddressSort() const { return m_thisAddress.sort(); } //@} /// Blockchain state. //@{ - smtutil::Expression state() const { return m_state.value(); } - smtutil::Expression state(unsigned _idx) const { return m_state.value(_idx); } - smtutil::SortPointer const& stateSort() const { return m_state.sort(); } - void newState() { m_state.newVar(); } + smtutil::Expression state() const { solAssert(m_state, ""); return m_state->value(); } + smtutil::Expression state(unsigned _idx) const { solAssert(m_state, ""); return m_state->value(_idx); } + smtutil::SortPointer const& stateSort() const { solAssert(m_state, ""); return m_state->sort(); } + void newState() { solAssert(m_state, ""); m_state->newVar(); } void newBalances(); + + /// Balance. /// @returns the symbolic balances. smtutil::Expression balances() const; /// @returns the symbolic balance of address `this`. smtutil::Expression balance() const; /// @returns the symbolic balance of an address. smtutil::Expression balance(smtutil::Expression _address) const; - /// Transfer _value from _from to _to. void transfer(smtutil::Expression _from, smtutil::Expression _to, smtutil::Expression _value); /// Adds _value to _account's balance. void addBalance(smtutil::Expression _account, smtutil::Expression _value); + + /// Storage. + smtutil::Expression storage(ContractDefinition const& _contract) const; + smtutil::Expression storage(ContractDefinition const& _contract, smtutil::Expression _address) const; + smtutil::Expression addressActive(smtutil::Expression _address) const; + void setAddressActive(smtutil::Expression _address, bool _active); + + void newStorage(); + void writeStateVars(ContractDefinition const& _contract, smtutil::Expression _address); + void readStateVars(ContractDefinition const& _contract, smtutil::Expression _address); //@} /// Transaction data. @@ -149,11 +162,15 @@ class SymbolicState smtutil::Expression cryptoFunction(std::string const& _member) const { return m_crypto.member(_member); } //@} + /// Calls the internal methods that build + /// - the symbolic ABI functions based on the abi.* calls + /// in _source and referenced sources. + /// - the symbolic storages for all contracts in _source and + /// referenced sources. + void prepareForSourceUnit(SourceUnit const& _source, bool _storage); + /// ABI functions. //@{ - /// Calls the internal methods that build the symbolic ABI functions - /// based on the abi.* calls in _source and referenced sources. - void prepareForSourceUnit(SourceUnit const& _source); smtutil::Expression abiFunction(FunctionCall const* _funCall); using SymbolicABIFunction = std::tuple< std::string, @@ -169,8 +186,15 @@ class SymbolicState //@} private: + std::string contractSuffix(ContractDefinition const& _contract) const; + std::string contractStorageKey(ContractDefinition const& _contract) const; + std::string stateVarStorageKey(VariableDeclaration const& _var, ContractDefinition const& _contract) const; + + /// Builds state.storage based on _contracts. + void buildState(std::set> const& _contracts, bool _allStorages); + /// Builds m_abi based on the abi.* calls _abiFunctions. - void buildABIFunctions(std::set const& _abiFunctions); + void buildABIFunctions(std::set> const& _abiFunctions); EncodingContext& m_context; @@ -186,11 +210,14 @@ class SymbolicState m_context }; - BlockchainVariable m_state{ - "state", - {{"balances", std::make_shared(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)}}, - m_context - }; + /// m_state is a tuple of + /// - balances: array of address to balance of address. + /// - isActive: array of address to Boolean, where element is true iff address is used. + /// - storage: tuple containing the storage of every contract, where + /// each element of the tuple represents a contract, + /// and is defined by an array where the index is the contract's address + /// and the element is a tuple containing the state variables of that contract. + std::unique_ptr m_state; BlockchainVariable m_tx{ "tx", diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index d40b51cea4..ccabebcc3b 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -618,4 +618,26 @@ optional symbolicTypeConversion(frontend::Type const* _from return std::nullopt; } +smtutil::Expression member(smtutil::Expression const& _tuple, string const& _member) +{ + TupleSort const& _sort = dynamic_cast(*_tuple.sort); + return smtutil::Expression::tuple_get( + _tuple, + _sort.memberToIndex.at(_member) + ); +} + +smtutil::Expression assignMember(smtutil::Expression const _tuple, map const& _values) +{ + TupleSort const& _sort = dynamic_cast(*_tuple.sort); + vector args; + for (auto const& m: _sort.members) + if (auto* value = util::valueOrNullptr(_values, m)) + args.emplace_back(*value); + else + args.emplace_back(member(_tuple, m)); + auto sortExpr = smtutil::Expression(make_shared(_tuple.sort), _tuple.name); + return smtutil::Expression::tuple_constructor(sortExpr, args); +} + } diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index 312e8581a9..747e27b7e3 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -82,4 +82,8 @@ void setSymbolicUnknownValue(smtutil::Expression _expr, frontend::Type const* _t smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, frontend::Type const* _type); std::optional symbolicTypeConversion(frontend::Type const* _from, frontend::Type const* _to); + +smtutil::Expression member(smtutil::Expression const& _tuple, std::string const& _member); +smtutil::Expression assignMember(smtutil::Expression const _tuple, std::map const& _values); + } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 27fa1c9896..b08e8fbf6f 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -445,7 +445,7 @@ std::optional checkSettingsKeys(Json::Value const& _input) std::optional checkModelCheckerSettingsKeys(Json::Value const& _input) { - static set keys{"contracts", "divModNoSlacks", "engine", "invariants", "showUnproved", "solvers", "targets", "timeout"}; + static set keys{"contracts", "divModNoSlacks", "engine", "extCalls", "invariants", "showUnproved", "solvers", "targets", "timeout"}; return checkKeys(_input, keys, "modelChecker"); } @@ -1016,6 +1016,16 @@ std::variant StandardCompiler: ret.modelCheckerSettings.engine = *engine; } + if (modelCheckerSettings.isMember("extCalls")) + { + if (!modelCheckerSettings["extCalls"].isString()) + return formatFatalError(Error::Type::JSONError, "settings.modelChecker.extCalls must be a string."); + std::optional extCalls = ModelCheckerExtCalls::fromString(modelCheckerSettings["extCalls"].asString()); + if (!extCalls) + return formatFatalError(Error::Type::JSONError, "Invalid model checker extCalls requested."); + ret.modelCheckerSettings.externalCalls = *extCalls; + } + if (modelCheckerSettings.isMember("invariants")) { auto const& invariantsArray = modelCheckerSettings["invariants"]; diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 37ceca1d40..eb03831beb 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -69,6 +69,7 @@ static string const g_strMetadataLiteral = "metadata-literal"; static string const g_strModelCheckerContracts = "model-checker-contracts"; static string const g_strModelCheckerDivModNoSlacks = "model-checker-div-mod-no-slacks"; static string const g_strModelCheckerEngine = "model-checker-engine"; +static string const g_strModelCheckerExtCalls = "model-checker-ext-calls"; static string const g_strModelCheckerInvariants = "model-checker-invariants"; static string const g_strModelCheckerShowUnproved = "model-checker-show-unproved"; static string const g_strModelCheckerSolvers = "model-checker-solvers"; @@ -831,6 +832,12 @@ General Information)").c_str(), po::value()->value_name("all,bmc,chc,none")->default_value("none"), "Select model checker engine." ) + ( + g_strModelCheckerExtCalls.c_str(), + po::value()->value_name("untrusted,trusted")->default_value("untrusted"), + "Select whether to assume (trusted) that external calls always invoke" + " the code given by the type of the contract, if that code is available." + ) ( g_strModelCheckerInvariants.c_str(), po::value()->value_name("default,all,contract,reentrancy")->default_value("default"), @@ -1289,6 +1296,15 @@ void CommandLineParser::processArgs() m_options.modelChecker.settings.engine = *engine; } + if (m_args.count(g_strModelCheckerExtCalls)) + { + string mode = m_args[g_strModelCheckerExtCalls].as(); + optional extCallsMode = ModelCheckerExtCalls::fromString(mode); + if (!extCallsMode) + solThrow(CommandLineValidationError, "Invalid option for --" + g_strModelCheckerExtCalls + ": " + mode); + m_options.modelChecker.settings.externalCalls = *extCallsMode; + } + if (m_args.count(g_strModelCheckerInvariants)) { string invsStr = m_args[g_strModelCheckerInvariants].as(); @@ -1327,6 +1343,7 @@ void CommandLineParser::processArgs() m_args.count(g_strModelCheckerContracts) || m_args.count(g_strModelCheckerDivModNoSlacks) || m_args.count(g_strModelCheckerEngine) || + m_args.count(g_strModelCheckerExtCalls) || m_args.count(g_strModelCheckerInvariants) || m_args.count(g_strModelCheckerShowUnproved) || m_args.count(g_strModelCheckerSolvers) || diff --git a/test/cmdlineTests/model_checker_contracts_inexistent_contract/err b/test/cmdlineTests/model_checker_contracts_inexistent_contract/err index 6326537e92..00b97763f3 100644 --- a/test/cmdlineTests/model_checker_contracts_inexistent_contract/err +++ b/test/cmdlineTests/model_checker_contracts_inexistent_contract/err @@ -1 +1,27 @@ Warning: Requested contract "C" does not exist in source "model_checker_contracts_inexistent_contract/input.sol". + +Warning: CHC: Assertion violation happens here. +Counterexample: + +x = 0 + +Transaction trace: +B.constructor() +B.f(0) + --> model_checker_contracts_inexistent_contract/input.sol:5:3: + | +5 | assert(x > 0); + | ^^^^^^^^^^^^^ + +Warning: CHC: Assertion violation happens here. +Counterexample: + +y = 0 + +Transaction trace: +A.constructor() +A.g(0) + --> model_checker_contracts_inexistent_contract/input.sol:10:3: + | +10 | assert(y > 0); + | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_contracts_only_one/err b/test/cmdlineTests/model_checker_contracts_only_one/err index 9c8ade6931..2088e19c7a 100644 --- a/test/cmdlineTests/model_checker_contracts_only_one/err +++ b/test/cmdlineTests/model_checker_contracts_only_one/err @@ -4,7 +4,7 @@ Counterexample: x = 0 Transaction trace: -A.constructor() +B.constructor() B.f(0) --> model_checker_contracts_only_one/input.sol:5:3: | diff --git a/test/cmdlineTests/model_checker_ext_calls_empty_arg/args b/test/cmdlineTests/model_checker_ext_calls_empty_arg/args new file mode 100644 index 0000000000..b0c065ef7b --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_empty_arg/args @@ -0,0 +1 @@ +--model-checker-engine chc --model-checker-ext-calls diff --git a/test/cmdlineTests/model_checker_ext_calls_empty_arg/err b/test/cmdlineTests/model_checker_ext_calls_empty_arg/err new file mode 100644 index 0000000000..7d7481c80e --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_empty_arg/err @@ -0,0 +1 @@ +No input files given. If you wish to use the standard input please specify "-" explicitly. diff --git a/test/cmdlineTests/model_checker_ext_calls_empty_arg/exit b/test/cmdlineTests/model_checker_ext_calls_empty_arg/exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_empty_arg/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/model_checker_ext_calls_empty_arg/input.sol b/test/cmdlineTests/model_checker_ext_calls_empty_arg/input.sol new file mode 100644 index 0000000000..bd341cea60 --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_empty_arg/input.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract Ext { + function f() public view returns (uint) { + return 42; + } +} + +contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 42); + } +} \ No newline at end of file diff --git a/test/cmdlineTests/model_checker_ext_calls_trusted_chc/args b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/args new file mode 100644 index 0000000000..a6240ee19f --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/args @@ -0,0 +1 @@ +--model-checker-engine chc --model-checker-ext-calls trusted diff --git a/test/cmdlineTests/model_checker_ext_calls_trusted_chc/err b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/err new file mode 100644 index 0000000000..a07e1575d1 --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/err @@ -0,0 +1,5 @@ +Warning: Function state mutability can be restricted to pure + --> model_checker_ext_calls_trusted_chc/input.sol:5:2: + | +5 | function f() public view returns (uint) { + | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/model_checker_ext_calls_trusted_chc/input.sol b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/input.sol new file mode 100644 index 0000000000..bd341cea60 --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/input.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract Ext { + function f() public view returns (uint) { + return 42; + } +} + +contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 42); + } +} \ No newline at end of file diff --git a/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/args b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/args new file mode 100644 index 0000000000..e249f02503 --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/args @@ -0,0 +1 @@ +--model-checker-engine chc --model-checker-ext-calls untrusted diff --git a/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err new file mode 100644 index 0000000000..b06333e43b --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err @@ -0,0 +1,14 @@ +Warning: CHC: Assertion violation happens here. +Counterexample: + +e = 0 +x = 1 + +Transaction trace: +test.constructor() +test.g(0) + e.f() -- untrusted external call + --> model_checker_ext_calls_untrusted_chc/input.sol:11:3: + | +11 | assert(x == 0); + | ^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/input.sol b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/input.sol new file mode 100644 index 0000000000..0d28d1c18b --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/input.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +abstract contract Ext { + function f() virtual public view returns (uint); +} + +contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 0); + } +} \ No newline at end of file diff --git a/test/cmdlineTests/model_checker_ext_calls_wrong_arg/args b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/args new file mode 100644 index 0000000000..478aa5e1d3 --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/args @@ -0,0 +1 @@ +--model-checker-engine chc --model-checker-ext-calls what diff --git a/test/cmdlineTests/model_checker_ext_calls_wrong_arg/err b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/err new file mode 100644 index 0000000000..746a0b5252 --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/err @@ -0,0 +1 @@ +Invalid option for --model-checker-ext-calls: what diff --git a/test/cmdlineTests/model_checker_ext_calls_wrong_arg/exit b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/model_checker_ext_calls_wrong_arg/input.sol b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/input.sol new file mode 100644 index 0000000000..bd341cea60 --- /dev/null +++ b/test/cmdlineTests/model_checker_ext_calls_wrong_arg/input.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract Ext { + function f() public view returns (uint) { + return 42; + } +} + +contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 42); + } +} \ No newline at end of file diff --git a/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json b/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json index e3714e8e68..7ff30950c1 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json @@ -10,6 +10,74 @@ "message": "Requested contract \"C\" does not exist in source \"Source\".", "severity": "warning", "type": "Warning" + }, + { + "component": "general", + "errorCode": "6328", + "formattedMessage": "Warning: CHC: Assertion violation happens here. +Counterexample: + +y = 0 + +Transaction trace: +B.constructor() +B.g(0) + --> Source:5:7: + | +5 | \t\t\t\t\t\tassert(y > 0); + | \t\t\t\t\t\t^^^^^^^^^^^^^ + +", + "message": "CHC: Assertion violation happens here. +Counterexample: + +y = 0 + +Transaction trace: +B.constructor() +B.g(0)", + "severity": "warning", + "sourceLocation": + { + "end": 137, + "file": "Source", + "start": 124 + }, + "type": "Warning" + }, + { + "component": "general", + "errorCode": "6328", + "formattedMessage": "Warning: CHC: Assertion violation happens here. +Counterexample: + +x = 0 + +Transaction trace: +A.constructor() +A.f(0) + --> Source:10:7: + | +10 | \t\t\t\t\t\tassert(x > 0); + | \t\t\t\t\t\t^^^^^^^^^^^^^ + +", + "message": "CHC: Assertion violation happens here. +Counterexample: + +x = 0 + +Transaction trace: +A.constructor() +A.f(0)", + "severity": "warning", + "sourceLocation": + { + "end": 231, + "file": "Source", + "start": 218 + }, + "type": "Warning" } ], "sources": diff --git a/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json b/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json index a875665817..cb18875e1b 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json @@ -10,7 +10,7 @@ Counterexample: y = 0 Transaction trace: -A.constructor() +B.constructor() B.g(0) --> Source:5:7: | @@ -24,7 +24,7 @@ Counterexample: y = 0 Transaction trace: -A.constructor() +B.constructor() B.g(0)", "severity": "warning", "sourceLocation": diff --git a/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json b/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json index 57c4f10fac..b4bfd66b84 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json @@ -10,7 +10,7 @@ Counterexample: y = 0 Transaction trace: -A.constructor() +B.constructor() B.g(0) --> Source:5:7: | @@ -24,7 +24,7 @@ Counterexample: y = 0 Transaction trace: -A.constructor() +B.constructor() B.g(0)", "severity": "warning", "sourceLocation": diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/input.json b/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/input.json new file mode 100644 index 0000000000..073516ddbd --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/input.json @@ -0,0 +1,30 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; + contract Ext { + function f() public view returns (uint) { + return 42; + } + } + + contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 42); + } + }" + } + }, + "settings": + { + "modelChecker": + { + "engine": "chc", + "extCalls": "" + } + } +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json new file mode 100644 index 0000000000..4e214a37b2 --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "Invalid model checker extCalls requested.", + "message": "Invalid model checker extCalls requested.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/input.json b/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/input.json new file mode 100644 index 0000000000..a03b77f2bb --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/input.json @@ -0,0 +1,30 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; + contract Ext { + function f() public view returns (uint) { + return 42; + } + } + + contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 42); + } + }" + } + }, + "settings": + { + "modelChecker": + { + "engine": "chc", + "extCalls": "trusted" + } + } +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json new file mode 100644 index 0000000000..93d73d1c46 --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json @@ -0,0 +1,32 @@ +{ + "errors": + [ + { + "component": "general", + "errorCode": "2018", + "formattedMessage": "Warning: Function state mutability can be restricted to pure + --> A:4:7: + | +4 | \t\t\t\t\t\tfunction f() public view returns (uint) { + | \t\t\t\t\t\t^ (Relevant source part starts here and spans across multiple lines). + +", + "message": "Function state mutability can be restricted to pure", + "severity": "warning", + "sourceLocation": + { + "end": 152, + "file": "A", + "start": 85 + }, + "type": "Warning" + } + ], + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/input.json b/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/input.json new file mode 100644 index 0000000000..9fadd08fab --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/input.json @@ -0,0 +1,28 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; + abstract contract Ext { + function f() virtual public view returns (uint); + } + + contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 0); + } + }" + } + }, + "settings": + { + "modelChecker": + { + "engine": "chc", + "extCalls": "untrusted" + } + } +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json new file mode 100644 index 0000000000..c6b072a858 --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json @@ -0,0 +1,50 @@ +{ + "errors": + [ + { + "component": "general", + "errorCode": "6328", + "formattedMessage": "Warning: CHC: Assertion violation happens here. +Counterexample: + +e = 0 +x = 1 + +Transaction trace: +test.constructor() +test.g(0) + e.f() -- untrusted external call + --> A:10:8: + | +10 | \t\t\t\t\t\t\tassert(x == 0); + | \t\t\t\t\t\t\t^^^^^^^^^^^^^^ + +", + "message": "CHC: Assertion violation happens here. +Counterexample: + +e = 0 +x = 1 + +Transaction trace: +test.constructor() +test.g(0) + e.f() -- untrusted external call", + "severity": "warning", + "sourceLocation": + { + "end": 254, + "file": "A", + "start": 240 + }, + "type": "Warning" + } + ], + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/input.json b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/input.json new file mode 100644 index 0000000000..15113c5ad8 --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/input.json @@ -0,0 +1,30 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; + contract Ext { + function f() public view returns (uint) { + return 42; + } + } + + contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 42); + } + }" + } + }, + "settings": + { + "modelChecker": + { + "engine": "chc", + "extCalls": "what" + } + } +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json new file mode 100644 index 0000000000..4e214a37b2 --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "Invalid model checker extCalls requested.", + "message": "Invalid model checker extCalls requested.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/input.json b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/input.json new file mode 100644 index 0000000000..cda245e7ff --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/input.json @@ -0,0 +1,30 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; + contract Ext { + function f() public view returns (uint) { + return 42; + } + } + + contract test { + function g(Ext e) public view { + uint x = e.f(); + assert(x == 42); + } + }" + } + }, + "settings": + { + "modelChecker": + { + "engine": "chc", + "extCalls": 2 + } + } +} diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json new file mode 100644 index 0000000000..e869637ed1 --- /dev/null +++ b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "settings.modelChecker.extCalls must be a string.", + "message": "settings.modelChecker.extCalls must be a string.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index fa8726d55e..85a221d4cd 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -3,14 +3,41 @@ { "smtlib2queries": { - "0x0ebc730de380833af1e52ed063befb32994bc637929c942b7fd089b7cd3ba64e": "(set-logic HORN) - + "0x75b95497d56c30e254a59358d72ddd4e78f9e90db621cfe677e85d05b2252411": "(set-option :produce-models true) +(set-logic ALL) +(declare-fun |x_3_3| () Int) +(declare-fun |error_0| () Int) +(declare-fun |this_0| () Int) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |tx_0| () |tx_type|) +(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) +(declare-fun |crypto_0| () |crypto_type|) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) +(declare-fun |abi_0| () |abi_type|) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) +(declare-fun |state_0| () |state_type|) +(declare-fun |x_3_4| () Int) +(declare-fun |x_3_0| () Int) +(declare-fun |expr_7_0| () Int) +(declare-fun |expr_8_0| () Int) +(declare-fun |expr_9_1| () Bool) + +(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) +(declare-const |EVALEXPR_0| Int) +(assert (= |EVALEXPR_0| x_3_0)) +(check-sat) +(get-value (|EVALEXPR_0| )) +", + "0xfb06d3f02a20bd362abded9ab80638bdc9dd43ccbf644517f3006206c0c47f67": "(set-logic HORN) + (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) +(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_14_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) (declare-fun |nondet_interface_1_C_14_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) (declare-fun |summary_constructor_2_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) @@ -97,7 +124,7 @@ (declare-fun |implicit_constructor_entry_13_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert @@ -124,34 +151,7 @@ (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) (=> error_target_3_0 false))) -(check-sat)", - "0xcb822e6220a39244d26887a0fa6f62b06718359056555679fb06dd7dff18bb86": "(set-option :produce-models true) -(set-logic ALL) -(declare-fun |x_3_3| () Int) -(declare-fun |error_0| () Int) -(declare-fun |this_0| () Int) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |state_0| () |state_type|) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |tx_0| () |tx_type|) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-fun |crypto_0| () |crypto_type|) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-fun |abi_0| () |abi_type|) -(declare-fun |x_3_4| () Int) -(declare-fun |x_3_0| () Int) -(declare-fun |expr_7_0| () Int) -(declare-fun |expr_8_0| () Int) -(declare-fun |expr_9_1| () Bool) - -(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) -(declare-const |EVALEXPR_0| Int) -(assert (= |EVALEXPR_0| x_3_0)) -(check-sat) -(get-value (|EVALEXPR_0| )) -" +(check-sat)" } }, "errors": diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index e3e52491dd..93590994a0 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -33,6 +33,12 @@ SMTCheckerTest::SMTCheckerTest(string const& _filename): SyntaxTest(_filename, E if (!contract.empty()) m_modelCheckerSettings.contracts.contracts[""] = {contract}; + auto extCallsMode = ModelCheckerExtCalls::fromString(m_reader.stringSetting("SMTExtCalls", "untrusted")); + if (extCallsMode) + m_modelCheckerSettings.externalCalls = *extCallsMode; + else + BOOST_THROW_EXCEPTION(runtime_error("Invalid SMT external calls mode.")); + auto const& showUnproved = m_reader.stringSetting("SMTShowUnproved", "yes"); if (showUnproved == "no") m_modelCheckerSettings.showUnproved = false; @@ -51,8 +57,13 @@ SMTCheckerTest::SMTCheckerTest(string const& _filename): SyntaxTest(_filename, E m_modelCheckerSettings.solvers &= ModelChecker::availableSolvers(); /// Underflow and Overflow are not enabled by default for Solidity >=0.8.7, - /// so we explicitly enable all targets for the tests. - m_modelCheckerSettings.targets = ModelCheckerTargets::All(); + /// so we explicitly enable all targets for the tests, + /// if the targets were not explicitly set by the test. + auto targets = ModelCheckerTargets::fromString(m_reader.stringSetting("SMTTargets", "all")); + if (targets) + m_modelCheckerSettings.targets = *targets; + else + BOOST_THROW_EXCEPTION(runtime_error("Invalid SMT targets.")); auto engine = ModelCheckerEngine::fromString(m_reader.stringSetting("SMTEngine", "all")); if (engine) diff --git a/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol b/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol index ddda215df8..7950c86125 100644 --- a/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol +++ b/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol @@ -22,4 +22,4 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Info 1180: Contract invariant(s) for :C:\n!(s1.arr.length <= 0)\n!(s2.arr.length <= 0)\n(((s2.arr[0].length + ((- 1) * s1.arr[0].length)) <= 0) && ((s1.arr[0].length + ((- 1) * s2.arr[0].length)) <= 0))\n +// Info 1180: Contract invariant(s) for :C:\n!(s1.arr.length <= 0)\n!(s2.arr.length <= 0)\n(((s1.arr[0].length + ((- 1) * s2.arr[0].length)) <= 0) && ((s2.arr[0].length + ((- 1) * s1.arr[0].length)) <= 0))\n diff --git a/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol b/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol index 7a7db383b2..7af3af40d9 100644 --- a/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol +++ b/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol @@ -31,4 +31,4 @@ contract C { // Warning 6328: (349-375): CHC: Assertion violation happens here.\nCounterexample:\narr = [[], [], [], [], [], [], [], [], []]\nx = 0\ny = 0\nz = 9\nt = 0\n\nTransaction trace:\nC.constructor()\nState: arr = [[], [], [], [], [], [], [], [], []]\nC.f() // Warning 6328: (379-402): CHC: Assertion violation happens here.\nCounterexample:\narr = [[], [], [], [], [], [], [], [], []]\nx = 0\ny = 0\nz = 9\nt = 0\n\nTransaction trace:\nC.constructor()\nState: arr = [[], [], [], [], [], [], [], [], []]\nC.f() // Warning 6328: (406-432): CHC: Assertion violation happens here.\nCounterexample:\narr = [[], [], [], [], [], [], [], [], []]\nx = 0\ny = 0\nz = 9\nt = 0\n\nTransaction trace:\nC.constructor()\nState: arr = [[], [], [], [], [], [], [], [], []]\nC.f() -// Info 1180: Contract invariant(s) for :C:\n!(arr.length <= 7)\n!(arr.length <= 8)\n +// Info 1180: Contract invariant(s) for :C:\n!(arr.length <= 5)\n!(arr.length <= 7)\n!(arr.length <= 8)\n diff --git a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol index 0d16306b72..aea10a3769 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol @@ -18,5 +18,6 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreOS: macos +// SMTIgnoreCex: yes // ---- // Warning 6328: (199-229): CHC: Assertion violation happens here.\nCounterexample:\nb = [1]\n\nTransaction trace:\nC.constructor()\nState: b = []\nC.g() diff --git a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_2d.sol b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_2d.sol index bbd5589a48..34b439e3a6 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_2d.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_2d.sol @@ -20,5 +20,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreCex: yes // ---- // Warning 6328: (362-420): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/complex/slither/external_function.sol b/test/libsolidity/smtCheckerTests/complex/slither/external_function.sol index 3f5096a3b5..936ad17037 100644 --- a/test/libsolidity/smtCheckerTests/complex/slither/external_function.sol +++ b/test/libsolidity/smtCheckerTests/complex/slither/external_function.sol @@ -83,6 +83,6 @@ contract InternalCall { // Warning 2018: (1111-1173): Function state mutability can be restricted to pure // Warning 2018: (1179-1241): Function state mutability can be restricted to pure // Warning 2018: (1247-1309): Function state mutability can be restricted to pure -// Warning 4588: (681-716): Assertion checker does not yet implement this type of function call. -// Warning 4588: (854-886): Assertion checker does not yet implement this type of function call. +// Warning 8729: (681-716): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 8729: (854-886): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. // Warning 5729: (1370-1375): BMC does not yet implement this type of function call. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_bmc_trusted.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_bmc_trusted.sol new file mode 100644 index 0000000000..81ddc515e1 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_bmc_trusted.sol @@ -0,0 +1,18 @@ +contract D { + uint x; + function f() public view returns (uint) { return x; } +} + +contract C { + function g() public { + D d = new D(); + uint y = d.f(); + assert(y == 0); // should fail in BMC + } +} +// ==== +// SMTEngine: bmc +// SMTExtCalls: trusted +// ---- +// Warning 8729: (124-131): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 4661: (153-167): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_bmc_untrusted.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_bmc_untrusted.sol new file mode 100644 index 0000000000..f69a8d6c72 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_bmc_untrusted.sol @@ -0,0 +1,17 @@ +contract D { + uint x; + function f() public view returns (uint) { return x; } +} + +contract C { + function g() public { + D d = new D(); + uint y = d.f(); + assert(y == 0); // should fail in ext calls untrusted mode + } +} +// ==== +// SMTEngine: bmc +// ---- +// Warning 8729: (124-131): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 4661: (153-167): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted.sol new file mode 100644 index 0000000000..388b0b0db8 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted.sol @@ -0,0 +1,16 @@ +contract D { + uint x; + function f() public view returns (uint) { return x; } +} + +contract C { + function g() public { + D d = new D(); + uint y = d.f(); + assert(y == 0); // should hold in ext calls trusted mode + } +} +// ==== +// SMTEngine: all +// SMTExtCalls: trusted +// ---- diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol new file mode 100644 index 0000000000..cf43dbda20 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol @@ -0,0 +1,19 @@ +contract D { + uint x; +} + +contract C { + function f() public { + D d1 = new D(); + D d2 = new D(); + + assert(d1 != d2); // should hold in ext calls trusted mode + assert(address(this) != address(d1)); // should hold in ext calls trusted mode + assert(address(this) != address(d2)); // should hold in ext calls trusted mode + } +} +// ==== +// SMTEngine: all +// SMTExtCalls: trusted +// ---- +// Info 1180: Contract invariant(s) for :C:\n(:var 0).isActive[address(this)]\n diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol new file mode 100644 index 0000000000..ddd4b41e68 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol @@ -0,0 +1,32 @@ +contract D { + uint x; + function inc() public { ++x; } + function f() public view returns (uint) { return x; } +} + +contract C { + function f() public { + D d = new D(); + assert(d.f() == 0); // should hold + d.inc(); + assert(d.f() == 1); // should hold + d = new D(); + assert(d.f() == 0); // should hold + assert(d.f() == 1); // should fail + } +} +// ==== +// SMTEngine: all +// SMTExtCalls: trusted +// SMTIgnoreOS: macos +// ---- +// Warning 4984: (47-50): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. +// Warning 6328: (167-185): CHC: Assertion violation might happen here. +// Warning 6328: (215-233): CHC: Assertion violation might happen here. +// Warning 6328: (267-285): CHC: Assertion violation might happen here. +// Warning 6328: (304-322): CHC: Assertion violation might happen here. +// Warning 2661: (47-50): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. +// Warning 4661: (167-185): BMC: Assertion violation happens here. +// Warning 4661: (215-233): BMC: Assertion violation happens here. +// Warning 4661: (267-285): BMC: Assertion violation happens here. +// Warning 4661: (304-322): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_keep_storage_constraints.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_keep_storage_constraints.sol new file mode 100644 index 0000000000..b2aa7ac984 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_keep_storage_constraints.sol @@ -0,0 +1,17 @@ +contract D { + uint x; +} + +contract C { + uint y; + function g() public { + D d = new D(); + assert(y == 0); // should hold + } +} +// ==== +// SMTEngine: all +// SMTExtCalls: trusted +// ---- +// Warning 2072: (72-75): Unused local variable. +// Info 1180: Contract invariant(s) for :C:\n(y <= 0)\n diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow.sol new file mode 100644 index 0000000000..4b3367b11c --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow.sol @@ -0,0 +1,24 @@ +contract D { + uint x; + function inc() public { ++x; } + function f() public view returns (uint) { return x; } +} + +contract C { + D d; + constructor() { + d = new D(); + assert(d.f() == 0); // should hold + } + function g() public view { + assert(d.f() == 0); // should fail + } +} +// ==== +// SMTEngine: all +// SMTExtCalls: trusted +// SMTIgnoreOS: macos +// ---- +// Warning 4984: (47-50): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. +// Warning 6328: (233-251): CHC: Assertion violation happens here. +// Warning 2661: (47-50): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_2.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_2.sol new file mode 100644 index 0000000000..66684df8c1 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_2.sol @@ -0,0 +1,20 @@ +contract D { + uint x; + function f() public view returns (uint) { return x; } +} + +contract C { + D d; + constructor() { + d = new D(); + assert(d.f() == 0); // should hold + } + function g() public view { + assert(d.f() == 0); // should hold + } +} +// ==== +// SMTEngine: all +// SMTExtCalls: trusted +// ---- +// Info 1180: Contract invariant(s) for :C:\n((:var 1).storage.storage_D_12[d].x_3_D_12 <= 0)\nReentrancy property(ies) for :D:\n((x' <= 0) || !(x <= 0))\n diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_3.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_3.sol new file mode 100644 index 0000000000..260909b87a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_3.sol @@ -0,0 +1,21 @@ +contract D { + uint x; + function s(uint _x) public { x = _x; } + function f() public view returns (uint) { return x; } +} + +contract C { + D d; + constructor() { + d = new D(); + } + function g() public view { + assert(d.f() == 0); // should fail + } +} +// ==== +// SMTContract: C +// SMTEngine: all +// SMTExtCalls: trusted +// ---- +// Warning 6328: (204-222): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_4.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_4.sol new file mode 100644 index 0000000000..5bd27c3b82 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_state_flow_4.sol @@ -0,0 +1,20 @@ +contract D { + bool b; + function s() public { b = true; } + function f() public view returns (bool) { return b; } +} + +contract C { + D d; + constructor() { + d = new D(); + } + function g() public view { + assert(d.f()); // should fail + } +} +// ==== +// SMTEngine: all +// SMTExtCalls: trusted +// ---- +// Warning 6328: (199-212): CHC: Assertion violation happens here.\nCounterexample:\nd = (- 1)\n\nTransaction trace:\nC.constructor()\nState: d = (- 1)\nC.g()\n D.f() -- trusted external call diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted.sol new file mode 100644 index 0000000000..a28d462105 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted.sol @@ -0,0 +1,17 @@ +contract D { + uint x; + function f() public view returns (uint) { return x; } +} + +contract C { + function g() public { + D d = new D(); + uint y = d.f(); + assert(y == 0); // should fail in ext calls untrusted mode + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 8729: (124-131): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 6328: (153-167): CHC: Assertion violation happens here.\nCounterexample:\n\nd = 0\ny = 1\n\nTransaction trace:\nC.constructor()\nC.g()\n d.f() -- untrusted external call diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol new file mode 100644 index 0000000000..c934e152b2 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol @@ -0,0 +1,22 @@ +contract D { + uint x; +} + +contract C { + function f() public { + D d1 = new D(); + D d2 = new D(); + + assert(d1 != d2); // should fail in ext calls untrusted mode + assert(address(this) != address(d1)); // should fail in ext calls untrusted mode + assert(address(this) != address(d2)); // should fail in ext calls untrusted mode + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 8729: (70-77): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 8729: (88-95): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 6328: (100-116): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 0\nd2 = 0\n\nTransaction trace:\nC.constructor()\nC.f() +// Warning 6328: (163-199): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 21238\nd2 = 21238\n\nTransaction trace:\nC.constructor()\nC.f() +// Warning 6328: (246-282): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 21238\nd2 = 21238\n\nTransaction trace:\nC.constructor()\nC.f() diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_erase_storage_constraints.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_erase_storage_constraints.sol new file mode 100644 index 0000000000..be18b33f63 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_erase_storage_constraints.sol @@ -0,0 +1,17 @@ +contract D { + uint x; +} + +contract C { + uint y; + function g() public { + D d = new D(); + assert(y == 0); // should fail in ext calls untrusted mode + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 2072: (72-75): Unused local variable. +// Warning 8729: (78-85): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 6328: (89-103): CHC: Assertion violation happens here.\nCounterexample:\ny = 1\nd = 0\n\nTransaction trace:\nC.constructor()\nState: y = 0\nC.g() diff --git a/test/libsolidity/smtCheckerTests/deployment/deployment_trusted_with_value_1.sol b/test/libsolidity/smtCheckerTests/deployment/deployment_trusted_with_value_1.sol new file mode 100644 index 0000000000..92195221e2 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/deployment/deployment_trusted_with_value_1.sol @@ -0,0 +1,20 @@ +contract A { + constructor() payable {} +} + +contract B { + function f() public payable { + require(address(this).balance == 100); + A a = new A{value: 50}(); + assert(address(this).balance == 50); // should hold + assert(address(this).balance == 60); // should fail + assert(address(a).balance >= 50); // should hold + assert(address(a).balance == 50); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (211-246): CHC: Assertion violation happens here. +// Warning 6328: (316-348): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_1.sol new file mode 100644 index 0000000000..7905d5b4fb --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_1.sol @@ -0,0 +1,28 @@ +contract D { + constructor(uint _x) { x = _x; } + uint public x; +} + +contract E { + constructor() { x = 2; } + uint public x; +} + +contract C { + constructor() { + address d = address(new D(42)); + assert(D(d).x() == 42); // should hold + assert(D(d).x() == 43); // should fail + uint y = E(d).x(); + assert(y == 2); // should fail, it would still call D.x() == 42 + assert(y == 42); // should hold, but fails due to false positive + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (231-253): CHC: Assertion violation happens here. +// Warning 6328: (293-307): CHC: Assertion violation happens here. +// Warning 6328: (359-374): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_2.sol new file mode 100644 index 0000000000..25cccead47 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_constructor_trusted_2.sol @@ -0,0 +1,25 @@ +contract D { + constructor(uint _x) { x = _x; } + function setD(uint _x) public { x = _x; } + uint public x; +} + +contract C { + constructor() { + address d = address(new D(42)); + assert(D(d).x() == 42); // should hold + assert(D(d).x() == 21); // should fail + d.call(abi.encodeCall(D.setD, (21))); + assert(D(d).x() == 21); // should hold, but false positive cus low level calls are not handled precisely + assert(D(d).x() == 42); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreCex: yes +// ---- +// Warning 9302: (257-293): Return value of low-level calls not used. +// Warning 6328: (216-238): CHC: Assertion violation happens here. +// Warning 6328: (297-319): CHC: Assertion violation happens here. +// Warning 6328: (404-426): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_1.sol new file mode 100644 index 0000000000..2dc5dd0fb8 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_1.sol @@ -0,0 +1,28 @@ +contract D { + constructor(uint _x) { x = _x; } + uint public x; +} + +contract E { + constructor() { x = 2; } + uint public x; +} + +contract C { + function f() public { + address d = address(new D(42)); + assert(D(d).x() == 42); // should hold + assert(D(d).x() == 43); // should fail + uint y = E(d).x(); + assert(y == 2); // should fail, it would still call D.x() == 42 + assert(y == 42); // should hold, but fails due to false positive + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (237-259): CHC: Assertion violation happens here. +// Warning 6328: (299-313): CHC: Assertion violation happens here. +// Warning 6328: (365-380): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_2.sol new file mode 100644 index 0000000000..9c36bfc74f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_2.sol @@ -0,0 +1,25 @@ +contract D { + constructor(uint _x) { x = _x; } + function setD(uint _x) public { x = _x; } + uint public x; +} + +contract C { + function f() public { + address d = address(new D(42)); + assert(D(d).x() == 42); // should hold + assert(D(d).x() == 21); // should fail + d.call(abi.encodeCall(D.setD, (21))); + assert(D(d).x() == 21); // should hold, but false positive cus low level calls are not handled precisely + assert(D(d).x() == 42); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreCex: yes +// ---- +// Warning 9302: (263-299): Return value of low-level calls not used. +// Warning 6328: (222-244): CHC: Assertion violation happens here. +// Warning 6328: (303-325): CHC: Assertion violation happens here. +// Warning 6328: (410-432): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_3.sol b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_3.sol new file mode 100644 index 0000000000..317fde003c --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/call_abstract_trusted_3.sol @@ -0,0 +1,29 @@ +contract D { + constructor(uint _x) { x = _x; } + function setD(uint _x) public { x = _x; } + uint public x; +} + +contract C { + uint x; + + function f() public { + x = 666; + address d = address(new D(42)); + assert(D(d).x() == 42); // should hold + assert(D(d).x() == 21); // should fail + d.call(abi.encodeCall(D.setD, (21))); + assert(D(d).x() == 21); // should hold, but false positive cus low level calls are not handled precisely + assert(D(d).x() == 42); // should fail + assert(x == 666); // should hold, C's storage should not have been havoced + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreCex: yes +// ---- +// Warning 9302: (284-320): Return value of low-level calls not used. +// Warning 6328: (243-265): CHC: Assertion violation happens here. +// Warning 6328: (324-346): CHC: Assertion violation happens here. +// Warning 6328: (431-453): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol b/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol index 87a9e22614..f0f844fff3 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol @@ -15,4 +15,4 @@ contract C { // Warning 2519: (106-112): This declaration shadows an existing declaration. // Warning 2072: (106-112): Unused local variable. // Warning 2072: (114-131): Unused local variable. -// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n((!(x <= 0) || (x' <= 0)) && (!(x <= 0) || ( <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n +// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n((!(x <= 0) || (x' <= 0)) && (( <= 0) || !(x <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol new file mode 100644 index 0000000000..8c7b589d1a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol @@ -0,0 +1,21 @@ +contract State { + function f(uint _x) public pure returns (uint) { + assert(_x < 100); // should fail + return _x; + } +} +contract C { + State s; + uint z = s.f(2); + + function f() public view { + assert(z == 2); // should hold in trusted mode + } +} +// ==== +// SMTContract: C +// SMTEngine: all +// SMTExtCalls: trusted +// SMTIgnoreInv: yes +// ---- +// Warning 6328: (69-85): CHC: Assertion violation happens here.\nCounterexample:\n\n_x = 100\n = 0\n\nTransaction trace:\nState.constructor()\nState.f(100) diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_2_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_2_trusted.sol new file mode 100644 index 0000000000..a814227292 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_2_trusted.sol @@ -0,0 +1,17 @@ +contract C { + uint z = this.g(2); + + function g(uint _x) public pure returns (uint) { + assert(_x > 0); // should fail + return _x; + } + + function f() public view { + assert(z == 2); // should hold + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (87-101): CHC: Assertion violation happens here.\nCounterexample:\nz = 2\n_x = 0\n = 0\n\nTransaction trace:\nC.constructor()\nState: z = 2\nC.g(0) +// Info 1180: Contract invariant(s) for :C:\n(!(z >= 3) && !(z <= 1))\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol new file mode 100644 index 0000000000..8ff241e729 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol @@ -0,0 +1,25 @@ +contract State { + function f(uint _x) public pure returns (uint) { + assert(_x < 100); // should fail + return _x; + } +} +contract C { + State s; + uint z; + + constructor() { + z = s.f(2); + } + + function f() public view { + assert(z == 2); // should hold in trusted mode + } +} +// ==== +// SMTContract: C +// SMTEngine: all +// SMTExtCalls: trusted +// ---- +// Warning 6328: (69-85): CHC: Assertion violation happens here.\nCounterexample:\n\n_x = 100\n = 0\n\nTransaction trace:\nState.constructor()\nState.f(100) +// Info 1180: Contract invariant(s) for :C:\n(!(z >= 3) && !(z <= 1))\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol new file mode 100644 index 0000000000..b7a161ac93 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol @@ -0,0 +1,41 @@ +contract A { + uint x; + function setX(uint _x) public { + x = _x; + } + function getX() public view returns (uint) { + return x; + } +} + +contract B { + A a; + constructor() { + a = new A(); + assert(a.getX() == 0); // should hold + } + function g() public view { + assert(a.getX() == 0); // should fail because A.setX() can be called without B + } + function getX() public view returns (uint) { + return a.getX(); + } +} + +contract C { + B b; + constructor() { + b = new B(); + assert(b.getX() == 0); // should hold + } + function f() public view { + assert(b.getX() == 0); // should fail because A.setX() can be called without A + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreOS: macos +// ---- +// Warning 6328: (256-277): CHC: Assertion violation happens here. +// Warning 6328: (533-554): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol new file mode 100644 index 0000000000..e65d1b1e74 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol @@ -0,0 +1,52 @@ +contract A { + uint x; + address immutable owner; + constructor() { + owner = msg.sender; + } + function setX(uint _x) public { + require(msg.sender == owner); + x = _x; + } + function getX() public view returns (uint) { + return x; + } +} + +contract B { + A a; + constructor() { + a = new A(); + assert(a.getX() == 0); // should hold + } + function g() public view { + assert(a.getX() == 0); // should hold, but fails because + // the nondet_interface constraint added for `A a` in between + // txs of `B` does not have the constraint that `msg.sender != address(this)` + // so `A.setX` is allowed with `msg.sender = address(this)` inside + // the current rules defining nondet_interface. + // If we want to support that, we likely need a new type of nondet_interface + // `nondet_interface_with_tx` that contains tx data as well as restricts + // every further `nondet_interface_with_tx` to not have that `msg.sender`. + } + function getX() public view returns (uint) { + return a.getX(); + } +} + +contract C { + B b; + constructor() { + b = new B(); + assert(b.getX() == 0); // should hold + } + function f() public view { + assert(b.getX() == 0); // should hold + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (434-455): CHC: Assertion violation happens here. +// Warning 6328: (1270-1291): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol new file mode 100644 index 0000000000..60bfd1660a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol @@ -0,0 +1,45 @@ +contract A { + uint x; + address immutable owner; + constructor() { + owner = msg.sender; + } + function setX(uint _x) public { + require(msg.sender == owner); + x = _x; + } + function getX() public view returns (uint) { + return x; + } +} + +contract B { + A a; + constructor() { + a = new A(); + assert(a.getX() == 0); // should hold + } + function g() public { + a.setX(42); + } + function getX() public view returns (uint) { + return a.getX(); + } +} + +contract C { + B b; + constructor() { + b = new B(); + assert(b.getX() == 0); // should hold + } + function f() public view { + assert(b.getX() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreOS: macos +// ---- +// Warning 6328: (561-582): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol new file mode 100644 index 0000000000..4e86c7b2b5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol @@ -0,0 +1,48 @@ +contract A { + uint x; + address immutable owner; + constructor() { + owner = msg.sender; + } + function setX(uint _x) public { + require(msg.sender == owner); + x = _x; + } + function getX() public view returns (uint) { + return x; + } +} + +contract B { + A a; + address immutable owner; + constructor() { + owner = msg.sender; + a = new A(); + assert(a.getX() == 0); // should hold + } + function g() public { + require(msg.sender == owner); + a.setX(42); + } + function getX() public view returns (uint) { + return a.getX(); + } +} + +contract C { + B b; + constructor() { + b = new B(); + assert(b.getX() == 0); // should hold + } + function f() public view { + assert(b.getX() == 0); // should hold + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreOS: macos +// ---- +// Warning 6328: (641-662): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol new file mode 100644 index 0000000000..54566b85f4 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol @@ -0,0 +1,50 @@ +contract A { + uint x; + address immutable owner; + constructor() { + owner = msg.sender; + } + function setX(uint _x) public { + require(msg.sender == owner); + x = _x; + } + function getX() public view returns (uint) { + return x; + } +} + +contract B { + A a; + address immutable owner; + constructor() { + owner = msg.sender; + a = new A(); + } + function g() public { + require(msg.sender == owner); + a.setX(42); + } + function getX() public view returns (uint) { + return a.getX(); + } +} + +contract C { + B b; + constructor() { + b = new B(); + assert(b.getX() == 0); // should hold + } + function f() public view { + assert(b.getX() == 0); // should fail + } + function h() public { + b.g(); + } +} +// ==== +// SMTContract: C +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (601-622): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_1.sol new file mode 100644 index 0000000000..582d967f3f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_1.sol @@ -0,0 +1,17 @@ +contract C { + uint x; + function i() public { ++x; } + function f() public { + x = 0; + this.i(); + assert(x == 1); // should hold in trusted mode + assert(x != 1); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (147-161): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f()\n C.i() -- trusted external call diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_2.sol new file mode 100644 index 0000000000..0f05a8b731 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_2.sol @@ -0,0 +1,16 @@ +contract C { + uint x; + function i() public { ++x; } + function f() public { + x = 0; + ((this)).i(); + assert(x == 1); // should hold in trusted mode + assert(x != 1); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (151-165): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f()\n C.i() -- trusted external call diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_3.sol new file mode 100644 index 0000000000..1b95859af8 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_semantic_this_3.sol @@ -0,0 +1,17 @@ +contract C { + uint x; + function i() public { ++x; } + function f() public { + x = 0; + C c = this; + c.i(); + assert(x == 1); // should hold in trusted mode + assert(x != 1); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (158-172): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_1.sol new file mode 100644 index 0000000000..c4bab9c759 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_1.sol @@ -0,0 +1,23 @@ +contract D { + uint public x; +} + +contract C { + struct S { + address d; + } + S[] ss; + constructor() { + ss.push(S(address(new D()))); + assert(D(ss[0].d).x() == 0); // should hold + } + function f() public view { + assert(D(ss[0].d).x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (210-237): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_2.sol new file mode 100644 index 0000000000..522c840f5b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_struct_trusted_2.sol @@ -0,0 +1,24 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + struct S { + address d; + } + S[] ss; + constructor() { + ss.push(S(address(new D()))); + assert(D(ss[0].d).x() == 0); // should hold + } + function f() public view { + assert(D(ss[0].d).x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (253-280): CHC: Assertion violation happens here.\nCounterexample:\nss = [{d: 0x4706}]\n\nTransaction trace:\nC.constructor()\nState: ss = [{d: 0x4706}]\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_1.sol new file mode 100644 index 0000000000..541999b9f9 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_1.sol @@ -0,0 +1,21 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + address[] ds; + constructor() { + ds.push(address(new D())); + assert(D(ds[0]).x() == 0); // should hold + } + function f() public view { + assert(D(ds[0]).x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (226-251): CHC: Assertion violation happens here.\nCounterexample:\nds = [0x0]\n\nTransaction trace:\nC.constructor()\nState: ds = [0x0]\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_2.sol new file mode 100644 index 0000000000..f7e31bf74a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_array_trusted_2.sol @@ -0,0 +1,20 @@ +contract D { + uint public x; +} + +contract C { + address[] ds; + constructor() { + ds.push(address(new D())); + assert(D(ds[0]).x() == 0); // should hold + } + function f() public view { + assert(D(ds[0]).x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (183-208): CHC: Assertion violation happens here.\nCounterexample:\nds = [0x25]\n\nTransaction trace:\nC.constructor()\nState: ds = [0x25]\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_1.sol new file mode 100644 index 0000000000..2ac70b33d3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_1.sol @@ -0,0 +1,24 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + struct S { + address d; + } + S s; + constructor() { + s.d = address(new D()); + assert(D(s.d).x() == 0); // should hold + } + function f() public view { + assert(D(s.d).x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (240-263): CHC: Assertion violation happens here.\nCounterexample:\ns = {d: 0x5039}\n\nTransaction trace:\nC.constructor()\nState: s = {d: 0x5039}\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_2.sol new file mode 100644 index 0000000000..e527c5bc01 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_2.sol @@ -0,0 +1,23 @@ +contract D { + uint public x; +} + +contract C { + struct S { + address d; + } + S s; + constructor() { + s.d = address(new D()); + assert(D(s.d).x() == 0); // should hold + } + function f() public view { + assert(D(s.d).x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (197-220): CHC: Assertion violation happens here.\nCounterexample:\ns = {d: 0x5039}\n\nTransaction trace:\nC.constructor()\nState: s = {d: 0x5039}\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_3.sol new file mode 100644 index 0000000000..fff8a97184 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_3.sol @@ -0,0 +1,26 @@ +contract D { + uint public x; +} + +contract C { + struct S { + address d; + } + struct T { + S s; + } + T t; + constructor() { + t.s.d = address(new D()); + assert(D(t.s.d).x() == 0); // should hold + } + function f() public view { + assert(D(t.s.d).x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (223-248): CHC: Assertion violation happens here.\nCounterexample:\nt = {s: {d: 0x5039}}\n\nTransaction trace:\nC.constructor()\nState: t = {s: {d: 0x5039}}\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_4.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_4.sol new file mode 100644 index 0000000000..63d026e52b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_address_inside_struct_trusted_4.sol @@ -0,0 +1,27 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + struct S { + address d; + } + struct T { + S s; + } + T t; + constructor() { + t.s.d = address(new D()); + assert(D(t.s.d).x() == 0); // should hold + } + function f() public view { + assert(D(t.s.d).x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (266-291): CHC: Assertion violation happens here.\nCounterexample:\nt = {s: {d: 0x5039}}\n\nTransaction trace:\nC.constructor()\nState: t = {s: {d: 0x5039}}\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_1.sol new file mode 100644 index 0000000000..0b8cd8e598 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_1.sol @@ -0,0 +1,23 @@ +contract D { + uint public x; +} + +contract C { + struct S { + D d; + } + S[] ss; + constructor() { + ss.push(S(new D())); + assert(ss[0].d.x() == 0); // should hold + } + function f() public view { + assert(ss[0].d.x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (192-216): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_2.sol new file mode 100644 index 0000000000..97f61fa045 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_struct_trusted_2.sol @@ -0,0 +1,24 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + struct S { + D d; + } + S[] ss; + constructor() { + ss.push(S(new D())); + assert(ss[0].d.x() == 0); // should hold + } + function f() public view { + assert(ss[0].d.x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (235-259): CHC: Assertion violation happens here.\nCounterexample:\nss = [{d: 20819}]\n\nTransaction trace:\nC.constructor()\nState: ss = [{d: 20819}]\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_1.sol new file mode 100644 index 0000000000..475c391844 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_1.sol @@ -0,0 +1,21 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + D[] ds; + constructor() { + ds.push(new D()); + assert(ds[0].x() == 0); // should hold + } + function f() public view { + assert(ds[0].x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (208-230): CHC: Assertion violation happens here.\nCounterexample:\nds = [39]\n\nTransaction trace:\nC.constructor()\nState: ds = [39]\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_2.sol new file mode 100644 index 0000000000..baeddda088 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_array_trusted_2.sol @@ -0,0 +1,21 @@ +contract D { + uint public x; +} + +contract C { + D[] ds; + constructor() { + ds.push(new D()); + assert(ds[0].x() == 0); // should hold + } + function f() public view { + assert(ds[0].x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (165-187): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_1.sol new file mode 100644 index 0000000000..293c223044 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_1.sol @@ -0,0 +1,24 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + struct S { + D d; + } + S s; + constructor() { + s.d = new D(); + assert(s.d.x() == 0); // should hold + } + function f() public view { + assert(s.d.x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (222-242): CHC: Assertion violation happens here.\nCounterexample:\ns = {d: 20819}\n\nTransaction trace:\nC.constructor()\nState: s = {d: 20819}\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_2.sol new file mode 100644 index 0000000000..59381960c5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_2.sol @@ -0,0 +1,24 @@ +contract D { + uint public x; +} + +contract C { + struct S { + D d; + } + S s; + constructor() { + s.d = new D(); + assert(s.d.x() == 0); // should hold + } + function f() public view { + assert(s.d.x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (179-199): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_3.sol new file mode 100644 index 0000000000..06cd20cfe3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_3.sol @@ -0,0 +1,27 @@ +contract D { + uint public x; +} + +contract C { + struct S { + D d; + } + struct T { + S s; + } + T t; + constructor() { + t.s.d = new D(); + assert(t.s.d.x() == 0); // should hold + } + function f() public view { + assert(t.s.d.x() == 0); // should hold, but fails because we havoc the state + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (205-227): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_4.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_4.sol new file mode 100644 index 0000000000..6a1fb22744 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_state_var_contract_inside_struct_trusted_4.sol @@ -0,0 +1,27 @@ +contract D { + uint public x; + function setD(uint _x) public { x = _x; } +} + +contract C { + struct S { + D d; + } + struct T { + S s; + } + T t; + constructor() { + t.s.d = new D(); + assert(t.s.d.x() == 0); // should hold + } + function f() public view { + assert(t.s.d.x() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (248-270): CHC: Assertion violation happens here.\nCounterexample:\nt = {s: {d: 20819}}\n\nTransaction trace:\nC.constructor()\nState: t = {s: {d: 20819}}\nC.f() diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol index 06390b12ca..c52e0773fb 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol @@ -11,4 +11,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (157-192): CHC: Assertion violation happens here. +// Warning 6328: (157-192): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.g()\n C.h() -- trusted external call diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_2.sol index fc2d844d9d..f804078cd1 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_2.sol @@ -1,7 +1,11 @@ contract C { function g(uint i) public { require(address(this).balance == 100); + // if called address is same as this, don't do anything with the value stuff + // or fix the receiving end this.h{value: i}(); + uint x = address(this).balance; + assert(x == 100); // should hold assert(address(this).balance == 100); // should hold assert(address(this).balance == 90); // should fail } @@ -12,4 +16,4 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (162-197): CHC: Assertion violation happens here. +// Warning 6328: (340-375): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_pure_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_pure_trusted.sol new file mode 100644 index 0000000000..6c634d4efb --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_pure_trusted.sol @@ -0,0 +1,33 @@ +contract Crypto { + function hash(bytes32) external pure returns (bytes32) { + return bytes32(0); + } +} + +contract C { + address owner; + bytes32 sig_1; + bytes32 sig_2; + Crypto d; + + constructor() { + owner = msg.sender; + } + + function f1(bytes32 _msg) public { + address prevOwner = owner; + sig_1 = d.hash(_msg); + sig_2 = d.hash(_msg); + assert(prevOwner == owner); + } + + function inv() public view { + assert(sig_1 == sig_2); + } +} +// ==== +// SMTContract: C +// SMTEngine: all +// SMTExtCalls: trusted +// ---- +// Info 1180: Contract invariant(s) for :C:\n((sig_1 <= 0) && (sig_2 <= 0))\nReentrancy property(ies) for :Crypto:\n( = 0)\n = 0 -> no errors\n = 1 -> Assertion failed at assert(prevOwner == owner)\n = 3 -> Assertion failed at assert(sig_1 == sig_2)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_2_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_2_trusted.sol new file mode 100644 index 0000000000..62f53b64c2 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_2_trusted.sol @@ -0,0 +1,47 @@ +contract State { + C c; + constructor(C _c) { + c = _c; + } + function f() public view returns (uint) { + return c.g(); + } +} + +contract C { + address owner; + uint y; + uint z; + State s; + bool insidef; + + constructor() { + owner = msg.sender; + s = new State(this); + } + + function zz() public { + require(insidef); + z = 3; + } + + function f() public { + require(!insidef); + address prevOwner = owner; + insidef = true; + s.f(); + assert(z == y); + assert(prevOwner == owner); + insidef = false; + } + + function g() public view returns (uint) { + return y; + } +} +// ==== +// SMTContract: C +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Info 1180: Contract invariant(s) for :C:\n((y <= 0) && (insidef || (z <= 0)))\nReentrancy property(ies) for :State:\n( = 0)\n = 0 -> no errors\n = 2 -> Assertion failed at assert(z == y)\n = 3 -> Assertion failed at assert(prevOwner == owner)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol new file mode 100644 index 0000000000..8000b3267d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol @@ -0,0 +1,56 @@ +contract Other { + C c; + constructor(C _c) { + c = _c; + } + function h() public { + c.setOwner(address(0)); + } +} + +contract State { + uint x; + Other o; + C c; + constructor(C _c) { + c = _c; + o = new Other(_c); + } + function f() public returns (uint) { + o.h(); + return c.g(); + } +} + +contract C { + address owner; + uint y; + State s; + + constructor() { + owner = msg.sender; + s = new State(this); + } + + function setOwner(address _owner) public { + owner = _owner; + } + + function f() public { + address prevOwner = owner; + uint z = s.f(); + assert(z == y); // should hold + assert(prevOwner == owner); // should not hold because of reentrancy + } + + function g() public view returns (uint) { + return y; + } +} +// ==== +// SMTContract: C +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (531-545): CHC: Assertion violation might happen here. +// Warning 6328: (564-590): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol new file mode 100644 index 0000000000..ee373e2937 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol @@ -0,0 +1,38 @@ +contract State { + C c; + constructor(C _c) { + c = _c; + } + function f() public view returns (uint) { + return c.g(); + } +} + +contract C { + address owner; + uint y; + State s; + + constructor() { + owner = msg.sender; + s = new State(this); + } + + function f() public view { + address prevOwner = owner; + uint z = s.f(); + assert(z == y); + assert(prevOwner == owner); + } + + function g() public view returns (uint) { + return y; + } +} +// ==== +// SMTContract: C +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (314-328): CHC: Assertion violation might happen here. +// Info 1180: Reentrancy property(ies) for :State:\n( = 0)\n = 0 -> no errors\n = 1 -> Assertion failed at assert(z == y)\n = 2 -> Assertion failed at assert(prevOwner == owner)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol new file mode 100644 index 0000000000..4d179ddf82 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol @@ -0,0 +1,44 @@ +contract State { + C c; + constructor(C _c) { + c = _c; + } + function f() public returns (uint) { + c.setOwner(address(0)); + return c.g(); + } +} + +contract C { + address owner; + uint y; + State s; + + constructor() { + owner = msg.sender; + s = new State(this); + } + + function setOwner(address _owner) public { + owner = _owner; + } + + function f() public { + address prevOwner = owner; + uint z = s.f(); + assert(z == y); // should hold + assert(prevOwner == owner); // should not hold because of reentrancy + } + + function g() public view returns (uint) { + return y; + } +} +// ==== +// SMTContract: C +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTIgnoreOS: macos +// ---- +// Warning 6328: (396-410): CHC: Assertion violation might happen here. +// Warning 6328: (429-455): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_trusted.sol new file mode 100644 index 0000000000..1c557f7a6d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_trusted.sol @@ -0,0 +1,36 @@ +contract State { + uint x; + function f() public returns (uint) { + if (x == 0) x = 1; + else if (x == 1) x = 2; + else if (x == 2) x = 0; + return x; + } +} + +contract C { + address owner; + uint y; + uint z; + State s; + + constructor() { + s = new State(); + owner = msg.sender; + } + + function f() public { + address prevOwner = owner; + y = s.f(); + z = s.f(); + assert(prevOwner == owner); + assert(y != z); + } +} +// ==== +// SMTContract: C +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (355-381): CHC: Assertion violation might happen here. +// Warning 6328: (385-399): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_unsafe_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_unsafe_trusted.sol new file mode 100644 index 0000000000..7d217e145a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_unsafe_trusted.sol @@ -0,0 +1,40 @@ +contract State { + uint x; + function f() public returns (uint) { + if (x == 0) x = 1; + else if (x == 1) x = 2; + else if (x == 2) x = 0; + return x; + } +} + +contract C { + address owner; + uint y; + uint z; + State s; + + constructor() { + owner = msg.sender; + s = new State(); + } + + function setOwner(address _owner) public { + owner = _owner; + } + + function f() public { + address prevOwner = owner; + y = s.f(); + z = s.f(); + assert(prevOwner == owner); + assert(y != z); + } +} +// ==== +// SMTContract: C +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (421-447): CHC: Assertion violation might happen here. +// Warning 6328: (451-465): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_2.sol index 19ff2bbad8..268db82b46 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_2.sol @@ -13,4 +13,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (117-131): CHC: Assertion violation happens here.\nCounterexample:\nlocked = false\ntarget = 0x0\n\nTransaction trace:\nC.constructor()\nState: locked = true\nC.call(0x0)\n D(target).e() -- untrusted external call, synthesized as:\n C.call(0x0) -- reentrant call +// Warning 6328: (117-131): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol index b50185449b..550e17b619 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol @@ -18,3 +18,5 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- +// Warning 6328: (167-181): CHC: Assertion violation might happen here. +// Warning 4661: (167-181): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_correct.sol b/test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_correct.sol new file mode 100644 index 0000000000..438feae217 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_correct.sol @@ -0,0 +1,64 @@ +interface Token { + function balanceOf(address _a) external view returns (uint); + function transfer(address _to, uint _amt) external; +} + +contract TokenCorrect is Token { + mapping (address => uint) balance; + constructor(address _a, uint _b) { + balance[_a] = _b; + } + function balanceOf(address _a) public view override returns (uint) { + return balance[_a]; + } + function transfer(address _to, uint _amt) public override { + require(balance[msg.sender] >= _amt); + balance[msg.sender] -= _amt; + balance[_to] += _amt; + } +} + +contract Test { + function property_transfer(address _token, address _to, uint _amt) public { + require(_to != address(this)); + + TokenCorrect t = TokenCorrect(_token); + + uint xPre = t.balanceOf(address(this)); + require(xPre >= _amt); + uint yPre = t.balanceOf(_to); + + t.transfer(_to, _amt); + uint xPost = t.balanceOf(address(this)); + uint yPost = t.balanceOf(_to); + + assert(xPost == xPre - _amt); + assert(yPost == yPre + _amt); + } + + function test_concrete() public { + TokenCorrect t = new TokenCorrect(address(this), 1000); + + uint b = t.balanceOf(address(this)); + assert(b == 1000); + + address other = address(0x333); + require(address(this) != other); + + uint c = t.balanceOf(other); + assert(c == 0); + + t.transfer(other, 100); + + uint d = t.balanceOf(address(this)); + assert(d == 900); + + uint e = t.balanceOf(other); + assert(e == 100); + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTContract: Test +// SMTTargets: assert diff --git a/test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_wrong.sol b/test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_wrong.sol new file mode 100644 index 0000000000..6bb6074b20 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/token_trusted_transfer_wrong.sol @@ -0,0 +1,68 @@ +interface Token { + function balanceOf(address _a) external view returns (uint); + function transfer(address _to, uint _amt) external; +} + +contract TokenWrong is Token { + mapping (address => uint) balance; + constructor(address _a, uint _b) { + balance[_a] = _b; + } + function balanceOf(address _a) public view override returns (uint) { + return balance[_a]; + } + function transfer(address _to, uint _amt) public override { + require(balance[msg.sender] >= _amt); + // Commented out to make this token implementation wrong. + //balance[msg.sender] -= _amt; + balance[_to] += _amt; + } +} + +contract Test { + function property_transfer(address _token, address _to, uint _amt) public { + require(_to != address(this)); + + TokenWrong t = TokenWrong(_token); + + uint xPre = t.balanceOf(address(this)); + require(xPre >= _amt); + uint yPre = t.balanceOf(_to); + + t.transfer(_to, _amt); + uint xPost = t.balanceOf(address(this)); + uint yPost = t.balanceOf(_to); + + assert(xPost == xPre - _amt); // should fail + assert(yPost == yPre + _amt); + } + + function test_concrete() public { + TokenWrong t = new TokenWrong(address(this), 1000); + + uint b = t.balanceOf(address(this)); + assert(b == 1000); + + address other = address(0x333); + require(address(this) != other); + + uint c = t.balanceOf(other); + assert(c == 0); + + t.transfer(other, 100); + + uint d = t.balanceOf(address(this)); + assert(d == 900); // should fail + + uint e = t.balanceOf(other); + assert(e == 100); + } +} +// ==== +// SMTContract: Test +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (950-978): CHC: Assertion violation happens here. +// Warning 6328: (1370-1386): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/file_level/new_operator.sol b/test/libsolidity/smtCheckerTests/file_level/new_operator.sol index 8a0f118ae7..925f53bc9c 100644 --- a/test/libsolidity/smtCheckerTests/file_level/new_operator.sol +++ b/test/libsolidity/smtCheckerTests/file_level/new_operator.sol @@ -14,5 +14,5 @@ contract D { // ==== // SMTEngine: all // ---- -// Warning 4588: (78-85): Assertion checker does not yet implement this type of function call. +// Warning 8729: (78-85): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. // Warning 6328: (133-152): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nD.constructor()\nD.f()\n test() -- internal call\n (new C()).x() -- untrusted external call diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol index 5efcb2da1b..3a3b295e45 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol @@ -25,4 +25,4 @@ contract C // SMTIgnoreOS: macos // ---- // Warning 6328: (234-253): CHC: Assertion violation happens here. -// Info 1180: Reentrancy property(ies) for :C:\n!( = 1)\n((!((map[1] + ((- 1) * map[0])) <= 0) || ((map'[1] + ((- 1) * map'[0])) <= 0)) && !( = 2) && (!((map[1] + ((- 1) * map[0])) >= 0) || ((map'[0] + ((- 1) * map'[1])) <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(map[0] == map[1])\n = 2 -> Assertion failed at assert(map[0] == map[1])\n = 3 -> Assertion failed at assert(map[0] == 0)\n +// Info 1180: Reentrancy property(ies) for :C:\n!( = 1)\n((!((map[1] + ((- 1) * map[0])) >= 0) || ((map'[0] + ((- 1) * map'[1])) <= 0)) && !( = 2) && (!((map[1] + ((- 1) * map[0])) <= 0) || ((map'[1] + ((- 1) * map'[0])) <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(map[0] == map[1])\n = 2 -> Assertion failed at assert(map[0] == map[1])\n = 3 -> Assertion failed at assert(map[0] == 0)\n diff --git a/test/libsolidity/smtCheckerTests/functions/getters/external_getter_1.sol b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_1.sol new file mode 100644 index 0000000000..00bfb35ca2 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_1.sol @@ -0,0 +1,22 @@ +contract D { + uint public d; + function g() public { + ++d; + } +} + +contract C { + function f() public { + D a = new D(); + assert(a.d() == 0); // should hold + a.g(); + assert(a.d() == 1); // should hold + assert(a.d() == 0); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (203-221): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/getters/external_getter_2.sol b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_2.sol new file mode 100644 index 0000000000..5da279fc95 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_2.sol @@ -0,0 +1,33 @@ +contract E { + uint public e; + function setE(uint _e) public { + e = _e; + } +} + +contract D { + E e; + constructor(E _e) { + e = _e; + } + function setE(uint x) public { + e.setE(x); + } +} + +contract C { + function f() public { + E e = new E(); + D d = new D(e); + assert(e.e() == 0); // should hold + d.setE(42); + assert(e.e() == 42); // should hold + assert(e.e() == 2); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// ---- +// Warning 6328: (344-362): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_1.sol b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_1.sol new file mode 100644 index 0000000000..b7673203e1 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_1.sol @@ -0,0 +1,18 @@ +contract C { + uint public x; + + function f() public { + x = 2; + x = 3; + uint y = this.x(); + assert(y == 3); // should hold + assert(y == 2); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (127-141): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_2.sol b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_2.sol new file mode 100644 index 0000000000..b3dfe04ade --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/getters/external_getter_this_2.sol @@ -0,0 +1,19 @@ +contract C { + uint public x; + + function f() public { + x = 2; + x = 3; + C c = this; + uint y = c.x(); + assert(y == 3); // should hold + assert(y == 2); // should fail + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// SMTTargets: assert +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (138-152): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol b/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol index 0117f9b49d..e30a5e7438 100644 --- a/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol +++ b/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol @@ -27,4 +27,4 @@ contract C is A { // ---- // Warning 6328: (199-214): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nA.constructor()\nState: x = 2\nA.i() // Warning 6328: (387-401): CHC: Assertion violation happens here.\nCounterexample:\nx = 10\n\nTransaction trace:\nC.constructor()\nState: x = 10\nC.i() -// Info 1180: Contract invariant(s) for :A:\n(!(x <= 1) && !(x >= 3))\nContract invariant(s) for :C:\n(!(x >= 11) && !(x <= 9))\n +// Info 1180: Contract invariant(s) for :A:\n(!(x <= 1) && !(x >= 3))\nContract invariant(s) for :C:\n(!(x <= 9) && !(x >= 11))\n diff --git a/test/libsolidity/smtCheckerTests/imports/ExtCall.sol b/test/libsolidity/smtCheckerTests/imports/ExtCall.sol index 047148a90c..7675bc42ea 100644 --- a/test/libsolidity/smtCheckerTests/imports/ExtCall.sol +++ b/test/libsolidity/smtCheckerTests/imports/ExtCall.sol @@ -39,4 +39,4 @@ contract ExtCallTest { // SMTIgnoreCex: yes // ---- // Warning 6328: (ExtCall.sol:362-381): CHC: Assertion violation happens here. -// Warning 4588: (ExtCall.t.sol:110-123): Assertion checker does not yet implement this type of function call. +// Warning 8729: (ExtCall.t.sol:110-123): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. diff --git a/test/libsolidity/smtCheckerTests/imports/import_as_module_2.sol b/test/libsolidity/smtCheckerTests/imports/import_as_module_2.sol index 8ddef2da9e..1298f1f097 100644 --- a/test/libsolidity/smtCheckerTests/imports/import_as_module_2.sol +++ b/test/libsolidity/smtCheckerTests/imports/import_as_module_2.sol @@ -17,6 +17,7 @@ function f(uint _x) pure { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (A:50-64): CHC: Assertion violation happens here.\nCounterexample:\n\n_y = 0\n\nTransaction trace:\nD.constructor()\nD.g(0)\n s1.sol:f(200) -- internal call\n s1.sol:f(0) -- internal call\n A:f(10) -- internal call\n A:f(0) -- internal call // Warning 6328: (s1.sol:28-44): CHC: Assertion violation happens here.\nCounterexample:\n\n_y = 0\n\nTransaction trace:\nD.constructor()\nD.g(0)\n s1.sol:f(200) -- internal call\n s1.sol:f(0) -- internal call diff --git a/test/libsolidity/smtCheckerTests/operators/compound_mul_mapping.sol b/test/libsolidity/smtCheckerTests/operators/compound_mul_mapping.sol index 42775cc9b2..b7b06b1fc8 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_mul_mapping.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_mul_mapping.sol @@ -11,5 +11,6 @@ contract C } // ==== // SMTEngine: all +// SMTIgnoreCex: yes // ---- -// Warning 6328: (164-183): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\np = 0\n\nTransaction trace:\nC.constructor()\nC.f(0, 0) +// Warning 6328: (164-183): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol index b26fcbd93c..923147d495 100644 --- a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol +++ b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol @@ -25,4 +25,4 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 2072: (255-261): Unused local variable. -// Info 1180: Reentrancy property(ies) for :C:\n((!(x' >= 3) || (a' = a)) && ( <= 0) && (!(x' <= 0) || !(x >= 2)) && (!(x <= 2) || !(x' >= 3)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 2 || x == 1)\n +// Info 1180: Reentrancy property(ies) for :C:\n((!(x <= 2) || !(x' >= 3)) && ( <= 0) && (!(x' <= 0) || !(x >= 2)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 2 || x == 1)\n diff --git a/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol b/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol index 0f511a05d1..7af8c96c89 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol @@ -11,6 +11,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreCex: yes // SMTIgnoreOS: macos // ---- // Warning 6328: (135-169): CHC: Assertion violation happens here.\nCounterexample:\n\n_i = 0\nx = 5892\n\nTransaction trace:\nC.constructor()\nC.g(0){ msg.value: 11 }\n _i.f() -- untrusted external call, synthesized as:\n C.g(0){ msg.value: 32278 } -- reentrant call\n _i.f() -- untrusted external call diff --git a/test/libsolidity/smtCheckerTests/try_catch/try_new.sol b/test/libsolidity/smtCheckerTests/try_catch/try_new.sol index e7075e0765..5c98c279d2 100644 --- a/test/libsolidity/smtCheckerTests/try_catch/try_new.sol +++ b/test/libsolidity/smtCheckerTests/try_catch/try_new.sol @@ -28,5 +28,5 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 4588: (231-245): Assertion checker does not yet implement this type of function call. -// Warning 4588: (492-507): Assertion checker does not yet implement this type of function call. +// Warning 8729: (231-245): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 8729: (492-507): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. diff --git a/test/libsolidity/smtCheckerTests/typecast/bytes_to_fixed_bytes_1.sol b/test/libsolidity/smtCheckerTests/typecast/bytes_to_fixed_bytes_1.sol index 1d00e7fe3b..ffd6304c98 100644 --- a/test/libsolidity/smtCheckerTests/typecast/bytes_to_fixed_bytes_1.sol +++ b/test/libsolidity/smtCheckerTests/typecast/bytes_to_fixed_bytes_1.sol @@ -11,4 +11,7 @@ contract C { assert(g == 0x0001020304050607080900010203040506070809000102030405060708090001); // should hold } } +// ==== +// SMTEngine: all +// SMTIgnoreCex: yes // ---- diff --git a/test/libsolidity/smtCheckerTests/typecast/string_to_bytes_push_1.sol b/test/libsolidity/smtCheckerTests/typecast/string_to_bytes_push_1.sol index 4910c417e8..33546b49c0 100644 --- a/test/libsolidity/smtCheckerTests/typecast/string_to_bytes_push_1.sol +++ b/test/libsolidity/smtCheckerTests/typecast/string_to_bytes_push_1.sol @@ -11,4 +11,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (132-160): CHC: Assertion violation happens here.\nCounterexample:\nx = [0x61, 0x62, 0x63, 0x61]\n\nTransaction trace:\nC.constructor()\nState: x = []\nC.s() +// Warning 6328: (132-160): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nState: x = []\nC.s() diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol index 44daa89128..7e23d77d65 100644 --- a/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol @@ -5,5 +5,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreCex: yes // ---- // Warning 6328: (66-80): CHC: Assertion violation happens here.\nCounterexample:\n\nx = true\ny = false\n\nTransaction trace:\nC.constructor()\nC.f(true, false) diff --git a/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol b/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol index 5cb307385b..1a72cad3da 100644 --- a/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol +++ b/test/libsolidity/smtCheckerTests/userTypes/user_type_as_struct_member_1.sol @@ -23,4 +23,3 @@ contract C { ); } } -// ---- diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index e8206e4833..bd51fe920e 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -145,6 +145,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) "--model-checker-contracts=contract1.yul:A,contract2.yul:B", "--model-checker-div-mod-no-slacks", "--model-checker-engine=bmc", + "--model-checker-ext-calls=trusted", "--model-checker-invariants=contract,reentrancy", "--model-checker-show-unproved", "--model-checker-solvers=z3,smtlib2", @@ -211,6 +212,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) {{{"contract1.yul", {"A"}}, {"contract2.yul", {"B"}}}}, true, {true, false}, + {ModelCheckerExtCalls::Mode::TRUSTED}, {{InvariantType::Contract, InvariantType::Reentrancy}}, true, {false, false, true, true}, diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 895957f4d2..47ab7e49c2 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -108,6 +108,7 @@ void FuzzerUtil::testCompiler( frontend::ModelCheckerContracts::Default(), /*divModWithSlacks*/true, frontend::ModelCheckerEngine::All(), + frontend::ModelCheckerExtCalls{}, frontend::ModelCheckerInvariants::All(), /*showUnproved=*/false, smtutil::SMTSolverChoice::All(), From 411841cbb54283d5206b39e411e8a58d4bf404b5 Mon Sep 17 00:00:00 2001 From: Nuno Santos Date: Mon, 6 Feb 2023 17:19:48 +0000 Subject: [PATCH 0079/1140] Tweak wording in value type docs (#13935) * Update value-types.rst - User-defined were written inconsistently (with/without hyphen) - Rewording some sentences for user clarity. * Update docs/types/value-types.rst Co-authored-by: chriseth --------- Co-authored-by: chriseth --- docs/types/value-types.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index de2724afa9..ffdec37961 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -4,8 +4,7 @@ Value Types =========== -The following types are also called value types because variables of these -types will always be passed by value, i.e. they are always copied when they +The following are called value types because their variables will always be passed by value, i.e. they are always copied when they are used as function arguments or in assignments. .. index:: ! bool, ! true, ! false @@ -47,7 +46,7 @@ access the minimum and maximum value representable by the type. Integers in Solidity are restricted to a certain range. For example, with ``uint32``, this is ``0`` up to ``2**32 - 1``. There are two modes in which arithmetic is performed on these types: The "wrapping" or "unchecked" mode and the "checked" mode. - By default, arithmetic is always "checked", which mean that if the result of an operation falls outside the value range + By default, arithmetic is always "checked", meaning that if an operation's result falls outside the value range of the type, the call is reverted through a :ref:`failing assertion`. You can switch to "unchecked" mode using ``unchecked { ... }``. More details can be found in the section about :ref:`unchecked `. @@ -182,7 +181,7 @@ Operators: Address ------- -The address type comes in two flavours, which are largely identical: +The address type comes in two largely identical flavors: - ``address``: Holds a 20 byte value (size of an Ethereum address). - ``address payable``: Same as ``address``, but with the additional members ``transfer`` and ``send``. @@ -653,13 +652,13 @@ smallest and respectively largest value of the given enum. .. _user-defined-value-types: -User Defined Value Types +User-defined Value Types ------------------------ -A user defined value type allows creating a zero cost abstraction over an elementary value type. +A user-defined value type allows creating a zero cost abstraction over an elementary value type. This is similar to an alias, but with stricter type requirements. -A user defined value type is defined using ``type C is V``, where ``C`` is the name of the newly +A user-defined value type is defined using ``type C is V``, where ``C`` is the name of the newly introduced type and ``V`` has to be a built-in value type (the "underlying type"). The function ``C.wrap`` is used to convert from the underlying type to the custom type. Similarly, the function ``C.unwrap`` is used to convert from the custom type to the underlying type. @@ -680,7 +679,7 @@ type with 18 decimals and a minimal library to do arithmetic operations on the t // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.8; - // Represent a 18 decimal, 256 bit wide fixed point type using a user defined value type. + // Represent a 18 decimal, 256 bit wide fixed point type using a user-defined value type. type UFixed256x18 is uint256; /// A minimal library to do fixed point operations on UFixed256x18. From 98c011328a1a6f46c4b466f235d1797bd3f57bf5 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 6 Feb 2023 16:53:23 -0300 Subject: [PATCH 0080/1140] Replace quote marks with quotation marks --- test/externalTests/gnosis.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index ab1fbf3e17..ed525e7a65 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -72,9 +72,10 @@ function gnosis_safe_test # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). - sed -i "s|\(it\)\(('should not allow to call setup on singleton'\)|\1.skip\2|g" test/core/Safe.Setup.spec.ts - sed -i "s|\(it\)\(('can be used only via DELEGATECALL opcode'\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts - sed -i "s|it\(('can only be called from Safe itself'\)|it.skip\1|g" test/libraries/Migration.spec.ts + sed -i "s|\(it\)\((\"should not allow to call setup on singleton\"\)|\1.skip\2|g" test/core/Safe.Setup.spec.ts + sed -i "s|\(it\)\((\"can be used only via DELEGATECALL opcode\"\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts + sed -i "s|it\((\"can only be called from Safe itself\"\)|it.skip\1|g" test/libraries/Migration.spec.ts + sed -i "s|\(it\)\((\"should revert if called directly\"\)|\1.skip\2|g" test/handlers/CompatibilityFallbackHandler.spec.ts neutralize_package_lock neutralize_package_json_hooks From a5c5e4602a51976ab59caa7282fa71ff59c3cb25 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 6 Feb 2023 18:04:10 -0300 Subject: [PATCH 0081/1140] Cleanup of duplicated line leftover from previous fix --- test/externalTests/gnosis.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index ed525e7a65..bafc3f2ca8 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -66,8 +66,8 @@ function gnosis_safe_test sed -i 's|"@openzeppelin/contracts": "\^3\.4\.0"|"@openzeppelin/contracts": "^4.0.0"|g' package.json # Disable two tests failing due to Hardhat's heuristics not yet updated to handle solc 0.8.10. - # TODO: Remove this when Hardhat implements them (https://github.com/nomiclabs/hardhat/issues/2051). - sed -i "s|\(it\)\(('should revert if called directly', async () => {\)|\1.skip\2|g" test/handlers/CompatibilityFallbackHandler.spec.ts + # TODO: Remove this when Hardhat implements them (https://github.com/nomiclabs/hardhat/issues/2451). + sed -i "s|\(it\)\((\"should revert if called directly\"\)|\1.skip\2|g" test/handlers/CompatibilityFallbackHandler.spec.ts # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. @@ -75,7 +75,6 @@ function gnosis_safe_test sed -i "s|\(it\)\((\"should not allow to call setup on singleton\"\)|\1.skip\2|g" test/core/Safe.Setup.spec.ts sed -i "s|\(it\)\((\"can be used only via DELEGATECALL opcode\"\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts sed -i "s|it\((\"can only be called from Safe itself\"\)|it.skip\1|g" test/libraries/Migration.spec.ts - sed -i "s|\(it\)\((\"should revert if called directly\"\)|\1.skip\2|g" test/handlers/CompatibilityFallbackHandler.spec.ts neutralize_package_lock neutralize_package_json_hooks From db9c11a2a5e44771ca2bcd2f86ee2f6b7ea3abf5 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Wed, 8 Feb 2023 16:55:14 +0100 Subject: [PATCH 0082/1140] fix abstract nondet exception --- Changelog.md | 1 + libsolidity/formal/SMTEncoder.cpp | 12 +++--------- libsolidity/formal/SMTEncoder.h | 3 --- .../natspec/abstract_free_function_1.sol | 17 +++++++++++++++++ 4 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/natspec/abstract_free_function_1.sol diff --git a/Changelog.md b/Changelog.md index 5ce4057a48..eefabf7d63 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: + * SMTChecker: Fix internal error when using the custom NatSpec annotation to abstract free functions. * TypeChecker: Also allow external library functions in ``using for``. diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index c3286fa041..5c4fc5ded0 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -2897,7 +2897,9 @@ vector SMTEncoder::stateVariablesIncludingInheritedA vector SMTEncoder::stateVariablesIncludingInheritedAndPrivate(FunctionDefinition const& _function) { - return stateVariablesIncludingInheritedAndPrivate(dynamic_cast(*_function.scope())); + if (auto contract = dynamic_cast(_function.scope())) + return stateVariablesIncludingInheritedAndPrivate(*contract); + return {}; } vector SMTEncoder::localVariablesIncludingModifiers(FunctionDefinition const& _function, ContractDefinition const* _contract) @@ -3020,14 +3022,6 @@ set const& SMTEncoder::contract return m_contractFunctionsWithoutVirtual.at(&_contract); } -SourceUnit const* SMTEncoder::sourceUnitContaining(Scopable const& _scopable) -{ - for (auto const* s = &_scopable; s; s = dynamic_cast(s->scope())) - if (auto const* source = dynamic_cast(s->scope())) - return source; - solAssert(false, ""); -} - map>> SMTEncoder::baseArguments(ContractDefinition const& _contract) { map>> baseArgs; diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index 06b03a7eb8..47e51b54de 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -113,9 +113,6 @@ class SMTEncoder: public ASTConstVisitor /// @returns the ModifierDefinition of a ModifierInvocation if possible, or nullptr. static ModifierDefinition const* resolveModifierInvocation(ModifierInvocation const& _invocation, ContractDefinition const* _contract); - /// @returns the SourceUnit that contains _scopable. - static SourceUnit const* sourceUnitContaining(Scopable const& _scopable); - /// @returns the arguments for each base constructor call in the hierarchy of @a _contract. std::map>> baseArguments(ContractDefinition const& _contract); diff --git a/test/libsolidity/smtCheckerTests/natspec/abstract_free_function_1.sol b/test/libsolidity/smtCheckerTests/natspec/abstract_free_function_1.sol new file mode 100644 index 0000000000..d013670594 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/natspec/abstract_free_function_1.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +contract C { + function f(uint x) external pure { + uint t = msb(x); + assert(t == 0); // should fail + } +} + +/// @custom:smtchecker abstract-function-nondet +function msb(uint256 x) pure returns (uint256 result) {} + +// ==== +// SMTEngine: chc +// ---- +// Warning 6328: (144-158): CHC: Assertion violation happens here. From 603f9f7208eacbbd1e07408b7f636d5b2ce0eea6 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Sun, 25 Dec 2022 22:43:26 +0100 Subject: [PATCH 0083/1140] Type recognition workaround for some GCC compilers Looks like somewhat old GCC compilers, namely 12.2.1, cannot recognize a string literal sometimes. Let's help it to avoid error logs like this one: ``` [ 75%] Building CXX object libsolidity/CMakeFiles/solidity.dir/codegen/ir/IRGeneratorForStatements.cpp.o cd /builddir/build/BUILD/solidity-0.8.18/redhat-linux-build/libsolidity && /usr/bin/g++ -DBOOST_ATOMIC_DYN_LINK -DBOOST_ATOMIC_NO_LIB -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_FILESYSTEM_NO_LIB -DBOOST_SYSTEM_DYN_LINK -DBOOST_SYSTEM_NO_LIB -DFMT_HEADER_ONLY=1 -DHAVE_CVC4 -DHAVE_Z3 -I/builddir/build/BUILD/solidity-0.8.18/redhat-linux-build/include -I/builddir/build/BUILD/solidity-0.8.18 -isystem /usr/include/z3 -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fuse-ld=gold -O3 -DNDEBUG -fstack-protector-strong -Wimplicit-fallthrough -fmacro-prefix-map=/builddir/build/BUILD/solidity-0.8.18=/solidity -Wpessimizing-move -Wredundant-move -Wall -Wextra -Werror -pedantic -Wmissing-declarations -Wno-unknown-pragmas -Wsign-conversion -Wconversion -Wextra-semi -Wduplicated-cond -Wlogical-op -fdiagnostics-color -std=c++17 -MD -MT libsolidity/CMakeFiles/solidity.dir/codegen/ir/IRGeneratorForStatements.cpp.o -MF CMakeFiles/solidity.dir/codegen/ir/IRGeneratorForStatements.cpp.o.d -o CMakeFiles/solidity.dir/codegen/ir/IRGeneratorForStatements.cpp.o -c /builddir/build/BUILD/solidity-0.8.18/libsolidity/codegen/ir/IRGeneratorForStatements.cpp In file included from /usr/include/c++/12/string:40, from /builddir/build/BUILD/solidity-0.8.18/libsolidity/ast/ASTForward.h:27, from /builddir/build/BUILD/solidity-0.8.18/libsolidity/ast/AST.h:26, from /builddir/build/BUILD/solidity-0.8.18/libsolidity/ast/ASTVisitor.h:26, from /builddir/build/BUILD/solidity-0.8.18/libsolidity/codegen/ir/IRGeneratorForStatements.h:24, from /builddir/build/BUILD/solidity-0.8.18/libsolidity/codegen/ir/IRGeneratorForStatements.cpp:22: In function 'std::char_traits::copy(char*, char const*, unsigned long)', inlined from 'std::__cxx11::basic_string, std::allocator >::_S_copy(char*, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.h:423:21, inlined from 'std::__cxx11::basic_string, std::allocator >::_M_replace(unsigned long, unsigned long, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.tcc:532:22, inlined from 'std::__cxx11::basic_string, std::allocator >::assign(char const*)' at /usr/include/c++/12/bits/basic_string.h:1647:19, inlined from 'std::__cxx11::basic_string, std::allocator >::operator=(char const*)' at /usr/include/c++/12/bits/basic_string.h:815:28, inlined from '(anonymous namespace)::CopyTranslate::translateReference(solidity::yul::Identifier const&)' at /builddir/build/BUILD/solidity-0.8.18/libsolidity/codegen/ir/IRGeneratorForStatements.cpp:182:13: /usr/include/c++/12/bits/char_traits.h:431:56: error: 'memcpy' accessing 9223372036854775810 or more bytes at offsets -4611686018427387902 and [-4611686018427387903, 4611686018427387904] may overlap up to 9223372036854775813 bytes at offset -3 [-Werror=restrict] 431 | return static_cast(__builtin_memcpy(__s1, __s2, __n)); | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~ cc1plus: all warnings being treated as errors gmake[2]: *** [libsolidity/CMakeFiles/solidity.dir/build.make:695: libsolidity/CMakeFiles/solidity.dir/codegen/ir/IRGeneratorForStatements.cpp.o] Error 1 gmake[2]: *** Waiting for unfinished jobs.... gmake[2]: Leaving directory '/builddir/build/BUILD/solidity-0.8.18/redhat-linux-build' gmake[1]: *** [CMakeFiles/Makefile2:414: libsolidity/CMakeFiles/solidity.dir/all] Error 2 gmake[1]: Leaving directory '/builddir/build/BUILD/solidity-0.8.18/redhat-linux-build' gmake: *** [Makefile:139: all] Error 2 ``` Signed-off-by: Peter Lemenkov --- libsolidity/ast/ASTJsonExporter.cpp | 3 ++- libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 8b46684bc4..7db502eefb 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -45,6 +45,7 @@ #include using namespace std; +using namespace std::string_literals; using namespace solidity::langutil; namespace @@ -138,7 +139,7 @@ Json::Value ASTJsonExporter::sourceLocationsToJson(vector const& string ASTJsonExporter::namePathToString(std::vector const& _namePath) { - return boost::algorithm::join(_namePath, "."); + return boost::algorithm::join(_namePath, "."s); } Json::Value ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 3e3041bc10..fd0199204b 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -179,7 +179,7 @@ struct CopyTranslate: public yul::ASTCopier else { solAssert(!IRVariable{*varDecl}.hasPart("offset")); - value = "0"; + value = "0"s; } } else if (varDecl->type()->dataStoredIn(DataLocation::CallData)) From a38549dc190b06bbc856734788563907c885ebeb Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Fri, 3 Feb 2023 11:29:58 +0100 Subject: [PATCH 0084/1140] Fixes handling bitwise operators for z3 model checker --- Changelog.md | 1 + libsmtutil/Z3Interface.cpp | 6 ++++++ .../bitwise_operators_do_not_throw_exceptions.sol | 12 ++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/operators/bitwise_operators_do_not_throw_exceptions.sol diff --git a/Changelog.md b/Changelog.md index 7619fbd40d..bff045843d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: * TypeChecker: Also allow external library functions in ``using for``. + * SMTChecker: Fix internal error caused by unhandled ``z3`` expressions that come from the solver when bitwise operators are used. ### 0.8.18 (2023-02-01) diff --git a/libsmtutil/Z3Interface.cpp b/libsmtutil/Z3Interface.cpp index 4abeffa169..21b31d19f8 100644 --- a/libsmtutil/Z3Interface.cpp +++ b/libsmtutil/Z3Interface.cpp @@ -344,6 +344,12 @@ Expression Z3Interface::fromZ3Expr(z3::expr const& _expr) return arguments[0] % arguments[1]; else if (kind == Z3_OP_XOR) return arguments[0] ^ arguments[1]; + else if (kind == Z3_OP_BOR) + return arguments[0] | arguments[1]; + else if (kind == Z3_OP_BAND) + return arguments[0] & arguments[1]; + else if (kind == Z3_OP_BXOR) + return arguments[0] ^ arguments[1]; else if (kind == Z3_OP_BNOT) return !arguments[0]; else if (kind == Z3_OP_BSHL) diff --git a/test/libsolidity/smtCheckerTests/operators/bitwise_operators_do_not_throw_exceptions.sol b/test/libsolidity/smtCheckerTests/operators/bitwise_operators_do_not_throw_exceptions.sol new file mode 100644 index 0000000000..267705a0eb --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/bitwise_operators_do_not_throw_exceptions.sol @@ -0,0 +1,12 @@ +contract C { + // tests that bitwise operators are parsed from z3 answer + function test(uint x, uint y) public pure { + x | y; + x & y; + x ^ y; + assert(true); + } +} +// ==== +// SMTEngine: all +// ---- From 47aa1c65ae7f3acc576372ec327f346d790bccea Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Nov 2022 11:49:40 +0100 Subject: [PATCH 0085/1140] Re-implement KnowledgeBase using groups of constantly-spaced variables. --- libyul/optimiser/DataFlowAnalyzer.cpp | 4 +- libyul/optimiser/KnowledgeBase.cpp | 144 +++++++++++++++------ libyul/optimiser/KnowledgeBase.h | 57 ++++++-- libyul/optimiser/UnusedStoreEliminator.cpp | 8 +- test/libyul/KnowledgeBaseTest.cpp | 8 +- 5 files changed, 165 insertions(+), 56 deletions(-) diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 59ba7c8f0e..81028e3007 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -50,7 +50,7 @@ DataFlowAnalyzer::DataFlowAnalyzer( ): m_dialect(_dialect), m_functionSideEffects(std::move(_functionSideEffects)), - m_knowledgeBase(_dialect, [this](YulString _var) { return variableValue(_var); }), + m_knowledgeBase([this](YulString _var) { return variableValue(_var); }), m_analyzeStores(_analyzeStores == MemoryAndStorage::Analyze) { if (m_analyzeStores) @@ -76,7 +76,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement) cxx20::erase_if(m_state.environment.storage, mapTuple([&](auto&& key, auto&& value) { return !m_knowledgeBase.knownToBeDifferent(vars->first, key) && - !m_knowledgeBase.knownToBeEqual(vars->second, value); + vars->second != value; })); m_state.environment.storage[vars->first] = vars->second; return; diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index c706d529b6..2fd5fb0a9b 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -36,37 +35,24 @@ using namespace solidity::yul; bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b) { - // Try to use the simplification rules together with the - // current values to turn `sub(_a, _b)` into a nonzero constant. - // If that fails, try `eq(_a, _b)`. - if (optional difference = differenceIfKnownConstant(_a, _b)) return difference != 0; - - Expression expr2 = simplify(FunctionCall{{}, {{}, "eq"_yulstring}, util::make_vector(Identifier{{}, _a}, Identifier{{}, _b})}); - if (holds_alternative(expr2)) - return valueOfLiteral(std::get(expr2)) == 0; - return false; } optional KnowledgeBase::differenceIfKnownConstant(YulString _a, YulString _b) { - // Try to use the simplification rules together with the - // current values to turn `sub(_a, _b)` into a constant. - - Expression expr1 = simplify(FunctionCall{{}, {{}, "sub"_yulstring}, util::make_vector(Identifier{{}, _a}, Identifier{{}, _b})}); - if (Literal const* value = get_if(&expr1)) - return valueOfLiteral(*value); - - return {}; + VariableOffset offA = explore(_a); + VariableOffset offB = explore(_b); + if (offA.reference == offB.reference) + return offA.offset - offB.offset; + else + return {}; } + bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b) { - // Try to use the simplification rules together with the - // current values to turn `sub(_a, _b)` into a constant whose absolute value is at least 32. - if (optional difference = differenceIfKnownConstant(_a, _b)) return difference >= 32 && difference <= u256(0) - 32; @@ -80,29 +66,113 @@ bool KnowledgeBase::knownToBeZero(YulString _a) optional KnowledgeBase::valueIfKnownConstant(YulString _a) { - if (AssignedValue const* value = m_variableValues(_a)) - if (Literal const* literal = get_if(value->value)) - return valueOfLiteral(*literal); - return {}; + VariableOffset offset = explore(_a); + if (offset.reference == YulString{}) + return offset.offset; + else + return nullopt; +} + +optional KnowledgeBase::valueIfKnownConstant(Expression const& _expression) +{ + if (Identifier const* ident = get_if(&_expression)) + return valueIfKnownConstant(ident->name); + else if (Literal const* lit = get_if(&_expression)) + return valueOfLiteral(*lit); + else + return {}; } -Expression KnowledgeBase::simplify(Expression _expression) +KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) { - m_counter = 0; - return simplifyRecursively(std::move(_expression)); + // We query the value first so that the variable is reset if it has changed + // since the last call. + Expression const* value = valueOf(_var); + if (VariableOffset const* varOff = util::valueOrNullptr(m_offsets, _var)) + return *varOff; + + if (value) + if (optional offset = explore(*value)) + return setOffset(_var, *offset); + return setOffset(_var, VariableOffset{_var, 0}); + } -Expression KnowledgeBase::simplifyRecursively(Expression _expression) +optional KnowledgeBase::explore(Expression const& _value) { - if (m_counter++ > 100) - return _expression; + if (Literal const* literal = std::get_if(&_value)) + return VariableOffset{YulString{}, valueOfLiteral(*literal)}; + else if (Identifier const* identifier = std::get_if(&_value)) + return explore(identifier->name); + else if (FunctionCall const* f = get_if(&_value)) + if (f->functionName.name == "add"_yulstring || f->functionName.name == "sub"_yulstring) + if (optional a = explore(f->arguments[0])) + if (optional b = explore(f->arguments[1])) + { + u256 offset = + f->functionName.name == "add"_yulstring ? + a->offset + b->offset : + a->offset - b->offset; + if (a->reference == b->reference) + // Offsets relative to the same reference variable + return VariableOffset{a->reference, offset}; + else if (a->reference == YulString{}) + // a is constant + return VariableOffset{b->reference, offset}; + else if (b->reference == YulString{}) + // b is constant + return VariableOffset{a->reference, offset}; + } - if (holds_alternative(_expression)) - for (Expression& arg: std::get(_expression).arguments) - arg = simplifyRecursively(arg); + return {}; +} - if (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_variableValues)) - return simplifyRecursively(match->action().toExpression(debugDataOf(_expression), langutil::EVMVersion())); +Expression const* KnowledgeBase::valueOf(YulString _var) +{ + Expression const* lastValue = m_lastKnownValue[_var]; + AssignedValue const* assignedValue = m_variableValues(_var); + Expression const* currentValue = assignedValue ? assignedValue->value : nullptr; + if (lastValue != currentValue) + reset(_var); + m_lastKnownValue[_var] = currentValue; + return currentValue; +} - return _expression; +void KnowledgeBase::reset(YulString _var) +{ + m_lastKnownValue.erase(_var); + if (VariableOffset const* offset = util::valueOrNullptr(m_offsets, _var)) + { + // Remove var from its group + if (offset->reference != YulString{}) + m_groupMembers[offset->reference].erase(_var); + m_offsets.erase(_var); + } + if (set* group = util::valueOrNullptr(m_groupMembers, _var)) + { + // _var was a representative, we might have to find a new one. + if (group->empty()) + m_groupMembers.erase(_var); + else + { + YulString newRepresentative = *group->begin(); + u256 newOffset = m_offsets[newRepresentative].offset; + for (YulString groupMember: *group) + { + yulAssert(m_offsets[groupMember].reference == _var); + m_offsets[groupMember].reference = newRepresentative; + m_offsets[newRepresentative].offset -= newOffset; + } + } + } +} + +KnowledgeBase::VariableOffset KnowledgeBase::setOffset(YulString _variable, VariableOffset _value) +{ + m_offsets[_variable] = _value; + // Constants are not tracked in m_groupMembers because + // the "representative" can never be reset. + if (_value.reference != YulString{}) + m_groupMembers[_value.reference].insert(_variable); + return _value; } diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 999d0e312b..82c82a7e93 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -38,32 +38,69 @@ struct AssignedValue; /** * Class that can answer questions about values of variables and their relations. + * + * Requires a callback that returns the current value of the variable. + * The value can change any time during the lifetime of the KnowledgeBase, + * it will update its internal data structure accordingly. + * + * This means that the code the KnowledgeBase is used on does not need to be in SSA + * form. + * The only requirement is that the assigned values are movable expressions. + * + * Internally, tries to find groups of variables that have a mutual constant + * difference and stores these differences always relative to a specific + * representative variable of the group. + * + * There is a special group which is the constant values. Those use the + * empty YulString as representative "variable". */ class KnowledgeBase { public: - KnowledgeBase( - Dialect const& _dialect, - std::function _variableValues - ): - m_dialect(_dialect), + KnowledgeBase(std::function _variableValues): m_variableValues(std::move(_variableValues)) {} bool knownToBeDifferent(YulString _a, YulString _b); std::optional differenceIfKnownConstant(YulString _a, YulString _b); bool knownToBeDifferentByAtLeast32(YulString _a, YulString _b); - bool knownToBeEqual(YulString _a, YulString _b) const { return _a == _b; } bool knownToBeZero(YulString _a); std::optional valueIfKnownConstant(YulString _a); + std::optional valueIfKnownConstant(Expression const& _expression); private: - Expression simplify(Expression _expression); - Expression simplifyRecursively(Expression _expression); + /** + * Constant offset relative to a reference variable, or absolute constant if the + * reference variable is the empty YulString. + */ + struct VariableOffset + { + YulString reference; + u256 offset; + }; - Dialect const& m_dialect; + VariableOffset explore(YulString _var); + std::optional explore(Expression const& _value); + + /// Retrieves the current value of a variable and potentially resets the variable if it is not up to date. + Expression const* valueOf(YulString _var); + + /// Resets all information about the variable and removes it from its group, + /// potentially finding a new representative. + void reset(YulString _var); + + VariableOffset setOffset(YulString _variable, VariableOffset _value); + + /// Callback to retrieve the current value of a variable. std::function m_variableValues; - size_t m_counter = 0; + + /// Offsets for each variable to one representative per group. + /// The empty string is the representative of the constant value zero. + std::map m_offsets; + /// Last known value of each variable we queried. + std::map m_lastKnownValue; + /// For each representative, variables that use it to offset from. + std::map> m_groupMembers; }; } diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index 2e96be2e70..d5155ad7e5 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -174,7 +174,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement) initialState = State::Used; auto startOffset = identifierNameIfSSA(funCall->arguments.at(1)); auto length = identifierNameIfSSA(funCall->arguments.at(2)); - KnowledgeBase knowledge(m_dialect, [this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); + KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); if (length && startOffset) { FunctionCall const* lengthCall = get_if(m_ssaValues.at(*length).value); @@ -267,7 +267,7 @@ bool UnusedStoreEliminator::knownUnrelated( UnusedStoreEliminator::Operation const& _op2 ) const { - KnowledgeBase knowledge(m_dialect, [this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); + KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); if (_op1.location != _op2.location) return true; @@ -348,7 +348,7 @@ bool UnusedStoreEliminator::knownCovered( return true; if (_covered.location == Location::Memory) { - KnowledgeBase knowledge(m_dialect, [this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); + KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); if (_covered.length && knowledge.knownToBeZero(*_covered.length)) return true; @@ -359,7 +359,7 @@ bool UnusedStoreEliminator::knownCovered( return false; optional coveredLength = knowledge.valueIfKnownConstant(*_covered.length); optional coveringLength = knowledge.valueIfKnownConstant(*_covering.length); - if (knowledge.knownToBeEqual(*_covered.start, *_covering.start)) + if (*_covered.start == *_covering.start) if (coveredLength && coveringLength && *coveredLength <= *coveringLength) return true; optional coveredStart = knowledge.valueIfKnownConstant(*_covered.start); diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index ec2f0313d1..7cb5a8ae3c 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -58,7 +58,7 @@ class KnowledgeBaseTest for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - return KnowledgeBase(m_dialect, [this](YulString _var) { return util::valueOrNullptr(m_values, _var); }); + return KnowledgeBase([this](YulString _var) { return util::valueOrNullptr(m_values, _var); }); } EVMDialect m_dialect{EVMVersion{}, true}; @@ -83,9 +83,11 @@ BOOST_AUTO_TEST_CASE(basic) BOOST_CHECK(!kb.knownToBeDifferent("a"_yulstring, "b"_yulstring)); // This only works if the variable names are the same. // It assumes that SSA+CSE+Simplifier actually replaces the variables. - BOOST_CHECK(!kb.knownToBeEqual("a"_yulstring, "b"_yulstring)); BOOST_CHECK(!kb.valueIfKnownConstant("a"_yulstring)); BOOST_CHECK(kb.valueIfKnownConstant("zero"_yulstring) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulstring, "b"_yulstring) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulstring, "c"_yulstring) == u256(0)); + BOOST_CHECK(kb.valueIfKnownConstant("e"_yulstring) == u256(0)); } BOOST_AUTO_TEST_CASE(difference) @@ -94,7 +96,7 @@ BOOST_AUTO_TEST_CASE(difference) let a := calldataload(0) let b := add(a, 200) let c := add(a, 220) - let d := add(c, 12) + let d := add(12, c) let e := sub(c, 12) })"); From 96e2a6d3fe7eb4b7fc197f30910411afbcb869a1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Nov 2022 14:06:37 +0100 Subject: [PATCH 0086/1140] Keep one instance of KnowledgeBase for UnusedStoreEliminator. --- libyul/optimiser/UnusedStoreEliminator.cpp | 60 +++++++++++++--------- libyul/optimiser/UnusedStoreEliminator.h | 11 ++-- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index d5155ad7e5..2455333952 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -92,6 +92,21 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) remover(_ast); } +UnusedStoreEliminator::UnusedStoreEliminator( + Dialect const& _dialect, + map const& _functionSideEffects, + map _controlFlowSideEffects, + map const& _ssaValues, + bool _ignoreMemory +): + UnusedStoreBase(_dialect), + m_ignoreMemory(_ignoreMemory), + m_functionSideEffects(_functionSideEffects), + m_controlFlowSideEffects(_controlFlowSideEffects), + m_ssaValues(_ssaValues), + m_knowledgeBase([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }) +{} + void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) { UnusedStoreBase::operator()(_functionCall); @@ -174,12 +189,11 @@ void UnusedStoreEliminator::visit(Statement const& _statement) initialState = State::Used; auto startOffset = identifierNameIfSSA(funCall->arguments.at(1)); auto length = identifierNameIfSSA(funCall->arguments.at(2)); - KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); if (length && startOffset) { FunctionCall const* lengthCall = get_if(m_ssaValues.at(*length).value); if ( - knowledge.knownToBeZero(*startOffset) && + m_knowledgeBase.knownToBeZero(*startOffset) && lengthCall && toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE ) @@ -267,8 +281,6 @@ bool UnusedStoreEliminator::knownUnrelated( UnusedStoreEliminator::Operation const& _op2 ) const { - KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); - if (_op1.location != _op2.location) return true; if (_op1.location == Location::Storage) @@ -278,26 +290,26 @@ bool UnusedStoreEliminator::knownUnrelated( yulAssert( _op1.length && _op2.length && - knowledge.valueIfKnownConstant(*_op1.length) == 1 && - knowledge.valueIfKnownConstant(*_op2.length) == 1 + m_knowledgeBase.valueIfKnownConstant(*_op1.length) == 1 && + m_knowledgeBase.valueIfKnownConstant(*_op2.length) == 1 ); - return knowledge.knownToBeDifferent(*_op1.start, *_op2.start); + return m_knowledgeBase.knownToBeDifferent(*_op1.start, *_op2.start); } } else { yulAssert(_op1.location == Location::Memory, ""); if ( - (_op1.length && knowledge.knownToBeZero(*_op1.length)) || - (_op2.length && knowledge.knownToBeZero(*_op2.length)) + (_op1.length && m_knowledgeBase.knownToBeZero(*_op1.length)) || + (_op2.length && m_knowledgeBase.knownToBeZero(*_op2.length)) ) return true; if (_op1.start && _op1.length && _op2.start) { - optional length1 = knowledge.valueIfKnownConstant(*_op1.length); - optional start1 = knowledge.valueIfKnownConstant(*_op1.start); - optional start2 = knowledge.valueIfKnownConstant(*_op2.start); + optional length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); + optional start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); + optional start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); if ( (length1 && start1 && start2) && *start1 + *length1 >= *start1 && // no overflow @@ -307,9 +319,9 @@ bool UnusedStoreEliminator::knownUnrelated( } if (_op2.start && _op2.length && _op1.start) { - optional length2 = knowledge.valueIfKnownConstant(*_op2.length); - optional start2 = knowledge.valueIfKnownConstant(*_op2.start); - optional start1 = knowledge.valueIfKnownConstant(*_op1.start); + optional length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); + optional start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); + optional start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); if ( (length2 && start2 && start1) && *start2 + *length2 >= *start2 && // no overflow @@ -320,12 +332,12 @@ bool UnusedStoreEliminator::knownUnrelated( if (_op1.start && _op1.length && _op2.start && _op2.length) { - optional length1 = knowledge.valueIfKnownConstant(*_op1.length); - optional length2 = knowledge.valueIfKnownConstant(*_op2.length); + optional length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); + optional length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); if ( (length1 && *length1 <= 32) && (length2 && *length2 <= 32) && - knowledge.knownToBeDifferentByAtLeast32(*_op1.start, *_op2.start) + m_knowledgeBase.knownToBeDifferentByAtLeast32(*_op1.start, *_op2.start) ) return true; } @@ -348,22 +360,20 @@ bool UnusedStoreEliminator::knownCovered( return true; if (_covered.location == Location::Memory) { - KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); - - if (_covered.length && knowledge.knownToBeZero(*_covered.length)) + if (_covered.length && m_knowledgeBase.knownToBeZero(*_covered.length)) return true; // Condition (i = cover_i_ng, e = cover_e_d): // i.start <= e.start && e.start + e.length <= i.start + i.length if (!_covered.start || !_covering.start || !_covered.length || !_covering.length) return false; - optional coveredLength = knowledge.valueIfKnownConstant(*_covered.length); - optional coveringLength = knowledge.valueIfKnownConstant(*_covering.length); + optional coveredLength = m_knowledgeBase.valueIfKnownConstant(*_covered.length); + optional coveringLength = m_knowledgeBase.valueIfKnownConstant(*_covering.length); if (*_covered.start == *_covering.start) if (coveredLength && coveringLength && *coveredLength <= *coveringLength) return true; - optional coveredStart = knowledge.valueIfKnownConstant(*_covered.start); - optional coveringStart = knowledge.valueIfKnownConstant(*_covering.start); + optional coveredStart = m_knowledgeBase.valueIfKnownConstant(*_covered.start); + optional coveringStart = m_knowledgeBase.valueIfKnownConstant(*_covering.start); if (coveredStart && coveringStart && coveredLength && coveringLength) if ( *coveringStart <= *coveredStart && diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index 8b5bfd7b14..7fbf9885ff 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -68,13 +69,7 @@ class UnusedStoreEliminator: public UnusedStoreBase std::map _controlFlowSideEffects, std::map const& _ssaValues, bool _ignoreMemory - ): - UnusedStoreBase(_dialect), - m_ignoreMemory(_ignoreMemory), - m_functionSideEffects(_functionSideEffects), - m_controlFlowSideEffects(_controlFlowSideEffects), - m_ssaValues(_ssaValues) - {} + ); using UnusedStoreBase::operator(); void operator()(FunctionCall const& _functionCall) override; @@ -121,6 +116,8 @@ class UnusedStoreEliminator: public UnusedStoreBase std::map const& m_ssaValues; std::map m_storeOperations; + + KnowledgeBase mutable m_knowledgeBase; }; } From 6bbef64034be733f987514a065a1b05b1b3aae65 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Nov 2022 14:22:40 +0100 Subject: [PATCH 0087/1140] Optimize in case this is SSA. --- libyul/optimiser/KnowledgeBase.cpp | 34 ++++++++++++++++++---- libyul/optimiser/KnowledgeBase.h | 9 ++++++ libyul/optimiser/UnusedStoreEliminator.cpp | 2 +- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 2fd5fb0a9b..23627653a5 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -33,6 +33,11 @@ using namespace std; using namespace solidity; using namespace solidity::yul; +KnowledgeBase::KnowledgeBase(map const& _ssaValues): + m_valuesAreSSA(true), + m_variableValues([_ssaValues](YulString _var) { return util::valueOrNullptr(_ssaValues, _var); }) +{} + bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b) { if (optional difference = differenceIfKnownConstant(_a, _b)) @@ -85,11 +90,23 @@ optional KnowledgeBase::valueIfKnownConstant(Expression const& _expression KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) { - // We query the value first so that the variable is reset if it has changed - // since the last call. - Expression const* value = valueOf(_var); - if (VariableOffset const* varOff = util::valueOrNullptr(m_offsets, _var)) - return *varOff; + Expression const* value = nullptr; + if (m_valuesAreSSA) + { + // In SSA, a once determined offset is always valid, so we first see + // if we already computed it. + if (VariableOffset const* varOff = util::valueOrNullptr(m_offsets, _var)) + return *varOff; + value = valueOf(_var); + } + else + { + // For non-SSA, we query the value first so that the variable is reset if it has changed + // since the last call. + value = valueOf(_var); + if (VariableOffset const* varOff = util::valueOrNullptr(m_offsets, _var)) + return *varOff; + } if (value) if (optional offset = explore(*value)) @@ -129,9 +146,12 @@ optional KnowledgeBase::explore(Expression const& Expression const* KnowledgeBase::valueOf(YulString _var) { - Expression const* lastValue = m_lastKnownValue[_var]; AssignedValue const* assignedValue = m_variableValues(_var); Expression const* currentValue = assignedValue ? assignedValue->value : nullptr; + if (m_valuesAreSSA) + return currentValue; + + Expression const* lastValue = m_lastKnownValue[_var]; if (lastValue != currentValue) reset(_var); m_lastKnownValue[_var] = currentValue; @@ -140,6 +160,8 @@ Expression const* KnowledgeBase::valueOf(YulString _var) void KnowledgeBase::reset(YulString _var) { + yulAssert(!m_valuesAreSSA); + m_lastKnownValue.erase(_var); if (VariableOffset const* offset = util::valueOrNullptr(m_offsets, _var)) { diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 82c82a7e93..934b2e21ad 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -47,6 +47,9 @@ struct AssignedValue; * form. * The only requirement is that the assigned values are movable expressions. * + * There is a constructor to provide all SSA values right at the beginning. + * If you use this, the KnowledgeBase will be slightly more efficient. + * * Internally, tries to find groups of variables that have a mutual constant * difference and stores these differences always relative to a specific * representative variable of the group. @@ -57,9 +60,13 @@ struct AssignedValue; class KnowledgeBase { public: + /// Constructor for arbitrary value callback that allows for variable values + /// to change in between calls to functions of this class. KnowledgeBase(std::function _variableValues): m_variableValues(std::move(_variableValues)) {} + /// Constructor to use if source code is in SSA form and values are constant. + KnowledgeBase(std::map const& _ssaValues); bool knownToBeDifferent(YulString _a, YulString _b); std::optional differenceIfKnownConstant(YulString _a, YulString _b); @@ -91,6 +98,8 @@ class KnowledgeBase VariableOffset setOffset(YulString _variable, VariableOffset _value); + /// If true, we can assume that variable values never change and skip some steps. + bool m_valuesAreSSA = false; /// Callback to retrieve the current value of a variable. std::function m_variableValues; diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index 2455333952..3df9c63196 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -104,7 +104,7 @@ UnusedStoreEliminator::UnusedStoreEliminator( m_functionSideEffects(_functionSideEffects), m_controlFlowSideEffects(_controlFlowSideEffects), m_ssaValues(_ssaValues), - m_knowledgeBase([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }) + m_knowledgeBase(_ssaValues) {} void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) From eec258c2d29d0b36635ad2e398603d6342176842 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Nov 2022 16:04:19 +0100 Subject: [PATCH 0088/1140] Bugfix. --- libyul/optimiser/KnowledgeBase.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 23627653a5..558dc89888 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -122,24 +122,33 @@ optional KnowledgeBase::explore(Expression const& else if (Identifier const* identifier = std::get_if(&_value)) return explore(identifier->name); else if (FunctionCall const* f = get_if(&_value)) - if (f->functionName.name == "add"_yulstring || f->functionName.name == "sub"_yulstring) + { + if (f->functionName.name == "add"_yulstring) + { if (optional a = explore(f->arguments[0])) if (optional b = explore(f->arguments[1])) { - u256 offset = - f->functionName.name == "add"_yulstring ? - a->offset + b->offset : - a->offset - b->offset; - if (a->reference == b->reference) - // Offsets relative to the same reference variable - return VariableOffset{a->reference, offset}; - else if (a->reference == YulString{}) + u256 offset = a->offset + b->offset; + if (a->reference.empty()) // a is constant return VariableOffset{b->reference, offset}; - else if (b->reference == YulString{}) + else if (b->reference.empty()) // b is constant return VariableOffset{a->reference, offset}; } + } + else if (f->functionName.name == "sub"_yulstring) + if (optional a = explore(f->arguments[0])) + if (optional b = explore(f->arguments[1])) + { + u256 offset = a->offset - b->offset; + if (a->reference == b->reference) + return VariableOffset{YulString{}, offset}; + else if (b->reference.empty()) + // b is constant + return VariableOffset{a->reference, offset}; + } + } return {}; } From 695b250557e1588147d7658455617327a900b95b Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Nov 2022 17:14:01 +0100 Subject: [PATCH 0089/1140] Update gas costs. --- .../array/copying/function_type_array_to_storage.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol index 1e8760250a..409bb2983c 100644 --- a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol @@ -46,7 +46,7 @@ contract C { } // ---- // test() -> 0x20, 0x14, "[a called][b called]" -// gas irOptimized: 116673 +// gas irOptimized: 116660 // gas legacy: 119030 // gas legacyOptimized: 117021 // test2() -> 0x20, 0x14, "[b called][a called]" From 3ac6edec5b88fc5f11f56f141242b1703e0aa935 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Nov 2022 18:02:56 +0100 Subject: [PATCH 0090/1140] Apply suggestions from code review --- libyul/optimiser/KnowledgeBase.cpp | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 558dc89888..96b352e402 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -52,7 +52,7 @@ optional KnowledgeBase::differenceIfKnownConstant(YulString _a, YulString if (offA.reference == offB.reference) return offA.offset - offB.offset; else - return {}; + return nullopt; } @@ -66,13 +66,13 @@ bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b) bool KnowledgeBase::knownToBeZero(YulString _a) { - return valueIfKnownConstant(_a) == u256{}; + return valueIfKnownConstant(_a) == 0; } optional KnowledgeBase::valueIfKnownConstant(YulString _a) { VariableOffset offset = explore(_a); - if (offset.reference == YulString{}) + if (offset.reference.empty()) return offset.offset; else return nullopt; @@ -85,7 +85,7 @@ optional KnowledgeBase::valueIfKnownConstant(Expression const& _expression else if (Literal const* lit = get_if(&_expression)) return valueOfLiteral(*lit); else - return {}; + return nullopt; } KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) @@ -117,9 +117,9 @@ KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) optional KnowledgeBase::explore(Expression const& _value) { - if (Literal const* literal = std::get_if(&_value)) + if (Literal const* literal = get_if(&_value)) return VariableOffset{YulString{}, valueOfLiteral(*literal)}; - else if (Identifier const* identifier = std::get_if(&_value)) + else if (Identifier const* identifier = get_if(&_value)) return explore(identifier->name); else if (FunctionCall const* f = get_if(&_value)) { @@ -150,7 +150,7 @@ optional KnowledgeBase::explore(Expression const& } } - return {}; + return nullopt; } Expression const* KnowledgeBase::valueOf(YulString _var) @@ -175,26 +175,33 @@ void KnowledgeBase::reset(YulString _var) if (VariableOffset const* offset = util::valueOrNullptr(m_offsets, _var)) { // Remove var from its group - if (offset->reference != YulString{}) + if (!offset->reference.empty()) m_groupMembers[offset->reference].erase(_var); m_offsets.erase(_var); } if (set* group = util::valueOrNullptr(m_groupMembers, _var)) { // _var was a representative, we might have to find a new one. - if (group->empty()) - m_groupMembers.erase(_var); - else + if (!group->empty()) { YulString newRepresentative = *group->begin(); + yulAssert(newRepresentative != _var); u256 newOffset = m_offsets[newRepresentative].offset; + // newOffset = newRepresentative - _var for (YulString groupMember: *group) { yulAssert(m_offsets[groupMember].reference == _var); m_offsets[groupMember].reference = newRepresentative; - m_offsets[newRepresentative].offset -= newOffset; + // groupMember = _var + m_offsets[groupMember].offset (old) + // = newRepresentative - newOffset + m_offsets[groupMember].offset (old) + // so subtracting newOffset from .offset yields the original relation again, + // just with _var replaced by newRepresentative + m_offsets[groupMember].offset -= newOffset; } + m_groupMembers[newRepresentative] = std::move(*group); + } + m_groupMembers.erase(_var); } } @@ -203,7 +210,7 @@ KnowledgeBase::VariableOffset KnowledgeBase::setOffset(YulString _variable, Vari m_offsets[_variable] = _value; // Constants are not tracked in m_groupMembers because // the "representative" can never be reset. - if (_value.reference != YulString{}) + if (!_value.reference.empty()) m_groupMembers[_value.reference].insert(_variable); return _value; } From 29e4becd73c47d16724263e63b27fc7ab139a278 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 9 Feb 2023 11:21:37 +0100 Subject: [PATCH 0091/1140] Introduce helpers for VariableOffset. --- libyul/optimiser/KnowledgeBase.cpp | 14 +++++--------- libyul/optimiser/KnowledgeBase.h | 13 +++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 96b352e402..e01090146d 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -71,11 +71,7 @@ bool KnowledgeBase::knownToBeZero(YulString _a) optional KnowledgeBase::valueIfKnownConstant(YulString _a) { - VariableOffset offset = explore(_a); - if (offset.reference.empty()) - return offset.offset; - else - return nullopt; + return explore(_a).absoluteValue(); } optional KnowledgeBase::valueIfKnownConstant(Expression const& _expression) @@ -129,10 +125,10 @@ optional KnowledgeBase::explore(Expression const& if (optional b = explore(f->arguments[1])) { u256 offset = a->offset + b->offset; - if (a->reference.empty()) + if (a->isAbsolute()) // a is constant return VariableOffset{b->reference, offset}; - else if (b->reference.empty()) + else if (b->isAbsolute()) // b is constant return VariableOffset{a->reference, offset}; } @@ -144,7 +140,7 @@ optional KnowledgeBase::explore(Expression const& u256 offset = a->offset - b->offset; if (a->reference == b->reference) return VariableOffset{YulString{}, offset}; - else if (b->reference.empty()) + else if (b->isAbsolute()) // b is constant return VariableOffset{a->reference, offset}; } @@ -175,7 +171,7 @@ void KnowledgeBase::reset(YulString _var) if (VariableOffset const* offset = util::valueOrNullptr(m_offsets, _var)) { // Remove var from its group - if (!offset->reference.empty()) + if (!offset->isAbsolute()) m_groupMembers[offset->reference].erase(_var); m_offsets.erase(_var); } diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 934b2e21ad..258f85f5cd 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -84,6 +84,19 @@ class KnowledgeBase { YulString reference; u256 offset; + + bool isAbsolute() const + { + return reference.empty(); + } + + std::optional absoluteValue() const + { + if (isAbsolute()) + return offset; + else + return std::nullopt; + } }; VariableOffset explore(YulString _var); From 627bbe2ea3eed9374975b34d4f4cb438a8fd4a46 Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Tue, 7 Feb 2023 23:53:38 +0100 Subject: [PATCH 0092/1140] Update stale issues policies --- .github/workflows/stale.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 18046d107c..4761c62ac2 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,8 +10,8 @@ permissions: pull-requests: write env: - BEFORE_ISSUE_STALE: 334 - BEFORE_ISSUE_CLOSE: 0 #FIXME: change to 14 days + BEFORE_ISSUE_STALE: 90 + BEFORE_ISSUE_CLOSE: 7 BEFORE_PR_STALE: 14 BEFORE_PR_CLOSE: 7 @@ -28,14 +28,13 @@ jobs: This issue has been marked as stale due to inactivity for the last ${{ env.BEFORE_ISSUE_STALE }} days. It will be automatically closed in ${{ env.BEFORE_ISSUE_CLOSE }} days. close-issue-message: | - Hi everyone! This issue has been closed due to inactivity. + Hi everyone! This issue has been automatically closed due to inactivity. If you think this issue is still relevant in the latest Solidity version and you have something to [contribute](https://docs.soliditylang.org/en/latest/contributing.html), feel free to reopen. However, unless the issue is a concrete proposal that can be implemented, we recommend starting a language discussion on the [forum](https://forum.soliditylang.org) instead. - any-of-issue-labels: stale # TODO: remove this when we're done with closing ancient issues - ascending: true # TODO: remove this when we're done with closing ancient issues + ascending: true stale-issue-label: stale close-issue-label: closed-due-inactivity - exempt-issue-labels: 'bug :bug:,roadmap,selected-for-development,must have' + exempt-issue-labels: 'bug :bug:,epic,roadmap,selected-for-development,must have,must have eventually,SMT' stale-pr-message: | This pull request is stale because it has been open for ${{ env.BEFORE_PR_STALE }} days with no activity. It will be closed in ${{ env.BEFORE_PR_CLOSE }} days unless the `stale` label is removed. @@ -48,6 +47,5 @@ jobs: exempt-pr-labels: 'external contribution :star:,roadmap,epic' exempt-draft-pr: false exempt-all-milestones: true - # remove-stale-when-updated: true # TODO: uncomment and remove the line below when we're done with closing ancient issues - remove-issue-stale-when-updated: false + remove-stale-when-updated: true operations-per-run: 128 From a5166f0a19971fc778172ffb0fcd790afaf1592b Mon Sep 17 00:00:00 2001 From: "Rodrigo Q. Saramago" Date: Sat, 11 Feb 2023 17:16:03 +0100 Subject: [PATCH 0093/1140] gp2 external test workaround --- test/externalTests/common.sh | 3 +-- test/externalTests/gp2.sh | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index b6a85c1e3b..97d0a337ee 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -235,8 +235,7 @@ function force_truffle_compiler_settings function name_hardhat_default_export { local config_file="$1" - - local import="import {HardhatUserConfig} from 'hardhat/types';" + local import="import {HardhatUserConfig} from 'hardhat/types/config';" local config="const config: HardhatUserConfig = {" sed -i "s|^\s*export\s*default\s*{|${import}\n${config}|g" "$config_file" echo "export default config;" >> "$config_file" diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index 9e9ee72af2..120379478a 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -76,6 +76,9 @@ function gp2_test # See https://github.com/cowprotocol/contracts/issues/32 yarn add @tenderly/hardhat-tenderly@1.1.6 + # Add missing sinon type definitions + yarn add @types/sinon + # Some dependencies come with pre-built artifacts. We want to build from scratch. rm -r node_modules/@gnosis.pm/safe-contracts/build/ From 7585cd95076b532e080a78f3242bb19853b7e909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 2 Feb 2023 14:47:03 +0100 Subject: [PATCH 0094/1140] ReleaseChecklist: List packages needed to update the PPA as prerequisites --- ReleaseChecklist.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 0e46522ba3..589f5ad4fa 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -7,6 +7,7 @@ - [ ] DockerHub account with push rights to the [``solc`` image](https://hub.docker.com/r/ethereum/solc). - [ ] Lauchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and a gnupg key for your email in the ``ethereum.org`` domain (has to be version 1, gpg2 won't work). + - [ ] Ubuntu/Debian dependencies of the PPA scripts: ``devscripts``, ``debhelper``, ``dput``, ``git``, ``wget``, ``ca-certificates``. - [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [``solc`` package](https://www.npmjs.com/package/solc). - [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). - [ ] [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (``/r/ethereum`` requirements). From 8b7879c7dad9d3850546ea2a8b34742033b04f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 2 Feb 2023 14:47:31 +0100 Subject: [PATCH 0095/1140] ReleaseChecklist: `static-z3.sh` is actually called `static_z3.sh` --- ReleaseChecklist.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 589f5ad4fa..8c38bd8e47 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -58,9 +58,9 @@ ### PPA - [ ] Create ``.release_ppa_auth`` at the root of your local Solidity checkout and set ``LAUNCHPAD_EMAIL`` and ``LAUNCHPAD_KEYID`` to your key's email and key id. - - [ ] Double-check that the ``DISTRIBUTIONS`` list in ``scripts/release_ppa.sh`` and ``scripts/deps-ppa/static-z3.sh`` contains the most recent versions of Ubuntu. + - [ ] Double-check that the ``DISTRIBUTIONS`` list in ``scripts/release_ppa.sh`` and ``scripts/deps-ppa/static_z3.sh`` contains the most recent versions of Ubuntu. - [ ] Make sure the [``~ethereum/cpp-build-deps`` PPA repository](https://launchpad.net/~ethereum/+archive/ubuntu/cpp-build-deps) contains ``libz3-static-dev builds`` for all current versions of Ubuntu. - If not, run ``scripts/deps-ppa/static-z3.sh`` and wait for the builds to succeed before continuing. + If not, run ``scripts/deps-ppa/static_z3.sh`` and wait for the builds to succeed before continuing. - [ ] Run ``scripts/release_ppa.sh v$VERSION`` to create the PPA release. - [ ] Wait for the [``~ethereum/ethereum-static`` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum-static) build to be finished and published for *all platforms*. **SERIOUSLY: DO NOT PROCEED EARLIER!!!** From 89c4ee69420612b18e6637e5b20213595d45c069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Feb 2023 19:01:22 +0100 Subject: [PATCH 0096/1140] Add a script for generating a list of contributors to paste in release notes --- ReleaseChecklist.md | 4 ++- scripts/list_contributors.sh | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100755 scripts/list_contributors.sh diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 8c38bd8e47..f5b5e3ada0 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -33,7 +33,9 @@ Set the target to the ``develop`` branch and the tag to the new version, e.g. ``v0.8.5``. Include the following warning: ``**The release is still in progress and the binaries may not yet be available from all sources.**``. Don't publish it yet - click the ``Save draft`` button instead. - - [ ] Thank voluntary contributors in the GitHub release notes (use ``git shortlog --summary --email v0.5.3..origin/develop``). + - [ ] Thank voluntary contributors in the GitHub release notes. + Use ``scripts/list_contributors.sh v`` to get initial list of names. + Remove different variants of the same name manually before using the output. - [ ] Check that all tests on the latest commit in ``develop`` are green. - [ ] Click the ``Publish release`` button on the release page, creating the tag. - [ ] Wait for the CI runs on the tag itself. diff --git a/scripts/list_contributors.sh b/scripts/list_contributors.sh new file mode 100755 index 0000000000..4b8f06d765 --- /dev/null +++ b/scripts/list_contributors.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# ------------------------------------------------------------------------------ +# Creates a list containing names of people who contributed to the project, for use +# in release notes. The names come from the author field on the commits between +# the current revision and the one specified as argument. +# +# Note that the output often requires extra manual processing to remove entries +# that refer to the same person (diacritics vs no diacritics, name vs nickname, etc.). +# +# Usage: +#