Introduces a new opcode, PAY, to send ether to an address without calling any of its functions
|Authors||Gavin John (@Pandapip1), Zainan Victor Zhou (@xinbenlv)|
Table of Contents
This EIP introduces a new opcode,
PAY, taking two stack parameters,
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
CALLopcode 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:
- Pops two values from the stack:
valwei from the executing address to the address
addr, even if
addris the zero address.
The base cost of this opcode is the additional cost of having a nonzero
msg.value in a
CALL opcode (currently
addr is not the zero address, the EIP-2929 account access costs for
addr (but NOT the current account) are also incurred: 100 gas for a warm account, 2600 gas for a cold account, and 25000 gas for a new account. If any of these costs are changed, the pricing for the
PAY opcode must also be changed.
The additional nonzero
msg.value cost of the
CALL should equal the cost of transferring ether. Therefore, that is the base cost of this opcode. Additionally, the access costs for the receiving account make sense, since the account needs to be accessed. However, it is reasonable to assume that optimized execution clients have the data for the executing contract cached.
The order of arguments mimicks that of
CALL, which pops
val. Beyond consistency, though, this ordering aids validators pattern-matching MEV opportunities, so
PAY always appears immediately after
This change requires a hard fork.
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.
Please cite this document as:
Gavin John (@Pandapip1), Zainan Victor Zhou (@xinbenlv), "EIP-5920: PAY opcode [DRAFT]," Ethereum Improvement Proposals, no. 5920, March 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5920.