本文作者针对 EIP-3074 提案提出了更安全的替代方案。EIP-3074 允许用户签名一个 commit hash,赋予 invoker 代表用户执行任何操作的权限,存在极高的安全风险。作者建议在协议层面强制执行 commit 的含义,使用户可以完全了解交易内容,并防止重放攻击。此外,还提出了通过替代 mempool 来实现账户抽象和批量处理问题,或完全避免硬分叉。
从开发者的角度来看,AUTH
/ AUTHCALL
机制非常吸引人。它使任何人都有能力提出一个可以实现不同批处理策略(例如,支持多个 nonce 以获得更好的并行性)、gas 抽象模型、复杂的账户抽象方法等的调用者。
这种灵活性来自于完全不带偏见地使用该机制。我们不是要求开发人员符合特定的模式,而是要求用户签署一个由调用者解析的 commit
哈希,并允许每个开发人员根据 commit 设置酌情限制。
然而,这种灵活性带来了极高的安全成本。我想提出一个更简单的替代方案的案例,该方案能够以更低的风险获得大部分好处。
为什么签署一个 AUTH commit
比签署一个到任何其他有漏洞/恶意合约的交易风险更高?
当签署一个到合约的交易时,用户承担着损失由该合约控制的资产的已知风险。用户可以签署一个到 ERC20 合约的批准交易,批准一个恶意的 DEX 合约。然后,这个恶意的 DEX 合约可以提取用户在该 ERC20 中的全部余额。但是……它不能在没有特定批准的情况下从其他 ERC20 合约中提取用户的代币。它也不能代表用户做其他任何事情。这个批准是特定的。
另一方面,EIP 3074 要求用户签署一张空白支票,并假设调用者是诚实的且没有漏洞的。一个恶意/有漏洞的调用者可以代表用户做任何事情 - 访问用户拥有的任何资产,代表用户投票,获取用户拥有的任何合约的所有权等。
更糟糕的是,调用者现在和将来都可以这样做,因为 nonce 的实现是由调用者控制的。一个有漏洞/恶意的 nonce 逻辑实现可能允许重放用户过去的交易。结合 commit
验证其他部分的有漏洞逻辑,它可以被用来代表用户执行任何未来的操作。即使发现了漏洞,用户也无法撤销那张空白支票。EOA 永远被攻破了。
编写一个正确的调用者是很棘手的,而且我们几乎可以确定偶尔会出错。EIP 末尾的调用者应该警惕的非详尽的检查/陷阱/条件列表让我们对此有所了解。这个列表不可避免地会增长,可能通过一个痛苦的发现过程。
此外,一个恶意的行为者可以实现一个看起来诚实的调用者,但带有一个故意的、微妙的漏洞,这个漏洞将在很多 EOA 对该调用者进行 AUTH 之后被利用。
如果攻击不是直接或立即从用户那里窃取,那么它可能会长时间未被注意到。
治理劫持示例
EveSwap 的用户不太可能注意到这个过程,因为他们的交易总是成功的,但最终结果对 AliceSwap 来说是毁灭性的。
跨链重放示例
EIP 正确地建议 commit
应该包含 chainid
。然而,这并不是由协议强制执行的,而是由调用者强制执行的。另一个链上具有相同地址的调用者可能会跳过此检查(或任何检查)。
commit
。它只检查 ownerOnly
,并作为其所有者的通用 AUTH/AUTHCALL 代理。用户从未在以太坊上进行交易,并且在 BobSpongeChain 上运行的调用者经过了严格的安全审计,并被发现是安全的。然而,每个人都损失了他们的资产。
以太坊通过 EIP-155 中的重放保护来防止这种情况。AUTHCALL 不会。通过将所有 commit
检查委托给调用者,我们失去了以太坊提供的任何交易保护。攻击之所以成为可能,是因为保护变成了可自由决定的。如果这个 EIP 被接受,AUTH 消息必须显式地包含 chainid
,而不是作为 commit
的一部分。
我们能做什么来代替?
我的建议是实现一个更带有主观性的机制,该机制在协议级别强制执行 commit
的含义。commit 结构将被类型化(如 EIP 712 中那样),因此钱包将以用户可读的格式呈现它。用户将确切地知道交易会是什么样子,并确信它以后不会在任何链上被重放,而无需依赖于实现调用者的个别开发人员的诚实和能力。
一个可能的实现:
AUTH
将用包含授权调用列表的类型化结构替换 commit
哈希。对于每个调用,将指定 {nonce,to,gas,calldata,value,chainid}。签名将被验证,整个列表将被保存为 authorized_transactions
,而不是 authorized
地址变量。
AUTHCALL
将获得一个新的参数 index
,该参数指向由上次 AUTH
创建的列表中的一个地址。
EOA 的 nonce 将在每次 AUTHCALL
时递增。不是由调用者存储的 nonce,而是实际的账户 nonce。
优点:
缺点:
不同的实现可以支持不同的 nonce 方案。但是,无论我们使用什么机制,都必须由协议而不是调用者来强制执行。
执行大量用户调用的复杂调用者应该被阻止。复杂的操作应该作为普通的智能合约来实现,而不是尝试使用多个 EOA 调用来实现一种算法。
替代方案:完全避免硬分叉
另一种选择是完全避免 AUTH 机制,并通过 @vbuterin 建议的替代 mempool 来解决账户抽象和批处理问题。
优点:
缺点:
除非要求是在没有迁移的情况下支持现有的 EOA,否则这似乎是更安全的选择。
- 原文链接: ethereum-magicians.org/t...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!