Skip to content

Commit

Permalink
Merge ff8d5b2 into c86cdf2
Browse files Browse the repository at this point in the history
  • Loading branch information
charles-cooper authored May 10, 2024
2 parents c86cdf2 + ff8d5b2 commit 62d8607
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions EIPS/eip-7705.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
eip: 7705
title: NONREENTRANT and REENTRANT opcodes
description: Opcodes to mark a contract as nonreentrant
author: Charles Cooper (@charles-cooper)
discussions-to: https://ethereum-magicians.org/t/eip-7705-nonreentrant-opcodes/19957
status: Draft
type: Standards Track
category: Core
created: 2024-05-09
---

## Abstract

Add two opcodes, `NONREENTRANT` and `REENTRANT`, which set and clear a contract's reentrancy status. After invoking `NONREENTRANT`, a contract cannot be `CALL`ed (or `STATICCALL`ed, or `DELEGATECALL`ed) until `REENTRANT` is invoked.

## Motivation

Reentrancy attacks account for a substantial portion of user funds stolen on EVM chains, including the famous "DAO hack" (a more complete list is available at [pcaversaccio/reentrancy-attacks](../../../../../pcaversaccio/reentrancy-attacks/blob/81a24bfa197900360a/README.md)). However, due to the cost of preventing against reentrancy attacks in application code, developers often opt-out of reentrancy protection. This cost has come down with the advent of transient storage ([EIP-1153](./eip-1153.md)), but it is still not cheap enough where it is a "no-brainer" to use it by default. This EIP proposes opcodes which make it cheaper to protect against reentrancy in application code.

## Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Two new opcodes are introduced, `NONREENTRANT` (0xF6) and `REENTRANT` (0xF7), which set and clear a contract's nonreentrancy flag. The effect of invoking `NONREENTRANT` is that a contract can no longer have execution context transferred to it (via any of the `*CALL` opcodes), until `REENTRANT` is invoked. `CALL`ing a contract which has the nonreentrancy flag set is equivalent to executing a single `REVERT` opcode.

Both `NONREENTRANT` and `REENTRANT` are idempotent; that is, invoking `NONREENTRANT` when a contract already has nonreentrant status is a no-op, and likewise for `REENTRANT`.

The scope of the nonreentrant flag is limited to the current transaction. That is, nonreentrant flags are cleared at the end of every transaction. In the presence of reversion (`REVERT` or exceptional halt), the contract's nonreentrancy flag reverts to whatever its value was before the call.

The cost of `NONREENTRANT` and `REENTRANT` are both set at 5 (`G_mid`).

## Rationale

The computational cost of pushing the current value to the call stack (for handling reverts) is accounted for in the overhead cost of the `*CALL` opcodes.

An alternative design could be considered which only introduces one opcode. This opcode, `NONREENTRANT`, would take a single stack item and set the nonreentrancy flag based on its value. This alternative design can be considered based on feedback.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

## Reference Implementation

## Security Considerations

TBD

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).

0 comments on commit 62d8607

Please sign in to comment.