深入探讨ERC-4337的主要组成部分:使用Alt Mempool的账户抽象——第二部分

本文深入探讨了ERC-4337中的EntryPoint合约,这是Account Abstraction的重要组成部分。文中详细介绍了EntryPoint的作用、功能实现以及如何处理用户操作,强调了其在整个系统中的关键作用,同时提及了版本更新和安全考虑。

深入探讨 ERC-4337 的主要组件:使用 Alt Mempool 的账户抽象 — 第二部分

欢迎回到我们对 ERC-4337:使用 Alt Mempool 的账户抽象 的探讨。在我们的上一篇文章中,我们分析了 Bundler,强调了它接收和执行 UserOperations 作为打包交易的角色,介绍了 “Alt Mempool” 的概念。

本部分将重点介绍 ERC-4337 的另一个重要组成部分:EntryPoint。对于新手,我们建议先阅读第一部分以获得全面的理解。

来源:ERC-4337: 使用 Alt Mempool 进行账户抽象

EntryPoint

EntryPoint 合约是 ERC-4337 的主要组件之一,作为 Bundler、钱包和支付者的可信单实例,负责验证和处理 UserOperations。

EntryPoint 的主要责任之一是确保一旦验证成功,操作将被执行,钱包或支付者将被收费,并且无论操作结果如何,Bundler 都将获得补偿。

该结构还包括一个 声誉系统,使支付者对后续回退失败负责,并可能受到限流或禁用。

处理用户操作

EntryPoint 实现了许多在 ERC 草案 中定义的功能。两个主要的函数,handleOpshandleAggregatedOps,负责执行用户操作的批处理。当不需要签名聚合时使用第一个函数,当操作需要签名聚合器时使用第二个函数。

handleOps

该函数处理一批用户操作,并用收取的Gas费补偿 beneficiary 账户。

account-abstraction/contracts/core/EntryPoint.sol – Medium


   contract EntryPoint { 
   // ... 
   function handleOps( 
   UserOperation[] calldataops, 
   address payable beneficiary 
   ) public nonReentrant { 
   uint256 opslen = ops.length; 
   UserOpInfo[] memory opInfos =newUserOpInfo[](opslen); 

   unchecked { 
   for (uint256 i =0; i < opslen; i++) { 
   UserOpInfo memory opInfo = opInfos[i]; 
   ( 
   uint256validationData, 
   uint256pmValidationData 
   ) =_validatePrepayment(i, ops[i], opInfo); 
   _validateAccountAndPaymasterValidationData( 
   i, 
   validationData, 
   pmValidationData, 
   address(0) 
   ); 
   } 

   uint256 collected =0; 
   emitBeforeExecution(); 

   for (uint256 i =0; i < opslen; i++) { 
   collected +=_executeUserOp(i, ops[i], opInfos[i]); 
   } 

   _compensate(beneficiary, collected); 
   } 
   } 
   // ... 
   } 

查看原文 EntryPoint.solGitHub 提供支持

EntryPoint.handleOps

在第一个循环内部,它调用 _validatePrepayment,该函数验证账户和支付者(如果定义)并确保总验证不超过 UserOperation 的 verificationGasLimit。该函数内部调用 _validateAccountPrepayment,负责通过 _createSenderIfNeeded 创建钱包合约。有趣的是,这允许 ERC-4337 钱包在部署之前就能在预定的反事实地址接收资产。

调动了第二个验证函数 _validateAccountAndPaymasterValidationData,若账户或支付者的 validationData 过期则回退。

在第二个循环中,针对每个操作调用 _executeUserOp,该函数调用 this.innerHandleOps,在钱包合约上执行 UserOperation calldata

account-abstraction/contracts/core/EntryPoint.sol – Medium

   contractEntryPoint { 
   // ... 
   function innerHandleOp( 
   bytes memory callData, 
   UserOpInfo memoryopInfo, 
   bytescalldatacontext 
   ) external returns (uint256actualGasCost) { 
   uint256 preGas =gasleft(); 
   require(msg.sender==address(this), "AA92 internal call only"); 
   // ... 
   // 检查是否 handleOps 调用时 gas 限制过低。中止整个包 
   // ... 
   // 在钱包智能合约账户上执行 UserOperation 并若操作回退则触发事件 
   bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit); 
   // ... 
   // 执行后操作 
   return _handlePostOp(0, mode, opInfo, context, actualGas); 
   // ... 
   } 
   } 

查看原文 EntryPoint.solGitHub 提供支持

EntryPoint.innerHandleOp

后操作在 calldata 执行后立即被调用。如果定义了支付者且其验证返回非空上下文,则会调用其 postOp。随后多余的金额会退还给账户(或支付者——如果它在请求中被使用)。

handleAggregatedOps

handleAggregatedOps 函数用于处理一批聚合的 UserOperations,并用收取的Gas费补偿 beneficiary

