-
-
Notifications
You must be signed in to change notification settings - Fork 887
VIP: make external entrypoints nonreentrant by default #4509
Copy link
Copy link
Closed
Labels
VIP: DiscussionUsed to denote VIPs and more complex issues that are waiting discussion in a meetingUsed to denote VIPs and more complex issues that are waiting discussion in a meetingrelease - mustrelease blockerrelease blocker
Milestone
Description
Simple Summary
Make external entrypoints (with some exceptions listed below) nonreentrant by default for all evm versions since cancun. The @nonreentrant decorator is replaced by the new defaults and a new @reentrant decorator. The @reentrant decorator designates that the given entrypoint should not read or write the lock to enable reentrancy as a feature/gas optimization.
Motivation
The aim of this proposal is to further align Vyper with it being an easily auditable and security-focused language. Safe and sensible defaults are fundamental to achieving those goals.
Specification
External functions
- External function is either
@reentrantor has the implicitnonreentrantbehavior.
@external
@reentrant
def foo():
# foo doesn't read or write the lock
...@external
def foo():
# foo reads the lock upon invocation and reverts if locked
# if unlocked, it locks the lock
...
# unlocks the lock, after body finishes executionPure and view functions
viewfunctions arenonreentrantby default, but they only read the lock upon invocation, no write operation is performedpurefunctions arereentrantby default due to state-acess restrictions
init function
__init__functions arereentrantby default. In theinitcontext, the contract isn't yet deployed, thus we consider this default safe
default function
__default__function is madenonreentrantby default
Public variables (getters)
publicvariables are made reentrant by default- It is maintained that read-only reentrancy based on only getters is unlikely. Furthermore, it is hypothesized that many users would make their variables
reentranthad this not been the default and thus hinder readability and conciseness of Vyper code. Furthermore, it could even lead to users turning this feature off (see the section on#pragma reentrant) - To enable locking of even getters, the following syntax could be introduced:
var: nonreentrant(public(uint256)) - Alternatively,
publicvariables could be blocked altogether in favor of manually written getters
New reentrant pragma
- This proposal is a breaking change. To allow users to revert back to the current (v0.4.1) behavior, add
#pragma reentrant, which enables the current (v0.4.1) reentrancy semantics.
Modules
- Due to the introduction of the new
reentrantpragma, there could be collision between individual modules the contract comprises of - Assume a collision happens, meaning that one module uses the pragma and the other one doesn't. We consider the following options as sensible:
- Abort compilation
#pragma reentrantmaintains its effect only in those modules where it is used, other modules arenonreentrantby default. Additionally, a warning is emitted to the user about the risk of reentrancy as the whole protocol might have been designed with the thought of it beingnonreentrantby default.
- We consider this point to be contentious and welcome feedback from others
Breaking changes
- All external entrypoints are nonreentrant by default
@nonreentrantdecorator doesn't work without#pragma reentrant
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
VIP: DiscussionUsed to denote VIPs and more complex issues that are waiting discussion in a meetingUsed to denote VIPs and more complex issues that are waiting discussion in a meetingrelease - mustrelease blockerrelease blocker