From 2f1fa9ae77e654a5704e05776440e45fabbde19b Mon Sep 17 00:00:00 2001 From: Emilio Almansi Date: Sun, 4 Jun 2023 12:58:59 +0700 Subject: [PATCH] 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; +} +// ----