Skip to content

Commit

Permalink
Merge pull request #2211 from crytic/fix-vyper-is-reentrant
Browse files Browse the repository at this point in the history
fix is_reentrant for internal vyper functions
  • Loading branch information
0xalpharush authored Dec 4, 2023
2 parents 3e62ea6 + b7ba2c4 commit deebe36
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
13 changes: 9 additions & 4 deletions slither/core/declarations/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -1500,10 +1500,13 @@ def is_reentrant(self) -> bool:
"""
Determine if the function can be re-entered
"""
reentrancy_modifier = "nonReentrant"

if self.function_language == FunctionLanguage.Vyper:
reentrancy_modifier = "nonreentrant(lock)"

# TODO: compare with hash of known nonReentrant modifier instead of the name
if "nonReentrant" in [m.name for m in self.modifiers] or "nonreentrant(lock)" in [
m.name for m in self.modifiers
]:
if reentrancy_modifier in [m.name for m in self.modifiers]:
return False

if self.visibility in ["public", "external"]:
Expand All @@ -1515,7 +1518,9 @@ def is_reentrant(self) -> bool:
]
if not all_entry_points:
return True
return not all(("nonReentrant" in [m.name for m in f.modifiers] for f in all_entry_points))
return not all(
(reentrancy_modifier in [m.name for m in f.modifiers] for f in all_entry_points)
)

# endregion
###################################################################################
Expand Down
9 changes: 8 additions & 1 deletion tests/unit/core/test_function_declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ def withdraw():
@external
@nonreentrant("lock")
def withdraw_locked():
self.withdraw_locked_internal()
@internal
def withdraw_locked_internal():
raw_call(msg.sender, b"", value= self.balances[msg.sender])
@payable
@external
Expand Down Expand Up @@ -376,10 +379,14 @@ def __default__():
assert not f.is_empty

f = functions["withdraw_locked()"]
assert not f.is_reentrant
assert f.is_reentrant is False
assert f.is_implemented
assert not f.is_empty

f = functions["withdraw_locked_internal()"]
assert f.is_reentrant is False
assert f.visibility == "internal"

var = contract.get_state_variable_from_name("balances")
assert var
assert var.solidity_signature == "balances(address)"
Expand Down

0 comments on commit deebe36

Please sign in to comment.