diff --git a/Changelog.md b/Changelog.md index 1aa6bc64b2f4..24199d062eb4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: Bugfixes: +* TypeChecker: Allow assignment of error and event selectors to constant variables. ### 0.8.31 (2025-12-03) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9e29983bad3b..f5c093dbd411 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3280,18 +3280,31 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) auto const* functionType = dynamic_cast(exprType); functionType && functionType->hasDeclaration() && - dynamic_cast(&functionType->declaration()) && memberName == "selector" ) - if (auto const* parentAccess = dynamic_cast(&_memberAccess.expression())) + { + if (dynamic_cast(&functionType->declaration())) { - bool isPure = *parentAccess->expression().annotation().isPure; - if (auto const* exprInt = dynamic_cast(&parentAccess->expression())) - if (exprInt->name() == "this" || exprInt->name() == "super") - isPure = true; + if (auto const* parentAccess = dynamic_cast(&_memberAccess.expression())) + { + bool isPure = *parentAccess->expression().annotation().isPure; + // Accessing a function selector using `super|this.f.selector`. + if (auto const* exprInt = dynamic_cast(&parentAccess->expression())) + if (exprInt->name() == "this" || exprInt->name() == "super") + isPure = true; - annotation.isPure = isPure; + annotation.isPure = isPure; + } } + // In case of event or error definition the selector is always compile-time constant, as it can be + // a keccak256 hash of the event signature or a function selector in case of an error. + else if ( + dynamic_cast(&functionType->declaration()) || + dynamic_cast(&functionType->declaration()) + ) + annotation.isPure = true; + } + if ( auto const* varDecl = dynamic_cast(annotation.referencedDeclaration); !annotation.isPure.set() && diff --git a/test/libsolidity/syntaxTests/types/functionTypes/selector/event_error_selector_pure_assignment.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/event_error_selector_pure_assignment.sol new file mode 100644 index 000000000000..263e8f8a1a68 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/functionTypes/selector/event_error_selector_pure_assignment.sol @@ -0,0 +1,20 @@ +event EvExt(); +error ErExt(); + +bytes32 constant eventExtSelectorGlobal = EvExt.selector; +bytes4 constant errorExtSelectorGlobal = ErExt.selector; + +contract C { + event Ev(); + error Er(); + + bytes4 constant errorExtSelector = ErExt.selector; + bytes32 constant eventExtSelector = EvExt.selector; + + bytes4 constant errorSelector = Er.selector; + bytes32 constant eventSelector = Ev.selector; + + bytes4 constant errorSelectorC = C.Er.selector; + bytes32 constant eventSelectorC = C.Ev.selector; +} +// ----