抽象账户是什么

抽象账户(也有叫合约钱包)是 EIP-4337 提案提出的一个标准。简单来说就是通过智能合约来实现一个“账户(account)”,在合约中自行实现签名验证的逻辑。这样,就使得该合约拥有了“签发交易”的能力。通过抽象账户签发的“交易”我们叫做用户操作(UserOperation,简称Op)。用户对Op进行签名以后,将其发给一个叫Bundler的链下程序,它负责将所有抽象账户所提交的Op打包,然后提交到链上合约EntryPoint中。EntryPoint合约收到Op后,会调用对应的抽象账户来验证其签名,验证通过后会将Op中的calldata取出,对抽象账户进行调用。整个简化版的流程就是这样,省略了诸如paymaster和aggregator之类的角色,想要更全面的了解的话可以阅读以下的文章。

参考文章:

当你阅读完上面的文章后,此时你应该对抽象账户有了一个大概的了解了,这时我们再来简单整理一下整个业务流程吧。

流程如下:

  1. 用户将 Op 进行签名,并发送给 Bundler;
  2. Bundler 调用 Entry Point 中的 handleOps 函数;
  3. EntryPoint 将 UserOperation 作为参数调用 Wallet Contract 中的 validateUserOp,验证所有需要验证的交易。只有在验证成功的情况下才会继续执行后续操作;
  4. 此时 Entry Point 会先确认 UserOperation 中指定的 Paymaster 的状况,例如是否拥有足够的 ETH 来支付这笔交易的手续费;
  5. 接着,Entry Point 调用 Paymaster Contract 中的 validatePaymasterUserOp,确认 Paymaster 愿意支付这笔交易的手续费。如果 Paymaster 愿意支付,那么这笔交易就会继续,否则就会失败;
  6. 然后调用 Wallet Contract 并执行 UserOperation 本身指定的内容;
  7. 接着调用 Paymaster Contract 的 Post-Op,Post-Op 处理直接赞助或划扣用户 ERC20 代币代付等自定义逻辑;
  8. Entry Point 在 Paymaster 质押的 ETH 余额中扣减交易所需支付的 gas fee;
  9. 最后 Entry Point 收集所有交易所需支付的 gas fee 总额 refund 给 Bundler ,交易执行完毕。

同时引用两张Stackup的流程图,帮助大家更直观的了解整个过程:

整个抽象账户项目的架构,各个角色之间的关系:

当用户发起一笔Op的时候,整个业务流程是如何运作的:

在审计过程中需要注意的安全问题

针对抽象账户这个项目的特点,在审计过程中有一些关键点需要特别留意一下。当然,具体的情况根据每个项目的不同而不同,这里只是抛砖引玉,审计工作还是要落实到具体的代码上。

签名问题

抽象账户发送一笔Op,需要进行两次签名检查。

  1. 第一个是在抽象账户中对Op进行签名检查,确保该Op是对应的抽象账户签发的。这个检查是必须要的。
  2. 第二个是用户使用paymaster的时候,需要提供paymaster所签名的信息进行校验。这个检查只有在使用paymaster服务的时候需要进行,不是必须的。

当进行以上这两种的签名与检查时,我们需要注意以下的问题:

  1. 签名是否能够避免重放攻击:具体包括抽象账户的重放攻击,跨链的重放攻击,针对仿盘的重放攻击,硬分叉的重放攻击。在进行审计时要留意签名内容是否包含抽象账户的 nonce 值, chianID,项目合约地址等信息。
  2. 签名的打包方式:在对签名内容进行打包时是否严谨,是否会出现不同的Op进行打包后得到相同字节码的情况。
  3. 抽象账户的签名验证实现:由于Op的签名是需要抽象账户自行实现的,需要针对其具体的实现方法进行分析,确保验证签名的过程严谨准确。

gas计算问题

Gas计算问题始终贯穿整个项目,Op 中采用了多个变量来规定gas上限,gas priority,gas 价格等。具体可以参考以下样例:

