该提案(ELIP-002)概述了一项升级,旨在通过惩罚(即削减)未能正确运行服务的运营商,加强 AVS 可以对其用户做出的可信承诺。
作者 | Matt Nelson, Yash Patil, Matt Curtis, Gautham Anant, Brett Palatiello, Bowen Li |
---|---|
创建时间 | 2024 年 12 月 12 日 |
状态 | 已合并 |
参考 | Slashing 功能分支 |
讨论 | 研究论坛帖子 |
EigenLayer 是一个让协议参与者相互做出可信承诺的平台。在 EigenLayer 上,AVS 拥有对其终端用户做出经济承诺的工具,例如由 Operator 运行的代码的正确或公平执行。通过 奖励 v2,EigenLayer 使 AVS 能够在 AVS 的服务得到正确运行时向 Operator 和 Staker 发放奖励(胡萝卜)。通过此 Slashing 升级,EigenLayer 将使 AVS 能够在可证明其正确运行服务的承诺被打破的情况下削减 stake(大棒)。
本提案概述了一项升级,通过惩罚(即 slashing)未能正确运行其服务的 Operator 来加强 AVS 可以对其用户做出的可信承诺。这些承诺由 AVS 设计和部署,范围可以从诸如不正确的计算、活性失败等故障。明确地说,此升级增加了两个新功能以促进 slashing 机制:唯一 Stake 和 Operator 集。
唯一 Stake 保证,Operator 的特定可slash stake 在特定时间只能分配给一个 AVS。这种单一配对可以加强 AVS 的安全性,而不会对其他 AVS 或整个协议产生外生风险。Operator 集提供了一种协议内结构,该结构将 Operator 的分割封装到本地组中,以用于 stake 安全的核算、分配和 slashing。
这些功能共同实现:
通过唯一 Stake 和 Operator 集,Operator 可以根据其可接受的风险和能力对可slash stake 进行细粒度的控制。这些解锁了 slashing,slashing 解锁了 AVS 的创造力,而解锁 AVS 的创造力使他们能够接触到用户并奖励 Staker 和 Operator。
Eigen Labs 提议启动具有唯一 Stake 和 Operator 集的 Slashing。Slashing 是启动 EigenLayer 经济飞轮的关键。Slashing 条件允许 AVS 向其用户做出加密经济承诺,即如果 Operator 不诚实或不正确地完成任务,将受到惩罚。同样,AVS 需要一种手段来奖励 Operator 和 Staker,因为实时 slashing 条件会对 stake 资产施加额外的 slashing 风险。
EigenLayer 安全模型的第一个迭代允许每个 Operator 选择加入 AVS 的一个子集,他们的整个委托 stake 可以被任何这些 AVS slash。这带来了一些挑战:Operator 对 slashing 风险的控制有限,AVS 无法保证在需要时访问可slash stake,需要一个全局协议否决委员会来减轻系统性 slashing 风险,并且必须允许 AVS 加入以避免将否决委员会暴露于法律或社会风险。为了解决这些问题,该协议需要像 唯一安全模型 中的唯一 Stake 这样的初始解决方案,以便 Operator 分配专门由特定 AVS slash 的 stake。
AVS 需要唯一 Stake 才能灵活地定义自己的 slashing 条件,而对其他生态系统参与者的影响最小。以前,大规模的许多类型的承诺都缺乏一种机制来提供以太坊 Proof of Stake 中可用的 EVM 执行或直接链上价值转移的无信任保证。当用于保护服务时,EigenLayer 扩展了底层 stake 可以被 slash 的条件;通过 slashing,我们可以扩展 AVS 可以向用户做出的功能性加密经济保证,从而在链上为全新的无信任工作类别和具有加密经济承诺的新颖服务提供动力。
唯一 Stake 需要一个新的核心协议结构来处理其核算,并为其实现中的 Operator、Staker 和 AVS 提供明确的安全保证。Quorum 是 EigenLayer 提供的一种可选工具,用于分割 Operator,但它没有提供必要的协议内保证来强制执行 slashing,也没有减轻级联 slashing 风险。我们认为 Operator 集是它们的演变,也是将此概念植入核心协议的一种手段。
最终,此版本对于将高质量的 Operator 与 AVS 连接起来至关重要。AVS 将拥有更多工具来奖励 Operator 的行为,以诚实和正确地验证服务和协议。
Slashing 释放了 AVS 的创造力,使其能够设计出满足客户需求的协议。此版本为 EigenLayer 创建应用程序基础设施以向其用户做出可信承诺的愿景提供了关键功能。此升级的目标是通过以下方式使所有 EigenLayer 参与者受益:
为了实现这些目标,本提案在 EigenLayer 上引入了以下特定功能:
Operator 集是由 AVS 创建的 Operator 的逻辑和分割集。可以出于 AVS 能够想到的任何原因来拆分这些 Operator 组。AVS 可以将任意“任务”分配给 Operator 集,这些任务可以代表要求 Operator 做的任何事情。任务可以包括计算、证明验证、签名聚合、活性 ping 或完全具有创造性的东西。Operator 集是唯一的组织级别,Operator 在该级别上将唯一 Stake 分配为 AVS 的可slash安全性,并且在发生故障时 AVS 在该级别上 slash stake。
唯一 Stake 是一种在 Operator 集级别上定义的会计工具,可确保 AVS 和 Operator 在处理 stake 安全性和 EigenLayer 上的 slashing 时保持关键的安全属性。唯一 Stake 由 Operator 在选择加入的基础上分配给不同的 Operator 集。只有唯一 Stake 可以被 AVS slash,它代表了 Operator 从 Staker 委托的 stake 的比例。
此升级添加了新的协议接口和原语,用于 Operator 集、唯一 Stake 分配和 Slashing,以提供:
这些是通过引入 AllocationManager
合同和更改 DelegationManager
以使用唯一安全模型来提供的。AVS 中间件合同也已更新。首先,我们将描述 Operator 集,以及它们如何为 Operator 提供对其可slash唯一 Stake 的细粒度、选择加入的控制,以及它们如何为 AVS 提供一些关键保证。
Operator 集功能将 (address avs, uint32 operatorSetId)
对封装为协议的一流原语,Operator 在其中注册和注销。需要 Operator 集才能将唯一 Stake 的保证应用于协议,并将基于承诺的 slashing 带给 AVS。AVS 可以使用它们来区分 Operator,具体取决于独特的业务逻辑、硬件配置文件、活性保证或 stake 组成。Operator 集有助于减少 AVS 基础设施中复杂的中间件代码,简化长期的 AVS 业务逻辑和奖励分配,并为 Staker 和 Operator 提供更多的协议可读性。
作为 AVS,Operator 集解锁了以下能力:
作为 Operator,Operator 集解锁了以下能力:
这种简单的数据结构旨在为 AVS 提供灵活的方式来分割任务、安全性和 Operator 类型。Operator 集在 AllocationManager
核心合同中定义。以下是 Operator 集原语:
struct OperatorSet {
address avs;
uint32 operatorSetId;
}
为了方便读者理解,这些接口通常在整个文档中以代码片段的形式提供。
AVS 通过 AllocationManager
创建新的 Operator 集。如果交易没有回滚,则 Operator 集将成功创建。AVS 可以根据不同的需求创建多个 Operator 集。然后,AVS 可以将特定的策略添加到该 Operator 集(或稍后删除),Operator 将使用这些策略来保护该 Operator 集。AVS 还可以指定一个额外的 AVSRegistrar
合同,该合同将业务逻辑应用于控制 Operator 向 Operator 集的注册。此 AVS 特定的合同可以实现各种自定义逻辑。例如,AVS 可能希望根据 Operator 分配的唯一 Stake 来控制注册,或者创建一个注册队列。
⚠️ 注意
在创建 Operator 集之前,AVS 必须在 EigenLayer 上注册其元数据。更多信息请参见下文。
为了确保社区和激励措施保持一致,通常期望 AVS 进行链下推广,以便在开始注册之前,与他们的 Operator 和 Staker 沟通其 Operator 集的目的和任务/安全构成。这可能包括任何潜在的硬件、软件或 stake 要求。AVS 可以自行决定 Operator 集内的任务分配,无论是基于 stake 还是其他链外方式。例如,AVS 的一个 Operator 集可能需要安全 Enclave 计算用于任务分配和 Operator 注册,而另一个 Operator 集可以在商品硬件上用于一般的证明目的。
为了使 Operator 加入 Operator 集,需要通过 AllocationManager
处理新的注册流程。AVS 和 Operator 都可以控制谁、如何以及何时可以注册 Operator。在 AVS 实例化 Operator 集及其可选的注册商合同后,Operator 可以开始注册过程。该流程遵循下图所示的模式,并在一个或两个交易中完成:
注册 | 注销 |
---|---|
![]() |
![]() |
图 1:上述注册/注销流程与 AVSDirectory
中基于 EIP-1271 的流程不同。
AVS 可能需要一个可选的交易首先分配唯一 Stake 作为注册商合同中的要求的一部分。稍后会详细介绍此分配,但如果该 Operator 集没有可slash stake 要求和/或 slashing 条件,AVS 可能会允许跳过此分配。第二个交易将 Operator 注册到该集合。Operator 成功注册表示他们已上线并准备好接收受该集合的 slashing 条件约束(或没有 slashing 条件)的任务。
注销可用于表示退出 Operator 集,或用于其他情况,例如表示 Operator 不活动期间或无法接收任务。AVS 可以自行决定实施特定的注销逻辑。注销会立即发生,没有延迟。它不会使分配给已注销集合的资金立即变得不可slash。对于 AVS stake 保证,Operator 在 DEALLOCATION_DELAY
期间仍然是可slash的,并且还必须等待该期间过去,然后才能再次注册到同一 Operator 集。Operator 可以通过其他途径使 stake 变得不可slash,例如取消分配和提款。稍后会详细介绍。
AVS 和 Operator 都可以单方面地从 Operator 集中注销。这是通过调用 AllocationManager
来完成的,这将尝试调用 AVS 的注册商合同以向 AVS 发出注销信号。只有在 AllocationManager
和 AVSRegistrar
合同中没有回滚时,才会将注销排队以完成。这是为了防止 AVSRegistrar
合同周围 gas 转发不足的极端情况,并保持一致的存储。Operator 可以通过完全取消分配来消除其对 Operator 集的访问权限。
以下是 AllocationManager 接口:
interface IAllocationManager {
/**
* @notice 允许 Operator 为 AVS 注册一个或多个 Operator 集。如果 Operator 有任何 stake 分配给这些 Operator 集,它会立即变为可slash。
* @dev 在 ALM 中注册后,此方法调用 AVS 注册商的 `IAVSRegistrar.registerOperator` 方法以完成注册。此调用必须成功才能使
* 注册成功。
*/
function registerForOperatorSets(
address operator,
RegisterParams calldata params
) external;
/**
* @notice 允许 Operator 或 AVS 从 AVS 的一个或多个 Operator 集中注销 Operator。
* 如果 Operator 有任何分配给 AVS 的可slash stake,则它仍然是可slash的,直到
* `DEALLOCATION_DELAY` 过去。
* @dev 在 ALM 中注销后,此方法调用 AVS 注册商的 `IAVSRegistrar.deregisterOperator` 方法以完成注销。此调用必须成功才能
* 注销成功。
*/
function deregisterFromOperatorSets(
DeregisterParams calldata params
) external;
/// @notice 分配延迟修改生效之前的延迟。
uint32 public immutable ALLOCATION_CONFIGURATION_DELAY;
/// @notice 清除取消分配并将其添加回 freeMagnitude 之前的延迟
/// 在此窗口中,取消分配仍然可以被分配给它们的 Operator 集 slash。
uint32 public immutable DEALLOCATION_DELAY;
/**
* @notice 由 AVS 调用以配置在 Operator 注册时调用的地址
* 或从 AVS 的 Operator 集中注销。如果未设置(或设置为 0),则默认为
* 到 AVS 的地址。
* @param registrar 新的注册商地址
*/
function setAVSRegistrar(
address avs,
IAVSRegistrar registrar
) external;
/**
* @notice 由 AVS 调用以发出一个 `AVSMetadataURIUpdated` 事件,指示信息已更新。
*
* @param metadataURI 与 AVS 关联的元数据的 URI。
*
* @dev 请注意,`metadataURI` *从未存储*,仅在 `AVSMetadataURIUpdated` 事件中发出。
*/
function updateAVSMetadataURI(
address avs,
string calldata metadataURI
) external;
/**
* @notice 允许 AVS 创建新的 Operator 集,定义 Operator 集使用的策略
*/
function createOperatorSets(
address avs,
CreateSetParams[] calldata params
) external;
/**
* @notice 允许 AVS 将策略添加到 Operator 集
* @dev 策略必须尚未存在于 Operator 集中
* @param avs 要设置策略的 avs
* @param operatorSetId 要添加策略的 Operator 集
* @param strategies 要添加的策略
*/
function addStrategiesToOperatorSet(
address avs,
uint32 operatorSetId,
IStrategy[] calldata strategies
) external;
/**
* @notice 允许 AVS 从 Operator 集中删除策略
* @dev 策略必须已存在于 Operator 集中
* @param avs 要删除策略的 avs
* @param operatorSetId 要从中删除策略的 Operator 集
* @param strategies 要删除的策略
*/
function removeStrategiesFromOperatorSet(
address avs,
uint32 operatorSetId,
IStrategy[] calldata strategies
) external;
}
对 Operator 集中策略的数量、AVS 可以创建的 Operator 集的数量或单个 Operator 集中可以有多少 Operator 没有强制限制。Operator 集中可能存在实际的 gas 成本限制。 例如,当大小变得非常大时,可能无法在单个交易中对 Operator 集中所有 Operator 执行操作。
展望未来,AllocationManager
将处理所有 Operator/AVS 关系。这种新的注册流程取代了 AVSDirectory
中的 M2 流程,但将在一段时间内并行支持。Operator 集将是在协议中编纂 AVS 和 Operator 之间关系的唯一手段。我们建议 AVS 随着设计变得清晰,逐渐使用新的流程将 Operator 注册到 Operator 集。要利用唯一 Stake 和 slashing,将需要 Operator 集注册,但最初是对现有 M2 流程的补充。更多信息请参见原理。
图 2 概述了 Operator 注册到 Operator 集的生命周期:
图 2:Operator 集注册的序列表示
唯一 Stake 是一种机制,用于保证可slash stake 一次只能分配给一个 Operator 集。在推理 EigenLayer slashing 时, 唯一Stake 有益于 Operator 和 AVS,具有以下一些属性:
当 Staker 在 EigenLayer 上存入资产时,它们将存储在称为策略的会计合同中。策略是 EigenLayer 上安全性的不同表达形式。如今,它们代表了委托给 Operator 的不同类型的 restake 资产(例如,Token),AVS 可以利用这些资产来保护其服务和维护加密经济保证。为了使委托可slash,Operator 必须将它们的各个比例分配为 Operator 集的唯一 Stake。分配只能由创建该 Operator 集的 AVS slash。
在下面的图 3 中,Operator 1 具有针对 ETH 策略的 100 个 stake ETH 的委托。然后,Operator 1 将该 ETH 的比例分配为多个 AVS 中 Operator 集内的唯一 Stake。
图 3:分配到 Operator 集
这 85 个分配的 ETH 只能由发起每个 Operator 集的 AVS slash。在这种情况下,AVS 2、3 和 4 可以分别 slash 其关联的 Operator 集 3、4 和 5。
让我们考虑另一个有三个 Operator 的示例。图 4 说明了 AVS 1 实例化的两个 Operator 集。AVS 1 为不同的任务创建了两个 Operator 集。例如,此 AVS 可以使用 Operator 集 1 将 ZK 证明的生成分配给 Operator(这是一项昂贵的计算),而使用 Operator 集 2 来验证这些证明(这是一项更便宜的计算)。
图 4:AVS 唯一的 Stake 示例
Operator 1 已注册到 Operator 集 1,但尚未分配任何唯一 Stake。Operator 2 将其 ETH 委托的 10% 分配给了 Operator 集 1(名义分配为 10 ETH)。这只能由 AVS 1 在 Operator 集 1 中 slash。Operator 2 还将 5% (5 ETH) 分配给了 Operator 集 2,这只能由 AVS 1 在 Operator 集 2 中 slash。
连同 Operator 3 的 20% 分配 (20 ETH) 一起,Operator 集 1 总共有 30 ETH 的唯一 Stake 可用于 slash,并且可以确定它不能在其他地方被 slash。Operator 集 2 的总唯一 Stake 分配为 15 ETH。AVS 1 可能会分发更有价值的任务,并针对 Operator 集 1 进行 slash 和奖励,以利用更多的唯一 Stake。
在协议中,唯一 Stake 通过 AllocationManger
中提供的函数分配给 Operator 集。在 AllocationManager
中,这些分配使用一种称为数量的会计工具进行跟踪。
对于每种策略,Operator 都从协议定义的总数量 1x10^18 (INITIAL_TOTAL_MAGNITUDE
) 开始。此总数量永远不会增加;为了说明 AVS 发起的 slashing 事件,该协议会单调减少被 slash Operator 的策略总数量。Operator 可以使用 modifyAllocations
函数将数量分配给 Operator 集。分配为 Operator 集唯一 Stake 的 Operator 委托的比例等于分配给该 Operator 集的数量除以 Operator 的总数量。对于给定的策略,所有数量分配的总和永远不能大于总数量(比例之和不能超过 100%),从而确保了唯一 Stake 的属性,即没有两个 Operator 集可以 slash 相同的 stake。
以下是 EIGEN 策略的 Operator 数量分配示例。这将在下一部分中扩展。
数量 | 比例 | EIGEN | |
---|---|---|---|
AVS_1_EIGEN |
3,000 | 30% | 30 |
AVS_2_EIGEN |
2,500 | 25% | 25 |
EigenDA_EIGEN |
2,000 | 20% | 20 |
不可slash |
2,500 | 25% | 25 |
总计 |
10,000 | 100% | 100 |
在此示例中,Operator 提交了一个交易,使用 modifyAllocations
函数同时为 Eigen 策略分配给三个 Operator 集。它在 Operator 的 EIGEN 策略中的多个 AVS 中分配了各种数量,并使用了 10,000 的总数量,而不是 1e18 以实现易读性。
分配和取消分配受到协议中某些安全延迟的影响。延迟从协议配置的常量到 Operator 可以添加的自定义约束(用于提高安全性)不等。它们与 AllocationManager
中的其他常量一起实例化:
参数 | 描述 | 值 | 设置器和配置 |
---|---|---|---|
ALLOCATION_CONFIGURATION_DELAY |
Operator 排队 ALLOCATION_DELAY 更改和更改生效之间的块数量。 |
126000 个块(约 17.5 天) | 核心协议:通过治理设置 |
ALLOCATION_DELAY |
Operator 的分配在给定策略的给定 Operator 集中生效所需的块数量。它必须由 Operator 在任何分配之前设置,并且全局应用于所有 Operator 集和策略。该协议对此值没有约束。它可以是任何无符号整数值,并且可以由 Operator 更改。 | 表示块数的无符号整数值 | Operator:通过 AllocationManager 设置 必须设置才能分配 |
DEALLOCATION_DELAY |
Operator 排队从策略的 Operator 集中取消分配 stake 之间以及取消分配生效之间的块数量。此延迟也适用于 Operator 注销 Operator 集,无论是通过他们自己的操作还是 AVS 的操作。 | 100800 个块(约 14 天) | 核心协议:通过治理设置 |
INITIAL_TOTAL_MAGNITUDE |
每个 Operator 的每种策略的单调递减的总数量的初始值。这将设置得足够高,可以从数量分配和 slashing 中获得更高的精度。 | 1e18 | 核心协议:常量,不太可能更改 |
WITHDRAWAL_DELAY |
Staker 排队提款和提款变为不可slash且可完成之间的块数量。 | 100800 个块(约 14 天) | 核心协议:通过治理设置 |
这些是在 EigenLayer 主网上使用的常量或参数。
🧪 注意
在 EigenLayer 测试网部署中,为了便于使用,
ALLOCATION_CONFIGURATION_DELAY
设置为 75 个块(约 15 分钟),DEALLOCATION_DELAY
设置为 50 个块(约 10 分钟)。
在为其第一个 Operator 集分配之前,Operator 需要在 AllocationManager
中设置 ALLOCATION_DELAY
。如果 Operator 是第一次向 EigenLayer 注册,则在注册期间需要提供 ALLOCATION_DELAY
。Operator 的 ALLOCATION_DELAY
最初设置或更新需要花费 ALLOCATION_CONFIGURATION_DELAY
中指定的时间量。这种延迟是为了确保 Staker 有时间适应其委托 Operator 的 stake 分配中的变化。如果分配被认为是不可取的,Staker 可以在 WITHDRAWAL_DELAY
的限制下提取他们的资金。下面捕获了这样做的理由。
AllocationManager
接口处理所有分配和取消分配信号:
interface IAllocationManager {
/**
* @notice 从策略到 Operator 集定义分配信息,用于 Operator
* @param currentMagnitude 从策略分配给 Operator 集的当前数量
* @param pendingDiff 待处理的数量更改(如果存在)(否则为 0)
* @param effectBlock 待处理的数量差异生效的块
*/
struct Allocation {
uint64 currentMagnitude;
int128 pendingDiff;
uint32 effectBlock;
}
/**
* @notice 用于修改 Operator 集可slash数量的分配的结构
* @param operatorSet 要修改分配的 Operator 集
* @param strategies 要修改分配的策略
* @param newMagnitudes 为每个策略分配给此 Operator 集的新数量
*/
struct AllocateParams {
OperatorSet operatorSet;
IStrategy[] strategies;
uint64[] newMagnitudes;
}
/**
@param delay 以块为单位的分配延迟 */ function setAllocationDelay( address operator, uint32 delay ) external;
/**
@dev 更新更新后的策略的 encumberedMagnitude */ function modifyAllocations( address operator, AllocateParams[] calldata params ) external;
/**
numToClear
个取消分配,并根据需要更新操作员的 encumberedMagnitude。
Magnitude 分配只能分配给有效的 Operator Sets,并且只能从不可惩罚的 magnitude 分配。分配在 AllocationManager
中排队,并在 ALLOCATION_DELAY
后自动生效。在 Operator 的 ALLOCATION_DELAY
过去之前,magnitude 不会被分配,即分配不是挂起的。不能从现有的排队分配、已分配给 Operator Set 的 magnitude 或待处理的取消分配中进行额外的 magnitude 分配。
AVS 可以在以下条件下,按照每个策略的 Unique Stake 总分配量,对 Operator 进行惩罚:
取消分配是使 Unique Stake 不可惩罚的主要手段。 Operators 应将对已注册 Operator Set 的分配视为可以随时被惩罚。 例如,AVS 可以随意地向 Operator Set 添加或删除策略,这可能会立即导致任何已分配的策略变为可惩罚的。从 Operator Set 取消注册是另一种情况。Operator 在取消注册后的 DEALLOCATION_DELAY
期间可被该 Operator Set 惩罚,但对该 Operator Set 的分配仍然存在。 如果 Operator 在延迟时间过后重新注册,则这些 Operator Set 分配会立即再次变为可惩罚的。
取消分配的行为类似于分配,并在 AllocationManager
中排队,并在 DEALLOCATION_DELAY
后自动生效。这是一个跨所有 Operator 和 Operator Set 全局设置的常量。此延迟允许 AVS 更新其 Unique Stake 视图,以反映 Operator 的减少的分配,并保证任务保持可惩罚的适当延迟。排队的取消分配不能被取消。延迟过后,此权益被视为不可惩罚。
影响 UX 的一些说明和注意事项:
DEALLOCATION_DELAY
,而是立即生效。这仅适用于未来的取消分配,不适用于仍在等待完成的待处理取消分配。这些 magnitude 的一个说明性示例对于显示分配流程很有用。假设在初始延迟之后,根据以下 magnitude,Operator 的排队分配将应用于 EIGEN 策略中的委托代币:
Magnitude | Proportion | EIGEN | |
---|---|---|---|
AVS_1_EIGEN |
3,000 | 30% | 30 |
AVS_2_EIGEN |
2,500 | 25% | 25 |
EigenDA_EIGEN |
2,000 | 20% | 20 |
Non-slashable |
2,500 | 25% | 25 |
Total |
10,000 | 100% | 100 |
上面表示按 Operator Set(在本例中,每个 AVS 一个,但这可能是多个集合)划分的不可惩罚和可惩罚权益。现在假设 Operator 排队了一个取消分配,表示减少到 Operator Set AVS_1_EIGEN 的分配。委托代币的数量没有改变,但它们的比例改变了。
Magnitude | Proportion | EIGEN | |
---|---|---|---|
AVS_1_EIGEN (待处理的取消分配) |
3,000 -> 2,000 | 30% -> 20% | 30 -> 20 |
AVS_2_EIGEN |
2,500 | 25% | 25 |
EigenDA_EIGEN |
2,000 | 20% | 20 |
Non-slashable |
2,500 | 25% | 25 |
Total |
10,000 | 100% | 100 |
在取消分配完成之前,减少的 magnitude 中的 10 EIGEN 仍被认为是可惩罚的。以下是取消分配及其相关延迟后的结果。请注意不可惩罚权益的增加。
Magnitude | Proportion | EIGEN | |
---|---|---|---|
AVS_1_EIGEN |
2,000 | 20% | 20 |
AVS_2_EIGEN |
2,500 | 25% | 25 |
EigenDA_EIGEN |
2,000 | 20% | 20 |
Non-slashable |
3,500 | 35% | 35 |
Total |
10,000 | 100% | 100 |
现在,Staker 发生了额外的 100 EIGEN 存款,Staker 已委托给 Operator。立即,该存款被应用,依照分配 magnitude 中规定的比例。
Magnitude | Proportion | EIGEN | |
---|---|---|---|
AVS_1_EIGEN |
2,000 | 20% | 40 |
AVS_2_EIGEN |
2,500 | 25% | 50 |
EigenDA_EIGEN |
2,000 | 20% | 40 |
Non-slashable |
3,500 | 35% | 70 |
Total |
10,000 | 100% | 200 |
每个 Operator Set 的可惩罚权益和整体不可惩罚权益都会相应增加。此论坛帖子中扩展了这个示例,其中包含更多详细信息。稍后我们将在惩罚的上下文中再次引用此示例。
Magnitude 分配使 Operator 委托权益的一部分可被 AVS 惩罚。因此,新的委托和存款立即以相同的比例可惩罚。没有“激活延迟”。存款和委托界面没有变化。
与取消分配和取消注册一样,提款和取消委托在排队后 WITHDRAWAL_DELAY
期间是可惩罚的,并且在延迟过后会自动变为不可惩罚的。托管过程保持不变:提款必须排队并在单独的交易中完成。提款完成时,惩罚将应用于收到的权益。
通过分配给 Operator Set 的 Unique Stake,AVS 可以开始分配带有 Operator 经济承诺的可惩罚任务。AVS 设计的关键在于考虑什么是可惩罚的违规行为,并与 Operator 和 Staker 有效地沟通这些条件。
协议提供了一个最大程度灵活的惩罚函数;AVS 可以因任何原因在任何 Operator Set 中惩罚任何 Operator。 惩罚不一定是客观可归因的(即,可在链上证明),但鼓励 AVS 在个人惩罚周围创建强大的可读性和流程。预计 AVS 惩罚设计中会考虑治理、欺诈证明、权力下放等。AVS 设计中可能包含其他延迟和否决期,以避免或取消 AVS 实施错误、不当惩罚或欺诈的情况,但 EigenLayer 协议不提供任何否决。
AllocationManager
提供了用于惩罚函数的接口:
/**
* @notice 由 AVS 调用,以惩罚给定操作员集合中的操作员。操作员必须注册
* 并且已将可惩罚的权益分配给操作员集合。
*
* @param avs 发起惩罚的 AVS 地址。
* @param params 惩罚参数,包含:
* - operator:要惩罚的操作员。
* - operatorSetId:操作员要从中惩罚的操作员集合的 ID。
* - strategies:要从中惩罚分配的策略数组(必须按升序排列)。
* - wadsToSlash:要从每个策略中惩罚的比例数组(必须介于 0 和 1e18 之间)。
* - description:操作员被惩罚原因的描述。
*
* @dev 对于每个策略:
* 1. 按 wadToSlash 比例减少操作员的当前分配 magnitude。
* 2. 按比例减少策略的最大和 encumbered magnitude。
* 3. 如果存在待处理的取消分配,则按比例减少它。
* 4. 更新 DelegationManager 中操作员的份额。
*
* @dev 较小的惩罚金额可能不会导致实际的代币销毁,因为
* 舍入,这将导致少量代币锁定在合约中
* 而不是通过销毁机制完全销毁。
*/
function slashOperator(address avs, SlashingParams calldata params) external;
/**
* @notice 包含惩罚参数的结构
* @param operator 要惩罚的地址
* @param operatorSetId 要代表其执行惩罚的 operatorSet 的 ID
* @param strategies 要惩罚的策略集
* @param wadsToSlash 要惩罚的 1e18 中的部分,这将与操作员的成比例
* 操作员集合的可惩罚权益分配
* @param description AVS 提供的惩罚描述,用于提高可读性
*/
struct SlashingParams {
address operator;
uint32 operatorSetId;
IStrategy[] strategies;
uint256[] wadsToSlash;
string description;
}
为了进行惩罚,AVS 指定将被惩罚的单个 Operator、Operator Set、将被惩罚的策略列表、要惩罚的比例列表(作为 wads
或“每 1e18
的部分”)以及用于提高可读性的描述。例如,8% 的惩罚将表示为 8e16
,或 80000000000000000
,如 wadsToSlash
参数中预期的那样。25% 的惩罚或 2.5e17
,合约将期望 250000000000000000
作为 wadsToSlash
。两个数组中的索引应在 strategies
和 wadsToSlash
之间匹配。
提供的所有策略都必须配置为 Operator Set 的一部分。对于指定的所有策略,Operator 对该 Operator Set 的分配将按相应的比例进行惩罚,同时保持其对所有其他 Operator Set 的名义分配。在底层,这是通过从指定的 Operator Set 和 Operator 的总 Magnitude 中减去分配的 magnitude 来实现的。以下面的示例为例。
惩罚会按比例减少委托给 Operator 的给定策略的所有 Staker 的资金,包括排队的取消分配和提款中的资金(尚未通过 WITHDRAWAL_DELAY
)。Operator 代表直接在每个策略的 DelegationManager
中减少。通过参考其委托的 Operator 的总 Magnitude,将更改传播到 Staker 提款和查看函数。
发生惩罚时,链上会发出一个事件,每个惩罚一个。发出的详细信息标识了被惩罚的 Operator、在哪个 Operator Set 中以及跨哪些策略,其中包含惩罚比例和元数据的字段:
/// @notice 当操作员因策略而被操作员集合惩罚时发出
/// `wadSlashed` 是被惩罚的操作员总委托权益的比例
event OperatorSlashed(
address operator, OperatorSet operatorSet, IStrategy[] strategies, uint256[] wadSlashed, string description
);
回到我们上面的例子,让我们假设 AVS_1_Eigen
Operator Set 将相关 Operator 惩罚了 50%。回想一下,最终分配的 magnitude 如下:
Magnitude | Proportion | EIGEN | |
---|---|---|---|
AVS_1_EIGEN |
2,000 | 20% | 40 |
AVS_2_EIGEN |
2,500 | 25% | 50 |
EigenDA_EIGEN |
2,000 | 20% | 40 |
Non-slashable |
3,500 | 35% | 70 |
Total |
10,000 | 100% | 200 |
现在,AVS_1
Operator Set AVS_1_EIGEN
中将 Operator 惩罚了 50%(wads
中为 5e17
):
Magnitude | Proportion | EIGEN | |
---|---|---|---|
AVS_1_EIGEN |
1,000 | 11% | 20 |
AVS_2_EIGEN |
2,500 | 28% | 50 |
EigenDA_EIGEN |
2,000 | 22% | 40 |
Non-slashable |
3,500 | 39% | 70 |
Total |
9000 | 100% | 180 |
请注意,通过一个 Operator Set 进行惩罚不会影响分配给其他 Operator Set 的 EIGEN 的 magnitude。Staker、Operator、AVS 和核心合约之间的交互在下面的序列图中以图形方式表示:
图 5:惩罚的序列表示
在此版本中,当资金被 AVS 惩罚时,EigenLayer 核心合约将使被惩罚的资金永久无法访问(“销毁”)。ERC-20 通过将代币发送到已失效的 0x00...00e16e4
地址来完成此操作。这样做是为了确保与各种 LRT 协议进行适当的核算。Natively Restaked ETH 将锁定在 EigenPod 合约中,永久无法访问。预计 Ethereum Pectra 升级将解除对 EigenLayer 升级的开发,该升级将通过将 Natively Restaked ETH 发送到已失效的地址来销毁 ETH,而不是像此版本中计划的那样永久锁定在 EigenPod 合约中。
利用 Unique Stake 的 AVS 可能希望以与任何其他任务或惩罚条件相关的更精细的粒度来奖励 Operator Set。此版本在 RewardsCoordinator
接口中为 AVS 提供了额外的功能,可以在奖励提交中指定一个 Operator Set,以提高他们可以提供的激励和奖励的灵活性。该接口将成为唯一的奖励分配机制,M2 注册和 AVSDirectory
将在以后的日期弃用。它在现有的奖励功能方面是累加的。
AVS 为其每个 Operator Set 指定一组策略。将验证奖励提交是否仅针对 Eigen Sidecar 奖励计算中奖励期间的每个奖励快照的 Operator Set 中的策略进行提交。如果提交的策略未在 Operator Set 中指定,则将忽略这些策略,并根据指定的乘数重新平衡指定的剩余策略。此外,还添加了奖励类型,用于代表 Operator Set 而不是 AVS 进行奖励。Operator 可以精细地设置其在 Operator Set 级别的费用。如果他们没有这样做,如果未配置任何内容,则任何奖励都将使用 10% 的全局默认值。将修改程序化激励计算,以包括已注册到 Operator Set 的 Operator 以及已注册到 AVS 的 Operator。如果存在早于惩罚版本且具有持续时间的 Operator Set 奖励提交,则会将这些特定的奖励快照退还给 AVS。
以下是接口添加:
interface IRewardsCoordinator {
/**
* @notice AVS 为操作员集合创建一个有效的 `OperatorDirectedRewardsSubmission` 时发出。
* @param caller 调用 `createOperatorDirectedOperatorSetRewardsSubmission` 的地址。
* @param operatorDirectedRewardsSubmissionHash (`avs`、`submissionNonce` 和 `operatorDirectedRewardsSubmission` 的 Keccak256 哈希。
* @param operatorSet 操作员定向奖励提交代表的操作员集合。
* @param submissionNonce Avs 的当前随机数。用于生成唯一的提交哈希。
* @param operatorDirectedRewardsSubmission 操作员定向奖励提交。包含代币、开始时间戳、持续时间、操作员奖励、描述以及策略和乘数。
*/
event OperatorDirectedOperatorSetRewardsSubmissionCreated(
address indexed caller,
bytes32 indexed operatorDirectedRewardsSubmissionHash,
OperatorSet operatorSet,
uint256 submissionNonce,
OperatorDirectedRewardsSubmission operatorDirectedRewardsSubmission
);
/**
* @notice 为操作员集合创建一个新的操作员定向奖励提交,以在操作员集合的操作员和委托给操作员的 Staker 集合之间进行分配。
* @param operatorSet 正在为其提交奖励的操作员集合
* @param operatorDirectedRewardsSubmissions 正在创建的操作员定向奖励提交
* @dev 预计由创建操作员集合的 AVS 调用
* @dev `rewardsSubmission` 的持续时间不能超过 `MAX_REWARDS_DURATION`
* @dev 代币将发送到 `RewardsCoordinator` 合约
* @dev 在调用此函数之前,`RewardsCoordinator` 合约需要对 `operatorDirectedRewardsSubmissions` 中所有 `operatorRewards` 的总和进行代币批准
* @dev 策略必须按地址升序排列才能检查重复项
* @dev 操作员必须按地址升序排列才能检查重复项
* @dev 如果 `operatorDirectedRewardsSubmissions` 格式不正确,则此函数将恢复
*/
function createOperatorDirectedOperatorSetRewardsSubmission(
OperatorSet calldata operatorSet,
OperatorDirectedRewardsSubmission[] calldata operatorDirectedRewardsSubmissions
) external;
/**
* @notice 当设置给定 operatorSet 的操作员拆分时发出。
* @param caller 调用 `setOperatorSetSplit` 的地址。
* @param operator 正在设置拆分的操作员。
* @param operatorSet 正由操作员为其设置拆分的操作员集合。
* @param activatedAt 将激活拆分的时间戳。
* @param oldOperatorSetSplitBips 操作员集合的旧拆分。
* @param newOperatorSetSplitBips 操作员集合的新拆分。
*/
event OperatorSetSplitBipsSet(
address indexed caller,
address indexed operator,
OperatorSet operatorSet,
uint32 activatedAt,
uint16 oldOperatorSetSplitBips,
uint16 newOperatorSetSplitBips
);
/**
* @notice 为特定操作员设置特定操作员集合的拆分。
* @param operator 正在设置拆分的操作员。
* @param operatorSet 操作员正在为其设置拆分的操作员集合。
* @param split 操作员针对特定操作员集合的拆分,以 bips 为单位。
* @dev 只能由操作员调用
* @dev 拆分必须介于 0 和 10000 bips 之间(含 0 和 10000 bips)
* @dev 拆分将在激活延迟后激活
*/
function setOperatorSetSplit(address operator, OperatorSet calldata operatorSet, uint16 split) external;
/// @notice 返回给定 `operatorSet` 的特定 `operator` 的拆分
function getOperatorSetSplit(address operator, OperatorSet calldata operatorSet) external view returns (uint16);
}
AVS 现在需要注册其元数据并声明自己,作为加入 EigenLayer 的第一步。这必须在他们创建 Operator Set 或将 Operator 注册到 Operator Set 之前进行。此步骤以前是可选的。此更改是为了确保 AVS 声明自己,以便告知所有生态系统参与者并启用 AVS 地址的验证。这些步骤有助于保护生态系统。
AVS 元数据的格式与以前相同。
AllocationManager
跟踪已注册元数据的 AVS。
/**
* @notice 由 AVS 调用以发出 `AVSMetadataURIUpdated` 事件,表明以下信息已更新。
*
* @param metadataURI 与 AVS 关联的元数据的 URI。
*
* @dev 请注意,`metadataURI` *永远不会存储*,并且仅在 `AVSMetadataURIUpdated` 事件中发出。
*/
function updateAVSMetadataURI(
address avs,
string calldata metadataURI
)
external
checkCanCall(avs)
以下是 AVS 在最初更新其元数据 URI 时应使用的格式。这不会在链上进行验证。
{
"name": "AVS",
"website": "https.avs.xyz/",
"description": "关于的一些描述",
"logo": "http://github.com/logo.png",
"twitter": "https://twitter.com/avs",
}
Operator Set 将在 AllocationManager
中采用一种新的方式,供 AVS 向核心协议进行注册。该合约将成为 AVS 向 EigenLayer 注册并向自己注册 Operator(通过 Operator Set)的唯一方式。AVSDirectory
的弃用计划在稍后的日期进行,整个更改集将在另一个 ELIP 中介绍。
M2 注册流程缺乏一项确定的能力,即 Operator 无法从 AVS 取消注册,从而可能导致 Operator 永久锁定在协议中的潜在滥用极端案例。将此功能添加到核心合约中可确保 Operator 可以选择退出他们不再希望提供安全性的 AVS。
先前的 M2 注册流程将在砍伐版本发布后可用,并在 Mainnet 启动后的稍后日期弃用。需要新的注册流程,以确保与 Operator Set 和砍伐集成时正确核算 Unique Stake。AVS 必须使用新的注册流程才能利用这些功能。我们建议 Operators 在运行其 M2 操作的同时并行注册到 Operator Set,然后在准备就绪时进行切换。没有可用的原子迁移交易。
分配延迟是由希望让其 Staker 有机会在分配生效之前进行提款的 Operator 使用的一种工具。Staker 可能希望监控其 Operator 的分配和相应的风险情况,并且分配延迟决定了 Staker 在分配生效并且他们的资金在新分配中面临砍伐风险之前,有多少时间可以监控和提款。预计分配延迟将在用户界面中显示,例如 app.eigenlayer.xyz,以便 Staker 和 Operator 清楚地表达其风险情况,以及 Operator 挂起的分配的详细信息。
与其选择全局延迟,不如使其可由 Operator 配置,以便选择其委托权益的敏捷性或安全性。例如,一些 Staker 运行自己的 Operator,因此大概希望将其分配延迟设置为零(例如,许多 LRT)和/或一些 Operator 可能更喜欢通过自己的合约在协议外强制执行额外的分配延迟或控制。
WITHDRAWAL_DELAY
设置为 14 天的块?有关提款延迟的更全面的理解,请参见此帖子。简明版本如下。
提款延迟受两个变量限制:
为了解释选择 14 天作为此窗口的原因,请考虑一个理论模型:
一些 AVS 表示,7 天是 AVS 可以同步到 EigenLayer 权益的经济合理的时间段。但是,如果他们愿意,AVS 可以或多或少地频繁地执行此操作。
在发生真正的欺诈的情况下,在欺诈证明提交到链上之后,预计取消者无需在链上进行干预。在欺诈证明提交到链上之后,可能有一个 3.5 天的窗口,在此之后,如果没有取消交易,任何实体都可以将砍伐请求转发到核心协议。
最后,可能会假设攻击者不会在 7 天的窗口内被审查超过 3.5 天,从而使他们能够在 3.5 天内将欺诈证明和转发交易发送到核心协议。
在发生真正的欺诈的情况下,
EigenLayer 可以在以后的版本中进行更新,以启用更长或更短的延迟,但是此提案有一个全局参数以简化操作。
DEALLOCATION_DELAY
设置为 14 天的块?提款和取消分配都被 AVS 视为可砍伐权益的减少,因此 DEALLOCATION_DELAY
的处理方式与 WITHDRAWAL_DELAY
相同。
ALLOCATION_CONFIGURATION_DELAY
设置为 17.5 天的块?分配配置延迟设置为 17.5 天,以便在新的分配延迟生效之前,为 Staker 提供 3.5 天的提款时间(3.5 + 14 = 17.5)。3.5 天用作审查抵抗间隔。
分配和注册到 Operator Set 不是原子的。这是有问题的,因为在分配生效时,由于外部因素,可能会阻止注册到 Operator Set(例如,Operator Set 中其他 Operator 的权益增加,导致 Operator 的 allocation 不再足以将其资格注册到 Operator Set 中)。
为了应对分配和注册流程的非原子性,并启用协议中权益的敏捷性,Operator 可以立即取消 non-slashable allocations。如果 Operator 未注册 Operator Set 或 Strategy 不是 Operator Set 的一部分,则该 Strategy 中的权益被认为是 non-slashable 的。
目前,EVM 不支持浮点运算。因此,该协议使用带有 18 位小数的定点运算。1×10^18 (也称为 WAD)是 DeFi 生态系统中 1 个单位的常见度量,足以表示权益的比例。
此提案选择存款/委托立即变得可砍伐,从而为 AVS 提供最高的安全性保证。如果 Staker 和 Operator 需要进一步的保障,则可以在核心协议的上游实施。
最初的安全模型具有以下结构:每个 Operator 都可以选择加入 AVS 子集,并且分配给该 Operator 的整个权益都可以被任何这些 AVS 进行砍伐,这意味着:
新的 Unique Security 模型经过专门设计,通过提供更大的灵活性和控制力 (通过Unique Stake) 来解决这些缺点:
2. **有保障的 slashable stake**: 每个 AVS 通过将分配给他们的所有 Operator 的 Unique Stake 加起来,就知道他们有多少 slashable stake。
3. **无需共同否决委员会**: 由于 slashing 被本地化到单个 AVS,因此没有必要设立共同否决委员会。 每个 AVS 都可以指定自己的 slashing 和治理机制。
4. **AVS 的无需许可的 onboarding**: 在 EigenLayer 上启动一个 AVS 是无需许可的,只需要 Operator 选择加入。
Unique Security 模型还有其他属性,例如将 Operator 委托和 Unique Stake 相结合,如[此处](https://www.blog.eigenlayer.xyz/introducing-the-eigenlayer-security-model/)所示。 此外,如果需要,此模型允许 AVS 通过与其他 AVS 共享 Operator Sets 来使用原始安全模型,但具有更合理的风险模型。
#### 为什么没有协议级别的否决委员会?
该协议选择最小的社会过载。 在 AVS 中上游实施所有否决功能可以打开设计空间,减少 EigenLayer 上的治理开销,并提高系统的整体敏捷性、灵活性和安全性。 我们鼓励 AVS 开发中的安全性和深思熟虑,而不是依赖于核心协议否决。
此外,Unique Security 模型消除了 Operator Sets 彼此暴露于 slashing 的风险。 这降低了协议级别否决委员会的原始动机的相关性。
#### token 分叉和主体间 slashing 呢?
[通过分叉 EIGEN token 进行的主体间 slashing](https://www.blog.eigenlayer.xyz/eigen/) 被认为超出了本提案和初始实施的范围。 本提案中的 Unique Stake 和 slashing 机制在 EIGEN token 分叉和主体间 slashing 方面具有前瞻性。
## 安全注意事项
### Magnitude 分配
无法取消分配。 必须为正确的值进行分配,否则 Operator 和 Staker 的风险状况可能会受到意外影响。
### 舍入和不精确性
由于会计处理中需要的更改以及减少 stake(在 Strategy 代码中称为“份额”)以考虑已发生的任何 slashing,因此由于除法舍入,可能存在小的精度误差。 这会影响为 Staker 提取的金额。 即使他们在存入和提取之间没有被 slashed,也可能会因此损失少量 `Wei`。 这已被考虑并围绕其进行设计,主要动机是避免任何下溢/溢出情况,在这种情况下,用户的操作会意外恢复。
此外,我们正在使用 OpenZeppelin 的 Math 实用程序库和 mulDiv 函数(感谢 Remco Bloemen)来实现安全性和精确度。
### 有缺陷的 Slashing 逻辑
时不时地,AVS 可能会部署有缺陷的 slashing 逻辑,而不管设计的意图如何。 正如本提案中所概述的那样,建议 AVS 在调用 slashing 函数之前使用时间锁、否决或欺诈证明期,以确定拟议 slashing 的真实性或纳入社会共识的要素。 鼓励在 testnet 上进行 slashing 条件的缓慢实验。
## 影响总结
### AVS
强烈建议现有 AVS 从任何现有 Quorum 和使用 `AVSDirectory` 迁移,转而使用 `AllocationManager` 和 Operator Set 功能。 这是 slashing 所必需的。 为了进行这种迁移,我们建议 AVS:
1. 在 `AllocationManager` 中注册元数据
2. 升级他们的合约以处理来自 `AllocationManager` 的回调
3. 就通过新的注册途径注册 Operator Sets 一事与 Operator 进行沟通
1. 对于可 slashing 的 Operator Sets,Operator 还应分配可 slashing 的 stake
2. AVS 应考虑 `AVSRegistrar` 合约的要求
4. 迁移到使用新的 Operator Set 注册的 operator 来基于委托的和可 slashing 的 stake 分配任务
这允许 AVS 达到一种状态,即他们的 Quorum 在核心协议中的 Operator Sets 中得到完全反映。 在发生此迁移之后,与 slashing 的集成就可以上线。
### Operator
所有 Operator 操作都选择加入 slashing 版本。 为了参与 Operator Sets 并获得相关的奖励,Operator 必须分配可 slashing 的 stake,然后注册到 Operator Sets。 这将需要与他们的利益相关者进行沟通,并了解 slashing 系统的相关风险。 Operator 还需要了解 AVS 的 slashing 条件以及他们期望运行的代码。
### Staker
在此升级之后,Staker 将看到其风险和回报情况发生变化。 最初在升级之后,如果 Staker 已经委托给 Operator,则只要 Operator 选择加入 Operator Sets 并分配 stake,其 stake 就可以被 slashing。 这将产生风险(和潜在回报)。 因此,Staker 应审查并确认他们对继续委托给 operator 的风险承受能力。 如果 Staker 计划将来进行委托,他们可以查看任何 Operator 的现有分配,以了解他们将通过委托选择加入的 AVS 和风险。 AVS 和 Operator 的 slashing 历史记录将是透明的,并且可以通过用户界面(如 [app.eigenlayer.xyz](https://app.eigenlayer.xyz/))公开,因此 Staker 可以查看 slashing 活动的链上历史记录。 可以在 EigenLayer 之上构建通知服务,或者可以在稍后提供。
### 突破性变化
#### Operator 负份额
在 `EigenPodManager` 中具有负份额(来自 pre-slashing 升级状态)的 Operator 应在将 100% 的 stake 分配给策略之前完成其排队的提款。 **不这样做会导致当前排队的提款无法完成。**
#### 自定义错误
除了源自外部继承合约(例如 OpenZeppelin)的错误之外,所有错误都已从字符串更新为[自定义错误](https://soliditylang.org/blog/2021/04/21/custom-errors/)。
对于自定义错误,我们将 solidity 版本从 `^0.8.12` 升级到 `^0.8.27`。 接口保持 `>=0.5.0`。
#### Operator 注册
`DelegationManager` 中的 `registerToOperator` 函数已更新为接收 `allocationDelay` 和 `initDelegationApprover`。 不再传入 `OperatorDetails` 结构体。
```solidity
/**
* @notice 在 EigenLayer 中将调用者注册为 operator。
* @param initDelegationApprover 是一个地址,如果设置,则当 staker 委托给 operator 时,必须提供签名。
* @param allocationDelay 分配生效前的延迟。
* @param metadataURI 是 operator 的元数据的 URI,即提供有关 operator 更多详细信息的链接。
*
* @dev 一旦注册了 operator,他们就不能“取消注册”为 operator,并且他们将被永久视为“委托给自己”。
* @dev 如果调用者已经委托给 operator,则此函数将恢复。
* @dev 请注意,`metadataURI` *从不存储 *,仅在 `OperatorMetadataURIUpdated` 事件中发出。
*/
function registerAsOperator(
address initDelegationApprover,
uint32 allocationDelay,
string calldata metadataURI
) external;
StrategyManager
中的 stakerStrategyShares
映射已重命名。 StrategyManager
中存入的 stake 由以下给出:
/// @notice 返回 `user` 在 `strategy` 中的当前份额
/// @dev 在与 EigenPodManager 通信时,strategy 必须是 beaconChainETH
/// @dev 如果用户有负份额,则返回 0。
function stakerDepositShares(
address user,
IStrategy strategy
) external view returns (uint256 depositShares);
可提取的 stake 由以下给出:
/**
* @notice 给定一个 staker 和一组策略,返回他们可以排队提款的份额以及相应的 depositShares。
* 此值取决于 staker 委托给哪个 operator。
* 返回的份额金额是 staker 将收到的 Strategy 份额的实际金额(取决于每个策略的基础份额与 token 的比率)。
*/
function getWithdrawableShares(
address staker,
IStrategy[] memory strategies
) external view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares);
注意:这是从 DelegationManager
读取的,而 stakerDepositShares()
是从 StrategyManager
读取的。 此 getWithdrawableShares
函数中返回的 uint256[] memory depositShares
也返回与上面相同的 depositShares
。 EigenPodManager
中的 podOwnerShares
自省已弃用,取而代之的是 podOwnerDepositShares
。
getDelegatableShares
已从 DelegationManager
中删除,取而代之的是两个函数:
getDepositedShares
返回 Staker 存入的原始金额,getWithdrawableShares
返回应用 slashing 后的 Staker 可提取金额。 对于所有 Operator 的 staker,getWithdrawableShares
的总和应小于或等于 Operator 的委托 stake。/**
* @notice 给定一个 staker 和一组策略,返回他们可以排队提款的份额以及相应的 depositShares。
* 此值取决于 staker 委托给哪个 operator。
* 返回的份额金额是 staker 将收到的 Strategy 份额的实际金额(取决于每个策略的基础份额与 token 的比率)。
*/
function getWithdrawableShares(
address staker,
IStrategy[] memory strategies
) external view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares);
/**
* @notice 返回 staker 及其所有策略的存储中的份额数
*/
function getDepositedShares(
address staker
) external view returns (IStrategy[] memory, uint256[] memory);
getOperatorDetails
getter 已删除,因为唯一相关的“详细信息”是委托批准者。 delegationApprover(address operator)
函数可用于检索此值。
modifyOperatorDetails
函数已更新以反映要修改的唯一 Operator 信息是委托批准者:
/**
* @notice 更新 operator 存储的 `delegationApprover`。
* @param operator 是要更新 delegationApprover 的 operator
* @param newDelegationApprover 是 operator 的新 delegationApprover
*
* @dev 调用者必须先前已在 EigenLayer 中注册为 operator。
*/
function modifyOperatorDetails(
address operator,
address newDelegationApprover
) external;
函数 strategyWithdrawalDelayBlocks(IStrategy strategy)
和 getWithdrawalDelay(IStrategy calldata strategies)
已删除。 你可以使用 DelegationManager
上的以下函数自省延迟:
/**
* @notice 返回排队完成提款所需经过的最小提款延迟(以区块为单位)。
* 也适用于传统的提款,因此在 slashing 升级之前未完成的任何提款都将受到此更长的延迟的约束。
* @dev 用于返回 `MIN_WITHDRAWAL_DELAY_BLOCKS` 值的向后兼容接口
*/
function minWithdrawalDelayBlocks() external view returns (uint32);
现在,排队提款时发出的事件名为 SlashingWithdrawalQueued
。 更新后的提款事件和结构如下:
/**
* @notice 当新提款排队时发出。
* @param withdrawalRoot 是 `withdrawal` 的哈希。
* @param withdrawal 是提款本身。
* @param sharesToWithdraw 是 `withdrawal` 中与策略相对应的预期排队提款的份额数组。
*/
event SlashingWithdrawalQueued(
bytes32 withdrawalRoot,
Withdrawal withdrawal,
uint256[] sharesToWithdraw
);
/**
* 用于指定现有排队提款的结构类型。 不是存储整个结构,而是仅存储哈希。
* 在对现有排队提款进行操作的函数中——例如,completeQueuedWithdrawal`,数据会重新提交,并且由 `calculateWithdrawalRoot` 计算提交数据的哈希,并针对存储的哈希进行检查,以确认提交数据的完整性。
*/
struct Withdrawal {
// 发起提款的地址
address staker;
// 在创建提款时 staker 委托到的地址
address delegatedTo;
// 可以完成提款 + 完成提款时将收到资金的地址
address withdrawer;
// 用于保证其他相同的提款具有唯一哈希的 Nonce
uint256 nonce;
// 创建提款时的区块号。
uint32 startBlock;
// 提款包含的策略数组
IStrategy[] strategies;
// 包含每个 `strategies` 数组中每个 Strategy 中 staker 的 scaledShares 提款量的数组
// 请注意,这些 scaledShares 需要乘以 operator 的 maxMagnitude 和 beaconChainScalingFactor 完成时,以包括排队提款延迟期间发生的 slashing。 这是因为 scaledShares = sharesToWithdraw / (maxMagnitude * beaconChainScalingFactor)
// 在排队时间。 如果策略不是 beaconChainStrategy,则 beaconChainScalingFactor 简单地等于 1。
// 为了考虑 slashing,我们稍后在最早的可能完成时间乘以 scaledShares * maxMagnitude * beaconChainScalingFactor
// 以获得在延迟期间应用 slashing 后的提款份额。
uint256[] scaledShares;
}
排队提款会发出一个带有 withdrawal
结构的事件,该结构当前必须被索引并在 WITHDRAWAL_DELAY
期间之后传递到 completeQueuedWithdrawal
函数中。 app.eigenlayer.xyz 可用于提供此 calldata,但并非强制性的。 通过 slashing 更新:
completeQueuedWithdrawal
参数会发生变化(以删除未使用的参数)。新的完整提款接口如下。 具体来说,未使用的 uint256
参数 (middlewareTimesIndex
) 从两种完整方法中删除。 通过使用 getQueuedWithdrawals
函数来检查排队的提款,可以仅通过 RPC 调用完成提款,无需运行索引器即可在前端应用程序之外完成提款。
// 一项提款,通过索引提款结构或调用 `getQueuedWithdrawals` 获得。
function completeQueuedWithdrawal(
Withdrawal calldata withdrawal,
IERC20[] calldata tokens,
bool receiveAsTokens
)
// 多项提款,当排队提款时索引提款或调用 `getQueuedWithdrawals` 获得。
function completeQueuedWithdrawals(
Withdrawal[] calldata withdrawals,
IERC20[][] calldata tokens,
bool[] calldata receiveAsTokens
)
// 检查当前排队的提款。 仅返回升级 post slashing 后排队但未完成的提款。
function getQueuedWithdrawals(
address staker
) external view returns (Withdrawal[] memory withdrawals, uint256[][] memory shares)
分配和 Slashing Unique Stake 的机制 - 协议研究 - EigenLayer 论坛 The Stake Guarantee Window Introducing the EigenLayer Security Model: A Novel Approach to Operating and Securing Decentralized Services
词汇表 | 定义 |
---|---|
分配/取消分配 | Operator 对 AVS 的 Operator Set 的安全性的链上承诺。 分配的行为将 Operator 委托的一部分标记为 Unique Stake,使其可以被 AVS slashing。 取消分配是相反的相同过程,但需要额外的时间延迟,以确保 AVS 可以适当地 slashing 过去发生的任务。 |
AVS | 在 EigenLayer 外部构建的服务,需要一组 Operator 进行主动验证。 AVS 在 Ethereum 上部署服务管理器合约,以允许 EigenLayer Operator 注册、slashing 和奖励分配。 注册后,Operator 同意运行 AVS 的链下代码。 |
AllocationManager |
一个管理 Operator \<> AVS 关系的合约。 它更新了 Operator 将 stake 资产分配给 Operator Sets 的情况,并执行了对 Operator stake 的 slashing。 |
AVS Registrar |
AVS 用于控制注册到 Operator Sets 中的合约。 |
存款 | Staker 在 EigenLayer 中添加的资产,用作接收奖励的安全性。 |
销毁 | 从流通中移除 token。 |
核心合约 | 由 EigenLayer 及其治理流程部署和控制的合约。 |
委托 | Staker 将其 stake 的 token 分配给选定的 Operator 的过程,授予他们使用这些 token 的价值来验证 AVS 的权限。 Operator 无法直接访问委托的 token,但可以导致 AVS 对其进行 slashing。 委托本身是给定 Operator 从 Staker 委托的 stake 的总和。 |
DelegationManager |
一个用于跟踪委托给 Operator 的策略中的 stake 资产的合约。 这些与分配逻辑和奖励联系在一起。 |
Magnitude | 用于跟踪 Operator 对 Operator Sets 的分配的记帐工具。 在 AllocationManager 中表示为 wads 。 Magnitude 表示 Operator 对特定 Strategy 的委托的比例。 Operator 的所有 Magnitude 的总和不能超过 INITIAL_TOTAL_MAGNITUDE 。 |
M2 | EigenLayer 协议的 Release 0.4.3。 |
Operator | 在 Eigenlayer 上注册 Operator 地址以接收委托并运行 AVS 基础设施的实体。 它们将分配给用作可 slashing 安全性的 Operator Sets。 |
Operator Set | Operator 的一个分段,他们使用为该集合保留的 stake 资产来保护 AVS 的特定任务集。 |
注册/取消注册 | 从 Operator Set 中包含/删除 Operator。 |
奖励 | 由 AVS 发送给 Staker 和/或 Operator 的 token,以补偿参与。 |
安全 | Operator 将遵循由密码经济资产提供的 AVS 定义的协议的保证,这些资产与适用的惩罚和 slashing 条件相关联。 AVS 使用安全来确保他们可以对其最终用户做出承诺。 |
Slashing | 由于不正确或不准确地完成 AVS 在 Operator Sets 中分配的任务而受到的惩罚。 slashing 导致资金的销毁/损失。 |
Staker | 直接向 Eigenlayer 提供资产的个人地址。 这样的地址可以是 EOA 钱包,也可以是由个人或机构控制的智能合约。 |
任务 | AVS 分配给 Operator Sets 的工作。 任务可以采用计算、证明验证、签名聚合、活跃度 ping 或完全具有创造性的形式 |
Unique Stake | 仅由一个 Operator Set 可 slashing 的资产。 Unique Stake 是在 Operator Set 级别定义的记帐工具,可确保 AVS 和 Operator 在处理 stake 安全性和在 EigenLayer 上进行 slashing 时保持关键的安全属性。 Unique Stake 由 Operator 在选择加入的基础上分配给不同的 Operator Sets。 Unique Stake 表示 Operator 的 Staker 委托的 stake 中 AVS 可以 slashing 的比例。 |
wad |
一个 wad 等于 1e18 。 这是一个带有 18 位小数的定点数。 例如,25% 的 slashing 将表示为 2.5e17 并作为 250000000000000000 提交给 slasher 函数,表示“每 wad 的部分”。 |
提款 | 资产在安全延迟后以及在名义金额上应用 slashing 后从 EigenLayer 协议中移出的过程。 |
- 原文链接: github.com/eigenfoundati...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!