PAY opcode

Introduces a new opcode, PAY, to send ether to an address without calling any of its functions
ReviewStandards Track: Core
Created: 2022-03-14
Requires: EIP-2929, EIP-7523
Gavin John (@Pandapip1), Zainan Victor Zhou (@xinbenlv), Sam Wilson (@SamWilsn)
DiscussionsOriginal linkEdit
1 min read

The proposed PAY opcode in EIP-5920 is a new opcode that allows for the transfer of ether to an address without calling any of its functions. It aims to improve the functionality and efficiency of the Ethereum network by addressing issues with the current method of sending ether, such as reentrancy attack vectors and DoS vectors, and the needlessly expensive CALL opcode for simple ether transfers. The PAY opcode is a dedicated opcode for ether transfers that solves these issues and is a useful addition to the EVM.

Anyone may contribute to propose contents.
Go propose


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.


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 stipend, which is not desirable from the point of view of the sender.
  • Secondly, it opens a DoS vector. Contracts which want to send ether must be cognizant of the possibility that the recipient will run out of gas or revert.
  • Finally, the CALL opcode is needlessly expensive for simple ether transfers, as it requires the memory and stack to be expanded, the recipient's full data including code and memory to be loaded, and finally needs to execute a call, which might do other unintentional operations. Having a dedicated opcode for ether transfers solves all of these issues, and would be a useful addition to the EVM.





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

  • Pops two values from the stack: addr then val.
  • Transfers val wei from the current target address to the address addr.
  • Marks addr as warm (adding addr to accessed_addresses.)

Gas Cost

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

  • Is addr in accessed_addresses?
  • 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.)


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.

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 creating a temporary contract and immediately SELFDESTRUCTing it, sending the ether to an arbitrary address. However, this opcode does make this process cheaper for already-vulnerable contracts.

Copyright and related rights waived via CC0.

Further reading
Anyone may contribute to propose contents.
Go propose
Adopted by projects
Anyone may contribute to propose contents.
Go propose

Not miss a beat of EIPs' update?

Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.

View all
Serve Ethereum Builders, Scale the Community.
Supported by