Rocket Pool rETH 集成 第 5 章:rETH 净值(NAV)
集成 rETH 时,“1 rETH 值多少 ETH/美元”这个问题有两个不同的答案:公允汇率(NAV)和二级市场价。用错了会导致估值偏差甚至被操纵清算。这一章讲清两者的区别、什么时候用哪个、以及怎么安全地取价。
目录
- 1. NAV 是什么
- 2. 两个”价格”:公允汇率 vs 市场价
- 3. 公允汇率怎么来的
- 4. 案例:估值用错价格的后果
- 5. 该用哪个价:场景对照
- 6. 预言机安全:抗操纵取价
- 7. 折溢价与套利
- 8. 本章小结
- 9. 动手练习
1. NAV 是什么
NAV(Net Asset Value,净值) 指 1 个 rETH 背后真正对应多少 ETH 价值。对 rETH 来说,NAV 就是它的公允兑换率 exchange rate:
rETH NAV = getExchangeRate() = 总质押 ETH 价值 / rETH 总供应量
它反映 rETH 的”内在价值”,由质押本金 + 累积收益决定,与二级市场的买卖压力无关。
2. 两个”价格”:公允汇率 vs 市场价
这是本章最重要的区分:
| 公允汇率(NAV) | 市场价 | |
|---|---|---|
| 来源 | rETH.getExchangeRate() | DEX 现货价(Balancer/Uniswap/Curve) |
| 含义 | 内在价值(本金+收益) | 当下买卖能成交的价 |
| 受什么影响 | 质押收益、slashing | 供需、流动性、抛压 |
| 易被操纵吗 | 难(链上质押状态决定) | 易(一笔大额 swap 即可推动现货价) |
| 通常关系 | 基准 | 围绕 NAV 上下波动(折价/溢价) |
正常情况下市场价 ≈ NAV,但短期会因供需偏离(折价或溢价,第 2 章讲过)。
3. 公允汇率怎么来的
getExchangeRate() 的值由 Rocket Pool 的 网络余额(network balances) 决定,而网络余额由 Oracle DAO(一组受信任的预言机节点)定期把信标链上的质押状态(验证节点余额、收益、罚没)上报到链上更新。
所以公允汇率:
- 不是某个 DEX 的现货价,而是协议层根据真实质押状态算出的内在价值。
- 更新有一定周期(不是每个区块),但非常难被单笔交易操纵(要操纵它得操纵整个 Oracle DAO 的上报)。
这就是为什么估值优先用它。
4. 案例:估值用错价格的后果
假设你写了一个借贷协议,接受 rETH 抵押,用二级市场现货价来估抵押品价值。
攻击者:
- 用闪电贷在 rETH/WETH 池砸盘,把 rETH 现货价瞬间打到 0.5 ETH(远低于公允 1.1)。
- 你的协议读到这个被操纵的低价,认为某用户抵押不足,错误清算他。
- 攻击者低价吃下抵押品,再把现货价拉回,获利。
如果你用的是公允汇率 getExchangeRate(1.1),现货价被怎么操纵都不影响估值,这个攻击就失效了。
教训:抵押品估值、清算判断,必须用抗操纵的公允汇率,绝不能用 DEX 现货价。
5. 该用哪个价:场景对照
| 场景 | 该用 | 原因 |
|---|---|---|
| 抵押品估值 / 清算 | 公允汇率 | 抗操纵,反映内在价值 |
| 计算”我的 rETH 值多少 ETH” | 公允汇率 | 内在价值 |
| 实际买入/卖出 rETH | 市场价 | 你真正成交的价 |
| 判断该走一级还是二级进出 | 两者比较 | 选更划算的 |
| 套利判断 | 两者之差 | 折溢价就是套利空间 |
口诀:“估值看 NAV,成交看市场。“
6. 预言机安全:抗操纵取价
如果你的协议确实需要一个”rETH 的 ETH/USD 价格喂价”,安全做法:
- 优先用
getExchangeRate得到 rETH→ETH,再乘一个抗操纵的 ETH/USD 价(如 Chainlink)。 - 不要直接用 DEX 现货价作为预言机。
- 如果必须参考市场价,用TWAP(Uniswap V3 第 10 章 / Balancer 的时间加权价),而非瞬时现货价。
- 可以加偏离检查:如果市场价偏离公允汇率超过阈值(比如 ±5%),暂停相关操作或报警(防止脱锚时被攻击)。
Chainlink 也提供 rETH 的喂价(综合公允汇率 + 市场),生产中常直接用。
7. 折溢价与套利
NAV 和市场价的差就是折溢价,本身是套利信号:
- 折价(市场价 < NAV):在 DEX 便宜买 rETH,理论上可在一级市场按 NAV 赎回 ETH 获利(受赎回流动性限制)。
- 溢价(市场价 > NAV):在一级市场按 NAV 铸造 rETH,在 DEX 高价卖出获利(受 deposit 容量限制)。
这些套利会推动市场价回归 NAV,是 rETH 锚定的市场机制。但实际套利受第 2 章说的赎回流动性、deposit 容量限制,不总能执行——这也是折溢价偶尔较大的原因。
8. 本章小结
- NAV = rETH 公允汇率 =
getExchangeRate(),反映本金+收益的内在价值。 - 两个价要分清:公允汇率(抗操纵、估值用) vs 市场价(DEX 现货、成交用)。
- 公允汇率由 Oracle DAO 上报质押状态决定,单笔交易难操纵。
- 估值/清算用错价(用 DEX 现货)会被闪电贷操纵清算——必须用公允汇率。
- 口诀:估值看 NAV,成交看市场;需喂价时用
getExchangeRate × Chainlink ETH/USD或 TWAP,加偏离检查。 - NAV 与市场价之差(折溢价)是套利信号,但受赎回/容量限制。
9. 动手练习
对应课程的 rETH NAV 项目:在链上计算 rETH 净值并和市场价对比。
练习:计算 NAV 并检测脱锚
主网分叉:
interface IRETH {
function getExchangeRate() external view returns (uint256);
function getEthValue(uint256 rethAmount) external view returns (uint256);
}
// 二级市场价:用 Balancer rETH/WETH 池或 Uniswap V3 rETH/WETH 池
思路:
- 公允 NAV:读
getExchangeRate(),即 1 rETH 的公允 ETH 值。 - 市场价:从 Balancer/Uniswap 池报价”1 rETH 能换多少 WETH”(用池子的 getRate / Quoter / TWAP)。
- 算折溢价:
premium = (市场价 − NAV) / NAV,打印百分比。 - 脱锚检测:写一个
requirePegged(uint maxDeviationBps):若|premium| > maxDeviationBps(如 200 = 2%)则 revert。这是给依赖 rETH 估值的协议的安全闸门。 - (进阶)模拟攻击:用一笔大额 swap 把市场价打偏,验证你的
requirePegged会触发,而基于getExchangeRate的估值不受影响。
运行
forge test --evm-version cancun --fork-url $FORK_URL \
--match-path test/RethNav.t.sol -vvv
下一章(第 6 章 EigenLayer 再质押):把 rETH 存进 EigenLayer 做 restaking,理解再质押的收益与额外风险。