FilCloud 船员 2021-07-15 10:11:13 发布在 ETH/以太坊 3391 0
如果你是以太坊上活跃用户,那么你也可能拥有一些(ERC-20)代币,用于与以太坊生态系统中不同的 DeFi 项目交互。
但是,这样做需要你拥有 ETH,因为你不能使用代币支付交易费用。此外,在向智能合约发送代币时,你通常必须做两个交易:第一个是批准使用你的代币的合约,第二个是将代币转移到目标合约。
EIP-3074 可以解决这些问题,还可以通过引入智能合约在外部拥有的帐户(EOA,或简单地说是常规以太坊地址)环境中发送交易的方式来解决更多问题。
EIP 引入了 AUTH 和 AUTHCALL 这两个 EVM 指令。第一个指令基于 ECDSA 签名设置环境变量 authorized,第二个指令则作为 authorized 发送调用。这本质上就是向智能合约授予外部账户的控制权。
AUTH 和 AUTHCALL EVM 指令(也称为操作码)允许智能合约基于签名消息授权 EOA,并从 EOA 发送交易(“调用”)。这带来了很多可能性,如:
赞助交易(又称元交易):支付来自另一个账户的交易的 gas。这样一来,不持有 ETH 的地址也能发送代币。
批量交易:通过单个调用中发送多个交易。这保证了在同一个块中执行两个或多个交易,并且还可以降低交易费用。
提升用户体验:例如,您可以在单个交易中调用 approve 和 transfer From。
不同于现有的解决方案,EIP-3074 不需要智能合约钱包。您可以简单地将交易发送到执行交易的调用者。
调用者是无状态、免信任的智能合约,它们不要求您预先将余额发送给合约。EIP-3074也没有引入新的交易类型。通过只引入两条新的EVM指令,在技术上应该更容易实现。
不幸的是,EIP-3074 仍在审查中,由于不同的(安全方面)考虑,目前还不知道何时启用 EIP。
如果你现在想体验,你可以使用 Puxi 测试网。在本文中,我将详细解释 EIP-3074 的工作原理。
如果您想看看 EIP-3074 的实际情况,我做了一个示例(批处理)交易调用者合约,你可以在这里找到:
https://github.com/Mrtenz/transaction-invoker
请注意,这个合约没有经过审计,仅作为概念证明。请勿在生产环境中使用。
AUTH 和 AUTHCALL 操作码
EIP-3074定义了两个新的操作码,可以从智能合约中调用:
AUTH(0xf6):基于签名和 commit(提交)提出授权的外部账户。共有 4 个输入参数:commit以及签名的 yParity、r 和 s。
AUTHCALL(0xf7):在授权的 EOA 上下文中发送调用(交易)。共有 8 个输入参数:gas、addr、value、valueExt、argsOffset、argsLength、retOffset 和 retLength。与现有的 CALL 操作码相似。
确认外部账户的授权需要来自该外部账户的签名消息。调用 AUTH 的智能合约可以通过消息签名复原出签名者,然后将其设置成 authorized EVM 环境变量。
现在,无论何时智能合约调用 AUTHCALL,调用者都会被设置成 authorized 地址。
当被调用的智能合约调用 CALLER(例如,通过 Solidity 的 msg.sender)时,将由已授权的外部账户的地址而非调用者地址(智能合约)执行调用。
发送一个或多个交易的基本流程如下所示:
上图显示 EIP-3074 的基本流程,其中调用者合约发送多个交易
EOA 签署授权消息;
EOA 或其他 gas 支付方将交易数据和授权信息发送给调用方合约;
调用者合约使用 AUTH 执行授权,并使用 AUTHCALL 发送交易。
将交易发送到合约的是谁并不重要,只要 EOA 的签名有效即可。这使得其他人(或另一个帐户)可以发送交易。
请注意,目前无法使用 EIP-3074 从 EOA 发送 ETH。这样做将极大地改变当前做出的重要假设,比如检查交易是否有效。
相反,它取自调用者自己的 ETH 余额。但是,你仍然可以将 ETH 发送给调用者,并由调用者代为发送。
AUTHCALL 操作码包含的 valueExt 字段,目前需要将其硬编码为 0。将来,如果找到合适的解决方案,这将允许调用者从 EOA 发送 ETH。
授权消息和 commit
为了执行授权,EOA 必须以特定格式签署消息:
0x03 || ||
这个消息由三个部分组成:魔术字节(0x03)、填充到 32 字节的调用者地址(执行authorize的智能合约的地址)和 32 字节的 commit。
(注:|| 用作字节连接运算符。)
授权消息格式,包含一个 commit 示例
该 commit 描述了 EOA 提交的数据,并且可以根据调用的某些属性(例如地址、值和随机数的哈希值)进行计算。调用者合约可以基于提供的属性重新计算提交,并在这些字段正确的情况下执行授权。
例如,假设我们想要发送以下交易(表示为JSON):
[ { “to”: “0x6b175474e89094c44da98b954eedeac495271d0f”, “value”: 123, “nonce”: 0 }, { “to”: “0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520”, “value: 123, “nonce”: 1 }]
我们可以对这些字段进行哈希计算(例如,用确定性的方式将它们连接起来,或使用 EIP 712 之类的规范),并将得到的哈希值用作 commit。
我们可以在智能合约中提供要发送的交易和授权消息的签名,如JSON数据所示。合约函数可能如下所示,例如:
function sendTransactions(Transaction[] calldata transactions, Signature calldata signature) external;
智能合约根据交易重新计算 commit,并将此 commit(连同签名)提供给 AUTH 调用。
此举的目的是找回签名者的地址,如果计算得到的 commit 无效,根据签名找回的地址将是错误的,也就是说交易将失败。
调用者完全负责确保此 commit 是安全的。你只需签署一条消息,将 0x0 作为提交,并授予智能合约对 EOA 的完全访问权限。
前几版 EIP-3074 对 commit 的格式要求更为严格,包括重放保护等,但是后面为了提高灵活性已经将其移除。这就要求你在与调用者进行交互时必须信任对方。
局限性和安全问题
由于能够根据签名更改 CALLER,EIP 3074 极大地改变了 EVM 的运作方式。这会为新合约和现有合约引入潜在漏洞。因此,EIP 3074 已经经过正式审核。
下面将解释一些可能的安全问题。出于这些不同的原因,EIP-3074建议只与受信任的调用者交互。
例如,像MyCrypto这样的钱包接口可以实现可信的调用者白名单,从而只允许您为某些调用者签署授权消息。
弱 commit 和重放攻击
如上所述,EIP-3074 没有为 commit 定义标准化的格式。调用者可以自由地以他们想要的任何方式实现这一点。这意味着调用方完全负责提供足够的保护,以防止(例如)重放攻击。
如果 commit 不包含某种随机数,攻击者就可以轻松获取已签署的消息,再一次发送给调用者。
恶意调用者完全不需要验证 commit,就可以获得 EOA 的控制权。每次签署消息时,请你务必谨慎。
EIP 3074 通过将调用者的地址包含在授权消息内,提供了最基础的重放攻击保护。这样一来,恶意调用者就无法重放其他调用者的授权消息。
可升级调用者
EIP-3074 明确声明调用者程序不可升级。如果调用者程序是可升级的,则有人可以部署该调用程序的另一个版本,该版本不验证提交,从而给予合约对 EOA 的完全控制。
重入攻击
目前,智能合约可以使用 required(tx.Origin==msg.sender)来验证交易是否从EOA(而不是另一个合约)发送。这允许简单地防止重入攻击,因为它可以防止合约调用该函数。
EIP-3074 也允许 tx.origin 作为授权消息的签名者。调用者执行的任何 AUTHCALL 都会导致 tx.origin == msg。发送方是真实的,即使调用是由智能合约执行的,因此可能引入重入攻击。
EIP-3074 指出:“[…]本 EIP 的作者没有找到任何这种形式的重入保护的例子,尽管搜索并非详尽无遗。”
结论
EIP-3074 为以太坊带来了许多令人兴奋的新可能性。AUTH 和 AUTHCALL 允许 EOA 将帐户控制权委托给智能合约调用者,从而可以发送批量交易、赞助交易等。
然而,它对以太坊上的交易工作方式进行了一些重大更改,因此在 EIP-3074 可以在主机上激活之前,我们需要更深入地思考其安全性。
End
非常感谢您对 IPFS&Filecoin 项目的持续支持。我们很高兴继续与您一起,为人类信息建立一个强大的,去中心化和高效的基础。