Skip to content

Commit feccaca

Browse files
Merge pull request #79 from charles-cooper/nonreentrancy-pragma-fixes
nonreentrancy fixes
2 parents 6ff8d52 + 8329221 commit feccaca

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

tests/functional/syntax/signatures/test_invalid_function_decorators.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ def nonreentrant_foo() -> uint256:
2727
(
2828
"""
2929
@external
30+
@nonreentrant
31+
@reentrant
32+
def foo() -> uint256:
33+
return 1
34+
""",
35+
StructureException,
36+
),
37+
(
38+
"""
39+
@external
40+
@reentrant
41+
@nonreentrant
42+
def foo() -> uint256:
43+
return 1
44+
""",
45+
StructureException,
46+
),
47+
(
48+
"""
49+
@external
3050
@nonreentrant("foo")
3151
def nonreentrant_foo() -> uint256:
3252
return 1

vyper/semantics/types/function.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -777,13 +777,7 @@ def visibility(self) -> Optional[FunctionVisibility]:
777777

778778
def set_state_mutability(self, decorator_node: vy_ast.Name):
779779
assert StateMutability.is_valid_value(decorator_node.id), "unreachable"
780-
if self.state_mutability_node is not None:
781-
raise FunctionDeclarationException(
782-
f"Mutability is already set to: {self.state_mutability}",
783-
self.state_mutability_node,
784-
decorator_node,
785-
hint="only one state mutability decorator is allowed per function",
786-
)
780+
self._check_none(self.state_mutability_node, decorator_node)
787781
self.state_mutability_node = decorator_node
788782

789783
@property
@@ -795,25 +789,28 @@ def state_mutability(self) -> StateMutability:
795789
def get_file_settings(self) -> Settings:
796790
return self.funcdef.module_node.settings
797791

792+
def _check_none(self, node_a, node_b):
793+
if node_a is not None:
794+
name_a = node_a.id
795+
name_b = node_b.id
796+
raise StructureException(f"tried to set {name_b}, but {name_a} is already set", node_a, node_b)
797+
798798
def set_nonreentrant(self, decorator_node: vy_ast.Name):
799-
if self.nonreentrant_node is not None:
800-
raise StructureException(
801-
"nonreentrant decorator is already set", self.nonreentrant_node, decorator_node
802-
)
799+
self._check_none(self.nonreentrant_node, decorator_node)
800+
self._check_none(self.reentrant_node, decorator_node)
803801

804802
self.nonreentrant_node = decorator_node
805803

806804
def set_reentrant(self, decorator_node: vy_ast.Name):
805+
self._check_none(self.nonreentrant_node, decorator_node)
806+
self._check_none(self.reentrant_node, decorator_node)
807+
807808
settings = self.get_file_settings()
808809

809810
if not settings.nonreentrancy_by_default:
810811
raise StructureException(
811812
"used @reentrant decorator, but `#pragma nonreentrancy` is not set"
812813
)
813-
if self.reentrant_node is not None:
814-
raise StructureException(
815-
"reentrant decorator is already set", self.reentrant_node, decorator_node
816-
)
817814

818815
self.reentrant_node = decorator_node
819816

0 commit comments

Comments
 (0)