不碰调用也能把钱送进去:EIP-5920 的 PAY 操作码 图 1
不碰调用也能把钱送进去:EIP-5920 的 PAY 操作码 · 图 1

白送一笔钱,在 EVM 里却是个动作

以太坊上给一个地址加余额,用户层面有标准办法:普通转账交易,或者把交易发给一个不收币的合约。可在合约内部,想把价值”塞”给另一个地址而不执行它的代码,长期没有直接工具——最接近的是带金额的 CALL,但那会顺带运行目标合约的接收逻辑,对方可以拒绝、可以重入、可以花掉你给的燃料。EIP-5920 提出 PAY 操作码:从栈里弹出一个三十二字节的地址和一个金额,给目标账户直接加钱,不进任何代码。它 2022 年 3 月创建,状态 Draft,需要硬分叉,至今只是提案。

规则细看

规范给的燃料账很简单:查一遍目标地址是否已在访问集合——热地址收便宜的价钱、冷地址收贵的价钱(沿用柏林升级的冷热账);目标不存在且金额大于零时,补一笔新建账户费;金额非零再收一笔价值转移费。地址参数是三十二字节原样取用,超出二十字节地址空间的高位不是截断而是直接让交易中止——提案解释这是给未来扩展地址空间留余地:若默默截断,合约可能依赖截断行为,将来地址变长时钱会送错门。

有一处细节写进了提案的合理性一节:参数顺序刻意对齐 CALL,让负责打包的交易排序观察方更容易做模式匹配——PAY 会紧跟在出块者地址读取之后出现。这句话读起来坦率得可爱,但也提醒我们:任何把资金流动标准化的改动,都在同时标准化它的可观测性。

为什么不算破坏既有规则

一个自然的质疑:凭空塞钱进别人账户,合约还能信自己的余额吗?提案的回答是——本来就不该信。SELFDESTRUCT(后来被 EIP-6780 大幅限制)早就能把余额倒进任意地址;出块者收优先费也会让账户被动进账。PAY 没有引入新的不可控,只是把这条通道变得更便宜更整齐。安全考虑段把这层窗户纸捅得很明白。

它还挂着一个前置条件:不能和”空账户”共存。以太坊状态早在 2016 年的 Spurious Dragon 清剿里就处置过一批余额为零、只剩 nonce 的账户,此后状态的一贯姿态是让”有实质内容的账户”这种判断有唯一答案。PAY 若创建只带余额的新账户没问题,但若某个只有零余额的空壳还活在状态树里,“新建账户”的判定就模糊了,因此提案要求与清理空账户的方向(EIP-7523)同行。

为什么值得存在

草稿动机的重心在效率与语义分离:代理钱包给用户发 ETH、合约批量派息、给出块者打点,这些场景要的是”价值移动”,不该捆绑”执行接收方代码”的风险和燃料。把两者拆开,调用归调用、送钱归送钱。今天这些场景靠普通转账交易间接覆盖,PAY 的独立价值更多体现在链内小额分发能省下的那部分燃料账单上。

原生转账与代币转账不是一回事

顺带澄清一个常混淆的点:在以太坊里”给别人转 ETH”和”给别人转 ERC-20 代币”机制完全不同。代币转账是合约存储里的记账——调用合约、改它内部的余额映射,ETH 一层没动;而 PAY 处理的是原生价值,直接改状态树里的账户余额,接收方若是合约也不会自动被叫醒。所以”收款合约要实现回调才能收币”这类经验只属于代币世界;原生价值的路径上,无论走转账交易、CALL 还是 PAY 讨论中的方案,钱进账户都不需要接收方点头。PAY 的争议点从来不在”能不能白送”,而在”值不值得为送钱单开一个操作码”。

状态提醒

Draft 不等于任何主网时间表。读 EIP 时把”状态”当版本号看:Draft 是想法入册,Review 起才谈实现,Final 只代表文档不再大改,激活另说。PAY 至今停在第一格。本文只讨论协议机制,不构成任何投资建议。