{"content":{"title":"LSD. 集成陷阱","body":"作者：Pavel Morozov， MixBytes 的安全研究员\r\n\r\n![](https://img.learnblockchain.cn/2025/03/09/47.jpg)\r\n\r\n## 介绍\r\n\r\nLiquid staking 代币代表用户在以太坊 PoS 网络中的股份。与基本质押不同，liquid staking 允许用户在仍然获得其质押的 ETH 奖励的同时，利用其流动性在其他协议中使用。在基本质押中，资金被锁定并在特定时间内无法访问，但通过 liquid staking，代币的价值来自于被质押的以太币。\r\n\r\n这些 liquid staking 代币，也称为 LSDs，具有多种功能。它们可以被转移、交易、用作抵押品或兑换为基础的质押 ETH。一些协议甚至随着时间的推移提高可兑换 ETH 的价值，从而导致代币价值的不断上升。其他协议引入了可重基（rebasable）代币，这意味着用户的代币余额可能会根据罚款等因素而波动。此外，某些协议还对 LSDs 实施奖励检查点，使得质押者可以转移他们的代币而不会失去已累积的奖励。\r\n\r\n在本文中，我们深入探讨不同 Liquid Staking 协议的关键概念。此外，我们还阐明在将 liquid staking 代币整合到其他协议时可能出现的安全问题。\r\n\r\n## Lido (stETH/wstETH)\r\n\r\n### 实施细节\r\n\r\n有两个代币 - stETH 和 wstETH。当用户提供 ETH 时，他们立即收到表示其股份的 stETH 代币。wstETH 可以使用 stETH 和一个特殊的包装合约来铸造。现在，事情变得有趣了：stETH 是一种可重基代币，意味着其余额反映用户参与的奖励或惩罚。另一方面，wstETH 维持一个恒定的余额，其价值（可兑换的 stETH 数量）随着时间的推移而增加。\r\n\r\n为了铸造 stETH 代币，用户可以调用 submit 函数并提供要质押的以太币。此外，stETH 代币也可以在处理预言机报告时通过调用 \\_processRewards 函数铸造。现在，当用户要将部分 stETH 转换为 ETH 奖励（或提取全部存款）时，他们需要发出请求并将其 stETH 锁定在提取队列中。结果，用户会收到一个独特的 NFT，代表他们在队列中的位置。然后，他们耐心等待预言机报告和请求的最终确认。一旦满足这些条件，用户可以销毁他们的 NFT 以获取请求的以太币。然而，提取数量是有限制的，这意味着用户可能需要将可销毁的 stETH 分为多个部分才能进入提取队列。值得注意的是，stETH:ETH 的比例在请求最终确认时确定，不能超过请求创建时的比例。然而，如果发生罚款或惩罚，它可以减少。\r\n\r\n现在，让我们谈谈系统中的一些保障措施，以防止剧烈波动。为了限制汇率和余额的重大变化，有一个聪明的合约，称为 OracleReportSanityChecker 合约。这个合约有助于减轻不正确报告的预言机数据的影响。此外，潜在的代币重基也有限制，这些限制可以配置。此外，每天可以加入或退出的验证者数量也有限制。这些措施有效地控制和限制了重基发生的可能性，尽管在建议的范围内仍然可能发生低于 0.05% 到 0.1% 的变动。\r\n\r\n### 安全问题\r\n\r\n寻求将 stETH 纳入其生态系统的协议必须接受重基的动态特性，向上和向下变化。通过这样做，他们承认与可重基代币相关的固有挑战。一个关键方面是余额不应该存储在状态变量中。相反，协议逻辑应考虑实际合约余额，可以通过 stETH.balanceOf(address(this)) 来获取。虽然 wstETH 在余额方面提供了更多的稳定性，但需要注意的是，也需要考虑其与 stETH 的兑换/解包比率。在这一方面，整合这些代币的协议有机会制定特定的余额或比率波动限制，以确保更顺利的整合和最佳的性能。\r\n\r\n## Coinbase Wrapped Staked ETH (cbETH)\r\n\r\n### 实施细节\r\n\r\ncbETH 不是一个普通的代币。它的功能被故意限制，赋予它一种独特的特性。这种限制源于其中心化特性，为该代币增添了一些独特性。在 cbETH 的世界中，只有少数特殊地址有权创建或销毁 cbETH 代币。这个权力由强大的 onlyMinters 声明来保护，确保铸造和销毁权限受到严格控制。masterMinter 地址掌握了赋予任何地址铸造和销毁权限的密钥。这意味着，通过 configureMinter 函数，masterMinter 可以授予特定数量的铸造和销毁权。简直像一个秘密代码，赋予访问创建和销毁 cbETH 隐藏领域的权限。\r\n\r\n不仅如此！在 cbETH 生态系统内部，还存在黑名单机制。转移、批准、铸造和销毁都可以受到此机制的影响。这为 cbETH 增加了一层额外的安全和控制，确保只有授权的操作才能在 cbETH 的领域内发生。\r\n\r\n这里的事情变得有趣。cbETH 的兑换率和余额动态取决于协议的配置。代币合约内嵌了 exchangeRate() 函数，提供 ETH 与 cbETH 之间兑换率的概览。然而，这一比例并不是任意的。它由几个特殊地址通过 onlyOracle 修饰符确定，这些地址有权推动兑换比例的变化。当然，这些地址在此类汇率变化的幅度上也受到限制。在与显著的额度相关的情况下，做好准备迎接可能会产生深远影响的显著波动。\r\n\r\n在这个代币和协议不断演变的领域，拥抱 stETH、wstETH 或 cbETH 需要对它们独特的特性和挑战有深入的了解。但不用担心，那些谨慎和创新地应对这些复杂性的参与者将会解锁出一个可能的世界。\r\n\r\n### 安全问题\r\n\r\n此外，在 exchangeRate() 下降或在较长时间内保持稳定的情况下（例如，在铸造者额度耗尽时），建立有效的保障措施至关重要。另外，整合协议还必须认识到 cbETH 来源于 Coinbase，这是一个中心化的交易所，所有限制都源于用户需要最初与交易所界面交互以铸造或销毁 cbETH 代币的要求。\r\n\r\n## Rocket Pool (rETH)\r\n\r\n### 实施细节\r\n\r\nrETH 代币的运作方式与其他代币不同，因为它无法重基。要确定 rETH 与基本的质押以太坊之间的当前兑换率，使用 getExchangeRate() 函数。此函数依赖于节点报告的以太币余额，并存储在一个特殊的合约 chamada RocketNetworkBalances 中。以太币余额除以当前的 rETH 供应量，该值被视为当前的兑换率。\r\n\r\nrETH 的铸造功能受到限制，只能由 RocketDepositPool 合约调用。另一方面，销毁功能没有限制，任何持有者都可以调用。然而，为了让销毁调用成功，RocketDepositPool 合约中必须有足够的以太币（多余的存款余额）以及在 RocketTokenRETH 合约中存储的以太币。\r\n\r\n网络以太币余额由被称为节点的受信任预言机提交。submitBalances 函数调用只有在达到所需的节点操作员余额提交数量后方会通过。值得注意的是，没有余额变化的检查，这可能在 RPL 节点共识攻击的情况下产生重大影响。\r\n\r\n此外，Rocket Pool 对以太币存款征收费用，这意味着用户收到的 rETH 代币少于他们添加到库房余额的以太币数量。从一开始，rETH:ETH 的比例对每个用户都小于 1。然替代，市场价格反映了这一比例，导致其昂贵于以太币本身，完全对应提取过程中的费用百分比。\r\n\r\n### 安全问题\r\n\r\n整合 rETH 的协议需要考虑在发生罚款时交易汇率可能下降的可能性。rETH 与 ETH 之间的比率在设定存款费用的期间可能会受到显著操纵，这将使其他整合 rETH 的协议在调整这些变化时面临不足的时间。此外，必须保持对 RPL 节点共识攻击风险的警惕，节点可能提交不正确的汇率数据。此外，协议所有者可以通过多重签名系统更改 rocketDepositPool 地址。这种变更将赋予新地址无限的铸造特权。\r\n\r\n## Frax (sfrxETH)\r\n\r\n### 实施细节\r\n\r\nsfrxETH 是一个运行在 ERC4626 Tokenized Vault 标准上的代币。与其他代币不同，它无法重基。获取 sfrxETH 的过程涉及将 frxETH 带入协议，允许任何人铸造这个独特的代币。相反，任何拥有 sfrxETH 的人可以将其兑换回 frxETH。这个系统的迷人之处在于铸造和销毁功能中没有额外的角色。当用户通过存入以太币铸造 sfrxETH 时，会扣留一定百分比的以太币。这部分以太币随后用于增强 frxETH/ETH Curve 池的流动性。这样，该机制确保了 LSD（流动性敏感存款）持有者可以迅速退出他们的头寸，而无需等待提取队列处理。\r\n\r\n此外，sfrxETH 可以按其当前汇率解包为 frxETH。随后，它可以通过 Curve 池交换为 ETH。有趣的是，在此过程过程中，Frax 扮演了流动性提供者（LP）角色，从而产生了农场奖励。这些奖励在量表投票中发挥着至关重要的作用，从而增加了池的 CRV 排放。因此，更多的 LP 被吸引参与到这个生态系统中。\r\n\r\n值得注意的是，sfrxETH 与 frxETH 之间的汇率只会向上移动，因为在发生罚款或惩罚的情况下，没有从保险库中撤回 frxETH 的机制。在这种情况下，保险库将通过算法市场操作控制器（AMO）获得补贴。AMO 可以缩小 LP 头寸、销毁 frxETH，并提供必要的以太币以匹配用户可赎回金额。\r\n\r\n此外，当 Frax 多签名合约将 ETH 奖励转换为 frxETH 并存入 sfrxETH 保险库时，sfrxETH 与 frxETH 之间的汇率会增加。这一独特特性为生态系统增加了另一层吸引力。\r\n\r\n### 安全问题\r\n\r\n整合 sfrxETH 的协议应当注意到在 Frax 团队多签合约实施奖励转账期间，sfrxETH 可能会与 frxETH 脱离。这创造了存款前运行的风险，投机者可以利用这一过程，并从整合了 sfrxETH 的协议中提取价值。此外，在发生罚款的情况下，sfrxETH:frxETH 的比率可能在很长一段时间内保持过期，因为 Frax 团队有权决定池的报销。\r\n\r\n## StakeWise (sETH2 和 rETH2)\r\n\r\n### 实施细节\r\n\r\n实施了两个代币：StakedEthToken (sETH2) 和 RewardEthToken (rETH2)。sETH2 不是可重基代币，而 rETH2 是可重基的。当用户质押 ETH 时，他们收到 sETH2 并开始接收 rETH2 作为奖励。\r\n\r\n当调用质押函数或向合约发送以太币时，池合约负责铸造 sETH2 代币。当前的实现不允许 rETH2 余额减少。然而，文档提到在未来的 V3 版本中，将能够对 sETH2 和 rETH2 代币执行重基。\r\n\r\n预言机提供更新的奖励数据。奖励是通过新总奖励与旧总奖励之差计算的，例如 `uint256 periodRewards = newTotalRewards.sub(totalRewards)`。有必要注意的是，不可能提交小于 totalRewards 的 smaller newTotalRewards。然而，协议预言机提交相应于每个质押者的奖励数据的 merkle root。在当前的实现中，在发生罚款的情况下，这些值可能会减少。此外，还存储有每个 rETH2 代币持有者的奖励检查点。这些值在当前实现中无法减少，但在发生罚款时，其增长速度可能会减缓。\r\n\r\n### 安全问题\r\n\r\n采用 rETH2 的协议必须意识到用户的 rETH2 余额当前无法减少，但未来计划实现这个功能。需要注意的是，在发生罚款的情况下，当前协议的行为未定义，因为没有规定的行动来减少用户的奖励余额或 sETH2 余额。但是，这些代币可以升级，未来可能会引入解决此问题的机制。\r\n\r\n## 结束\r\n\r\n目前实现 liquid staking 协议及其代币的方式多种多样。必须考虑合约的所有权和过大的权限，因为它们可能扰乱使用这些代币的协议逻辑（如 cbETH 和 Rocket Pool）。整合 liquid staking 衍生品（LSDs）的协议也应考虑汇率或代币价值的波动。通常情况下，汇率是上升的，协议不会包括降低它的机制（如 Frax 和 StakeWise 的情况）。然而，由于验证者罚款或惩罚，汇率也可能意外下降（如 Lido 所观察到的那样）。在不对余额施加惩罚或奖励的协议中，应当建立报销机制，以确保失去的质押以太币不会影响 LSD 转换为以太币的比率。\r\n\r\n还必须提到不同的协议配置。DAO 或协议所有者可以修改铸造费用（正如 Rocket Pool 的例子），这可能会对整合协议产生负面影响，使它们获得的 LSDs 少于预期。预言机也可以改变提交奖励或汇率数据的方法，导致某些协议出现不同的套利机会和潜在的流动性损失。\r\n\r\n此外，依赖于协议团队行动的协议需要特殊关注。例如，frxETH 情况涉及在罚款或惩罚期间的决策窗口，而 StakeWise 旨在敲定其协议的第三版，这可能会改变销毁和惩罚机制。\r\n\r\n- MixBytes 是谁？\r\n\r\n[MixBytes](https://mixbytes.io/) 是一个由区块链审计专家和安全研究员组成的团队，专注于提供全面的智能合约审计和技术咨询服务，涵盖 EVM 兼容和 Substrate 基础的项目。加入我们 [X](https://twitter.com/MixBytes) ，跟随行业最新趋势和见解。\r\n\r\n>- 原文链接： [mixbytes.io/blog/liquid...](https://mixbytes.io/blog/liquid)\r\n>- 登链社区 AI 助手，为大家转译优秀英文文章，如有翻译不通的地方，还请包涵～"},"author":{"user":"https://learnblockchain.cn/people/24680","address":null},"history":null,"timestamp":1741514451,"version":1}