本文详细介绍了以太坊智能账户的四种主要模型,包括ERC-5189、ERC-4337、RIP-7560和EIP-7701,阐明了这些模型如何提高账户的自我管理能力和交易的灵活性。作者探讨了每个模型的结构、工作机制和潜在风险,为理解以太坊账户抽象提供了深入分析和对比。
在这一系列的前两篇文章中,我们探讨了以太坊的传统账户如何通过向其添加代码或使其具备自治性来扩展其能力。我们希望突出的一点是,我们所覆盖的机制是对 EOAs 和合约账户现状的改进;它们并不一定引入新的账户类型(除了 EIP-7702)。
然而,完全的账户抽象不能仅依靠对现状的简单改进实现。必须从头开始构建,依赖新的机制和模型。这得益于引入 智能账户,其能力远超 EOAs、7702 类型账户和合约账户。
遵循以太坊无限花园的特性,实现智能账户没有单一的路径。存在多种机制,每种都有其优缺点和依赖关系。
本文涵盖了使智能账户成为可能的四种主要模型,既包括作为协议外的实现(通过 ERC-5189 的推荐操作和通过 ERC-4337 的替代内存池),也包括作为本地/嵌入式实现(基于 RIP-7560 的 rollup 的原生 AA 和基于 EIP-7701 的 L1 原生 AA)。
我们提供了这些机制的概述、其规范的逐步介绍以及它们之间的比较,以促进范围广泛的读者对这个主题的更深入理解。希望大家喜欢。继续阅读…
ERC-5189 提议增加 推荐者合约 作为用户智能合约钱包和捆绑者之间的中介。这些推荐者包含灵活的验证/执行逻辑,管理从特定智能合约钱包发送的交易。通过这种方式,推荐者合约帮助捆绑者通过代理用户访问后者的内存池,来确定有效的支付费用的交易。
在 ERC-5189 标准中,用户交易被封装在称为 操作 的结构中,这由以下字段构成:
用户填写这些字段的交易变量,并将对象发送到捆绑者的内存池。推荐者合约中的预定义限制决定了用户操作的有效性,通常定制为与特定智能合约钱包提供者一起工作。
通过这种方式,该标准允许推荐者合约的灵活性;例如,将验证的瓶颈放在智能合约钱包提供者上,确保这些提供者能够轻松地根据需要为其推荐者合约添加新功能或完全替换它。
以下是技术细节,首先是涉及机制的实体的概述:sender
/ entrypoint
、推荐者合约和捆绑者。
这些实体是 ERC-5189 操作的执行目标,就像“正常”以太坊交易中的 msg.sender
。
本质上,最终用户(entrypoint
)通过 callData
字段定义其所需的状态变化,其值的函数在其中执行。它还指定为该操作选择的推荐者,帮助捆绑者检查该 calldata
的逻辑是否有效。在捆绑者运行检查后,它将操作作为以太坊交易执行,其中“entrypoint
”使用 calldata
的函数被调用。
如前所述,推荐者是一个通过开放的接口部署的智能合约,允许其与智能合约钱包无信任集成,以便它们能够轻松进行用户发送操作的验证。
interface Endorser {
struct Operation {
address entrypoint;
bytes callData;
uint256 fixedGas;
uint256 gasLimit;
address endorser;
bytes endorserCallData;
uint256 endorserGasLimit;
uint256 maxFeePerGas;
uint256 priorityFeePerGas;
address feeToken;
uint256 feeScalingFactor;
uint256 feeNormalizationFactor;
bool hasUntrustedContext;
}
struct GlobalDependency {
bool baseFee;
bool blobBaseFee;
bool chainId;
bool coinBase;
bool difficulty;
bool gasLimit;
bool number;
bool timestamp;
bool txOrigin;
bool txGasPrice;
uint256 maxBlockNumber;
uint256 maxBlockTimestamp;
}
struct Constraint {
bytes32 slot;
bytes32 minValue;
bytes32 maxValue;
}
struct Dependency {
address addr;
bool balance;
bool code;
bool nonce;
bool allSlots;
bytes32[] slots;
Constraint[] constraints;
}
struct Replacement {
address oldAddr;
address newAddr;
SlotReplacement[] slots;
}
struct SlotReplacement {
bytes32 slot;
bytes32 value;
}
function simulationSettings(
Operation calldata _operation
) external view returns (
Replacement[] memory replacements
);
function isOperationReady(
Operation calldata _operation
) external returns (
bool readiness,
GlobalDependency memory globalDependency,
Dependency[] memory dependencies
);
}
推荐者旨在由钱包开发者设计,因为深入了解钱包的操作和存储空间设计是防止失败的必要条件。它们主要检查以下几点:
entrypoint
是有效的合约账户。entrypoint
为其操作附加了有效的签名。calldata
是有效的。它们在一个 推荐者注册表 中注册,该注册表提供了隐含的功能——用于识别合格推荐者的中心注册表。该注册表是资源受限的,因此仅在地址燃烧非零数量的 ETH 时才会将地址附加为合格推荐者。这还为捆绑者提供了限制访问其内存池的途径,因为他们可以选择仅对燃烧达到指定数量 ETH 的推荐者提供其执行服务。
在 ERC-5189 中,捆绑者负责处理作为 操作 对象发送给它们的账户抽象交易。它们的预期功能包括:
ERC-5189 的设计极大依赖于推荐者合约,以提供垃圾邮件过滤服务和捆绑者的费用支付保证。这种方法有效地将捆绑者从对抗行为者的负面影响中保护出来,除非推荐者本身是恶意的。
由于推荐者作为用户和捆绑者之间的代理,它们本质上是具有特权的实体,隐含能够对捆绑者造成坏处和审查用户。为了限制这一点,当推荐者将:
在上述任一情形中,违规的推荐者将被禁止在捆绑者的内存池中,因此捆绑者将不再执行其用户的操作。违规推荐者的待处理操作也将被丢弃。
以下是捆绑者和推荐者在操作的三个阶段(预验证、验证和执行)中的行为概述。
捆绑者处理此阶段,因为操作直接流向它们。这些检查通过规定捆绑者执行以下步骤来减少操作失败的概率:
endorserGasLimit
值足够低。这有助于防止推荐者在验证阶段消耗过多的 gas,从而可能对捆绑者造成损害。fixedGas
值是否足以覆盖与交易提交相关的费用,并且 gasLimit
值至少大于一正常的 [CALL
] 的费用。通过这种方式,捆绑者可以避免浪费资源处理那些由于 calldata
错误定价而在执行阶段可能失败的操作。maxFeePerGas
和 priorityPerGas
的值高于其可接受的最低值。此检查解决了捆绑者面临的无利可图区块构建的问题,确保操作支付足够的费用以纳入区块。捆绑者在预验证阶段运行这些检查,以确定操作在机制的第二阶段由推荐者帮助进行验证。
在此阶段,捆绑者调用推荐者合约以验证待执行的操作。推荐者合约在操作放入捆绑者的内存池之前验证操作。这得益于两个函数:
simulationSettings()
isOperationReady()
。这两个函数分别负责运行 预模拟 检查和 预执行 检查。捆绑者在操作上调用这些函数,推荐者“执行其职责”。
以下是对每个函数背景下推荐者所做的过程的更技术性观察,以便我们理解每一步的必要性。
simulationSettings()
:此函数返回执行前必须对链上变量进行的修改,以便在捆绑者的本地环境中模拟执行。常见的目标变量是智能合约的存储槽,例如代币合约、链上价格馈送等。simulationSettings()
函数跟踪这些合约的代币余额和非ces(以及其他事项),并返回捆绑者在模拟其链外执行前必须应用于操作的修改。
因此,该函数为执行模拟奠定了基础,确保捆绑者的本地环境与链上条件一致。
为了更好地理解该函数的必要性,有必要记住,任何账户抽象机制的主要目标之一是 简化交易批量处理。交易批量处理的许多应用之一是在原子性上部署和调用智能合约。
在 ERC-5189 的背景下,由于合约尚未在链上部署,所以没有地址。然而,模拟之所以能够成功,是因为合约已经存在。为避免这个问题,推荐者在 simulationSettings()
函数在部署 + 调用操作时调用时提供了一个(可替换的)地址值。
在另一个场景中,用户可能希望使用 ERC-20 代币支付费用,这是账户抽象机制的众多目标之一。然而,由于捆绑者不访问链上状态(出于成本问题),因此没有简单的方法来验证用户确实拥有足够的所选 ERC-20 代币。
在这种情况下,推荐者合约建议修改代币的存储槽,以便当捆绑者调用 simulationSettings()
函数时,提供一个足够的值以继续模拟。
归结起来,simulationSettings()
函数通过以下方式帮助捆绑者高效处理其接收到的操作:
isOperationReady()
:此函数用于评估操作在捆绑者内存池中的有效性。它评估待处理操作成功的概率,并同时返回一个布尔值(true/false)和一组保留该值正确的依赖项列表。
isOperationReady()
函数在捆绑者调用时的返回值为:
globalDependency
- 此数据结构提供一个可能影响任何交易有效性的普遍区块链变量列表。该结构中最值得注意的部分是“maxBlockNumber
”和“maxBlockTimeStamp
”字段,可以用来限制提交的操作的有效性至特定时间段。因此提供了一种“有效期至 x”的功能。这一阶段相对简单,因为大多数复杂工作已在先前阶段通过多项检查完成。要在其内存池中执行验证后的操作,捆绑者向 entrypoint
合约的地址提交调用。此调用导致由 entrypoint
通过 callData
字段原始指定的函数逻辑在该 entrypoint
内部执行。
重要的是,捆绑者对多个操作重复此过程,以构建一个块,然后将该块传递给提议者以附加到区块链。
为使 gas 抽象或货币多样化带来最小开销,ERC-5189 机制的设计使得捆绑者可以在执行期间为用户的操作支付网络费用。这得益于推荐者,推荐者确保操作在执行后为捆绑者指定了适当的费用金额和支付代币。
以下是关于 ERC-5189 费用支付机制的技术细节。
捆绑者预计只执行经过支付保证的操作。该机制的设计目标包括:
捆绑者在预验证阶段需要进行以下检查,以确保操作提供适当的费用:
feeToken
必须是 ETH 或其他可接受/已验证的代币合约,以防止使用假 ERC-20 代币来支付 Gas。feeScalingFactor
和 feeNormalizationFactor
必须在使用 ETH 支付费用时具有“1”的值,或在使用其他代币时具有可接受的转换率。sender
(entrypoint
)正在支付其 Gas,则操作必须被推荐。从上述讨论中,我们可以指出,ERC-5189 的费用支付机制支持三种模型:
entrypoint
通过支付 ETH 给捆绑者来结清其操作的 Gas 费用。entrypoint
通过用可能是 ERC-20、ERC-777 或其他捆绑者愿意接受的特定代币向捆绑者支付其 Gas 费用。在这个模型中,捆绑者规定代币转换为 ETH 的汇率,并在验证阶段由推荐者验证 entrypoint
是否持有足够的代币。执行后,entrypoint
再将双方商定的价值转移给捆绑者。entrypoint
的以太 Gas 费用。然而,想要补贴其用户的 DApps 也可以作为第三方。在这里,操作的赞助者通过其附加的推荐者受到捆绑者的验证,提供了捆绑者的支付保证。
虽然 ERC-5189 是一个很好的提案,具有许多好处,但在验证阶段的大灵活性路径给网络带来一些安全风险。尽管其预验证阶段涵盖了一些攻击向量,例如内存池垃圾邮件风险和 gas 过度消费,但这并不全面。
其设计带来的一些其他风险包括:
gasLimit
的上限,某个实体可以为其验证预算,这会大大降低 ERC-5189 中捆绑者所构建的区块的效率。因为捆绑者损失了来自其内存池中其他待处理操作所提供的费用。任何账户抽象机制都必须处理灵活性上的过/欠索引问题。例如,如何确保网络及其运营商在没有严格执行规则的前提下保持安全?
ERC-5189 提出,由于负责交易执行的捆绑者也应承担确保安全的责任,毕竟,他们是因此获得报酬的。然而,这种自由市场模型在以太坊这样分散的环境中可能不太可行,特别是如果网络仍希望保持其珍视的去中心化。那么可以做些什么呢?
正如我们在本系列中探讨的那样,账户抽象机制有多种形式,具有不同的功能和目标。然而,共同的特性是 AA 交易的验证发生在 EVM 中,而不是在共识层。这意味着可以对 EVM 的可访问性施加某些限制,以确保参与任何 AA 模型范围的实体得到保护,避免遭受攻击,防止网络被削弱。
ERC-7562 提案通过在任何账户抽象机制的验证阶段定义一套强制实施的规则提供了这些限制的蓝图。你可能会想知道,为什么在验证阶段必须遵循这些规则。原因并不复杂。当两个交易在执行阶段“碰撞”时,两个交易都可以纳入一个区块,其中一个被回退,但两者都支付了纳入费用。然而,当两个交易在验证阶段碰撞时,则会影响整个块的有效性,从而阻止块构建者完成其工作。
这个方法听起来简单,对吗?好吧,你可以跳到下一节的结尾;从这里开始情况变得更糟(或更好,如果你有兴趣)。我们将简要研究这些规则,然后介绍它们在 ERC-4337 和 RIP-7560 中的实际应用。
通过将有效性规则的执行从共识层转移到 EVM,账户抽象所启用的功能得以实现。从直观上来看,这将需要每一层相当多的工作,而这项工作的主要部分将是随着每一层的适用而弃用或确立的不变性,从而不降低网络的完整性。
这些规则主要定义在 ERC-7562 中,该机制作为辅助机制,帮助账户抽象交易执行者(无论是捆绑者还是其他实体)正确验证发送给它们的交易。它引入了一系列防止网络中实体进行恶意行为的规则,无论是相互针对还是针对网络。
在深入规范之前,重要的是要注意,ERC-7562 最初是专门为 ERC-4337 设计的,后被推广以适应任何 AA 机制的背景。因此,它的大多数术语来源于 ERC-4337 的规范,尽管这些规则可以适用于任何其他机制。
ERC-7562 的规则分为两大类:
以下深入探讨这些规则的内容。
这些规则适用于每个 userOp
,在它们被接受进入捆绑者的本地内存池以供执行和传播之前。它们定义了可以访问其他账户存储和网络操作码的实体的全局限制。
由于以太坊的状态模型,交易是相互依赖的,但不指明它们提前处理的状态。这一特性可能导致同一时间 wishing 更新同一状态的交易失效。
以太坊的原生执行机制(与 EOAs)通过将交易的有效性条件限制在 EOA 的本地环境来处理这种情形。所以无效交易仅影响该 EOA,而不会影响整个网络或区块构建者。然而,AA 交易中的非确定性更为棘手,因为它们本质上依赖于可变状态,这可能被利用来破坏网络。
这里最大的问题是,从智能账户发出的交易仍然会发生某种验证成本,如果交易无效,则构建者需要承担这些成本。如果这种情况发生得足够频繁,构建者构建一个有利可图的区块将变得过于昂贵,因此他们将开始失去其插槽并影响网络的完整性。
网络可以通过明确将交易分为两个阶段来应对这一挑战。其中一个阶段是,区块构建者不确定其有效性且账户尚未承诺支付费用;另一个阶段则是,区块构建者验证了交易并同意支付最低费用纳入块。这样,通过在账户对产生的 gas 负责之前,网络可以对账户行为施加某些限制。
这些网络规则旨在限制 AA 交易的状态访问,以防止网络受到打击。捆绑者必须在第一项检查期间丢弃未通过检查的交易。如果在第二项检查期间未通过检查,则违规实体在网络中的声誉会出现降级,该交易则会被整体排除在捆绑之外。如果捆绑者执行并传播了一个错误交易,其与其他捆绑者通过捆绑者的 P2P 层的连接将被切断,涉嫌违规的捆绑者也将被标记为垃圾信息发送者。
网络范围规则分为三类,具体取决于它们旨在限制的资源:
userOperation
] 结构中的某个实体可以访问(或不可以访问)的操作码。设限术是出于以下理由:捆绑者在捆绑包创建前以本地方式执行验证模拟,因此某些操作码可以用于访问仅在创建区块时才会泄露的信息。
因此,具有访问此类操作码的实体可以使交易通过链外模拟,但在链上回退,从而浪费捆绑者的计算工作。
设限术旨在防止 userOp
在验证过程中不可避免的重叠,从而导致原本有效的交易失效。
因此,限制 userOp
的存储访问仅限于特定关联账户,以允许每个账户在单个捆绑包中保证纳入的一个 userOp
。
此规则有助于确保交易验证是确定的,并且可以容易地重播,以防止内存池膨胀(由于失败的交易)和捆绑者对其造成损害。
违反上述规则的实体将重新评估其声誉。
这次讨论让我们看到了声誉系统的必要性,以及捆绑者应如何根据自身的声誉分数与其他实体相互作用。
声誉系统的变量定义如下:
opsSeen
- 每个实体接收到的唯一有效 [userOperation
] 计数器。opsIncluded
- 每个实体在执行的捆绑包中被包含的唯一有效 [userOperation
] 计数器。inclusionRate
- 定义 opsIncluded
与 opsSeen
之间的关系。max_seen
- 定义为:[opsSeen // MIN_INCLUSION_RATE_DENOMINATOR
]。前两个变量每小时更新一次,表达为:[value = value * 23//24],而 [MIN_INCLUSION_RATE_DENOMINATOR
] 是适用于客户端的网络全局常量值 100 个单位,以及 10 个单位的捆绑者。
根据这些值衍生的基于声誉的规则旨在确保捆绑者的 DoS 抵抗,包括:
max_seen
> opsIncluded
+ BAN_SLACK
],其中 BAN_SLACK
是 50 个单位的常量值。max_seen
> opsIncluded
+ THROTTLING_SLACK
],其中 THROTTLING_SLACK
是 10 个单位的常量值。基于声誉的指引的衍生包括:
[THROTTLED_ENTITY_MEMPOOL_COUNT]
的内存池中。[THROTTLED_ENTITY_BUNDLE_COUNT]
中,并在捆绑的持续时间限制为十(10)个区块,期间其提交的交易在捆绑池中仍被视为有效,必须纳入一个捆绑包或根据 [THROTTLED_ENTITY_LIVE_BLOCKS]
策略被丢弃。opsSeen
] 值设置为 [BAN_OPS_SEEN_PENALTY]
,值为 10,000 个单位,而其 [opsIncluded
] 值设置为零(0),使其在网络上被禁用。按系统中的抵押拥有情况检查([ MIN_STAKE_VALUE
] 和 [ MIN_UNSTAKE_DELAY
] 字段的值)使其在一定程度上能够规避声誉系统的限制。这表明, [OK] 实体可以在内存池和/或捆绑中有无限的交易。
根据规范为边缘情况存在其他实体特定规则。
所有这些规则为什么必要?实体普遍存在,例如聚合器和支付者合约,可以被同时多个 AA 交易访问和使用,因为它们通常能够促进每个捆绑包多个交易的验证,应该默认可重用。
然而,具有恶意行为的实体可能会滥用这种特权,撤回对一次交易执行的支持,导致已处理的交易的大规模无效化。这造成了捆绑者计算资源的浪费并降低了他们的效率。此外,它们可以向捆绑者的内存池中淹没看似有效的交易,然后在捆绑过程中反复导致其回滚。
为防止这种情况,使用局部定义(和执行)的声誉和抵押系统以评估何时限制或禁止在网络中使用违规实体。声誉系统使捆绑者能够验证全球实体是否可信,而抵押系统使恶意实体对捆绑者进行连续 Sybil 攻击的成本更高。
这些基于声誉的指导方针在捆绑者执行 AA 交易和区块构建过程中保护捆绑者免受 Sybil 及 DoS 攻击。
它们被视为“软规则”,未通过检查的交易会立即从捆绑者的内存池中丢弃(即不传播或纳入区块)。但至于违规实体则不会有任何惩罚。
两条一般性本地规则是:
userOp
不能使用已经在捆绑者内存池的另一 userOp
中指定为关联账户的实体。userOp
在捆绑者的内存池中,如果作为另一 userOp
的[ sender
],则不得使用其关联账户的存储。这就是(实际上是大部分内容)有关 ERC-7562 的了。现在是时候深入研究 ERC-4337,并突出它在对抗 ERC-5189 的协议外 AA 模型竞赛中“胜利”的原因(剧透:这主要是因为它包含了 ERC-7562)。
ERC-4337 是将以太坊的账户抽象目标推进到理念阶段的第一步,同时为以太坊提供了通向最终目标的路线图。该倡议引入了一种用于新交易结构的替代内存池,称为 userOperations。这些结构由 捆绑者 打包——类似于 MEV 领域中的构建者——并通过 入口点合约 进行验证。
与 ERC-5189 一样,ERC-4337 移除了交易起源于 EOAs 的必要性,使合约账户能够更加独立。这使得这些账户可以表现得像“智能账户”,而不需要改变以太坊的基本机制。
在探讨这两种协议外 AA 启动机制的相似和差异之前,让我们探索 ERC-4337 的技术细节。
ERC-4337 的 userOp
结构描述了用户希望执行的交易及其他变量,如下表所示。
我们将从对 ERC-4337 中各实体的预期行为和功能进行概述开始——发送者、工厂合约、Entrypoint
合约(不同于 ERC-5189 的 entrypoint
)、支付者、聚合器和捆绑者。
由于在 ERC-4337 中不能使用 EOAs,首次使用者可能需要按惯例部署一个“有状态”的合约账户。 实质上,部署和使用一个合约账户需要对链上状态进行更改。这给希望设置新的账户但又不想将其与 EOA 关联的用户带来了困境,因为他们没有办法进行必要的修改并部署他们的合约账户。
在 ERC-4337 中,通过工厂合约有效绕过了该难题,该合约按需部署兼容 ERC-4337 的合约账户(发送者)。当 userOp
的 initCode
字段包含一个非零值(此值是账户的预期部署逻辑)时,工厂合约就会被调用。
在底层,通过工厂合约创建账户是用 CREATE2
操作码实现的,因此创建的账户具有“确定性”地址(即其地址值可以由用户提前知道),从而可以在验证之前向其发送资金。用于此的 Gas 费用由将很快介绍的支付者处理。
发送者是负责发起 userOp
请求的实体;即,它向标准 4337 内存池或替代内存池发送要执行的 userOp
请求。其核心接口设置如下所示:
interface IAccount {
function validateUserOp
(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
external returns (uint256 validationData);
}
捆绑者通过 entrypoint
合约调用它以开始验证过程时,必须运行以下检查:
entrypoint
合约发出的。entrypoint
接口公开的签名是所提交的 [userOpHash
] 的有效组件。entrypoint
合约支付 missingAccountsFund
的最低押金。这个押金是处理他们的 userOp
请求所需的金额的估算,且可以多付。超出部分可以在执行循环后撤回——需支付 10% 的罚金——方法是向 entrypoint
合约发出 withdrawTo
调用。authorizer
] - 负责为 userOp
提供有效签名的地址。否则,将返回一个聚合器的地址,当使用时将指定为 authorizer
。validUntil
] - 全天字节时间戳,定义 userOp
的执行时间框架的有效期;即,它指定了许可的执行时间必须在什么之前执行,否则将被视为无效。validAfter
] - 此时间戳用于定义 userOp
的有效持续时间的开始;即,在 [ validAfter
] 时,userOp
进入以 [ validUntil
] 结束的执行时间框架。重要的是要注意,发送者只能在每个捆绑包中拥有一个 userOp
,除非它们在系统中拥有抵押,并向捆绑者提交愿意从单个发送者接受并处理多个 userOp
请求的请求。
该实体是 4337 专用内存池的一种“守卫”。它负责:
userOperation
进行的预验证和验证逻辑进行检查。calldata
。它公开以下接口,为捆绑者开始处理 userOps
提供了调用方式:
function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary);
function handleAggregatedOps(
UserOpsPerAggregator[] calldata opsPerAggregator,
address payable beneficiary
);
struct UserOpsPerAggregator {
PackedUserOperation[] userOps;
IAggregator aggregator;
bytes signature;
}
如上伪代码所示,根据发送者的签名方案,可以使用两个不同的 entrypoint
模型:
handleOps
] 对于仅需要单个签名来验证和授权的账户发起的 userOp
的验证逻辑。handleAggregatedOps
] 是第二个 entrypoint
模型,主要负责为从多个聚合器合约获得的打包的 [ userOperation
] 结构提供验证逻辑。它的功能与 [ handleOps
] 完全相同,然而,由于它必须将正确的聚合器转移到每个 userOp
上,因此逻辑流将全然不同,然后在继续进行每个账户的验证检查之前,调用每个聚合器的[validateSignatures
]。
entrypoint
合约在发送者上调用上述任一函数,并开始预验证阶段。
签名聚合器是一个附属合约,捆绑者可以信任其为多个 userOp
提供单个签名。 它必须经过网络白名单验证才能被视为可用。
它们的主要功能是使多个 [ userOperation
] 请求的签名能够组合成一个,便于捆绑者轻松验证。 此功能允许捆绑者在一个过程中验证多个 userOp
,从而减少执行成本。
userOp
的 [ sender
] 表明在捆绑者最初对其(在本地模拟过程中)调用 validateUserOp()
时,它使用了签名聚合器,通过在 aggregatorInfo
结构中返回其聚合器的值。The bundler 然后会检查聚合器是否在白名单内,是否已质押,以及是否未被限速或禁止。如果聚合器通过了这些检查,bundler 继续进行:
validateUserOpSignature()
- 验证每个 userOp
提交的签名。aggregateSignatures()
- 为所有在同一捆中使用相同聚合器的 userOp
创建一个签名。总而言之,签名聚合器使 bundler 能够运行 “ aggregateSignatures()
”,该函数将多个 userOp
所使用的所有签名方案聚合为一个值。然后,bundler 通过 Entrypoint
合约调用 validateSignatures
,以确保签名正确实施。
paymaster
是第二个附属合约,能实现 userOp
结构的无信任油费支付抽象。它们的设计是以更高的费用向用户收取执行 userOp
时的预期费用,资产类型为用户选择的支持资产;如果用户在任何时候请求,超出部分是可退款的。
ERC-4337 中油费抽象的主要应用是用户可以创建一个实现了特殊逻辑的账户(通过工厂合约),而不需要从个人 EOA 资助所收取的状态租金。通过这种方式,用户可以像 EOA 一样本地生成账户,但账户实现了与合约账户类似的特殊逻辑。
如果 userOp
利用 paymaster
合约,验证循环会修改,以便 handleOps
调用也检查该合约是否在 Entrypoint
合约有足够的 ETH 存款用于请求的执行。如果 paymaster
有足够的存款,将调用 validatePaymasterUserOp
验证 paymaster
是否愿意支付请求的执行费用。
如同聚合器,paymaster 默认可以访问全局状态。它们可以在一个捆中为尽可能多的 userOp
表明支持。这赋予了它们一个侵犯攻击向量,paymaster 可以表示对某个 userOp
包含在捆中的支持,然后在执行过程中撤回,导致 userOp
无效和浪费 bundler 的计算能力。
为了防止这种大规模失效攻击,系统默认限制 paymaster 的访问,限制它们的存储访问,并对它们可以支持的每个解析捆中的 userOp
数量设定上限。不过,paymaster 可以通过在系统中持有质押来访问更多存储。
这些实体负责对 userOp
的端到端处理;即,bundler:
userOp
,userOp
,以下是 bundler 视角下, userOp
在 ERC-4337 机制的三个阶段中的生命周期概览。
预计 bundler 在接收到 userOp
时运行本地仿真,以验证其签名是否正确以及为执行提供了足够的费用。
每个 userOp
在 bundler 的内存池中的处理过程如下:
userOp
是否具有有效的 [ nonce
] 字段:ERC4337 为以太坊奠定了二维 nonce 的基础,想要在一个捆中包含来自同一发送方的多个 userOp
的 bundler 必须跟踪每个发送方的 [ key
] 和 [ sequence
] 对。如果他们只想在每个捆中包含一个 userOp
,则仅跟踪 [ key
] 值就足够了。sender
] 是否是已存在的合约,或者 userOp
是否有 [ initCode
] 值:如果发送方已经存在,bundler 将其前 20 个字节解析为工厂地址,并记录它在系统中是否有质押。如果不存在,bundler 的 handleOps
调用将在发送方地址上使用 initCode
字段提供的详细信息部署一个账户。如果账户不存在且 [ initCode
] 字段为空,整个调用将立即失败。sender
] 是否为 userOp
的每个步骤提供了足够的气体:bundler 必须计算发送方(或 paymaster)为其 userOp
的调用应支付的气体总量,并支付账户必须存入 entrypoint
的费用。然后,它检查该账户是否持有最低返回值。paymasterAndData
] 字段是否为空,或者如果该字段被填充,则是否以 paymaster 合约的地址开头。如果发送方使用 paymaster,bundler 必须检查指定的合约:合约链上代码不为空
有足够的以太存款支付 userOp
未被限速或禁止。
callgas
值是否非零,并且至少是一个普通 [ CALL
] 操作码的费用。maxFeePerGas
] 和 [ maxPriorityFeePerGas
] 是否在他们愿意接受的范围内,其最小值应当等于最新块的当前基础费用。userOp
,或者新的 userOp
意图替换现有条目。在后者情况下,新 userOp
必须具有相同的 [ sender
] 和 [ nonce
] 值,但 [ maxFeePerGas
] 和 [ maxPriorityFeePerGas
] 值必须增加。这些检查实施以确保每个 [ userOperation
] 结构中每个对象的个体有效性,然后 bundler 开始解析它们。
验证阶段按 ERC-7562 中所述进行,因此我们将直接进入执行阶段。
在通过验证循环后,[ userOperation
] 将通过 [ handleOps
] 的执行循环调用。执行循环如下进行:
handleOps
函数调用带有 [ userOperation
] 的账户的 calldata
,允许账户指定 calldata
将如何解析以供执行。最理想的情况下,账户应具有一个 [ execution
] 函数,该函数可以将其作为一系列调用执行。entrypoint
。通过使其 calldata
开头为 methodsig
– [ IAccountExecute.executeUserOp
],账户使之成为可能,这将允许 entrypoint
合约通过编码 [ executeUserOp (UserOp, UserOpHash)
] 来构建一个 calldata
结构。从这个过程中得到的 calldata
然后用于调用账户。userOperation
] 中支付给 bundler 提供的地址。在捆的创建过程中,bundler 应:
userOp
的 [ sender
] 地址的 userOp
。这是为了确保发送方的状态在执行期间保持不变。userOp
进行排序——如果有的话——并跟踪每个 paymaster 的余额。这使其可以检查 paymaster 是否可以轻松支付捆中使用它的所有 userOp
。userOp
进行排序——如果有的话——然后为每个运行聚合器特定的代码,以创建每个 userOp
的正确聚合签名。这些措施防止相互依赖的 userOp
及其相关合约之间的冲突。
构建整个捆并在将其发送给区块生产者之前,bundler 预计将在以下方式中进行第二次检查:
debug_traceCall
_] 以强制实施操作码和存储访问的验证规则,并验证整个批次。userOp
从捆和其内存池中。factory
] 或 [ paymaster
] 合约,并且该 [ sender
] 在系统中没有质押,则 bundler 将视情况对前者实施禁止。如果 [ sender
] 在系统中有质押,则 bundler 将禁止他们。进行这些后续检查的理由是,质押实体被授予更多的瞬态存储访问权限,这一特权可能被滥用,以便在同一捆中的 userOp
之间传播数据,从而有效削弱系统。
至此关于 ERC-4337 的介绍结束。下表总结了 ERC-5189 和 ERC-4337 之间的差异。
ERC-4337 对普通用户的最大缺陷是处理最基本 userOp
的高费用(高达 42k gwei,而基本 EOA 交易为 21k gwei)。这一高成本直观上限制了其可用性和采用率,只有少数愿意为智能账户提供的功能支付费用的人才会使用。
此外,ERC-4337 无法受益于协议升级——最明显的例子是以 crLists 形式提供的更严格的审查抵抗保障——使得其用户面临审查风险,这在当前机制大规模采用时风险只会加剧。
为了解决这些问题,并进一步确认以太坊对以 rollup 为中心的路线图的承诺,RIP-7560 被引入。该机制是 EIP-2938 的一个总结的 ERC-4337 兼容版本; 它将后者适应于前者机制的规范,同时解决智能账户当前面临的最大挑战。
RIP-7560 引入了第一个在协议中实现的验证执行分离,通过“方法选择器”显式化阶段。在 Solidity 代码中,这些方法选择器是函数的简单且具成本效益的表示(明确来说,它们是函数签名 keccak256 哈希的前四个字节)。在 RIP-7560 中,这些方法选择器用于“指向”在处理账户交易时必须对智能账户进行的具体调用。
这些调用的逻辑实现在网络的执行层;即,RIP-7560 类型交易的验证和执行发生在 EVM 上,尽管在不同的阶段。
RIP-7560 交易由智能账户作为符合 EIP-2718 的对象(AA_TX_TYPE
)启动,具有两个不同的阶段:验证和执行。每个阶段由多个调用帧组成,具体取决于账户请求的复杂性。它们通过 RPC 被发送到公开内存池(或任何其他“传统”交易处理机制),然后由区块构建者和提议者处理。
缺乏一个负责交易处理的第三方(例如 ERC-5189 的支持者和 ERC-4337 的 bundler)消除了预验证阶段的必要性。
以下是 RIP-7560 交易的阶段概览及其相应帧,以便更好地理解其机制。
在此阶段,作为 AA_TX_TYPE
部分发送到内存池的智能账户发送的对象的值被评估为正确。它由以下帧组成:
sender
] 部署 - 在这一帧中, AA_SENDER_CREATOR
(直觉上,负责创建智能账户的调用)调用一个 [ deployer
](类似于 ERC-4337 中的工厂合约),并提供 [ deployerData
] 的值。此调用将 [ sender
] 转变为智能账户,并且每个账户只能发生一次。sender
] 验证 - 此帧由两个子调用组成:AA_ENTRY_POINT
调用 validateTransaction
函数,以使其:i. 使用适当的 [ authorizationData
] 值进行身份验证
ii. 进行 nonce 检查
iii. 运行气体检查(如果没有指定 paymaster
)
AA_ENTRY_POINT
传送回调,使用以下任意一个函数:i. acceptAccount
,这表明发送方已验证 AA_TX_TYPE
的对象,并将为其执行支付Gas费。
ii. sigFailAccount
,这表明发送方无法验证其身份(即,它使用了不正确的 [ authorizationData
] 值)。
在发送者通过验证阶段的情况下,它将返回两个值给 AA_ENTRY_POINT
,同时附上 acceptAccount
的回调
validAfter
和 validUntil
(与 ERC-4337 中的功能相同)任何其他情况,例如:
AA_ENTRY_POINT
AA_ENTRY_POINT
acceptAccount
将导致该交易无效并被丢弃。
paymaster
] 验证 - 在这一帧中,对 paymaster(如果有的话)进行验证,并期望其明示协议同意支付发送方交易的Gas费。它从 AA_ENTRY_POINT
调用指定的 paymaster,使用 validatePaymasterTransaction
函数,以使 paymaster 评估该交易并返回两种回调中的任意一种:acceptPaymaster
,这意味着paymaster正在愿意支付报价中的交易在区块中的费用。如果 paymaster 返回此调用,还必须提供 validAfter
和 validUntil
值,以及 context 值。context 字段旨在存储 payer 可能需要的任何其他数据,以便在后续交易阶段进行会计。sigFailPaymaster
,这意味着 paymaster 不愿付款执行费用,无论是由于验证或发送者与之之间的会计错误。如果 paymaster 返回此调用,该交易将丢弃并不会包含在区块中。在完成验证阶段后,执行阶段开始,将执行有效负载 executionData
传递给发送方,paymaster 整理账户。
(sender).call(executionData);
然后,该交易进入后交易帧。可以说,RIP-7560 中引入的最大功能是,智能账户(隐含包含代码)能够自己支付Gas费。这实质上意味着将智能账户重新安装为网络中的完全自治实体,从部署到管理。
尽管我们稍后会重申这一发展的好处,但让我们首先看看 RIP-7560 中Gas费结算是如何发生的。
由于去除交易本质上的 ECDSA 基础验证,因此不需要在 AA_TX_TYPE
交易中调用 ecRecover 机制;而是,它们的Gas费以 maxPossibleGasCost
来表示,该值包括:
AA_BASE_GAS_COST
为 15k 处理单元,表示任何交易至少所需的气体。validationGasLimit
,其值由用户借助他们的钱包供应商提供(与 EOA 交易相同)。此值是他们愿意支付以包含在交易的最大金额。它基于交易的复杂性和链上情况的估计。validationGasLimit
取决于四个变量: executionData
, paymasterData
, deployerData
和 authorizationData
。在验证阶段,块构建者计算这四个变量的值,并将其 added into 身体的气体使用量。若用户估计的 validationGasLimit
小于块构建者计算出的 calldataGasUsed
,则交易将被视为无效并丢弃。paymasterValidationGasLimit
,用于限制 paymaster(如使用)的气体在 paymaster 验证帧中花费的上限。它必须大于或等于 paymasterValidationGasUsed
的值。callGasLimit
,在发送方执行帧中可以消耗的气体的上限。它必须大于或等于 gasUsedByExecution
。paymasterPostOpGasLimit
,用于限制 paymaster 在后交易帧中可以花费的气体上限。maxPossibleGasCost
可以直接从发送方余额或 paymaster 中收取,通过 validateTransaction
或 validatePaymasterTransaction
函数调用。AA_TX_TYPE
交易的Gas费在验证阶段收取,以防止 DoS 攻击。
由于 RIP-7560 针对 Rollups,因此为,使其适应现有和潜在的各种 rollup 设计,它必须尽可能通用。
RIP-7560 中必须保持尽量通用的一个方面是交易手段的验证和执行窗口分离。
大多数 rollup 每个实现一个单个序列化模型,交易缓冲到一个单独的实体中,该实体按接收到的顺序执行它们。然而,其他 rollup 使用公开(或甚至私有)内存池授予用户更高程度的审查抵抗。
在采用私有或公共内存池的 Rollups 中,块构建者很难识别一个交易,其执行阶段可能使构建者的内存池中的其他待处理交易失效。RIP-7711 弥补了这一问题。它为块构建者提供了一种机制,以便指示 AA_TX_TYPE
交易可以被捆绑,从而避免在验证阶段“碰撞”。
在 RIP-7711 中,AA_TX_TYPE
交易的验证阶段和执行阶段(称为 BUNDLE_TRANSACTION_TYPE
)被授予非原子性。这意味着在从头到尾处理包含一组 BUNDLE_TRANSACTION_TYPE
的 AA_TX_TYPE
交易时,构建者分阶段完成整套餐的验证阶段,然后再进入执行阶段。因此,块构建者可以有效地构建非碰撞的 AA_TX_TYPE
交易的区块。
如果与 ERC-7562 共同实施,使用 BUNDLE_TRANSACTION_TYPE
机制将使区块生产者在检测到验证碰撞时,能够避免执行碰撞,从而便于更轻松地对(潜在的)敌对状态访问应用适当的惩罚。
如上一节所述,RIP-7560 中验证和执行的分离使用了 solidity 方法选择器。尽管这对 Rollups 来说并无太大意义,但由于在主网上涉及更高的风险,该方法无法复现。
更具体而言,使用 solidity 方法选择器意味着执行层的语言不可知性特性受损,使得协议在编译器级别面临攻击的风险(尽管这发生的机会相对较低,但不为零,正如 Vyper 事件所示)。
因此,主网的原生 AA 模型必须采取更复杂的方法。其中一种被考虑的方法是通过 EVM 对象格式(EOF)实现账户抽象。
迄今为止,EOF 已被证明是一个备受争议的升级,因为它引入了复杂性。然而,我们将在这里避免对机制进行深入分析,甚至避免争论其看法利弊,以免给本文带来更多的复杂性。相反,本节将概述 EOF 的特性以及它们如何实现账户抽象。我们还将评估 EIP-7701,该 EIP 采用 EOF 智能账户将账户抽象引入以太坊 L1。
EVM 对象格式的决定性特性包括:
前者特性,即逻辑容器化,是我们在这里的主要关注点,因为它使智能账户能够显式定义其验证和/或执行逻辑,并确保它们不会重叠。该机制的首个版本(EOFv1)引入了容器化作为“代码-数据分离”,使按其规范部署的代码能够在链上使用两个主要类型的字段初始化:
通过此机制,代码和数据的显式分离使 EVM 字节码能够以可扩展和版本化的方式进行部署。对于字节码逻辑的变更可以采用向后兼容的方式进行,而字节码的逻辑根据 EOF 的版本规则保证是有效的。
EOFv1 的代码分区可以应用于 RIP-7560 机制,以显式将代码分区分配给特定实体,这样实体就不仅通过复杂的调用-回调方法与 AA_ENTRY_POINT
交互,而是被明确限制为如下特定逻辑:
任何未分配的代码部分可以由其他账户调用,而实体不能调用分配给他们的任何其他函数,从而实现价值处理上下文的细粒度定义。
现在我们已经涵盖了这些模型的工作原理,并对账户抽象有了大致认识(或者更深入一些),让我们重申一下,这一直是以太坊交易的目标。
如果我们假设由于在这些模型中进行的深入研究,已经在表面上解决了 以太坊账户困境,那么我们现在可以做什么?这些模型与传统账户有什么不同,这些差异是否重要?
简短的回答是,改进很多,它们都很重要。然而,更长的回答在于下一节,我们将覆盖的这些发展的回顾,追溯到 Vitalik 发布的原始抽象文章。
本节概述了 Vitalik 在交易中的验证无关性的方法。简单来说,任何账户抽象模型应该能够超越 EOA 交易所受的本质 ECDSA 验证循环。
ERC-4337、RIP-7560 和 EIP-7701 都提供了这种手段。它们的验证和执行阶段分离实现了“即插即用”的模型,用户可以利用这一模型为他们的交易引入其他签名方案。这使得使用更优化的方案成为可能,同时为量子抗性签名方案铺平了道路。
这种改进打开的一些用例包括:
在这一方面的改进中尚未被归纳的是,在密钥丢失的情况下,很容易恢复资产,这是在传统模型中几乎不可能的任务。通过利用旋转密钥模型、社会恢复机制、多重签名身份验证机制或任何其他可能机制,用户可以在丢失主要密钥后,轻松找回访问其资产的权限。
本节讨论以太坊的状态模型在交易方面的缺陷。我们之前提到的问题根源在于,即使在它们的验证阶段,交易可能会彼此“碰撞”,致使网络面临 DoS 攻击的风险。
这个问题通过 ERC-7562 中规定的规则得到了解决,这些规则限制了交易在验证期间可以访问的状态,并允许网络安全地支持账户抽象。
对于这一点,案例是简单的:一个无许可网络应该能够支持多种货币。否则,它仍然对国家俘获和其他形式的审查具有更低的抗性。这种类型的发展在确保 DoS 抵抗的收费机制的权益证明网络中更为棘手。但是,以太坊几乎不会退缩于挑战。
ERC-4337、RIP-7560 和 EIP-7701 都通过支持 自验证的 paymaster 合约,解决了货币多样性问题,用户可以使用他们选择的气体货币进行订阅。这一方案通过在 ERC-4337 中的 Entrypoint 合约,RIP-7560 和 EIP-7701 中的协定达到协议级别,事先收取交易的Gas费,而不是等到执行完成或撤回后再收取。
这种方法有助于货币多样性,而不会引入 DoS 攻击的脆弱性。它允许用户进行交易,即使他们没有 ETH,因为其他代理可以资助他们、他们想要接入的 dApp,甚至通过非 ETH 货币支付区块构建者。
本叙述标志着我们关于以太坊账户抽象的系列文章的结束。我们主要关注了实现对传统账户增加或引入新账户标准功能的主要机制。未来,我们可能会深入探讨其他机制,这些机制在此基础上提供更多功能,如跨链消息系统、链特定地址和模块化智能账户。
致谢:特别感谢 Daniel Ayuko 的审阅和反馈。我们也感谢 SafeDAO 通过 OBRA 项目资助本报告的工作.
- 原文链接: research.2077.xyz/charti...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!