引介 | 对 EIP-3074 的批评以及一种简单的替代
摘要: 我的提议是实现一个更明确的机制,在协议层面强制规定 commit 的含义。
对于开发者来说,AUTH
/AUTHCALL
机制非常具有吸引力。它可以让人们创建调用者来实现不同的批量处理策略(例如,支持多个 nonce 来实现更好的并行性)、gas 抽象模型和复杂的账户抽象方法等。
这种灵活性源于这一机制赋予了开发者极大的自由。AUTH
/AUTHCALL
机制不要求开发者遵循特定的模式,而是要求用户签署一个 commit
哈希值(commit 内容将由调用者来解析),让开发者基于 commit
自行设置限制。
然而,这种灵活性是以牺牲安全性为代价的。在本文中,我想要介绍一种更简单的替代方案。这个方案具备 AUTH
/AUTHCALL
机制的绝大多数优点,但是风险远低于后者。
为什么签署一个 AUTH commit
所带来的风险高于签署一个与存在漏洞/恶意合约相关的事务?
用户在签署与合约相关的事务时,所承担的风险是已知的,即,可能会损失在该合约控制范围内的资产。比方说,用户给一个 ERC 20 合约签署了批准事务,授权恶意的 DEX 合约。这个恶意 DEX 合约就可以提走用户在 ERC 20 合约中的全部余额。但是,它无法从该用户的其它 ERC 20 合约中提走代币,除非得到该用户的批准。它也不能代表用户进行其它操作,因为这也需要专门获得用户的批准。
相较之下,EIP 3074 不仅要求用户签署 “空白支票”,而且假设调用者是诚实且没有漏洞的。一个恶意/存在漏洞的调用者可以代表用户执行任何操作 —— 访问用户持有的资产,代表用户进行投票,控制用户所有的合约等。
更糟糕的是,调用者随时都可以作恶,因为 nonce 实现是由调用者控制的。存在漏洞/恶意的 nonce 逻辑实现可以重放用户过去的事务。如果 commit
验证的其它部分的逻辑也存在漏洞,调用者就可以利用这个 nonce 逻辑实现来代表用户执行任何操作。即使漏洞被发现,用户也无法撤回空白支票。这个外部账户(EOA)已经被永久入侵了。
编写一个正确的调用者程序很难,而且我们几乎可以肯定,调用者会不定期出现错误,从 EIP 3074 最后列出的调用者应该警惕的检查/漏洞/情况非详尽清单中可见一斑。这份清单势必会变得越来越长,很可能伴随着痛苦的发现过程。
此外,恶意参与者可以编写一个看似无害的调用者程序,但是故意留下一个细微的漏洞,等到大量外部账户授权该调用者之后才会被攻击者利用。
如果攻击者没有直接或立即利用这个漏洞从用户那里窃取资金,这个漏洞可能很长时间都不会被发现。
治理劫持示例
-
恶意去中心化交易所 EveSwap 为其用户编写了一个调用者程序。这个调用者程序通过空投 EVE 代币来为用户提供 gas 资助,并批量处理用户的批准和转账事务。 -
EveSwap 的调用者程序看似无害,而且永远不会窃取用户的代币,因为这样马上就会露馅。 -
用户很开心。交易都成功了,交易费也很便宜。几个月来平安无事。 -
然而,每当有人使用 EveSwap 交易 AliceSwap 的治理代币 ALI 时,会自动将用户的 AliceSwap 投票权委托给 EveSwap。 -
一旦授权人数达到某个阈值,EveSwap 就会通过治理提案劫持 AliceSwap。
跨链重放示例
commit
应该包含 chainid
。但是,这是由调用者,而非协议执行的。在另一条链上有着相同地址的调用者可能会跳过该检查(或与此相关的检查)。-
EveSwap 在兼容 EVM 的 BobSpongeChain 上运行,后者支持 EIP 3074。EveSwap 在 BobSpongeChain 上部署了一个诚实的调用者。 -
用户使用该调用者在 BobSpongeChain 上交易,然后使用桥将资产转移到以太坊上。 -
EveSwap 使用同一个部署密钥在以太坊上部署了另一个地址相同的调用者。这个在以太坊上的调用者不会检查 commit
,只会检查ownerOnly
,并充当其所有者的通用 AUTH/AUTHCALL 代理。 -
这样一来,EveSwap 就可以劫持用户在以太坊上的外部账户并卷走他们的资产了。
commit
检查都交给调用者完成,我们失去了以太坊提供的一切交易保护。攻击是在所难免的,因为保护措施很随意。如果要接受EIP 3074,AUTH 消息必须明确包含 chainid
,而非将其作为 commit
的一部分。我们还能采取什么别的手段?
commit
的含义。commit 结构将是类型化的(如 EIP 712 所述),钱包会以用户可读的形式将 commit 呈现出来。用户可以确切地知道事务是什么样子的,并确信这个事务不会在任何链上重放,无需依赖于调用者程序开发者的品行和能力。AUTH
将使用包含授权调用列表的类型化结构代替 commit
哈希值。每个调用都将指定 {nonce,to,gas,calldata,value,chainid}。签名将被验证,整个授权调用列表将保存为 authorized_transactions
而非 authorized
地址变量。AUTHCALL
将得到一个新的参数 index
,该参数指向最后一个 AUTH
创建的列表中的地址。AUTHCALL
递增。nonce 并非由调用者存储,而是实际的账户 nonce。-
用户可以清楚地了解情况。 -
安全性由协议保障。 -
依然支持批处理和账户抽象。
-
nonce 实现,不支持并行。 -
复杂调用者程序的事务处理起来很繁琐,因为用户必须查看并接受整个调用列表。
替代方案:完全避免硬分叉
-
无需硬分叉,可由智能合约和可以感知这些智能合约的节点支持。 -
可用于一切支持 EIP 3074 的实现,而不会引入额外的风险。
-
不向后兼容已有的外部账户。用户需要部署一个合约钱包并将资产转移到该钱包内。
(完)
原文链接:
https://blog.mycrypto.com/eip-3074/
作者: Maarten Zuidhoorn
翻译&校对: 闵敏 & 阿剑
作者:以太坊爱好者;来自链得得内容开放平台“得得号”,本文仅代表作者观点,不代表链得得官方立场凡“得得号”文章,原创性和内容的真实性由投稿人保证,如果稿件因抄袭、作假等行为导致的法律后果,由投稿人本人负责得得号平台发布文章,如有侵权、违规及其他不当言论内容,请广大读者监督,一经证实,平台会立即下线。如遇文章内容问题,请联系微信:chaindd123。
评论(0)
Oh! no
您是否确认要删除该条评论吗?