以太坊 - [EIP-4788]: https://learnblockchain.cn/docs/eips/EIPS/eip-4788 - Layr-Labs

本文档详细介绍了 EigenPod 合约,它允许用户(Pod Owner)通过 restake beacon chain 验证器来赚取收益。

EigenPod

文件 类型 代理
EigenPod.sol 实例化的,每个用户部署一个 信标代理

EigenPod 通过 EigenPodManager 由 Staker (在本文档中称为 Pod Owner) 部署。EigenPods 允许 Pod Owner 重新质押一个或多个信标链验证器,获得可以委托给 Operator 以赚取收益的份额。当 Pod Owner 开始在信标链上运行验证器时,他们为该验证器选择提款凭证。提款凭证是 ETH 地址,该地址用于:

  • 当验证器退出信标链时,验证器的本金将被发送到该地址
  • 当验证器在信标链上提案/证明区块时,验证器的共识奖励将被发送到该地址

此外,在运行验证器节点软件时,验证器会配置一个费用接收者。费用接收者接收:

  • 当验证器提出区块时,接收执行层奖励
  • 如果验证器运行 MEV-boost/其他自定义区块提议者软件,则接收 MEV 奖励

EigenPod 可以用作验证器的提款凭证或费用接收者,或者两者都用作。 在之前的版本中,只能使用 EigenPod 作为提款凭证。但是,现在情况已经改变!

EigenPod 支持具有 0x01 和 0x02 提款凭证的验证器,以及高达(及超过)2048 ETH 的验证器。

有关 EigenPod 设计的更多背景和历史信息,请查看 这个 HackMD


EigenPod 系统的主要目标确保份额得到 1:1 的 ETH 支持,这些 ETH 要么已经在 EigenPod 中,要么最终会流经 EigenPod。** 为了支持这一目标,EigenPod

  • 充当由 Pod Owner 控制的一个或多个信标链验证器的提款凭证
  • 验证信标链状态证明
  • 解释这些证明以在信标链 ETH 策略中添加或删除份额

由于信标链证明与信标链本身异步处理,因此信标链上的事件与任何受影响的 EigenPod 中相应的份额更新之间存在固有的滞后。 因此,EigenPod 系统的 次要目标尽可能地减少滞后,并 确保各种时间窗口不会 (i) 创建无支持的份额或 (ii) 阻止现有份额的提取。**

高级概念

重要定义

Pod Owner: 部署了 EigenPod 的 Staker 称为 Pod Owner。这两个术语在本文档中可以互换使用。

  • Pod Owner 只能部署一个 EigenPod,但可以从同一个 EigenPod 重新质押任意数量的信标链验证器。
  • Pod Owner 可以将其 EigenPodManager 份额委托给 Operator(通过 DelegationManager)。
  • 这些份额对应于 Pod Owner 通过其 EigenPod 持有的重新质押的信标链 ETH 的数量。

证明提交者: 由 Pod Owner 指定的地址,具有调用某些 EigenPod 方法的权限。提供此角色是为了允许 Pod Owner 通过热钱包管理其日常 EigenPod 任务,而不是控制所有资金的 Pod Owner 地址。证明提交者可以调用多个 EigenPod 方法。有关更多详细信息,请参阅 setProofSubmitter 文档

