确认弹窗曾经无字可显
钱包给普通用户最重要的一屏,是交易确认页:“你要向某某地址转 1.5 个代币”。但按 EIP-1193 时代的调用方式,网页交给钱包的 data 字段本来就是一串没有标签的十六进制——函数由前 4 个字节的选择器表示,参数各占 32 字节的槽位。钱包若不知道这个合约的 ABI(接口说明),就只能给你看原始字节。EIP-2566 在 2020 年 3 月 23 日把这个痛点写成提案:新增一个与 eth_sendTransaction 并行的方法 eth_sendTransactionToContractFunction,唯一区别是交易对象里多一个 abi 字段,dApp 必须把被调函数的 ABI 一并交给钱包,钱包据此还原出可读的函数名和参数。状态至今 Stagnant(停滞)。

它防的攻击很具体
提案的动机部分给了一个精确的场景:恶意 dApp 在你不知情时把 transfer(address,uint256) 里那个 address 参数换成攻击者地址。整笔交易的其余部分都正常,代币照转,收款人换了。若确认页只显示十六进制,普通用户几乎不可能逐字符比对;若钱包能显示”收款人:0x……”的可读字段,偷换就有机会被肉眼拦住。这正是今天确认界面逐字段展示的价值所在——区别只在于今天大多数钱包不是靠 dApp 自报 ABI,而是靠本地合约库和已验证的 ABI 源来解码。
设计里没人解决的问题
细读规范会发现一个提案没有处理的裂缝:abi 字段和 data 字段是两样东西,由调用方分别填写,规范没有规定两者不一致时怎么办。一个恶意 dApp 完全可以提交真实的 data 加一份”美化”过的 ABI,让钱包把危险调用显示得人畜无害——可读性反成了欺骗的包装纸。当年 EIP-2566 因此被批评为把信任从”解码逻辑”转移到了”自报接口”,而后者恰恰是最不可信的一方。与之相比,签名类场景后来用 EIP-712 的结构化类型解决(见 钱包弹出的结构化签名窗口:域名信息四行到底在防什么):类型定义进哈希摘要,改一个字段签名即废,显示与数据被密码学绑在一起。交易执行路径上则没有这种把戏可用,所以现实选择了另一条工程路线。
今天你看到的可读参数从哪来
主流钱包对已知代币和热门合约内置了 ABI 与解码器;遇到陌生合约时,钱包尝试从 Etherscan 这类站点获取已验证源码对应的 ABI,或按通用规则猜解常见函数选择器;再解不出来,就退化为展示原始数据。这条路线的弱点是”合约身份”问题——同名代币、仿冒合约可以复用合法 ABI 的全部外观。所以核对顺序始终是:先看合约地址是否来自可信列表,再看函数语义是否与你刚才的操作匹配,最后才是金额与收款地址。完整解码方法见 交易的输入数据字段怎么读:四字节选择器、参数槽位与解不出来的情况。
用户层面的三种显示状态
把钱包确认页按信息来源分三层,能帮你快速估计风险:第一层是钱包自己内置解码的原生操作(转账、兑换常用合约),显示与执行之间链条最短;第二层是依赖外部 ABI 源解码的调用,显示对了不代表对面合约可信;第三层是完全解码失败、只剩十六进制的请求,此时你等于蒙眼签字。第三层出现时最稳妥的做法是中止,回去确认 dApp 是否给了操作说明,或换一笔同功能的已知合约调用路径对照。任何要求你”别担心直接确认”的客服话术,都该触发反向警觉。
从停滞提案带走的两件事
EIP-2566 停在 Stagnant,教会生态的不是”新方法不好”,而是”信息来源要先于显示形式被解决”。显示得再漂亮,数据源头不对就毫无意义。第二条适用于所有版本的所有钱包:确认页是你最后的防线,而不是第一道提醒——地址、合约、额度这些字段值得逐字核对,尤其是钱包已经替你把它显示得很友好的时候。工具替你做的可读化,本质上也是一种翻译,而翻译历来是出问题的环节。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。