---
eip: 5920
title: PAY opcode
description: Introduces a new opcode, PAY, to send ether to an address without calling any of its functions
author: Gavin John (@Pandapip1), Zainan Victor Zhou (@xinbenlv), Sam Wilson (@SamWilsn), Jochem Brouwer (@jochem-brouwer), Charles Cooper (@charles-cooper)
discussions-to: https://ethereum-magicians.org/t/eip-5920-pay-opcode/11717
status: Stagnant
type: Standards Track
category: Core
created: 2022-03-14
requires: 214, 2929, 7523
---

## Abstract

This EIP introduces a new opcode, `PAY`, taking two stack parameters, `addr` and `val`, that transfers `val` wei to the address `addr` without calling any of its functions.

## Motivation

Currently, to send ether to an address requires you to call into that address, which transfers execution context to that address, which creates several issues:

- First of all, it opens a reentrancy attack vector, as the recipient can call back into the sender. More generally, the recipient can unilaterally execute arbitrary state changes, limited only by the gas forwarded, which is not desirable from the point of view of the sender.
  - In practice, when calling into another account and sending ether, 2300 gas (the "gas stipend") is always available "for free" in the newly created call frame. Although it is currently not possible to make storage state changes with the 2300 gas stipend (see the last minute rejection of [EIP-1283](./eip-1283.md) from Constantinople to be replaced with the "gas stipend safe" [EIP-2200](./eip-2200.md) version in Istanbul), it is possible to do this with transient storage ([EIP-1153](./eip-1153.md)). This is a security risk where potentially the transient storage gets changed unintentionally. The goal is to send ether, and not have to consider these potential unintuitive security problems.
- Secondly, it opens a DoS vector. Contracts wanting to send ether must be cognizant of the possibility that the recipient will run out of gas or revert.
- Future potential call-like opcodes may not provide a way to restrict the amount of gas being forwarded to the recipient, so the meager mitigation against unintended side effects in use today (gas limit) is not guaranteed to be available.
- The `CALL` and `EXTCALL` opcodes will execute code on the recipient, which is unintended when wanting to send ether and which could lead to unintentional operations. The code execution also has to be paid for in gas, even when the intention is to only send ether, which is thus an unnecessary waste of gas.
- Finally, [EIP-7702](./eip-7702.md) allows to delegate externally owned accounts (EOAs) to other accounts, which breaks the invariant that EOAs cannot contain code. Therefore, calling such EOA with the intention to send ether will thus also execute code and cost unnecessary gas.

Having a dedicated opcode for ether transfers solves all of these issues, and would be a useful addition to the EVM.

## Specification

### Constants

| Constant                   | Definition                |
| -------------------------- | ------------------------- |
| `WARM_STORAGE_READ_COST`   | [EIP-2929](./eip-2929.md) |
| `COLD_ACCOUNT_ACCESS_COST` | [EIP-2929](./eip-2929.md) |
| `GAS_NEW_ACCOUNT`          | [EELS][gna]               |
| `GAS_CALL_VALUE`           | [EELS][gcv]               |

[gna]: https://github.com/ethereum/execution-specs/blob/4d953035fb0cceda7cf21d71b2ab7a9a6f4632f0/src/ethereum/frontier/vm/gas.py#L52
[gcv]: https://github.com/ethereum/execution-specs/blob/4d953035fb0cceda7cf21d71b2ab7a9a6f4632f0/src/ethereum/frontier/vm/gas.py#L53

### Behavior

A new opcode is introduced: `PAY` (`0xfc`), which:

- Halt with exceptional failure if the current frame is static, as defined in [EIP-214](./eip-214.md).
- Pops two values from the stack: `addr` then `val`.
- Exceptionally halts if `addr` has any of the high 12 bytes set to a non-zero value (i.e. it does not contain a 20-byte address).
- Charges the gas cost detailed below.
- Marks `addr` as warm (adding `addr` to `accessed_addresses`).
- Transfers `val` wei from the current address to the address `addr`, only if the current address has a balance greater than or equal to `val`.
- Push `1` on the stack if the `PAY` operation was successful, or `0` if it failed.
  - Currently only insufficient balance would produce a `0` return value.

### Gas Cost

The gas cost for `PAY` is the sum of the following:

- Is `addr` in `accessed_addresses`?
    - If yes, `WARM_STORAGE_READ_COST`;
    - Otherwise, `COLD_ACCOUNT_ACCESS_COST`.
- Does `addr` exist or is `val` zero?
    - If yes to either, zero;
    - Otherwise, `GAS_NEW_ACCOUNT`.
- Is `val` zero?
    - If yes, zero;
    - Otherwise, `GAS_CALL_VALUE`.

`PAY` cannot be implemented on networks with empty accounts (see [EIP-7523](./eip-7523.md)).

## Rationale

### Argument order

The order of arguments mimics that of `CALL`, which pops `addr` before `val`. Beyond consistency, though, this ordering aids validators pattern-matching MEV opportunities, so `PAY` always appears immediately after `COINBASE`.

### Halting for invalid address

The halting behavior is designed to allow for Address Space Extension.
If the high bytes were truncated, as in `CALL`, contracts could depend on the truncating behavior.
If the address space were extended beyond 20 bytes, `PAY` would either not be able to target those accounts, or code expecting truncation could send ether to the wrong address.

Because this behavior may be changed, contracts should not rely on this halting behavior and use methods designated to intentionally halt (such as the [`INVALID`](./eip-141.md) opcode).

## Backwards Compatibility

This change requires a hard fork.

## Security Considerations

Existing contracts should not rely on their balance being under their control, since it is already possible to send ether to an address without calling it, by using the `SELFDESTRUCT` opcode (somewhat restricted in [EIP-6780](./eip-6780.md)).
It is also possible to involuntarily fund an account with priority fees sent to a `block.coinbase`.
However, this opcode does make this process cheaper and easier. It thus does not break an invariant.

## Copyright

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