活跃验证器集: 此术语在本文档中经常使用,用于描述提款凭证已验证为指向 EigenPod 的验证器集。活跃验证器集 用于确定完成检查点所需的证明数量(请参阅 检查点验证器)。

  • 当验证器的提款凭证得到验证时,验证器进入 活跃验证器集(请参阅 verifyWithdrawalCredentials
  • 当检查点证明表明它们的余额为 0 时,验证器离开 活跃验证器集(请参阅 verifyCheckpointProofs

在实现中,活跃验证器集 由两个状态变量组成:

  • uint256 activeValidatorCount
    • 当验证器进入 活跃验证器集 时,递增 1
    • 当验证器离开 活跃验证器集 时,递减 1
  • mapping(bytes32 => ValidatorInfo) _validatorPubkeyHashToInfo (具体来说,是 status 字段)
    • 进入 活跃验证器集 时,VALIDATOR_STATUS.INACTIVE -> VALIDATOR_STATUS.ACTIVE
    • 离开 活跃验证器集 时,VALIDATOR_STATUS.ACTIVE -> VALIDATOR_STATUS.WITHDRAWN

检查点: EigenPod 和信标链状态的快照,用于根据信标链余额和原生 ETH 余额的组合更新 Pod Owner 的份额。检查点允许 EigenPod 考虑验证器退出、共识奖励的部分提款或其验证器赚取的执行层费用。完成检查点将会在 EigenPod 中计入这些金额,从而使 Pod Owner 能够复投其重新质押的份额或提取累积的收益。

在给定的 EigenPod 中,一次只能有一个 检查点 处于活动状态。pod 的 当前检查点 由以下数据结构表示:

struct Checkpoint {
    bytes32 beaconBlockRoot;      // proofs are verified against a beacon block root
    uint24 proofsRemaining;       // number of proofs remaining before the checkpoint is completed
    uint64 podBalanceGwei;        // native ETH that will be awarded shares when the checkpoint is completed
    int64 balanceDeltasGwei;      // total change in beacon chain balance tracked across submitted proofs
    uint64 prevBeaconBalanceGwei; // total recorded beacon chain balance as of the last checkpoint
}

通过为 pod 的 活跃验证器集 中的每个验证器提交一个信标链证明来完成检查点。有关详细信息,请参阅 检查点验证器


重新质押信标链 ETH

如果 Pod Owner 拥有的验证器的提款凭证是 EigenPod,则 Pod Owner 可以使用 verifyWithdrawalCredentials 开始重新质押 ETH,即使它仍在信标链上。一旦验证器的提款凭证得到验证:

  • Pod Owner 通过 EigenPodManager.podOwnerShares 获得可委托的份额
  • 验证器进入 pod 的 活跃验证器集,并且必须包含在未来的检查点证明中(请参阅 检查点验证器

方法:

verifyWithdrawalCredentials

function verifyWithdrawalCredentials(
    uint64 beaconTimestamp,
    BeaconChainProofs.StateRootProof calldata stateRootProof,
    uint40[] calldata validatorIndices,
    bytes[] calldata validatorFieldsProofs,
    bytes32[][] calldata validatorFields
)
    external
    onlyOwnerOrProofSubmitter
    onlyWhenNotPaused(PAUSED_EIGENPODS_VERIFY_CREDENTIALS)

struct StateRootProof {
    bytes32 beaconStateRoot;
    bytes proof;
}

此方法首先根据 EIP-4788 oracle 返回的信标区块根验证信标状态根。然后,它根据信标状态根验证一个或多个提款凭证证明。最后,根据每个经过验证的验证器的有效余额总和,Pod Owner 将获得份额(通过 EigenPodManager.recordBeaconChainETHBalanceUpdate)。

提款凭证证明使用验证器的 ValidatorIndex 和一个 merkle 证明来证明在给定区块中存在一个 Validator 容器。信标链 Validator 容器包含此方法中使用的重要信息:

  • pubkey:一个 BLS 公钥哈希,用于在 EigenPod 中唯一标识验证器
  • withdrawal_credentials:用于验证验证器是否会在退出信标链时将其本金提取到此 EigenPod。可以具有 0x01 或 0x02 前缀。
  • effective_balance:验证器的余额,每 epoch 更新一次,上限为 32 ETH。用于向 Pod Owner 授予份额
  • activation_epoch:最初设置为 type(uint64).max,当验证器的余额至少达到 32 ETH 时,此值会更新,表示验证器已准备好在信标链上处于活动状态。此方法要求验证器要么已经处于活动状态,要么正在信标链上激活。
  • exit_epoch:最初设置为 type(uint64).max,当验证器启动从信标链退出时,此值会更新。此方法要求验证器尚未启动从信标链退出。
    • 如果验证器在调用 verifyWithdrawalCredentials 之前已退出,则可以通过检查点系统核算、授予份额和/或提取其 ETH(请参阅 检查点验证器)。

请注意,除非你想为信标链上的 ETH 接收份额,否则需要验证你的验证器的提款凭证。 你可以选择在不验证提款凭证的情况下使用你的 EigenPod;你仍然可以通过 检查点系统 提取收益(或接收收益份额)。

效果

  • 对于每组唯一的已验证提款凭证:
    • activeValidatorCount 增加 1
    • 验证器的信息记录在状态中 (_validatorPubkeyHashToInfo[pubkeyHash]):
      • 从传入的 validatorIndices 中记录 validatorIndex
      • restakedBalanceGwei 设置为验证器的有效余额
      • lastCheckpointedAt 设置为 lastCheckpointTimestampcurrentCheckpointTimestamp
      • VALIDATOR_STATUSINACTIVE 变为 ACTIVE
  • 根据证明的有效余额总和,Pod Owner 将获得份额。请参阅 EigenPodManager.recordBeaconChainETHBalanceUpdate

要求

  • 调用者必须是 Pod Owner 或证明提交者
  • 暂停状态不能设置:PAUSED_EIGENPODS_VERIFY_CREDENTIALS
  • 输入数组的长度必须相等
  • beaconTimestamp
    • 必须大于 currentCheckpointTimestamp
    • 必须可以通过 EIP-4788 oracle 查询。通常,这意味着 beaconTimestamp 对应于在过去 8192 个区块(约 27 小时)内创建的有效信标区块。
  • stateRootProof 必须根据 EIP-4788 oracle 返回的 beaconBlockRoot 验证 beaconStateRoot
  • 对于每个验证器:
    • 验证器必须未经过先前验证(VALIDATOR_STATUS 应为 INACTIVE
    • 验证器的 activation_epoch 不能等于 type(uint64).max(又名 FAR_FUTURE_EPOCH
    • 验证器的 exit_epoch 必须等于 type(uint64).max(又名 FAR_FUTURE_EPOCH
    • 验证器的 withdrawal_credentials 必须指向 EigenPod
    • validatorFieldsProof 必须是在给定 validatorIndexbeaconStateRoot 下相应的 validatorFields 的有效 merkle 证明
  • 请参阅 EigenPodManager.recordBeaconChainETHBalanceUpdate

检查点验证器

检查点证明构成了提交给 EigenPod 的大部分证明。完成检查点意味着为 pod 的 活跃验证器集 中的每个验证器提交一个检查点证明。

EigenPods 使用检查点来检测:

  • 验证器何时从信标链退出,离开 pod 的 活跃验证器集
  • pod 何时从验证器累积了费用/部分提款
  • 信标链上的任何验证器的余额是否增加/减少
  • 合并请求何时完成

当检查点完成时,每个事件的份额都会相应更新。OwnedShares 可以通过 DelegationManager 提款队列提取(请参阅 DelegationManager:取消委托和提取),这意味着 EigenPod 的检查点证明在允许 Pod Owner 从系统中退出资金方面也发挥着重要作用。

重要提示:

  • EigenPods 在给定时间只能有一个活跃的检查点,并且一旦开始,检查点无法取消(只能完成)
  • 检查点证明完全基于当前余额证明。即使部分/全部提款是通过检查点证明处理的,此系统也使用提款证明。

方法:

startCheckpoint

function startCheckpoint(bool revertIfNoBalance)
    external
    onlyOwnerOrProofSubmitter() 
    onlyWhenNotPaused(PAUSED_START_CHECKPOINT) 

此方法允许 Pod Owner(或证明提交者)启动检查点,开始证明 pod 的 活跃验证器集 的过程。startCheckpoint 会对以下三件事进行快照:

  • podBalanceGweiEigenPod 的原生 ETH 余额,减去通过先前检查点已计入份额的任何余额
    • 注意:如果 revertIfNoBalance == true,如果 podBalanceGwei == 0,此方法将恢复。这是为了允许 Pod Owner 避免意外创建检查点。
  • activeValidatorCount:pod 的 活跃验证器集 中的验证器数量,又名具有已验证提款凭证并且尚未通过先前检查点证明已退出的验证器数量
    • 这将成为检查点的 proofsRemaining,即需要提交给 verifyCheckpointProofs 以完成检查点的证明数量
  • beaconBlockRoot:前一个 slot 的信标区块根,通过使用当前 block.timestamp 查询 EIP-4788 oracle 来获取
    • 这被用作此检查点提交的所有证明的单一事实来源

startCheckpoint 在检查点过程的安全性中起着非常重要的作用:它保证 pod 的原生 ETH 余额和检查点中证明的任何信标余额是 100% 不同的。也就是说:如果在调用 startCheckpoint 之前的区块中处理了部分/全部退出,则:

  • 提取的 ETH 已经在调用 startCheckpoint 时的 pod 中,并计入 podBalanceGwei
  • 针对 beaconBlockRoot 的验证器当前余额的证明将包括提取的 ETH

此保证意味着,如果我们使用检查点来汇总 pod 的 活跃验证器集 的信标链余额,我们可以根据 pod 的信标链余额及其原生 ETH 余额的总和授予有保证支持的份额

效果

  • currentCheckpointTimestamp 设置为 block.timestamp
  • 创建一个新的 Checkpoint
    • beaconBlockRoot:设置为当前区块的父信标区块根,通过使用 block.timestamp 作为输入查询 EIP-4788 oracle 来获取。
    • proofsRemaining:设置为 activeValidatorCount 的当前值(请注意,此值可能为 0)
    • podBalanceGwei:设置为 pod 的原生 ETH 余额,减去先前检查点中已计入的任何余额
    • balanceDeltasGwei:最初设置为 0
  • 如果 checkpoint.proofsRemaining == 0,则新的检查点会自动完成:
    • withdrawableRestakedExecutionLayerGwei 增加 checkpoint.podBalanceGwei
    • lastCheckpointTimestamp 设置为 currentCheckpointTimestamp
    • 删除 currentCheckpointTimestamp_currentCheckpoint
    • 更新 Pod Owner 的份额(请参阅 EigenPodManager.recordBeaconChainETHBalanceUpdate

要求

  • 调用者必须是 Pod Owner 或证明提交者
  • 暂停状态不能设置:PAUSED_START_CHECKPOINT
  • 检查点不能处于活动状态(currentCheckpointTimestamp == 0
  • 完成的最后一个检查点不能在当前区块中启动(lastCheckpointTimestamp != block.timestamp
  • 如果 revertIfNoBalance == true,pod 的原生 ETH 余额必须包含一些尚未在 Pod Owner 的份额中计入的非零值

verifyCheckpointProofs

function verifyCheckpointProofs(
    BeaconChainProofs.BalanceContainerProof calldata balanceContainerProof,
    BeaconChainProofs.BalanceProof[] calldata proofs
)
    external 
    onlyWhenNotPaused(PAUSED_EIGENPODS_VERIFY_CHECKPOINT_PROOFS) 

struct BalanceContainerProof {
    bytes32 balanceContainerRoot;
    bytes proof;
}

struct BalanceProof {
    bytes32 pubkeyHash;
    bytes32 balanceRoot;
    bytes proof;
}

verifyCheckpointProofs 用于在 pod 的当前检查点上取得进展(或完成)。此方法接受验证器针对 balanceContainerRoot 的当前余额的一个或多个 merkle 证明。此外,balanceContainerProof 针对当前检查点 的 beaconBlockRoot 验证此 balanceContainerRoot

提交给此方法的证明涉及验证器的当前余额,而不是他们的有效余额。 加粗当前余额每 slot 更新一次,而有效余额大约每 epoch 更新一次。当前余额存储在 BeaconState.balances 字段 中。

对于通过 proofs 提交的每个验证器:

  • 验证器的 status 应为 ACTIVE。也就是说,它的提款凭证已验证(请参阅 verifyWithdrawalCredentials),并且截至上次在检查点证明中看到它时,它具有非零余额。
  • 验证器的 lastCheckpointedAt 应小于 currentCheckpointTimestamp。这是为了防止验证器对检查点的进度计数超过一次。

如果这两个条件中的任何一个未得到满足,证明将被跳过,但执行将继续。执行继续而不会恢复,以防止潜在的恶意向量,即任何人都可以抢先提交一批证明,从该批次提交一个证明,并导致该批次恢复。

每个提交的有效证明都会将当前检查点 的 proofsRemaining 减少 1。如果 proofsRemaining 达到 0,则会自动完成检查点,并相应地更新 Pod Owner 的份额。

效果

  • 更新存储中的 _currentCheckpoint
  • 对于每个成功检查点化的验证器:
    • 检查点中剩余的证明数量减少(checkpoint.proofsRemaining--
    • 使用验证器先前的 restakedBalanceGwei 计算余额增量。此增量被添加到 checkpoint.balanceDeltasGwei 以跟踪信标链余额总增量。
    • 更新验证器的 restakedBalanceGweilastCheckpointedAt 字段。此外,如果证明表明验证器的余额为 0,则验证器的状态将更改为 VALIDATOR_STATUS.WITHDRAWN,并且 pod 的 activeValidatorCount 会减少。
  • 如果检查点的 proofsRemaining 降至 0,则会自动完成检查点:
    • checkpoint.podBalanceGwei 被添加到 withdrawableRestakedExecutionLayerGwei,使其在未来的检查点中被计入
    • lastCheckpointTimestamp 设置为 currentCheckpointTimestampcurrentCheckpointTimestamp 设置为 0。
    • Pod Owner 的总份额增量计算为 checkpoint.podBalanceGweicheckpoint.balanceDeltasGwei 的总和,并转发到 EigenPodManager(请参阅 EigenPodManager.recordBeaconChainETHBalanceUpdate

要求

  • 暂停状态不能设置:PAUSED_EIGENPODS_VERIFY_CHECKPOINT_PROOFS
  • 检查点当前必须处于活动状态(currentCheckpointTimestamp != 0
  • balanceContainerProof 必须包含针对 _currentCheckpoint.beaconBlockRoot 的信标链余额容器的有效 merkle 证明
  • proofs 中的每个 proof 必须包含针对 balanceContainerProof.balanceContainerRoot 的验证器的 balanceRoot 的有效 merkle 证明

过时证明

定期检查点验证器在系统的健康运行中起着重要作用,因为完成的检查点可确保 pod 的份额和支持资产是最新的。

通常,检查点只能由 Pod Owner 启动(请参阅 startCheckpoint)。这是因为完成具有大量验证器的检查点可能是一项昂贵的操作,因此将 startCheckpoint 限制为只能由 Pod Owner 调用可防止恶意向量,即任何人都可以廉价地强制 Pod Owner 执行检查点。

在大多数情况下,Pod Owner 有动力执行自己的定期检查点,因为完成检查点是访问发送到 pod 的收益的唯一方法。但是,如果信标链验证器被削减,则 Pod Owner 可能不再有动力启动/完成检查点。毕竟,他们会损失等于削减金额的份额。除非他们在 pod 中有足够的未声明收益来弥补这一点,否则他们只会因完成检查点而损失。

在这种情况下,可以使用 verifyStaleBalance 允许第三方代表 Pod Owner 启动检查点。

方法:

verifyStaleBalance

function verifyStaleBalance(
    uint64 beaconTimestamp,
    BeaconChainProofs.StateRootProof calldata stateRootProof,
    BeaconChainProofs.ValidatorProof calldata proof
)
    external
    onlyWhenNotPaused(PAUSED_START_CHECKPOINT) 
    onlyWhenNotPaused(PAUSED_VERIFY_STALE_BALANCE)

允许任何人证明 pod 的 活跃验证器集 中的验证器已在信标链上被削减。成功的证明允许调用者启动检查点。请注意,如果 pod 当前具有活动检查点,则需要先完成现有检查点,然后 verifyStaleBalance 才能启动检查点。

有效证明具有以下要求:

  • beaconTimestamp 必须比验证器上次检查点的时间戳更新
  • 有问题的验证器必须在 活跃验证器集 中(具有状态 VALIDATOR_STATUS.ACTIVE
  • 证明必须表明验证器已被削减

如果满足这些要求并且证明对于 beaconTimestamp 给出的信标区块根有效,则会启动检查点。

效果:

  • currentCheckpointTimestamp 设置为 block.timestamp
  • 创建一个新的 Checkpoint
    • beaconBlockRoot:设置为当前区块的父信标区块根,通过使用 block.timestamp 作为输入查询 EIP-4788 oracle 来获取。
    • proofsRemaining:设置为 activeValidatorCount 的当前值
    • podBalanceGwei:设置为 pod 的原生 ETH 余额,减去先前检查点中已计入的任何余额
    • balanceDeltasGwei:最初设置为 0

要求:

  • 暂停状态不能设置:PAUSED_START_CHECKPOINT
  • 暂停状态不能设置:PAUSED_VERIFY_STALE_BALANCE
  • 检查点不能处于活动状态(currentCheckpointTimestamp == 0
  • 最后一个完成的检查点不能是当前区块
  • 对于由 proof.validatorFields 给出的验证器:
    • beaconTimestamp 必须大于 validatorInfo.lastCheckpointedAt
    • validatorInfo.status 必须为 VALIDATOR_STATUS.ACTIVE
    • proof.validatorFields 必须表明验证器被削减
  • stateRootProof 必须根据 EIP-4788 oracle 返回的 beaconBlockRoot 验证 beaconStateRoot
  • ValidatorProof 必须包含在 validatorInfo.validatorIndexbeaconStateRoot 下相应的 validatorFields 的有效 merkle 证明

合并和提款

与 Pectra 中引入的预部署交互的方法。请参阅 此处 的补充文档:

requestConsolidation

/// SEE FULL METHOD DOCS IN IEigenPod.sol
// 请参阅 IEigenPod.sol 中的完整方法文档
function requestConsolidation(
    ConsolidationRequest[] calldata requests
) external payable onlyOwnerOrProofSubmitter;

/**
 * @param srcPubkey the pubkey of the source validator for the consolidation
 * @param targetPubkey the pubkey of the target validator for the consolidation
 * @dev Note that if srcPubkey == targetPubkey, this is a "switch request," and will
 * change the validator's withdrawal credential type from 0x01 to 0x02.
 * 注意:如果 srcPubkey == targetPubkey,则这是一个“切换请求”,会将验证器的提款凭证类型从 0x01 更改为 0x02。
 * For more notes on usage, see `requestConsolidation`
 * 有关使用方法的更多说明,请参阅 `requestConsolidation`
 */
struct ConsolidationRequest {
    bytes srcPubkey;
    bytes targetPubkey;
}

/// @notice Returns the fee required to add a consolidation request to the EIP-7251 predeploy this block.
// 返回在此区块中将合并请求添加到 EIP-7251 预部署所需的费用。
/// @dev Note that the predeploy updates its fee every block according to https://learnblockchain.cn/docs/eips/EIPS/eip-7251#fee-calculation
// 请注意,预部署根据 https://learnblockchain.cn/docs/eips/EIPS/eip-7251#fee-calculation 每区块更新其费用
/// Consider overestimating the amount sent to ensure the fee does not update before your transaction.
// 考虑高估发送的金额,以确保费用在你的交易之前不会更新。
function getConsolidationRequestFee() external view returns (uint256);

此方法允许 pod 所有者或证明提交者通过 EIP-7521 预部署提交验证器合并请求。合并请求有两种形式:

  • “切换请求”会将验证器的提款凭证从 0x01 “eth1”前缀切换到 0x02 “复利”前缀。对于切换请求,srcPubkey == targetPubkey
  • 标准请求会将源验证器的余额合并_到_目标 0x02 验证器中。对于标准请求,srcPubkey != targetPubkey

要启动合并请求(基本操作指南在此):

  • 预部署需要为每个请求支付费用。可以使用 getConsolidationRequestFee 查询该区块的当前费用。这应该对于传入的 requests 数组中的每个请求进行乘法运算,并作为 msg.value 提供。预部署每个区块都会根据排队的合并请求数量与处理的合并请求数量来更新其费用。
    • 请注意,在方法的最后,任何未使用的费用都会转移回 msg.sender
  • target 验证器必须具有已验证的提款凭证(getValidatorStatus 返回 ACTIVE
  • 对于标准请求,target 验证器必须在信标链上具有 0x02 提款凭证。

当标准合并在信标链上完成时,源验证器的余额将转移到目标验证器。对于所有意图和目的,源验证器将显示为“已退出” - 其退出 epoch 和可提取 epoch 已设置,并且其余额降至零。当由检查点处理时,此 0 余额将导致验证器标记为 WITHDRAWN,从而免除其在未来的检查点证明中出现。

请注意,信标链可能会由于多种原因“跳过”合并请求。这种跳过对于 EigenPod 本质上是不可见的。有关可能导致请求被跳过的所有条件的完整列表,请参阅 process_consolidation_request 规范

效果

  • 将每个 request 排队到 EIP 7521 预部署中,每次发送当前的合并请求费用。
  • 如果提供了过多的 msg.value,则将剩余部分转移回 msg.sender

要求

  • 调用者必须是 Pod Owner 或证明提交者
  • 暂停状态不能设置:PAUSED_CONSOLIDATIONS
  • msg.value 必须至少为 getConsolidationRequestFee() * requests.length
  • 对于 requests 中的每个 request
    • request.srcPubkeyrequest.targetPubkey 必须具有 48 的长度
    • request.targetPubkey 必须对应于提款凭证已证明指向 pod 的验证器(VALIDATOR_STATUS.ACTIVE
  • 如果提供了过多的 msg.value,则必须成功将多余的金额转移回 msg.sender

requestWithdrawal

/// SEE FULL METHOD DOCS IN IEigenPod.sol
// 请参阅 IEigenPod.sol 中的完整方法文档
function requestWithdrawal(
    WithdrawalRequest[] calldata requests
) external payable onlyOwnerOrProofSubmitter;

/**
 * @param pubkey the pubkey of the validator to withdraw from
 * 要从中提取的验证器的公钥
 * @param amountGwei the amount (in gwei) to withdraw from the beacon chain to the pod
 * 要从信标链提取到 pod 的金额(以 gwei 为单位)
 * @dev Note that if amountGwei == 0, this is a "full exit request," and will fully exit
 * 注意:如果 amountGwei == 0,则这是一个“完全退出请求”,将完全退出
 * the validator to the pod.
 * 验证器到 pod。
 * For more notes on usage, see `requestWithdrawal`
 * 有关使用方法的更多说明,该方法允许 pod 所有者或证明提交者通过 [EIP-7002](https://learnblockchain.cn/docs/eips/EIPS/eip-7002) 预部署提交验证者提款请求。提款请求有两种形式:
* “完全提款”将使验证者完全退出信标链。对于完全提款,`request.amountGwei == 0`。
* “部分提款”将从信标链中退出验证者余额的一部分,最低降至 32 ETH。任何请求的金额将导致验证者的余额低于 32 ETH 都会被忽略。

为了发起提款请求:
* 预部署需要为每个请求支付费用。可以使用 `getWithdrawalRequestFee` 查询当前区块的费用。这应该乘以传入的 `requests` 数组中的每个请求,并作为 `msg.value` 提供。预部署会根据排队的提款请求与已处理的提款请求的数量,每个区块更新其费用。
    * 请注意,任何未使用的费用都会在此方法结束时转回给 `msg.sender`。
* 对于部分提款,请注意,只有当验证者具有 0x02 提款凭证时,信标链才会处理这些提款。

当提款请求在信标链上完成时,请求的金额将从验证者的信标链余额中扣除,并退出到 pod。请注意,在任何时候,部分提款请求都不会导致验证者的余额低于 32 ETH。如果你计划使用请求来跟踪已提取的余额,这一点尤其重要:**你请求的金额可能不等于提取的金额**。例如,我的验证者有 33 ETH,我请求提取 2 ETH,则提款请求只会导致提取 1 ETH。

请注意,信标链可能会因多种原因“跳过”提款请求。这种跳过对于 `EigenPod` 来说本质上是不可见的。有关可能导致请求被跳过的完整条件列表,请参见 [`process_withdrawal_request` 规范](https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/beacon-chain.md#new-process_withdrawal_request)。

**最后,** 请注意,如果验证者有通过此预部署发起的待处理的部分/完全提款,那么在这些请求完成之前,它将**没有资格**成为标准合并中的**来源**验证者。对于**目标**验证者,没有这样的要求。

*效果*:
* 在 EIP 7002 预部署中对每个 `request` 进行排队,每次发送当前提款请求费用。
* 如果提供了过多的 `msg.value`,则将剩余部分转回给 `msg.sender`。

*要求*:
* 调用者必须是 Pod 所有者或证明提交者
* 暂停状态不能设置:`PAUSED_WITHDRAWAL_REQUESTS`
* `msg.value` 必须至少为 `getWithdrawalRequestFee() * requests.length`
* 对于 `requests` 中的每个 `request`:
    * `request.pubkey` 的长度必须为 48
* 如果提供了过多的 `msg.value`,则必须成功将多余的部分转回给 `msg.sender`。

---

### 其他方法

不适合其他部分的小方法:
* [`setProofSubmitter`](#setproofsubmitter)
* [`stake`](#stake)
* [`withdrawRestakedBeaconChainETH`](#withdrawrestakedbeaconchaineth)
* [`recoverTokens`](#recovertokens)

#### `setProofSubmitter`

```solidity
function setProofSubmitter(address newProofSubmitter) external onlyEigenPodOwner

允许 Pod 所有者更新 EigenPod 的证明提交者地址。证明提交者是一个辅助地址,可以调用各种与验证者和证明相关的 EigenPod 方法,但在 EigenPod 合约之外没有权限(例如,此地址无法通过 DelegationManager 管理委托或排队提款)。

此方法/角色旨在允许 Pod 所有者创建一个热钱包来执行与验证者和证明相关的任务,而无需暴露对资金的访问权限。

如果设置,Pod 所有者或证明提交者都可以调用:

  • verifyWithdrawalCredentials
  • startCheckpoint
  • requestConsolidation
  • requestWithdrawal

Pod 所有者可以使用 newProofSubmitter == 0 调用此方法以删除当前的证明提交者。如果没有指定的证明提交者,则只有 Pod 所有者可以调用上述方法。

效果

  • proofSubmitter 更新为 newProofSubmitter

要求

  • 调用者必须是 Pod 所有者

stake

function stake(
    bytes calldata pubkey,
    bytes calldata signature,
    bytes32 depositDataRoot
)
    external 
    payable 
    onlyEigenPodManager

处理对信标链存款合约的调用。仅通过 EigenPodManager.stake 调用。

请注意,此方法仅支持存入 0x01 提款凭证。对于 0x02 凭证,pod 所有者应直接与存款合约交互。

效果

  • 将 32 ETH 存入信标链存款合约,并将 pod 的地址作为存款的提款凭证提供

要求

  • 调用者必须是 EigenPodManager
  • 调用值必须为 32 ETH
  • 给定提供的 pubkeysignaturedepositDataRoot,存款合约的 deposit 方法必须成功

withdrawRestakedBeaconChainETH

function withdrawRestakedBeaconChainETH(
    address recipient, 
    uint256 amountWei
)
    external 
    onlyEigenPodManager

当以 tokens(原生 ETH) 形式提取 Pod 所有者的份额时,EigenPodManager 会调用此方法。输入 amountWei 将转换为 Gwei,并从 withdrawableRestakedExecutionLayerGwei 中扣除,withdrawableRestakedExecutionLayerGwei 跟踪已在检查点中核算的原生 ETH 余额(请参见 检查点验证者)。

如果 EigenPod 没有可用于转移的 amountWei,则此方法将恢复。

请注意,如果 amountWei 不是一个完整的 gwei 金额,则子 gwei 部分将被截断,并且可能无法恢复。

效果

  • 将 pod 的 withdrawableRestakedExecutionLayerGwei 减少 amountWei / GWEI_TO_WEI
  • amountWei 转换为 gwei,然后将该金额发送给 recipient

要求

  • amountWei / GWEI_TO_WEI 必须不大于经过验证的 withdrawableRestakedExecutionLayerGwei
  • Pod 必须至少具有 amountWei ETH 余额
  • recipient 在转移 amountWei 时不得恢复

recoverTokens

function recoverTokens(
    IERC20[] memory tokenList,
    uint256[] memory amountsToWithdraw,
    address recipient
) 
    external 
    onlyEigenPodOwner 
    onlyWhenNotPaused(PAUSED_NON_PROOF_WITHDRAWALS)

允许 Pod 所有者挽救意外发送到 EigenPod 的 ERC20 tokens。

效果:

  • tokenList 中的每个 ERC20 调用 transfer,将相应的 amountsToWithdraw 发送给 recipient

要求:

  • 调用者必须是 Pod 所有者
  • 暂停状态不能设置:PAUSED_NON_PROOF_WITHDRAWALS
  • tokenListamountsToWithdraw 必须具有相同的长度
  • 原文链接: github.com/Layr-Labs/eig...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

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