account-abstraction/contracts/core/EntryPoint.sol – Medium

   contract EntryPoint { 
   // ... 
   function handleAggregatedOps( 
   UserOpsPerAggregator\[\] calldataopsPerAggregator, 
   address payablebeneficiary 
   ) public nonReentrant { 

   uint256 opasLen = opsPerAggregator.length; 
   uint256 totalOps =0; 
   for (uint256 i =0; i < opasLen; i++) { 
   UserOpsPerAggregator calldata opa = opsPerAggregator\[i\]; 
   UserOperation\[\] calldata ops = opa.userOps; 
   IAggregator aggregator = opa.aggregator; 

   // address(1) 是 “签名错误”的特别标记 
   require( 
   address(aggregator) !=address(1), 
   "AA96 无效的聚合器" 
   ); 

   if (address(aggregator) !=address(0)) { 
   // solhint-disable-next-line no-empty-blocks 
   try aggregator.validateSignatures(ops, opa.signature) {} catch { 
   revertSignatureValidationFailed(address(aggregator)); 
   } 
   } 

   totalOps += ops.length; 
   } 

   // ... 
   for (uint256 a =0; a < opasLen; a++) { 
   // ... _validatePrepayment 
   // ... _validateAccountAndPaymasterValidationData 
   } 

   // ... 
   for (uint256 a =0; a < opasLen; a++) { 
   // ... _executeUserOp 
   } 
   // ... 
   _compensate(beneficiary, collected); 
   } 
   // ... 
   } 

查看原文 EntryPoint.sol

EntryPoint.handleAggregatedOps

该函数与 handleOps 非常相似,主要区别在于它尝试使用聚合器的 validateSignatures 函数验证签名,然后再继续进行 _validatePrepayment_validateAccountAndPaymasterValidationData_executeUserOp

管理存款和保证金

为了确保在 handleOpshandleAggregatedOpsbeneficiary 可以获得补偿,EntryPoint 需要管理实体的存款和保证金。为此,它从 StakeManager 合约扩展。

存款仅是用于支付用户操作的余额(由支付者或账户支付),而保证金则是支付者锁定的至少 unstakeDelay 值,这对于 声誉系统 是必要的。

这开始时可能会让人感到困惑,因为 ERC-4337 的一个主要构思是将账户需要以以太支付交易的要求抽象出来。实际上,所有的 UserOperations 必须在 EntryPoint 上有一个 ETH 存款才能被执行。特别之处在于,这可以通过代表反事实钱包的 depositTo 进行,或者由支付者进行。人们可以想象一个改进的用户体验,即用户通过法定货币支付存款,以便于他们的智能合约钱包得以部署。

验证非ces

ERC-4337 初始发布的 v0.4 将非ces 计算和检查的责任留给了钱包,因为这将为智能合约账户提供最大的灵活性,使其能够包含不同的非ces 方案。虽然鼓励使用非ces 进行重放检查,但这并未在任何地方强制执行。账户可以忽略非ces 字段,发送多个 UserOperations 使用相同的值,并使用不同的机制防止自己受到重放攻击,这将使 userOpHash 变为非唯一值。

这可能会对区块浏览器产生副作用,因为它们将不再有唯一标识符来查找和标记具体操作。也可能会让等待交易响应的应用感到困惑,这可能对应用和钱包的操作方式产生不利影响,正如在 这个 GitHub 问题 中讨论的那样。

因此,新的版本 v0.6EntryPoint 继承了 NonceManager处理账户的非ces,同时仍然保持足够的灵活性以启用不同的重放保护机制。

这也突显了 ERC-4337 的一个重要方面:EntryPoint 被期望随着时间的推移进行更新。Bundler 已经具备这一期望,因为它支持 eth_supportedEntryPoints RPC 方法,该方法列出支持的 EntryPoint 版本。

安全注意事项

作为所有 ERC-4337 的中心信任点,EntryPoint 合约需要进行非常严格的审计和形式化验证。尽管如此,预计这种架构会减少整个生态系统的审计和形式化验证负担。

单个 账户 需要做的工作量大大减少,因为它们只需验证 validateUserOp 函数及其“检查签名、递增非ces 和支付费用”的逻辑,并检查其他函数是否为 msg.sender == ENTRY_POINT 限制。

最后,EntryPoint 还必须确保 只有在 validateUserOp 通过的情况下才调用一个账户,而且如果它调用了 validateUserOp 并且通过了,它还必须进行的通用调用 calldata 等于 op.calldata。这样做是为了 确保安全性,防范任意劫持和费用耗尽的风险。

最后的想法

在我们对 ERC-4337:使用 Alt Mempool 的账户抽象 的第二部分中,我们深入探讨了 EntryPoint 合约的复杂性——整个系统的基石。作为处理 UserOperations 的中心点,EntryPoint 保证了打包交易的有效执行。此外,从版本 v0.4 到 v0.6 的演变中,EntryPoint 现在强调了更严格的验证系统,同时仍然为自定义账户实现保留了灵活性。

请继续关注我们系列的 第三部分,我们将深入探讨 ERC-4337 的其他组件 及其工作流程。如果你对账户抽象的安全使用有任何问题,请随时与我们联系

  • 原文链接: medium.com/oak-security/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Oak Security
Oak Security
Securing the decentralized, trustless future. https://www.oaksecurity.io/