账户抽象
账户抽象(Account Abstraction)
账户抽象是以太坊改善用户体验的核心方向,目标是让智能合约钱包成为一等公民,消除 EOA(外部账户)与合约账户的根本区别。
背景:EOA 的局限性
传统以太坊账户(EOA)的限制:
- 每笔交易必须由私钥签名,丢失私钥即永久失去资产
- 只能用 ETH 支付 Gas,无法让他人代付
- 无法批量发送多笔交易(需要逐一签名)
- 无法设置消费限额、时间锁等自定义逻辑
ERC-4337:无需协议变更的账户抽象
ERC-4337 于 2023 年 3 月上线,通过引入平行的 UserOperation 交易池,无需修改以太坊协议即可实现账户抽象。
核心组件
| 组件 | 作用 |
|---|---|
| UserOperation | 类似交易的结构体,包含调用数据、Gas 限制、签名等 |
| Bundler | 收集 UserOperation,打包成普通交易提交上链 |
| EntryPoint 合约 | 统一入口,验证并执行 UserOperation |
| 智能合约钱包 | 用户的账户合约,实现自定义验证逻辑 |
| Paymaster | 可选,代替用户支付 Gas(支持 ERC-20 付 Gas) |
UserOperation 结构
struct UserOperation { address sender; // 智能合约钱包地址 uint256 nonce; bytes initCode; // 首次部署钱包时使用 bytes callData; // 实际调用数据 uint256 callGasLimit; uint256 verificationGasLimit; uint256 preVerificationGas; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; bytes paymasterAndData; // Paymaster 地址 + 数据 bytes signature;}实现的能力
- 社交恢复:通过受信任联系人恢复账户,无需助记词
- 批量交易:一次操作执行多个调用(如 approve + swap)
- Gas 赞助:Paymaster 代付 Gas,用户无需持有 ETH
- ERC-20 付 Gas:用 USDC 等代币支付 Gas 费
- 会话密钥:授权特定操作在有限时间/金额内自动执行
- 多签:多个密钥共同授权
EIP-7702:Pectra 升级引入(2025 年 5 月)
EIP-7702 是协议层的账户抽象步骤,允许 EOA 在单笔交易内临时设置合约代码。
EOA 发送一笔特殊交易 → 临时将自身代码设为指定合约 → 执行合约逻辑(批量调用、Gas 赞助等)→ 交易结束后代码可保留或清除与 ERC-4337 的关系
| ERC-4337 | EIP-7702 | |
|---|---|---|
| 需要迁移地址 | 是(新合约地址) | 否(原 EOA 地址不变) |
| 协议层变更 | 否 | 是 |
| 适用场景 | 新用户 | 已有 EOA 用户升级 |
| 自定义验证 | 完整支持 | 部分支持 |
当前数据(2025)
- 智能合约钱包部署数:2600 万+
- 累计 UserOperation:1.7 亿+
- 主要实现:Safe、Biconomy、ZeroDev、Alchemy Account Kit
对开发者的影响
集成 ERC-4337
import { createSmartAccountClient } from 'permissionless'import { signerToSimpleSmartAccount } from 'permissionless/accounts'
const smartAccount = await signerToSimpleSmartAccount(publicClient, { signer, factoryAddress: '0x...', entryPoint: ENTRYPOINT_ADDRESS_V07,})
const smartAccountClient = createSmartAccountClient({ account: smartAccount, entryPoint: ENTRYPOINT_ADDRESS_V07, chain: mainnet, bundlerTransport: http('https://...'), middleware: { gasPrice: async () => (await bundlerClient.getUserOperationGasPrice()).fast, sponsorUserOperation: paymasterClient.sponsorUserOperation, },})
// 发送 UserOperation(对开发者透明,与普通交易写法相同)const txHash = await smartAccountClient.sendTransaction({ to: '0x...', value: parseEther('0.1'),})