UserOperation 结构体,用于表示用户在智能合约中的操作请求:
- sender:发送此请求的账户地址。
- nonce:请求的唯一标识符,用于防止重复请求攻击。
- initCode:如果设置了此字段,则表示要创建一个新的账户合约,并将其初始化为指定的字节码。
- callData:要在此操作期间执行的方法调用数据。
- callGasLimit:用于限制此调用允许使用的最大 gas 数量。
- verificationGasLimit:用于验证此用户操作是否有效的所需 gas 量。
- preVerificationGas:在 handleOps 方法中计算 gas 费用之前,添加到付款总额中的附加 gas 数量。这是为了覆盖批处理的开销。
- maxFeePerGas 和 maxPriorityFeePerGas:与 EIP-1559 中的 gas 相关参数相同,用于计算最终的 gas 费用。
- paymasterAndData:如果设置了此字段,则表示支付方地址和特定于支付方的数据。支付方将为交易支付费用,而不是发送请求的账户。
- signature:发件人验证的签名,涵盖整个请求、EntryPoint 地址和链 ID。

审计过程中要确认每个gas的相关设置是否经过检查,取值是否安全。为了确保gas消耗在limit范围内,所以会在交易执行过程中计算实际gas消耗。在审计过程中需要确认gas消耗的计算是否严谨,是否与对应的limit值进行对比检查。其次是Op中的参数设置过大或过小时是否会造成资损或运行错误等问题。

代币计价问题

代币计价问题通常发生在EntryPoint提供了使用ERC20代币来支付gas费用,或paymaster合约提供了使用ERC20代币来代付gas费用的情况下。首先计算得出执行Op所需要总的gas消耗,然后通过预言机/Defi/签名中的价格来计算等价的ERC20代币,最后从抽象账户获取所需要的ERC20完成gas的代付。

在审计的过程中要注意的问题有:

  1. 用来代付的token是否在白名单的范围内,是否为正规的代币,是否存在使用恶意代币进行支付的隐患。
  2. 从预言机渠道获取代币价格时,需要注意价格的 decimal 和 token 对应的 decimal 在计算过程中是否使用正确。预言机地址是否限制在白名单中。预言机获取的价格是否具有时效性,避免获取到过时的价格。
  3. 从Defi中获取代币价格或兑换代币时,是否对滑点进行了限制,是否存在闪电贷影响代币兑换价格的风险。在swap操作中,tokenIn和tokenOut的计算与使用是否恰当。
  4. 在签名中获取价格时,要注意签名价格是否具有时效性,在价格剧烈波动的场景下这种策略是否会造成用户或者项目方的资产损失。签名的价格是否与代币一一对应。是否存在中心化风险。

钱包逻辑问题

合约钱包/抽象账户至少需要实现下面两个函数,在对钱包部分进行审计时,要重点关注以上两个函数的实现情况,以及验签是否有问题,有没有做好权限管理,在调用的过程中是否存在重入风险等。

  1. 校验 User Operation 签名的函数,以供 EntryPoint 在 validation loop 中调用。其中的签名方法由合约钱包自行实现。
  2. 发起交易的函数,以供EntryPoint 在 execution loop 中调用。

还有一个重点就是对钱包的代理模式进行检查,了解清楚其代理模式。

  1. 明确implement合约(逻辑合约)的替换方式。
  2. EntryPoint是否对钱包合约的implement有限定的要求,是否要求implement合约要在白名单的地址中选取,在与钱包进行交互时是否对implement进行检查,implement是否会在Op执行的过程中进行替换。
  3. 在钱包Proxy合约中的变量,是否能够通过修改implement的方式进行修改。如果能够被修改,是否会对业务流程造成影响,是否会存在安全隐患。

后记

以上就是在抽象账户审计过程中总结归纳的一些经验,不能说是一个全面的审计Check List,但是希望能够给初次接触此类项目的同学一下入手的角度。由于抽象账户这个概念涉及的内容很多,局限于个人的学识,这篇文章还存在很多没能覆盖到的方面,也希望各位师傅能够提出您的看法与建议,大家一起交流学习。

