原生账户抽象

  • ethereum
  • 发布于 2025-03-25 13:33
  • 阅读 37

本文提出了一种结合EIP-2938和ERC-4337的原生账户抽象提案,通过将以太坊交易拆分为验证、执行和后交易逻辑的多个步骤,实现了更好的兼容性和效率。文章详细阐述了新交易类型的定义、规则及其在现有协议中的应用,尤其关注了向后兼容性和安全性。

摘要

EIP-2938ERC-4337 结合成一个全面的原生账户抽象提案。

我们提议将以太坊交易范围分为多个步骤:验证、执行和事务后逻辑。交易的有效性由交易的验证步骤的结果决定。

我们进一步为授权和Gas费用支付分开交易验证,允许合约 B 支付来自账户合约 A 的交易的Gas费。

这一提案的好处在于与新兴的 ERC-4337 生态系统的向后兼容,同时实现原生账户抽象的长期目标。

动机

ERC-4337 作为一种纯自愿的 ERC 可以做很多事情。然而,与原生支持相比,任何非协议内的方法来实现账户抽象都面临几种缺点。在某些关键领域,它不如真正的协议内解决方案强大:

  • 基本的 UserOperation 相比基本交易的额外Gas开销约为 42k,而基本交易约为 21k。

  • 在协议内审查抵抗技术方面获得的收益较少,如 crLists,针对的是交易而会忽视 UserOperations

  • 依赖于远小于参与节点集的的非标准 RPC 方法,如 eth_sendRawTransactionConditional

  • 无法使用 tx.origin 或依赖于其的合约,因为它返回的是一个无意义的捆绑地址。

EIP-2938 定义了一种非常成熟的账户抽象替代方法。然而,它并没有很好地转换为在没有协议变化的情况下用于生产的 ERC-4337 的架构。因此,EIP-2938 的实现将无法从有使用 ERC-4337 所获得的生产经验中受益,也无法与之保持向后兼容。

未来在某个时刻,所有的 EOAs 在以太坊上可能会被预部署的智能合约所替代。然而,这在没有将原生账户抽象添加到协议中的情况下是不可能的。

规范

常量

名称
FORK_BLOCK TBD
AA_TX_TYPE TBD
AA_ENTRY_POINT address(7560)
AA_SENDER_CREATOR address(ffff7560)
AA_BASE_GAS_COST 15000
VERSION 1
MAX_CONTEXT_SIZE 65536
MAX_REVERT_REASON_SIZE 1024

定义

  • 交易: 由账户发起的动作,并由一组输入参数表示。该动作将在被包含在区块中时更改以太坊区块链的状态。
  • RIP-7560 交易: 由智能合约账户发起的动作,并用与 EIP-2718 兼容的交易封装对象表示。
  • RIP-7560 调用帧: EVM 代码执行的单个原子元素,由对特定地址的单个顶级调用和给定数据表示。一个 RIP-7560 调用帧可以包含内部调用帧,但它们不会被称为 “RIP-7560 调用帧”。一个 RIP-7560 调用帧可以成功或回退。
  • RIP-7560 交易阶段: 一组组成 RIP-7560 交易流程中的单一步骤的 RIP-7560 调用帧。RIP-7560 交易有两个阶段:验证执行
  • 支付方: 一个智能合约,它在 RIP-7560 交易中的唯一作用是支付其Gas费用。

新交易类型

引入一种新的 EIP-2718 交易,其类型为 AA_TX_TYPE。此类型的交易称为 "AA 交易"。它们的负载应被解释为:

0x04 || 0x00 || rlp([
  chainId,
  nonceKey, nonceSequence,
  sender, senderValidationData,
  deployer, deployerData,
  paymaster, paymasterData,
  executionData,
  builderFee,
  maxPriorityFeePerGas, maxFeePerGas,
  validationGasLimit, paymasterValidationGasLimit, paymasterPostOpGasLimit
  callGasLimit,
  accessList,
  authorizationList
])
authorizationList = [[chain_id, address, nonce, y_parity, r, s], ...]

此交易的基本Gas费用设置为 AA_BASE_GAS_COST 而不是 21000,以反映 “内在” ECDSA 签名验证的缺乏。

