Vyper theorytheory 0/50 · 0%
Security patterns · medium

23. Reentrancy guard: @nonreentrant

Locking a function against reentrant calls.

Vyper provides a built-in reentrancy guard via the `@nonreentrant("key")` decorator, which uses a storage-backed lock so a locked function cannot be re-entered while it's still executing, even across different functions sharing the same key.

@external
@nonreentrant("withdraw_lock")
def withdraw():
    amount: uint256 = self.balances[msg.sender]
    self.balances[msg.sender] = 0
    send(msg.sender, amount)

Still follow checks-effects-interactions as a first line of defence — zero out the balance before sending — and use the guard as a second, belt-and-braces layer.

Check your understanding

  1. 1. Which decorator provides Vyper's built-in reentrancy lock?

  2. 2. What should you still do even with the guard applied?

  3. 3. Do two functions with the same nonreentrant key share a lock?