From 2f1fa9ae77e654a5704e05776440e45fabbde19b Mon Sep 17 00:00:00 2001 From: Emilio Almansi Date: Sun, 4 Jun 2023 12:58:59 +0700 Subject: [PATCH 1/2] Fix non-constant event and error selectors --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 23 +++++++++++++++++++ .../constant_from_error_selector.sol | 10 ++++++++ .../constant_from_event_selector.sol | 10 ++++++++ .../constant_from_function_selector.sol | 9 ++++++++ 5 files changed, 53 insertions(+) create mode 100644 test/libsolidity/syntaxTests/constants/constant_from_error_selector.sol create mode 100644 test/libsolidity/syntaxTests/constants/constant_from_event_selector.sol create mode 100644 test/libsolidity/syntaxTests/constants/constant_from_function_selector.sol diff --git a/Changelog.md b/Changelog.md index aac8ab8b2..8cd329408 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,6 +21,7 @@ Bugfixes: * SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function. * Yul Optimizer: Ensure that the assignment of memory slots for variables moved to memory does not depend on AST IDs that may depend on whether additional files are included during compilation. * Yul Optimizer: Fix optimized IR being unnecessarily passed through the Yul optimizer again before bytecode generation. + * TypeChecker: Fix non-constant event and error selectors. AST Changes: * AST: Add the ``experimentalSolidity`` field to the ``SourceUnit`` nodes, which indicate whether the experimental parsing mode has been enabled via ``pragma experimental solidity``. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e7721fd9e..43c3eb191 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3358,6 +3358,29 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) annotation.isPure = isPure; } + if ( + auto const* functionType = dynamic_cast(exprType); + !annotation.isPure.set() && + functionType && + functionType->kind() == FunctionType::Kind::Event && + functionType->hasDeclaration() && + memberName == "selector" + ) + if ( + auto const* eventDefinition = dynamic_cast(&functionType->declaration()); + eventDefinition && + !eventDefinition->isAnonymous() + ) + annotation.isPure = true; + if ( + auto const* functionType = dynamic_cast(exprType); + !annotation.isPure.set() && + functionType && + functionType->kind() == FunctionType::Kind::Error && + functionType->hasDeclaration() && + memberName == "selector" + ) + annotation.isPure = true; if ( auto const* varDecl = dynamic_cast(annotation.referencedDeclaration); !annotation.isPure.set() && diff --git a/test/libsolidity/syntaxTests/constants/constant_from_error_selector.sol b/test/libsolidity/syntaxTests/constants/constant_from_error_selector.sol new file mode 100644 index 000000000..b120e3045 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/constant_from_error_selector.sol @@ -0,0 +1,10 @@ +interface I { + error Er1(); +} +contract C { + function f() external {} + error Er2(); + bytes4 constant errorSelector1 = I.Er1.selector; + bytes4 constant errorSelector2 = Er2.selector; +} +// ---- diff --git a/test/libsolidity/syntaxTests/constants/constant_from_event_selector.sol b/test/libsolidity/syntaxTests/constants/constant_from_event_selector.sol new file mode 100644 index 000000000..4a3898989 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/constant_from_event_selector.sol @@ -0,0 +1,10 @@ +interface I { + event Ev1(); +} +contract C { + function f() external {} + event Ev2(); + bytes32 constant eventSelector1 = I.Ev1.selector; + bytes32 constant eventSelector2 = Ev2.selector; +} +// ---- diff --git a/test/libsolidity/syntaxTests/constants/constant_from_function_selector.sol b/test/libsolidity/syntaxTests/constants/constant_from_function_selector.sol new file mode 100644 index 000000000..8acc25388 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/constant_from_function_selector.sol @@ -0,0 +1,9 @@ +interface I { + function f() external; +} +contract C { + function f() external {} + bytes4 constant functionSelector1 = I.f.selector; + bytes4 constant functionSelector2 = this.f.selector; +} +// ---- From 2a5f046e87d7c3a13c462c6eed7773f8920d8d26 Mon Sep 17 00:00:00 2001 From: Emilio Almansi Date: Sun, 18 Jun 2023 13:56:46 +0800 Subject: [PATCH 2/2] Skip tests failing due to known issue with hardhat --- test/externalTests/zeppelin.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 5c0271125..cf8df4363 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -93,6 +93,10 @@ function zeppelin_test sed -i "s|it(\('cannot nest reinitializers'\)|it.skip(\1|g" test/proxy/utils/Initializable.test.js sed -i "s|it(\('prevents re-initialization'\)|it.skip(\1|g" test/proxy/utils/Initializable.test.js sed -i "s|it(\('can lock contract after initialization'\)|it.skip(\1|g" test/proxy/utils/Initializable.test.js + sed -i "s|it(\('calling upgradeTo on the implementation reverts'\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js + sed -i "s|it(\('calling upgradeToAndCall on the implementation reverts'\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js + sed -i "s|it(\('calling upgradeTo from a contract that is not an ERC1967 proxy\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js + sed -i "s|it(\('calling upgradeToAndCall from a contract that is not an ERC1967 proxy\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js # Here only the testToInt(248) and testToInt(256) cases fail so change the loop range to skip them sed -i "s|range(8, 256, 8)\(.forEach(bits => testToInt(bits));\)|range(8, 240, 8)\1|" test/utils/math/SafeCast.test.js