authorizationList 参数的行为完全与 EIP-7702 中定义的相同。

RIP-7560 交易的定义:

下表表示 RIP-7560 交易字段的完整列表:

名称 类型 描述
sender DATA, 20 Bytes 发起交易的智能合约账户地址
deployer DATA, 20 Bytes 部署者的地址 - 账户工厂合约(可选)
deployerData DATA 提供给部署者合约的数据(如果设置了 deployer
paymaster DATA, 20 Bytes 支付方合约的地址(可选)
paymasterData DATA 提供给支付方合约的数据(如果设置了 paymaster
executionData DATA 提供给账户合约进行执行的数据
nonceKey QUANTITY 一个 192 位的nonce键。使用 nonceKey != 0 在 RIP-7712 中定义。
nonceSequence QUANTITY 一个 64 位的nonce序列。使用 nonceKey != 0 在 RIP-7712 中定义。
builderFee QUANTITY 从发送者或支付方传递到 coinbase 的值
maxPriorityFeePerGas QUANTITY 包含的最大Gas价格作为对验证者的奖励
maxFeePerGas QUANTITY 每单位Gas的最大费用
validationGasLimit QUANTITY 提供给交易账户验证帧的Gas
paymasterValidationGasLimit QUANTITY 提供给交易支付方验证帧的Gas(如果设置了 paymaster
paymasterPostOpGasLimit QUANTITY 提供给交易支付方 postOp 帧的Gas(如果设置了 paymaster
callGasLimit QUANTITY 提供给交易 RIP-7560 执行调用帧的Gas
accessList OBJECT 与 EIP-2930 兼容的访问列表结构
EIP-7702 authorizations (WIP) ARRAY 与 EOAs 注入兼容的 EIP-7702 合约列表
authorizationData DATA 将用于账户验证交易的数据

RIP-7560 交易收据的定义:

交易收据对象的结构已修改,以支持 RIP-7560 交易收据。

名称 类型 描述
sender DATA, 20 Bytes 此交易的发送者地址
paymaster DATA, 20 Bytes 如果它为该交易支付,支付方的地址,否则为 null
deployer DATA, 20 Bytes 如果交易中包含,部署者的地址,否则为 null
senderCreationGasUsed QUANTITY 发送者部署帧实际使用的Gas量,如果框架未执行则为零
senderValidationGasUsed QUANTITY 发送方验证帧实际使用的Gas量
paymasterValidationGasUsed QUANTITY 支付方验证帧实际使用的Gas量,如果框架未执行则为零
executionGasUsed QUANTITY RIP-7560 执行调用帧实际使用的Gas量
postOpGasUsed QUANTITY 支付方 postOp 帧实际使用的Gas量,如果框架未执行则为零
executionStatus QUANTITY 0(成功),1(执行回退),2(postOp 回退),3(执行和 postOp 均回退)
validationLogs ARRAY 该交易的验证帧生成的日志对象数组
transactionHash DATA, 32 Bytes 交易的哈希
transactionIndex QUANTITY 交易在区块中的索引位置的整数
blockHash DATA, 32 Bytes 此交易所处区块的哈希
blockNumber QUANTITY 此交易所在区块的块号
cumulativeGasUsed QUANTITY 此交易在区块中执行时的Gas总消费量
effectiveGasPrice QUANTITY 每单位Gas支付的基本费用与小费的总和
gasUsed QUANTITY 此特定交易单独使用的Gas量
logs ARRAY 此交易的执行帧生成的日志对象数组
logsBloom DATA, 256 Bytes 用于轻客户端快速检索相关日志的布隆过滤器
type QUANTITY 交易类型的整数

Gas费用直接从合约余额中收取

AA_TX_TYPE 交易的最大Gas费用定义为:

maxPossibleGasCost = AA_BASE_GAS_COST +
  validationGasLimit +
  paymasterValidationGasLimit +
  callGasLimit +
  paymasterPostOpGasLimit

如果未指定 paymaster,则 maxPossibleGasCost 在任何执行帧进行计算之前,从 sender 地址的余额中预先收取。

如果指定了 paymaster,则Gas费用从其余额中收取。如果被预先收取的账户余额不足,无论是 sender 还是 paymaster,交易都是无效的。

交易执行结束后,被预先收取的地址可能会获得Gas退款。

maxPriorityFeePerGasmaxFeePerGas 的含义与 EIP-1559 中定义的没有变化。

按交易输入收取Gas费用

对于所有现有交易类型,关于 data 参数按字节收取 G_txdatazero (4 gas) 和 G_txdatanonzero (16 gas)。

交易类型 AA_TX_TYPE 引入以下动态长度输入:executionDatapaymasterDatadeployerDataauthorizationData。这些参数的Gas费用将计入交易数据成本。该交易数据Gas成本称为 calldataGasUsed,并在交易执行之前从 validationGasLimit 中减去。如果 validationGasLimit 小于 calldataGasUsed,则交易将被视为无效。

建造者费用

由于需要考虑块构建者在将 AA_TX_TYPE 交易包含在其区块中时所需进行的额外离线工作,以及在 L2 rollups 上操作的构建者的潜在 L1 Gas费用,并且因为这些工作与验证所花费的Gas量无关,也不与Gas价格相关,因此 sender 可能决定支付额外的 builderFee 作为对块构建者的 “小费”。

该值以 wei 为单位,由 sender 或(如果指定)paymaster 传递到当前区块的 coinbase 中,作为Gas预收费的一部分。

单个交易的多个执行帧

所有现有交易类型仅具有隐式验证阶段,其中检查余额、nonce 和签名,以及具有 tx.origin == msg.sender 的单个顶级执行帧,而该地址由交易 ECDSA 签名确定。

然而,在处理类型为 AA_TX_TYPE 的交易时,将创建多个执行帧。可能的帧的完整列表尝试复刻 ERC-4337 流程:

  1. 验证阶段
    • sender 部署帧(每个账户一次)
    • sender 验证帧(必需)
    • paymaster 验证帧(可选)
  2. 执行阶段
    • sender 执行帧(必需)
    • paymaster 交易后帧(可选)

“验证阶段”中的所有执行帧必须成功完成而不得回退,并且 senderpaymaster 验证帧必须包含对对应 AA_ENTRY_POINT 批准回调函数的调用,才能使交易在区块中的指定位置被视为有效。

在所有顶层帧中,全局变量具有以下含义:

操作码名称 Solidity 等效
CALLER msg.sender AA_ENTRY_POINT 地址。AA_SENDER_CREATOR 用于 “部署帧”。
ORIGIN tx.origin 交易的 sender 地址
CALLDATA* msg.data 交易数据设置为相应帧的输入

交易执行上下文

请注意 EVM 中某些行为取决于交易上下文。这些行为是:

  1. EIP-2200 中的 SSTORE 操作码成本
  2. EIP-2929 中的冷地址和槽的访问费用
  3. EIP-1163 中瞬态存储中的可用值
  4. EIP-3529 中的执行后指定的最大Gas退款
  5. EIP-6780 中的 SELFDESTRUCT 操作码的可用性

这些功能不受将交易分成多个帧的影响。比如在一个帧中使用 TSTORE 设置的值将在下一帧中继续可用。

发送方部署帧

deployer 地址从 AA_SENDER_CREATOR 地址调用,使用 deployerData 作为调用数据输入。

此帧的 gas 限制设置为 validationGasLimit。该帧使用的Gas量称为 senderCreationGasUsed

发送者部署帧必须导致 sender 地址被初始化为合约代码。

发送方验证帧

我们定义以下 Solidity 结构来表示链上的 AA 交易:

struct TransactionTypeRIP7560 {
    address sender;
    address paymaster;
    address deployer;
    uint256 nonceKey;
    uint256 nonceSequence;
    uint256 builderFee;
    uint256 maxFeePerGas;
    uint256 maxPriorityFeePerGas;
    uint256 validationGasLimit;
    uint256 paymasterValidationGasLimit;
    uint256 paymasterPostOpGasLimit;
    uint256 callGasLimit;
    bytes senderValidationData;
    bytes paymasterData;
    bytes deployerData;
    bytes executionData;
    address[] authorizationList;
    bool[] authorizationListStatus;
}

请注意,authorizationList 结构参数仅包含从每个 RLP 编码的交易负载元素中恢复的地址列表。

由于为 authorizationList 提供任何元素都与其有效性无关,并且在链上验证时避免重复执行 ecrecover,因此引入 authorizationListStatus 结构参数。其元素为设置 EOAs 代码导致的条目返回 true,否则返回 false

然后定义以下 Solidity 方法,sender 交易会使用相应的数据被调用:

function validateTransaction(uint256 version, bytes32 txHash, bytes transaction) external;

此帧的 gas 限制设置为 validationGasLimit - senderCreationGasUsed - calldataGasUsedtransaction 参数被解释为 TransactionTypeRIP7560 的 ABI 编码。 txHash 参数表示 AA_TX_TYPE 交易的哈希,authorizationData 为空,如第 计算 AA_TX_TYPE 交易哈希 节中定义。version 参数被添加以在将来此结构修改时保持 Solidity 方法ID 的有效性。

该帧使用的Gas量称为 senderValidationGasUsed

接下来定义下列 Solidity 方法作为 AA_ENTRY_POINT 批准回调函数:

function acceptAccount(uint256 validAfter, uint256 validUntil) external;
function sigFailAccount(uint256 validAfter, uint256 validUntil) external;

AA_ENTRY_POINT 批准回调的调用具有以下含义:

  • acceptAccount - 该回调在账户验证交易并同意支付执行费用后由账户调用。
  • sigFailAccount - 当交易在语法上有效,但 authorizationData 不正确时,账户会调用此回调。请注意,此回调在Gas估算时使用,并不表示交易有效。

传递给回调函数的参数具有以下含义:

  • validAfter - 一个时间戳。交易仅在此时间之后有效。
  • validUntil - 一个时间戳。交易仅在此时间之前有效。零是一个特殊值,表示 “无限期有效”。

账户必须进行一次确切的调用到 AA_ENTRY_POINT,才能被视为有效。任何其他结果,例如账户未调用 AA_ENTRY_POINT 回调,调用任何非 acceptAccount 的调用,多个调用 AA_ENTRY_POINT,或导致执行回退,都将被视作验证失败,交易将被拒绝,不会被链上包含。

这些回调可以由账户直接调用,也可以在运行于账户上下文中的 DELEGATECALL 内部调用。如果在验证帧期间,从任何其他合约调用回调,交易将被拒绝,并不会被链上包含。

支付方验证帧

交易的 paymaster,如果已指定,将使用以下数据调用:

function validatePaymasterTransaction(uint256 version, bytes32 txHash, bytes transaction) external;

此帧的 gas 限制设置为 paymasterValidationGasLimit

此帧使用的 gas 量称为 paymasterValidationGasUsed

  • version 参数为 VERSION
  • transaction 参数被解释为 TransactionTypeRIP7560 的 ABI 编码。\
  • txHash 参数代表 AA_TX_TYPE 交易的哈希,authorizationData 为空,如第 计算 AA_TX_TYPE 交易哈希 节中定义。

接下来定义下列 Solidity 方法作为 AA_ENTRY_POINT 批准回调函数:

function acceptPaymaster(uint256 validAfter, uint256 validUntil, bytes context);
function sigFailPaymaster(uint256 validAfter, uint256 validUntil, bytes context);

AA_ENTRY_POINT 批准回调的调用具有以下含义:

  • acceptPaymaster - 支付方在验证交易后同意支付执行费用时调用该回调。
  • sigFailPaymaster - 如果支付方的 paymasterData 预计包含某种签名,但实际上并不包含有效的签名时,支付方会调用此回调。请注意,此回调在Gas估算时使用,并不表示交易有效。

传递给回调函数的参数具有以下含义:

  • validAftervalidUntil - 同 acceptAccount 中的定义相同
  • context - 支付方合约提供的可选字节数组,该数组稍后传递给 postPaymasterTransaction。此值的长度不得超过 MAX_CONTEXT_SIZE 字节。

支付方必须进行一次确切的调用到 AA_ENTRY_POINT,才能被视为有效。任何其他结果,例如支付方未调用 AA_ENTRY_POINT 回调,调用任何非 acceptPaymaster 的调用,多个调用 AA_ENTRY_POINT,或使执行回退,都将被视作验证失败,交易将被拒绝,不会被链上包含。

这些回调可以由支付方直接调用,也可以在运行于支付方上下文中的 DELEGATECALL 内部调用。如果在验证帧期间,从任何其他合约调用回调,交易将被拒绝,并不会被链上包含。

发送方执行帧

sender 地址使用 executionData 输入调用。

此帧的 gas 限制设置为 callGasLimit。\ calldataGasUsed 价值的计算在 交易输入的Gas费用收取 部分中定义。\ 此帧使用的Gas量称为 gasUsedByExecution

验证帧不会回退,即使执行帧引发回退。此时,postPaymasterTransaction 仍然可以与 success: false 标志一起调用。

支付方事务后帧

在发送方执行帧结束后,支付方可能需要执行某些事务后的逻辑,例如进行某种清理或记账。如果Gas支付验证帧在 acceptPaymaster 回调中提供了非零 context,则支付方将再次被调用,输入如下:

function postPaymasterTransaction(bool success, uint256 actualGasCost, bytes context) external;
  • success 指示此交易的执行帧是否成功完成且无回退。
  • actualGasCost 参数是截至这一点,支付方为此交易实际花费的Gas量。注意,它不包含 postPaymasterTransaction 函数自身的Gas成本。

此帧的 gas 限制设置为 paymasterPostOpGasLimit

postPaymasterTransaction 帧中的回退也会导致交易执行帧的回退。支付方收取的Gas费用将包括验证帧以及回退的执行帧和 postPaymasterTransaction 帧的Gas成本。

系统交易事件

我们定义以下系统级事件,它们作为 RIP-7560 交易的一部分被触发:

    event RIP7560TransactionEvent(
        address indexed sender,
        address indexed paymaster,
        address indexed deployer,
        uint256 nonce,
        uint256 executionStatus
    );

    event RIP7560TransactionRevertReason(
        address indexed sender,
        uint256 nonce,
        bytes revertReason
    );

    event RIP7560TransactionPostOpRevertReason(
        address indexed sender,
        address indexed paymaster,
        uint256 nonce,
        bytes revertReason
    );
  • RIP7560TransactionEvent 在每个 RIP-7560 交易结束时触发。

  • RIP7560TransactionRevertReason 在 RIP-7560 交易的执行帧因回退而产生非零长度返回数据的情况下触发。

  • RIP7560TransactionPostOpRevertReason 如果 RIP-7560 交易支付方的 “postOp” 调用因产生非零长度返回数据而引发回退,则触发。

返回的字节数组作为 revertReason 参数被截断为其最大长度 MAX_REVERT_REASON_SIZE。超出该长度的数据将在交易收据中不可观察。

系统交易事件的Gas成本不单独收取,而是包含在交易的 AA_BASE_GAS_COST 中。

executionStatus 的值如下:

  • success = 0
  • executionFailure = 1
  • postOpFailure = 2
  • executionAndPostOpFailure = 3

执行流程图

由账户抽象交易确定的执行流程通过以下流程图可视化:

原生账户抽象交易的执行流程

执行层交易验证

在执行层,对区块的交易有效条件的扩展如下:


func validateAccountAbstractionTransaction(tx *Transaction) {
    assert !(sender.code.length > 0 && deployer != address(0))

    if (sender.code.length == 0 && deployer != address(0)) {
        calldataGasUsed := calculateCallDataGasUsed(tx)
        retDeployer, error := evm.Call(
            from: AA_SENDER_CREATOR,
            to: deployer,
            input: deployerData,
            gas: validationGasLimit - calldataGasUsed)
        assert error == nil
        assert sender.code.length > 0
    }

    senderInput := ABI.encodeWithSelector('validateTransaction', tx, tx.hash);
    callbackParamsSender, error := evm.Call(
        from: AA_ENTRY_POINT,
        to: sender,
        input: senderInput,
        gas: validationGasLimit - retDeployer.gasUsed)
    assert error == nil
    assert callbackParamsSender != nil
    assert Date.now() <= callbackParamsSender.validUntil
    assert Date.now() >= callbackParamsSender.validAfter
    assert callbackParamsSender.isValidAuthorizationData

    if (paymaster != address(0)) {
        paymasterInput := ABI.encodeWithSelector('validatePaymasterTransaction', tx, tx.hash)
        callbackParamsPaymaster, error := evm.Call(
            from: AA_ENTRY_POINT,
            to: paymaster,
            input: paymasterInput,
            gas: paymasterValidationGasLimit)
        assert error == nil
        assert callbackParamsPaymaster != nil
        assert Date.now() <= callbackParamsPaymaster.validUntil
        assert Date.now() >= callbackParamsPaymaster.validAfter
        assert callbackParamsPaymaster.isValidAuthorizationData
    }
}

为了防御 DoS 攻击向量,区块构建者应考虑 ERC-7562 中描述的操作码禁止和存储访问规则。

块验证的工作量大致与没有 AA 交易时相同。在任何情况下,验证必须执行整个区块以验证状态更改。在执行过程中,当前会验证签名、nonce 和Gas支付。通过账户抽象,它也将验证所有验证帧是否成功。所需的内存仅略有增长,主要用于存储从支付方验证帧传递到其事务后帧的 context 值。

只要所有交易验证步骤成功执行并提供正确值到其 AA_ENTRY_POINT 回调,则该块被视为有效。愿意放宽对验证帧应用的规则的区块构建者可以这样做。

交易流程图

放大单个交易,AA 交易的验证部分可能包括多个执行帧:

在区块内的单个原生账户抽象交易中的帧

交易有效性时间范围参数

支付方验证帧发送方验证帧 各自提供 validUntilvalidAfter 的值。

这些值允许 senderpaymaster 合约指定该交易将在何时有效的区块时间范围。

交易不能被包含在超出此时间范围的区块中。如果被包含,该区块将被视为无效。

传递 validUntil = 0validAfter = 0 将禁用检查。

计算 AA_TX_TYPE 交易哈希

keccak256(AA_TX_TYPE || 0x00 || rlp(transaction_payload)

请注意,chainIdaccessListauthorizationList 参数被包含在交易哈希计算中,但在链上并不可用,作为 TransactionTypeRIP7560 结构的一部分。

为了计算交易哈希,在签署交易和验证交易签名时,authorizationData 参数的值被视为一个空的字节数组。

理由

在核心 EIP 中使用 Solidity 方法选择器

与此账户抽象提案相关的合约,例如 senderpaymaster,必须知道要执行哪些代码并理解提供给它们的 calldata,以便验证交易。

我们认为,最直接的实现是依赖 Solidity 的 4 字节方法选择器,因为这是公认的事实标准。

AA_SENDER_CREATOR 地址调用 deployer

重要的是,deployer 不是从 AA_ENTRY_POINT 调用,而是从 AA_SENDER_CREATOR 调用。这是必要的,以确保 AA_ENTRY_POINT 永远不会在未先完成成功验证的情况下调用 sender 执行函数。

没有这种保护,因为我们不控制 deployerData 字段,它可能会构造得看起来像是来自 AA_ENTRY_POINTsender 的合法调用。

使用 AA_ENTRY_POINT 批准回调

在智能合约上下文中,成功的验证帧执行会导致交易的Gas支付。重要的是要防止任何不知情的合约被欺骗“接受” RIP-7560 交易验证,从而可能导致此合约被抽干。

为此,我们要求指定的调用到 AA_ENTRY_POINT 地址以表明 RIP-7560 交易的接受。

对于 authorizationData 检查失败的使用 sigFailAccountsigFailPaymaster

如果一个账户或支付方在各自的验证帧中可以验证交易的所有相关细节,但交易的 authorizationData 不正确,则会调用此回调。

此回调在Gas估算期间使用,有助于钱包和应用程序在生成任何真正的签名之前确定验证过程所用的Gas量。预计交易在用有效的 authorizationData 更新后将消耗相同数量的Gas。

系统交易事件

这些事件是 ERC-4337 中由 EntryPoint.sol 合约发出的事件的等效物。它们提供了一组通过现有以太坊 API 通常无法获得的功能。

其中包括能够获取由给定的 senderpaymasterfactory 发起的最新交易的能力,以及观察发生在已包含交易上的交易回退原因。

现有的 ERC-4337 基础设施很可能依赖这些事件以实现其基本功能,因此我们在 RIP-7560 中也保留这些事件。

向后兼容性

该 EIP 保留了 ERC-4337 大部分设计元素。这允许在最低程度或没有修改的情况下在两个系统中使用相同的客户端代码和智能合约,同时提供显著的用户体验改进。

现有合约不受此变化的重大影响。假设 tx.origin 被保证为 EOA 的假设不再有效。假设 tx.origin 是支付当前交易的地址的假设也不再有效。

任何期望以太坊交易有单个顶级执行帧的代码都必须适应新的交易类型。

EIP-3607 引入了一项禁令,禁止从已部署代码的发送者那里进行交易。此限制不适用于 AA_TX_TYPE 交易。

现有 ERC-4337 项目及后续路线图的迁移路径

现有的打包者可以在网络上共同存在

ERC-4337 不是协议变化,可以与此 EIP 永久平行运行。由于与 ERC-4337 的相似性,相同的区块构建者可以轻松支持 ERC-4337 和 AA_TX_TYPE 交易。

账户需要将其 EntryPoint 升级到适配器合约

ERC-4337 背后的团队将提供一个参考实现,该合约将转换 paymastersender 合约的 ABI。此适配器可由 ERC-4337 合约设为受信任的 EntryPoint 地址。

作为兼容层支持 ERC-4337 RPC 调用

在过渡期间,sender 合约可能支持 ERC-4337 和 AA_TX_TYPE 交易,只要某些链可能采用此 EIP,而另一些链则不采用。

安全考虑

此 EIP 创建了一种复杂和复杂的机制,旨在扩展智能合约账户的使用。所有这一切都带来了很多新的风险向量和攻击面。

以下是已知的原生账户抽象的一些非详尽的安全考虑列表。

直接向合约余额收费

此 EIP 增加了一种新的方式,智能合约可以通过有效的回调调用来简单地收费,只需使用符合 validateTransactionvalidatePaymasterTransaction 的方法 ID 的函数调用 AA_ENTRY_POINT 地址。

这给意外或恶意包含此类方法但未公开这些合约可用作 AA_TX_TYPE 交易中的 senderpaymaster 的合约带来了新的风险。

通过要求这些合约在 AA_ENTRY_POINT 地址上调用 acceptAccountacceptPaymaster 回调来缓解此问题,使合约与 AA_ENTRY_POINT 地址的交互变得显式。

代码审查人员应了解 RIP-7560 交易的这一特性。

在验证帧中观察回退原因

现有的交易类型会在回退时也包含在一个区块中,并提供回退原因供调试用途。薄弱错误通知的现象包括:

  • 低Gas费用
  • 余额不足
  • 无效的nonce
  • 审查

这不是发生在 AA_TX_TYPE 交易的验证阶段中的回退的情况。为此,开发人员应跟踪正在签署的这些交易的有效性,并鼓励依赖 validUntil 时间范围参数,确保未按预定时间包含的交易不会意外地再次变为有效。

对区块构建者的拒绝服务攻击

重要的是要考虑区块构建者在规定时间内填充区块的能力。

就区块有效性而言,在区块中包含时,所有验证和 RIP-7560 执行调用帧都可以读取和写入任何状态。这意味着交易在技术上能够使彼此无效。

区块构建者可能面临因包含单个交易而使多个合格交易无效的风险,导致拒绝服务。顺序块构建者只要按接收顺序处理进入的交易,就不会有这样的风险。

作为缓解措施,AA 交易应受限于存储访问规则,以避免对区块构建者的 DoS。这些规则在 ERC-7562 中定义。

充分缓解可以通过将验证与分离到另一上下文中实现,具体参见 RIP-7711

原子 "验证与执行" 回退函数

我们建议智能合约账户开发人员确保用户能够控制其账户,即使 AA_TX_TYPE 交易因任何原因变得不可用。

这可以通过提供一个公共函数来轻松实现,该函数包括对智能合约账户的验证和执行处理程序的调用。

版权

通过 CC0 放弃版权和相关权利。

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

0 条评论

请先 登录 后评论
ethereum
ethereum
江湖只有他的大名,没有他的介绍。