【项目学习】ERC-4337 抽象账户项目审计过程中需要注意的安全问题的更多相关文章

  1. Halo 开源项目学习(一):项目启动

    项目简介 Halo 是一个优秀的开源博客发布应用,在 GitHub 上广受好评,正好最近在练习写博客,借此记录一下学习 Halo 的过程. 项目下载 从 GitHub 上拉取项目源码,Halo 从 1 ...

  2. 值得学习的C语言开源项目

    值得学习的C语言开源项目   - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工 ...

  3. 【C/C++开发】值得学习的C语言开源项目

    值得学习的C语言开源项目 - 1. Webbench Webbench是一个在Linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的 ...

  4. 值得学习的C/C++开源项目 持续更新

    值得学习的C语言开源项目 持续更新 文章目录 值得学习的C语言开源项目 持续更新 - 1. Webbench - 2. Tinyhttpd - 3. cJSON - 4. CMockery - 5. ...

  5. Python学习路径及练手项目合集

    Python学习路径及练手项目合集 https://zhuanlan.zhihu.com/p/23561159

  6. ReactNative新手学习之路01-创建项目开始

    新手学习之路01-创建项目开始 小菜鸟准备学习RN开发,决定写下自己的学习历程,方便其他也想要学习RN的人,后期会持续更新写下自己所有学习经历,一步步从菜鸟成长成业内高手.开发环境准备,本文默认环境已 ...

  7. 转:从开源项目学习 C 语言基本的编码规则

    从开源项目学习 C 语言基本的编码规则 每个项目都有自己的风格指南:一组有关怎样为那个项目编码约定.一些经理选择基本的编码规则,另一些经理则更偏好非常高级的规则,对许多项目而言则没有特定的编码规则,项 ...

  8. Python之路【第二十四篇】:Python学习路径及练手项目合集

      Python学习路径及练手项目合集 Wayne Shi· 2 个月前 参照:https://zhuanlan.zhihu.com/p/23561159 更多文章欢迎关注专栏:学习编程. 本系列Py ...

  9. SpringMVC项目学习1_web.xml

    最近接触的所有项目都是SpringMVC+ajax的项目,因此以一个项目为例学习下. --------------------------------------------------------- ...

  10. 跟着刚哥学习Spring框架--创建HelloWorld项目(一)

    1.Spring框架简介 Spring是一个开源框架,Spring是在2003年兴起的一个轻量级的开源框架,由Rod johnson创建.主要对JavaBean的生命周期进行管理的轻量级框架,Spri ...

随机推荐

  1. MySQL(五)配置文件、系统变量与MySQL架构

    1 配置文件的使用 my.cnf配置文件 /etc/my.cnf: [root@hadoop103 ~]# cat /etc/my.cnf # For advice on how to change ...

  2. 【Java SE】IO流

    1.File类 ①File类的一个对象代表一个文件或一个文件目录 ②File类声明在java.io下 1.1 FIle类的声明 路径分隔符 Windows和DOS系统默认使用'',UNIX和URL使用 ...

  3. 对象数组排序 和 类比JDK实现 sort()的方法

    1.定义自己的 MyComparable 接口 1 package Test.treeSetDemo; 2 3 public interface MyComparable <E>{ 4 i ...

  4. OpenCv单模版多目标匹配

    OpenCv单模版多目标匹配 单模版匹配出现的问题 一. 关于单模版匹配,我一开始用的是光线较暗的图,结果根据模版匹配到的位置并不正确. 我后来想用阈值把图形的特征提取出来,在把模版的特征和原图的特征 ...

  5. 《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(16)-Charles其他骚操作之大结局

    1.简介 今天就说一些Charles的其他操作.以及抓包跨域的问题和常见的问题如何解决.到此Charles这一系列的文章也要和大家说再见了,其他什么小程序.Android7.0等等的问题可以查看宏哥的 ...

  6. UIOTOS:一款无门槛的前端0代码搭建工具

    什么是UIOTOS? UIOTOS中文名称前端大师,是一款基于图形技术的前端0代码工具,支持通过连线和嵌套无门槛来搭建各类复杂的的交互界面,包括后台管理系统.组态数据大屏等,实现跟代码开发媲美的效果. ...

  7. Python工具箱系列(三十)

    PostgreSQL MySQL的口号是"世界上最流行的开源关系型数据库",而PostgreSQL的Slogan则是"世界上最先进的开源关系型数据库(PostgreSQL ...

  8. 2023-04-08:社交网络中的最优邀请策略探究。本文以小红准备开宴会为例,提出一种基于贪心算法和二分查找的解决方案,帮助读者在保证愉悦值不低于k的前提下,最小化宴会的阶层差距。

    2023-04-08:小红有n个朋友, 她准备开个宴会,邀请一些朋友, i号朋友的愉悦值为a[i],财富值为b[i], 如果两个朋友同时参加宴会,这两个朋友之间的隔阂是其财富值差值的绝对值, 宴会的隔 ...

  9. 2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现。

    2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现. 答案2023-03-10: 方法一.使用 github.com/moonfdd/ffmpeg-go 库,基于雷霄骅的 ...

  10. pgadmin数据输出不存在了?

    菜单栏→文件→重置布局.这样数据输出就显示了.