前言
随着EIP4337标准的逐步落地,账户抽象(Account Abstraction, AA)钱包正成为Web3安全领域的热点。作为查找币安全团队的技术分享,本文旨在为审计人员提供一套基于EIP4337标准的账户抽象钱包安全审计检查项,并结合实际案例给出针对性的审计指南。我们假设读者已熟悉EIP4337和EIP7562标准的核心内容,因此不再赘述标准细节,而是聚焦于技术实现与安全风险。
EIP4337架构与交易执行流程
架构概览
EIP4337的核心设计在于将用户操作(UserOperation)与以太坊原生交易解耦。用户通过EOA签署UserOperation数据,并将其提交至独立的Alt Mempool(替代内存池)。该内存池独立于以太坊主网内存池,专门汇总用户提交的UserOp。Bundler(打包者)从该内存池中提取UserOp,并在本地模拟执行,模拟失败的UserOp将被丢弃。最终,所有UserOp的执行由Bundler调用EntryPoint合约完成。
交易执行流程
- 用户签署:EOA生成并签署
UserOperation,包含调用目标、数据、签名等字段。 - 提交至Alt Mempool:用户通过RPC将UserOp发送至独立的Alt Mempool。
- Bundler提取与模拟:Bundler从内存池提取UserOp,并在本地模拟执行以验证合法性。
- EntryPoint调用:Bundler调用EntryPoint合约,EntryPoint经过验证后调用用户AA钱包。
- 执行Calldata:AA钱包执行用户指定的calldata,完成交易逻辑。
- 费用支付:用户向Bundler支付手续费,或指定Paymaster进行代付。
审计人员需熟悉上述流程,特别是EntryPoint与AA钱包的交互细节,以识别潜在攻击面。
安全审计检查项
基于上述架构,查找币安全团队整理出以下核心检查项,建议审计人员在审计每个4337钱包时逐一验证:
1. 检查EVM兼容链兼容性
- 问题:多数AA钱包部署在Ethereum主网,但主网上海升级后新增
PUSH0字节码。Solidity 0.8.20及以上版本默认编译为上海升级后的字节码,可能导致在其他EVM兼容链(如Polygon、BSC)上部署失败。 - 审计建议:检查合约编译的Solidity版本,确认是否包含
PUSH0字节码。多链部署时,建议使用<0.8.20版本或指定evm_version = "paris"。 - 示例配置:
solc = "0.8.19" evm_version = "paris"
2. 检查接口实现与返回值是否符合EIP4337标准
- 钱包核心接口:
validateUserOp必须返回validationData,包含authorizer、validUntil和validAfter。function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external returns (uint256 validationData); - Paymaster核心接口:
validatePaymasterUserOp返回context和validationData;postOp处理执行后逻辑。function validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) external returns (bytes memory context, uint256 validationData); function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 actualUserOpFeePerGas) external; - 签名验证:失败时
authorizer返回SIG_VALIDATION_FAILED(1);成功时返回SIG_VALIDATION_SUCCESS(0),而非revert。其他失败情况必须revert。
3. 检查钱包调用者是否可信
- 风险:钱包或Paymaster的
validateUserOp、executeUserOp、validatePaymasterUserOp、postOp等函数应限制调用者,仅允许EntryPoint合约调用。若未限制,攻击者可伪造UserOp绕过验证。 - 审计建议:使用
require(msg.sender == entryPoint)或onlyEntryPoint修饰器。
4. 检查handleOps与innerHandleOp的交互安全
- 问题:在
innerHandleOp执行失败时,postOp可能不被触发(即使指定了Paymaster)。攻击者可利用此漏洞,使innerHandleOp和postOp均失败,耗尽Paymaster资金。 - 审计建议:Paymaster需设计容错机制,确保即使
postOp未执行,也能正确处理费用。例如,在validatePaymasterUserOp中预扣费用,或使用时间锁延迟结算。
5. 检查模块化钱包的实施安全
- 风险:EIP4337钱包可能支持用户自定义模块(如社交恢复、合约升级、保险库)。若模块管理不当,攻击者可注入恶意模块。
- 审计建议:
- 确保“增加/移除/使用”模块的操作有权限控制(如多签或时间锁)。
- 使用
DELEGATECALL执行模块时,检查钱包插槽存储的数据安全性,防止存储冲突或重入攻击。 - 对模块函数进行白名单限制,避免任意调用。
6. 检查UserOperation的Gas限制
- 问题:
UserOperation中的preVerificationGas、verificationGasLimit、callGasLimit等参数可能被操纵,导致Gas耗尽或执行失败。 - 审计建议:确保钱包在
validateUserOp中验证Gas参数合理性,防止恶意用户设置过低Gas导致交易卡死。
7. 检查签名验证逻辑
- 风险:签名验证可能被绕过,如使用
ecrecover时未检查v值范围,或支持多种签名方案(如ECDSA、BLS)时未正确区分。 - 审计建议:使用标准化签名库(如OpenZeppelin的
ECDSA),并验证签名参数(如v∈ {27, 28})。对多签名方案,需明确标识签名类型。
8. 检查非重入与重放攻击
- 问题:
UserOperation的nonce机制可防止重放,但若nonce管理不当,攻击者可重复提交相同UserOp。 - 审计建议:钱包应使用递增的
nonce,或基于用户地址和时间戳生成唯一标识。validateUserOp中需检查nonce的合法性。
9. 检查Paymaster的postOp执行逻辑
- 风险:
postOp可能被多次调用或跳过,导致费用计算错误。 - 审计建议:
postOp应使用状态变量记录执行状态,防止重入。同时,确保postOp的mode参数(如opSucceeded、opReverted)被正确处理。
10. 检查EntryPoint的deposit与withdraw函数
- 问题:用户或Paymaster通过
deposit存入资金,Bundler通过withdraw提取费用。若权限控制不当,攻击者可盗取存款。 - 审计建议:确保
withdraw仅由Bundler调用,且金额受限于实际Gas消耗。使用onlyEntryPoint或onlyBundler修饰器。
总结
上述检查项基于EIP4337标准,覆盖了账户抽象钱包的核心安全维度。由于不同钱包实现差异较大,且EIP4337生态仍处于早期阶段,审计人员需结合实际代码进行深入分析。对于正在开发的项目,查找币安全团队建议开发者在设计阶段即考虑这些检查项,以降低后期修复成本。最后,本文旨在提供技术参考,具体审计需结合工具(如Slither、Mythril)和手动审查。
本文由查找币安全团队整理发布