Re-Entrancy Lock

Vyper has a handy way to secure your contract from re-entrancy.

A re-entrancy lock can be created on a function with @nonreentrant.

Contract with re-entrancy lock

# pragma version ^0.4.0

@external
@nonreentrant
def func():
    raw_call(msg.sender, b"", value=0)

Contract without re-entrancy lock

# pragma version ^0.4.0

@external
def func():
    raw_call(msg.sender, b"", value=0)

Contract to test re-entrancy

# pragma version ^0.4.0

interface ILock:
    def func(): nonpayable

count: public(uint256)

@external
@payable
def __default__():
    if self.count < 2:
        self.count += 1
        extcall ILock(msg.sender).func()

@external
def reset():
    self.count = 0

@external
def test_lock(to: address):
    extcall ILock(to).func()

Try on Smart Contract Engineer