Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Part 3 β€” Module 1: Liquid Staking & Restaking

Difficulty: Intermediate

Estimated reading time: ~40 minutes | Exercises: ~2-3 hours


πŸ“š Table of Contents

Liquid Staking Fundamentals

Protocol Architecture

EigenLayer & Restaking

LST Integration Patterns

Wrap Up


πŸ’‘ Liquid Staking Fundamentals

πŸ’‘ Concept: Why Liquid Staking Exists

The problem: Ethereum staking requires 32 ETH and running a validator. Staked ETH is locked β€” you can’t use it as DeFi collateral, you can’t trade it, you can’t LP with it. For an asset class worth billions, that’s a massive capital efficiency problem.

The solution: Liquid staking protocols pool user deposits, run validators on their behalf, and issue a liquid receipt token (LST) that represents the staked position. The LST accrues staking rewards (~3-4% APR) while remaining freely tradeable and composable with DeFi.

Why this matters for DeFi developers: LSTs are the largest DeFi sector by TVL (~$50B+). wstETH is the most popular collateral type on Aave. Every major lending protocol, AMM, and vault must handle LSTs correctly β€” and β€œcorrectly” means understanding exchange rates, rebasing mechanics, oracle pricing, and de-peg risk. If you’re building DeFi, you’re integrating with LSTs.

Without liquid staking:                 With liquid staking:

32 ETH β†’ Validator                      10 ETH β†’ Lido
   β”‚                                       β”‚
   β”‚  Locked. Earning ~3.5%                β”‚  Receive 10 stETH
   β”‚  Can't use in DeFi.                   β”‚  Earning ~3.5% (balance rebases daily)
   β”‚                                       β”‚
   β–Ό                                       β–Ό
No DeFi composability.               Use stETH in DeFi:
                                      β€’ Collateral on Aave
                                      β€’ LP on Curve
                                      β€’ Deposit in Pendle (split yield)
                                      β€’ Collateral in CDPs
                                      β€’ Restake via EigenLayer

πŸ’‘ Concept: Two Models: Rebasing vs Non-Rebasing

LSTs represent staked ETH plus accumulated rewards. There are two fundamentally different approaches to reflecting those rewards.

Rebasing (stETH β€” Lido):

Your token balance increases daily. If you hold 10 stETH today, you’ll hold 10.001 stETH tomorrow (assuming ~3.5% APR). The token always represents ~1 staked ETH β€” the balance adjusts to reflect accumulated rewards.

Day 0:   balanceOf(you) = 10.000000 stETH
Day 1:   balanceOf(you) = 10.000959 stETH  (daily rebase at ~3.5% APR)
Day 30:  balanceOf(you) = 10.028767 stETH
Day 365: balanceOf(you) = 10.350000 stETH  (~3.5% growth)

The rebase happens automatically when Lido’s oracle reports new validator balances. You don’t call any function β€” your balanceOf() return value simply changes.

The DeFi integration problem: Many contracts assume token balances don’t change between transactions. A vault that stores balanceOf(address(this)) on deposit will find a different balance later β€” breaking accounting. This is the β€œweird token” callback issue from P2M1.

πŸ”— Connection: This is exactly why P2M1 covered rebasing tokens as a β€œweird token” category. Contracts that cache balances, emit transfer events, or calculate shares based on balance differences all break with stETH.

Non-Rebasing / Wrapped (wstETH, rETH):

Your token balance stays fixed. Instead, the exchange rate increases over time. 10 wstETH today might be worth 11.9 stETH, and 10 wstETH in a year will be worth ~12.3 stETH. Same number of tokens, more underlying value.

Day 0:   balanceOf(you) = 10 wstETH  β†’  worth 11.900 stETH  (at 1.190 rate)
Day 365: balanceOf(you) = 10 wstETH  β†’  worth 12.317 stETH  (at 1.232 rate)

Your balance didn't change. The exchange rate did.

This is the ERC-4626 pattern. wstETH behaves exactly like vault shares β€” fixed balance, increasing exchange rate. rETH works the same way. This is why DeFi protocols overwhelmingly prefer wstETH over stETH.

πŸ”— Connection: This maps directly to P2M7’s vault share math. convertToAssets(shares) in ERC-4626 is analogous to getStETHByWstETH(wstETHAmount) in Lido. Same mental model, same integration patterns.

Comparison:

Rebasing (stETH)Non-Rebasing (wstETH, rETH)
Balance changes?Yes β€” daily rebaseNo β€” fixed
Exchange rate?Always ~1:1 by definitionIncreases over time
DeFi-friendly?No β€” breaks many integrationsYes β€” standard ERC-20 behavior
Mental modelLike a bank account (balance grows)Like vault shares (share price grows)
Internal trackingShares (hidden from user)Shares ARE the token
Used in DeFi asRarely directly β€” wrapped to wstETH firstDirectly β€” wstETH and rETH composable everywhere

The pattern: In practice, stETH exists for user-facing simplicity (people understand β€œmy balance grows”), while wstETH exists for DeFi composability. This is why Aave, Compound, Maker, and every lending protocol lists wstETH, not stETH.

πŸ” Deep Dive: The Exchange Rate

The exchange rate is how non-rebasing LSTs reflect accumulated rewards. Understanding the math is critical for pricing, oracles, and integration.

wstETH exchange rate:

stEthPerToken = totalPooledEther / totalShares

Where totalPooledEther is all ETH controlled by Lido (staked + buffered) and totalShares is the total internal shares issued. When validators earn rewards, totalPooledEther increases while totalShares stays the same β€” so stEthPerToken increases.

Numeric walkthrough:

Given (approximate values, early 2026):
  totalPooledEther = 9,600,000 ETH
  totalShares      = 8,100,000 shares

  stEthPerToken = 9,600,000 / 8,100,000 = 1.1852

  So: 1 wstETH = 1.1852 stETH = 1.1852 ETH (at protocol rate)

After one year of ~3.5% staking rewards:
  totalPooledEther = 9,600,000 Γ— 1.035 = 9,936,000 ETH
  totalShares      = 8,100,000 (unchanged β€” no new deposits for simplicity)

  stEthPerToken = 9,936,000 / 8,100,000 = 1.2267

  So: 1 wstETH = 1.2267 stETH (3.5% increase in exchange rate)

Converting between wstETH and stETH:

Wrapping:   wstETH amount = stETH amount / stEthPerToken
Unwrapping: stETH amount  = wstETH amount Γ— stEthPerToken
Example: Wrap 100 stETH when stEthPerToken = 1.1852
  wstETH received = 100 / 1.1852 = 84.37 wstETH

Later: Unwrap 84.37 wstETH when stEthPerToken = 1.2267
  stETH received = 84.37 Γ— 1.2267 = 103.50 stETH

  Gain: 3.50 stETH β€” the staking rewards accumulated while holding wstETH

rETH exchange rate:

Rocket Pool’s rETH uses a similar pattern but with different internals. The exchange rate is updated by Rocket Pool’s Oracle DAO rather than derived from beacon chain balances.

rETH exchange rate = total ETH backing rETH / total rETH supply

Approximate value (early 2026): ~1.12 ETH per rETH
  (Rocket Pool launched Nov 2021, ~4 years of ~3% net yield after commission)

Example: 10 rETH Γ— 1.12 = 11.2 ETH equivalent

Note: Rocket Pool takes a 14% commission on staking rewards (distributed to node operators as RPL). So if beacon chain yields 3.5%, rETH holders earn ~3.0% net. This commission is why rETH’s exchange rate grows slightly slower than wstETH’s.

πŸ’» Quick Try:

Fork mainnet in Foundry and check current exchange rates:

// In a Foundry test with mainnet fork
IWstETH wstETH = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0);
uint256 rate = wstETH.stEthPerToken();
console.log("wstETH exchange rate:", rate); // ~1.19e18

IRocketTokenRETH rETH = IRocketTokenRETH(0xae78736Cd615f374D3085123A210448E74Fc6393);
uint256 rethRate = rETH.getExchangeRate();
console.log("rETH exchange rate:", rethRate); // ~1.12e18

Deploy, call these view functions, and observe both rates are > 1.0 β€” reflecting years of accumulated staking rewards.

πŸ’‘ Concept: Withdrawal Queue (Post-Shapella)

Before Ethereum’s Shapella upgrade (April 2023), staked ETH could not be withdrawn. LSTs traded at a discount to ETH because there was no redemption mechanism β€” the only way to exit was selling on a DEX.

After Shapella: Lido and Rocket Pool implemented withdrawal queues. Users can request to redeem their LST for underlying ETH, but the process takes time:

Request flow:
  User calls requestWithdrawals(stETHAmount)
       β”‚
       β–Ό
  Protocol queues withdrawal
  User receives NFT receipt (Lido uses ERC-721)
       β”‚
       β–Ό
  Wait for validators to exit + ETH to become available
  (typically 1-5 days, can be longer during high demand)
       β”‚
       β–Ό
  Withdrawal finalized
  User calls claimWithdrawal(requestId)
  ETH returned to user

Impact on LST/ETH peg:

  • The withdrawal queue creates an arbitrage loop: if stETH trades below 1 ETH on a DEX, arbitrageurs buy cheap stETH β†’ request withdrawal β†’ receive 1 ETH β†’ profit. This keeps the peg tight.
  • During extreme demand (mass exits), the queue lengthens and the peg can weaken β€” arbitrageurs must lock capital longer, reducing their incentive.
  • Post-Shapella, stETH has traded very close to 1:1 with ETH. The June 2022 de-peg (0.93 ETH) happened pre-Shapella when no withdrawal mechanism existed.

🎯 Build Exercise: LST Oracle Consumer

Workspace: workspace/src/part3/module1/

Build a WstETHOracle contract that correctly prices wstETH in USD using a two-step pipeline.

What you’ll implement:

  • getWstETHValueUSD(uint256 wstETHAmount) β€” exchange rate Γ— Chainlink ETH/USD, with staleness checks on both data sources
  • getWstETHValueUSDSafe(uint256 wstETHAmount) β€” same pipeline but with dual oracle pattern: uses min(protocolRate, marketRate) for the stETH β†’ ETH conversion
  • Staleness checks on both Chainlink feeds (ETH/USD and stETH/ETH)
  • Decimal normalization across the pipeline

What’s provided:

  • Mock wstETH contract with configurable exchange rate (stEthPerToken)
  • Mock Chainlink aggregator for ETH/USD and stETH/ETH feeds
  • Interfaces for IWstETH and Chainlink AggregatorV3Interface

Tests verify:

  • Basic pricing matches manual calculation (known exchange rate Γ— known price)
  • Dual oracle uses market price during simulated de-peg (stETH/ETH < 1.0)
  • Staleness check reverts on stale ETH/USD feed
  • Staleness check reverts on stale stETH/ETH feed
  • Exchange rate growth over time produces correct price increase
  • Zero amount reverts with ZeroAmount error
  • Decimal normalization is correct across the pipeline

🎯 Goal: Internalize the two-step LST pricing pipeline and the dual oracle safety pattern. This is the exact oracle design used by Aave, Morpho, and every lending protocol that accepts wstETH.


πŸ“‹ Summary: Liquid Staking Fundamentals

Covered:

  • Why liquid staking exists β€” capital efficiency for staked ETH
  • Two models β€” rebasing (stETH, balance changes) vs non-rebasing (wstETH/rETH, exchange rate changes)
  • Exchange rate math β€” stEthPerToken and getExchangeRate() with numeric walkthroughs
  • Why DeFi prefers non-rebasing β€” same ERC-4626 mental model, no integration surprises
  • Withdrawal queue β€” post-Shapella redemption mechanism and its peg stabilization role

Key insight: Non-rebasing LSTs are conceptually identical to ERC-4626 vault shares. If you understand convertToAssets(shares), you understand getStETHByWstETH(wstETHAmount). The pricing pipeline, the manipulation concerns, and the oracle integration patterns all carry over from P2M7 and P2M9.

Next: How Lido and Rocket Pool actually implement this β€” the contract architecture that makes liquid staking work.

πŸ’Ό Job Market Context

What DeFi teams expect you to know:

  1. β€œHow would you integrate wstETH as collateral in a lending protocol?”

    • Good answer: β€œUse the exchange rate to convert wstETH to ETH, then Chainlink for ETH/USD.”
    • Great answer: β€œTwo-step pricing: getStETHByWstETH() for the exchange rate, then Chainlink ETH/USD. But I’d also use a Chainlink stETH/ETH market feed as a second oracle, taking the minimum β€” the dual oracle pattern. During a de-peg (like June 2022), the exchange rate says 1:1 but the market says 0.93. Without the dual oracle, positions appear healthier than they really are, and liquidations don’t fire when they should.”
  2. β€œExplain the difference between stETH and wstETH and when you’d use each.”

    • Good answer: β€œstETH rebases, wstETH doesn’t.”
    • Great answer: β€œBoth represent the same underlying staked ETH. stETH uses rebasing β€” your balance grows daily as oracle reports update totalPooledEther. Internally, stETH tracks shares, and balanceOf() returns shares Γ— totalPooledEther / totalShares. wstETH is a wrapper that exposes those shares directly as a standard ERC-20 β€” your balance is fixed, and the exchange rate stEthPerToken grows instead. You’d use wstETH for any DeFi integration β€” lending, vaults, AMMs β€” because rebasing breaks contracts that cache balances.”

Interview Red Flags:

  • 🚩 Saying β€œstETH is always worth 1 ETH” without qualifying that this is the protocol exchange rate, not the market rate
  • 🚩 Not knowing why DeFi protocols prefer wstETH over stETH (rebasing breaks balance caching)
  • 🚩 Treating the exchange rate as a simple constant rather than understanding it’s derived from totalPooledEther / totalShares

Pro tip: When discussing LSTs in interviews, lead with the two-model distinction (rebasing vs non-rebasing) and immediately connect it to DeFi composability. Saying β€œwstETH exists because rebasing breaks DeFi” shows you understand the real engineering constraint, not just the token names.


πŸ’‘ Protocol Architecture

πŸ’‘ Concept: Lido Architecture

Lido is the largest liquid staking protocol (~70% market share of ETH LSTs). Understanding its architecture is essential because most DeFi LST integrations target wstETH.

User                   Lido Protocol                         Beacon Chain
  β”‚                         β”‚                                     β”‚
  │── submit(ETH) ─────→  Lido (stETH)                          β”‚
  β”‚                    β”‚  β€’ mint shares to user                   β”‚
  β”‚                    β”‚  β€’ buffer ETH                            β”‚
  β”‚                    β”‚        β”‚                                  β”‚
  β”‚                    β”‚  StakingRouter                           β”‚
  β”‚                    β”‚  β€’ allocate to Node Operators ────────→  Validators
  β”‚                    β”‚                                          β”‚
  β”‚                    β”‚  AccountingOracle                        β”‚
  β”‚                    β”‚  ← CL balance report ─────────────────  β”‚
  β”‚                    β”‚  β€’ update totalPooledEther               β”‚
  β”‚                    β”‚  β€’ triggers rebase for all holders       β”‚
  β”‚                    β”‚                                          β”‚
  │── wrap(stETH) ──→ WstETH                                    β”‚
  β”‚                    β”‚  β€’ holds stETH shares internally         β”‚
  β”‚                    β”‚  β€’ user gets fixed-balance wstETH        β”‚
  β”‚                    β”‚                                          β”‚
  │── requestWithdrawals β†’ WithdrawalQueueERC721                 β”‚
  β”‚                    β”‚  β€’ mint NFT receipt                      β”‚
  β”‚                    β”‚  β€’ finalized when ETH available ←──────  β”‚
  │── claimWithdrawal ─→  β€’ return ETH to user                  β”‚

Key contracts:

ContractRoleKey functions
Lido.sol (stETH)Main contract β€” ERC-20 rebasing token + depositsubmit(), getSharesByPooledEth(), getPooledEthByShares()
WstETH.solNon-rebasing wrapperwrap(), unwrap(), stEthPerToken(), getStETHByWstETH()
AccountingOracle.solReports beacon chain statesubmitReportData() β†’ triggers handleOracleReport()
StakingRouter.solRoutes ETH to node operatorsdeposit(), module-based operator allocation
WithdrawalQueueERC721.solWithdrawal requests as NFTsrequestWithdrawals(), claimWithdrawals()
NodeOperatorsRegistry.solCurated operator setOperator management (permissioned β€” centralization point)

πŸ” Deep Dive: Shares-Based Accounting in Lido

Lido’s stETH looks like a simple rebasing token from the outside, but internally it uses shares-based accounting β€” the same pattern as Aave’s aTokens and ERC-4626 vaults.

The core math:

// Internal: every stETH holder has a shares balance
mapping(address => uint256) private shares;
uint256 public totalShares;
uint256 public totalPooledEther; // updated by oracle

// External: balanceOf returns stETH (not shares)
function balanceOf(address account) public view returns (uint256) {
    return shares[account] * totalPooledEther / totalShares;
}

// Deposit: ETH β†’ shares
function submit(address referral) external payable returns (uint256) {
    uint256 sharesToMint = msg.value * totalShares / totalPooledEther;
    shares[msg.sender] += sharesToMint;
    totalShares += sharesToMint;
    totalPooledEther += msg.value;
    return sharesToMint;
}

How the rebase works:

Before oracle report:
  totalPooledEther = 1,000,000 ETH
  totalShares      = 900,000
  Alice has         = 9,000 shares

  Alice's balance = 9,000 Γ— 1,000,000 / 900,000 = 10,000 stETH

Oracle reports: validators earned 100 ETH in rewards.

After oracle report:
  totalPooledEther = 1,000,100 ETH  (increased by 100)
  totalShares      = 900,000         (unchanged)
  Alice has         = 9,000 shares   (unchanged)

  Alice's balance = 9,000 Γ— 1,000,100 / 900,000 = 10,001.00 stETH

Alice's balance increased by 1 stETH without any transaction. That's the rebase.

Why shares internally? Because updating totalPooledEther once (O(1)) is far cheaper than iterating over every holder’s balance (O(n)). The math resolves everything at read time. This is the same insight behind ERC-4626 and Aave’s scaled balances β€” one global variable update serves all holders.

πŸ”— Connection: This is the exact pattern from P2M7’s vault share math. The only difference is naming: ERC-4626 calls it totalAssets / totalSupply, Lido calls it totalPooledEther / totalShares. Same math, same O(1) rebase mechanism.

πŸ’‘ Concept: wstETH: The Non-Rebasing Wrapper

wstETH is a thin wrapper around stETH shares. When you β€œwrap” stETH, you’re converting from the rebasing representation to the shares representation. When you β€œunwrap,” you convert back.

// Simplified from Lido's WstETH.sol
contract WstETH is ERC20 {
    IStETH public stETH;

    function wrap(uint256 stETHAmount) external returns (uint256) {
        // Convert stETH amount to shares
        uint256 wstETHAmount = stETH.getSharesByPooledEth(stETHAmount);
        // Transfer stETH in (as shares internally)
        stETH.transferFrom(msg.sender, address(this), stETHAmount);
        // Mint wstETH 1:1 with shares
        _mint(msg.sender, wstETHAmount);
        return wstETHAmount;
    }

    function unwrap(uint256 wstETHAmount) external returns (uint256) {
        // Convert shares back to stETH amount
        uint256 stETHAmount = stETH.getPooledEthByShares(wstETHAmount);
        // Burn wstETH
        _burn(msg.sender, wstETHAmount);
        // Transfer stETH out
        stETH.transfer(msg.sender, stETHAmount);
        return stETHAmount;
    }

    // The exchange rate β€” how much stETH one wstETH is worth
    function stEthPerToken() external view returns (uint256) {
        return stETH.getPooledEthByShares(1 ether); // 1 share β†’ X stETH
    }

    // Conversion helpers
    function getWstETHByStETH(uint256 stETHAmount) external view returns (uint256) {
        return stETH.getSharesByPooledEth(stETHAmount);
    }

    function getStETHByWstETH(uint256 wstETHAmount) external view returns (uint256) {
        return stETH.getPooledEthByShares(wstETHAmount);
    }
}

The key insight: 1 wstETH = 1 Lido share. The β€œwrapping” is conceptual β€” wstETH simply exposes shares as a standard ERC-20 instead of hiding them behind the rebasing balanceOf(). This is why wstETH is DeFi-compatible: its balance never changes, only the rate returned by stEthPerToken() grows.

πŸ’‘ Concept: Oracle Reporting & the Rebase Mechanism

The oracle is how Lido learns about validator performance on the beacon chain (consensus layer). This is a trust assumption worth understanding.

The flow:

Beacon Chain validators earn rewards
       β”‚
       β–Ό
Oracle committee (5/9 quorum in V1; V2 uses HashConsensus)
reports new total CL balance
       β”‚
       β–Ό
AccountingOracle.submitReportData()
       β”‚
       β–Ό
Lido._handleOracleReport()
  β€’ Updates totalPooledEther
  β€’ Applies sanity checks:
    - APR can't exceed a configured max (~10%)
    - Balance can't drop more than configured limit (slashing protection)
  β€’ Mints fee shares (10% of rewards β†’ treasury + node operators)
  β€’ All stETH holders' balanceOf() now returns updated values

The trust model: Lido relies on a permissioned oracle committee to report beacon chain balances accurately. This is a centralization point β€” if the oracle reports inflated balances, stETH becomes over-valued. The sanity checks (max APR cap, max balance drop) limit the damage from a compromised oracle, but the trust assumption exists.

Sanity check example:

Last reported: totalPooledEther = 9,600,000 ETH
New report claims: totalPooledEther = 10,500,000 ETH

APR implied: (10,500,000 - 9,600,000) / 9,600,000 = 9.375%
Max allowed APR: 10%

9.375% < 10% β†’ passes sanity check

But if new report claimed 11,000,000 ETH:
APR implied: 14.6% β†’ exceeds 10% cap β†’ REJECTED

(Simplified β€” Lido's actual checks use per-report balance limits, not annualized rates.
 This annualized framing illustrates the concept.)

Frequency: Oracle reports happen roughly once per day. (Lido V1 used a fixed ~225-epoch cadence; V2 uses configurable reporting frames that can vary.) Between reports, the exchange rate is stale β€” it doesn’t reflect the latest beacon chain rewards. This staleness is normally negligible but matters during rapid market changes.

πŸ”— Connection: This oracle sanity check pattern is analogous to the rate cap you saw in P2M9’s vault share pricing β€” both limit how fast an exchange rate can grow to prevent manipulation. Lido’s cap is built into the protocol itself; your P2M9 stablecoin cap was external.

πŸ’‘ Concept: Rocket Pool: Decentralized Alternative

Rocket Pool takes a different approach to decentralization. Where Lido uses a curated set of professional operators, Rocket Pool is permissionless β€” anyone can run a validator.

The minipool model:

Traditional staking:     Validator needs 32 ETH from one source

Rocket Pool minipool:    Validator needs:
                           β€’ 8 ETH from node operator (+ RPL stake as insurance)
                           β€’ 24 ETH from rETH depositors (pooled)
                         Or:
                           β€’ 16 ETH from node operator (+ RPL stake)
                           β€’ 16 ETH from rETH depositors

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚            32 ETH Validator              β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 8 ETH      β”‚        24 ETH              β”‚
  β”‚ (operator) β”‚   (rETH depositors pool)   β”‚
  β”‚ + RPL bond β”‚                             β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

rETH exchange rate:

// Simplified from RocketTokenRETH.sol
function getExchangeRate() public view returns (uint256) {
    uint256 totalEth = address(rocketDepositPool).balance
                     + totalStakedEthInMinipools
                     + rewardsAccumulated;
    uint256 rethSupply = totalSupply();
    if (rethSupply == 0) return 1 ether;
    return totalEth * 1 ether / rethSupply;
}

The rate is updated by Rocket Pool’s Oracle DAO (a set of trusted nodes) rather than derived directly from the contract’s beacon chain view. This introduces a similar trust assumption to Lido’s oracle, but with a different governance structure.

Trade-offs: Lido vs Rocket Pool

Lido (stETH/wstETH)Rocket Pool (rETH)
Market share~70% of LST market~5-8%
Operator modelCurated (permissioned)Permissionless (8 ETH + RPL)
OracleOracle committee (5/9)Oracle DAO (trusted node set)
DeFi liquidityDeep (Curve, Aave, Uniswap, etc.)Thinner but growing
Commission10% of rewards14% of rewards
Exchange rate (approx. early 2026)~1.19~1.12
GovernanceLDO token + dual governancepDAO + oDAO
Centralization concernOperator set concentrationOracle DAO trust

Why this matters for integration: When you build a protocol that accepts LST collateral, you’ll likely support both wstETH and rETH. The oracle pricing pattern is the same (exchange rate Γ— underlying price), but the liquidity profiles differ. wstETH can be liquidated against deep Curve/Uniswap pools; rETH has thinner secondary market liquidity, so you’d set a lower LTV for rETH collateral.

πŸ“– Code Reading Strategy

Lido β€” reading order:

#FileWhy ReadKey Functions
1WstETH.solSimplest entry point β€” clean wrapperwrap(), unwrap(), stEthPerToken()
2Lido.sol (stETH)Core token β€” shares-based accountingsubmit(), _transferShares(), getPooledEthByShares()
3AccountingOracle.solHow rebase is triggeredsubmitReportData(), sanity checks
4WithdrawalQueueERC721.solExit mechanismrequestWithdrawals(), _finalize()

Don’t get stuck on: Lido’s governance contracts, the Burner contract (handles cover/slashing accounting), or the StakingRouter module system. These are protocol-governance concerns, not DeFi integration concerns.

Rocket Pool β€” reading order:

#FileWhy ReadKey Functions
1RocketTokenRETH.solThe token β€” exchange rategetExchangeRate(), mint(), burn()
2RocketDepositPool.solDeposit entry pointdeposit() β†’ allocates to minipools

Don’t get stuck on: Rocket Pool’s minipool lifecycle contracts (RocketMinipoolManager, RocketMinipoolDelegate). These are validator-operations concerns, not DeFi integration concerns.

Repos: Lido | Rocket Pool

πŸ“‹ Summary: Protocol Architecture

Covered:

  • Lido architecture β€” 6 key contracts with roles and data flow
  • Shares-based accounting β€” internal shares + totalPooledEther enables O(1) rebase
  • wstETH wrapper β€” exposes shares as standard ERC-20 (no rebase surprises)
  • Oracle reporting β€” how beacon chain rewards become stETH balance changes, including sanity checks
  • Rocket Pool β€” permissionless minipool model, rETH exchange rate, trade-offs vs Lido
  • Code reading strategy with file-level specifics

Key insight: Both Lido and Rocket Pool use the same underlying math (shares Γ— rate = value) but expose it differently. Lido shows it as a rebasing balance (stETH) with a wrapper option (wstETH). Rocket Pool only offers the non-rebasing form (rETH). For DeFi integration, both are β€œexchange rate Γ— underlying price” β€” the same pipeline.

Next: Restaking β€” the layer built on top of liquid staking, and the new risk frontier.

🧭 Checkpoint β€” Before Moving On: Can you explain the difference between stETH and wstETH in terms of how they represent staking rewards? Can you calculate a wstETH β†’ stETH conversion given a stEthPerToken value? If you can, you understand the foundation that everything else in this module builds on.

πŸ’Ό Job Market Context

What DeFi teams expect you to know:

  1. β€œHow does Lido’s oracle work, and what are the trust assumptions?”
    • Good answer: β€œOracle committee reports beacon chain balances, triggering rebase.”
    • Great answer: β€œA permissioned oracle committee (5/9 quorum) submits beacon chain balance reports to AccountingOracle. The report updates totalPooledEther, which changes every stETH holder’s balanceOf() return value. Sanity checks cap the maximum APR and maximum balance drop to limit damage from a compromised oracle. The trust assumption is that the oracle committee honestly reports balances β€” if they inflate the report, stETH becomes temporarily overvalued. This is similar to how Chainlink oracles are a trust assumption for price feeds.”

Interview Red Flags:

  • 🚩 Not being able to explain the oracle reporting mechanism β€” it’s a critical trust assumption, not a minor detail
  • 🚩 Describing the rebase as β€œautomatic” without explaining that it’s triggered by an oracle committee report
  • 🚩 Ignoring the sanity checks (APR cap, max balance drop) that limit oracle manipulation damage

Pro tip: When teams ask about Lido’s oracle, mention the sanity bounds unprompted. Showing you know that AccountingOracle caps max APR and max balance drop per report signals that you’ve read the actual code, not just the docs.


πŸ’‘ EigenLayer & Restaking

πŸ’‘ Concept: What is Restaking?

Staked ETH secures Ethereum’s consensus layer. Restaking extends this security to additional protocols by allowing stakers to opt in to securing additional services with the same stake.

The concept:

Traditional staking:
  32 ETH β†’ Secures Ethereum β†’ Earns ~3.5% APR

Restaking:
  32 ETH β†’ Secures Ethereum β†’ Earns ~3.5% APR
         β†’ ALSO secures Oracle Network β†’ Earns +0.5% APR
         β†’ ALSO secures Bridge Protocol β†’ Earns +0.3% APR
         β†’ ALSO secures Data Availability β†’ Earns +0.4% APR

  Same capital, multiple revenue streams.
  Trade-off: additional slashing risk for each service.

Why it matters: Before EigenLayer, every new protocol that needed economic security had to bootstrap its own staking system β€” recruit validators, create a token, incentivize staking. Restaking lets protocols β€œrent” Ethereum’s existing security. This is a fundamental shift in how decentralized infrastructure is bootstrapped.

πŸ’» Quick Try (read-only, optional):

If you have an Ethereum mainnet RPC (e.g., Alchemy/Infura), you can inspect EigenLayer’s live state:

// In Foundry's cast:
// cast call 0x858646372CC42E1A627fcE94aa7A7033e7CF075A "getTotalShares(address)(uint256)" 0x93c4b944D05dfe6df7645A86cd2206016c51564D --rpc-url $RPC
// (StrategyManager β†’ stETH strategy shares)

This is a read-only peek at how much stETH is restaked in EigenLayer. No testnet deployment needed β€” just a mainnet RPC call.

πŸ’‘ Concept: EigenLayer Architecture

EigenLayer is the dominant restaking protocol. It has four core components:

                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚    AVS Contracts       β”‚
                      β”‚  (EigenDA, oracles,    β”‚
                      β”‚   bridges, sequencers) β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚ registers + validates
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚      Operators         β”‚
                      β”‚  (run AVS software,    β”‚
                      β”‚   sign attestations)   β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚ delegation
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚  DelegationManager     β”‚
                      β”‚  (stakers β†’ operators) β”‚
                      β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
                            β”‚           β”‚
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
               β”‚StrategyManagerβ”‚  β”‚ EigenPodManager   β”‚
               β”‚  (LST deposit)β”‚  β”‚ (native ETH       β”‚
               β”‚  wstETH, rETHβ”‚  β”‚  restaking via     β”‚
               β”‚  cbETH, etc. β”‚  β”‚  beacon proofs)    β”‚
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

StrategyManager β€” Handles LST restaking. Users deposit LSTs (wstETH, rETH, etc.) into strategies. Each strategy holds one token type. The deposited tokens become the staker’s restaked capital.

EigenPodManager β€” Handles native ETH restaking. Validators point their withdrawal credentials to an EigenPod contract. The pod verifies beacon chain proofs to confirm the validator’s balance and status. No LST needed β€” raw staked ETH is restaked.

DelegationManager β€” The bridge between stakers and operators. Stakers delegate their restaked assets to operators who actually run AVS infrastructure. Stakers earn rewards but also bear slashing risk from the operator’s behavior.

AVS (Actively Validated Services) β€” The protocols secured by restaked ETH. Each AVS defines its own:

  • What operators must do (run specific software, provide attestations)
  • What constitutes misbehavior (triggers slashing)
  • How rewards are distributed

Major AVSes include EigenDA (data availability), various oracle networks, and bridge validation services.

The delegation and slashing flow:

Staker deposits 100 wstETH into StrategyManager
       β”‚
       β–Ό
Staker delegates to Operator A via DelegationManager
       β”‚
       β–Ό
Operator A opts into EigenDA AVS + Oracle AVS
       β”‚
       β”œβ”€β”€ Operator runs EigenDA node β†’ earns rewards β†’ distributed to staker
       β”‚
       └── Operator runs Oracle node β†’ earns rewards β†’ distributed to staker

If Operator A misbehaves on either AVS:
       β”‚
       β–Ό
AVS triggers slashing β†’ portion of staker's 100 wstETH is seized

Key point for DeFi developers: You don’t need to understand EigenLayer’s internals deeply to integrate with it. What matters is understanding that restaked assets have additional slashing risk beyond normal staking β€” and this risk affects how you should value LRTs (liquid restaking tokens) as collateral.

πŸ’‘ Concept: Liquid Restaking Tokens (LRTs)

LRTs are to restaking what LSTs are to staking β€” liquid receipt tokens for restaked positions.

Staking:                        Restaking:
ETH β†’ Lido β†’ stETH (LST)       stETH β†’ EigenLayer β†’ deposit receipt
                                  β”‚
                                  └── Not liquid! Locked in EigenLayer.

Liquid Restaking:
ETH β†’ EtherFi β†’ weETH (LRT)
  Internally: EtherFi stakes ETH β†’ restakes via EigenLayer β†’ issues weETH
  User gets: liquid token representing staked + restaked ETH

Major LRTs (early 2026):

LRTProtocolStrategyNotes
weETHEtherFiNative restakingLargest LRT by TVL
ezETHRenzoMulti-AVS restakingDiversified operator set
rsETHKelpDAOLST restakingAccepts multiple LSTs
pufETHPufferNative + anti-slashingUses Secure-Signer TEE technology

LRT exchange rates reflect both staking rewards AND restaking rewards (minus fees). They’re more complex than LST exchange rates because the yield sources are more diverse and the risk profile is different.

Integration caution: LRTs are newer and less battle-tested than LSTs. Their exchange rate mechanisms vary more across protocols, their oracle infrastructure is less mature, and their liquidity on DEXes is thinner. For DeFi integration (lending, collateral), LRTs warrant lower LTVs and more conservative oracle designs than wstETH or rETH.

⚠️ The Risk Landscape

Risk stacking visualization:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  LRT (weETH, ezETH)                                 β”‚ ← LRT contract risk
β”‚  β€’ Smart contract bugs in LRT protocol               β”‚   + liquidity risk
β”‚  β€’ Exchange rate oracle accuracy                      β”‚   + de-peg risk
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Restaking (EigenLayer)                              β”‚ ← AVS slashing risk
β”‚  β€’ Operator misbehavior β†’ slashing                   β”‚   + operator risk
β”‚  β€’ AVS-specific failure modes                        β”‚   + smart contract risk
β”‚  β€’ Correlated slashing across AVSes                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  LST (wstETH, rETH)                                 β”‚ ← Protocol risk
β”‚  β€’ Lido/Rocket Pool smart contract bug               β”‚   + oracle risk
β”‚  β€’ Oracle committee compromise                       β”‚   + de-peg risk
β”‚  β€’ Validator slashing (minor β€” diversified)          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  ETH Staking (Beacon Chain)                          β”‚ ← Validator risk
β”‚  β€’ Individual validator slashing                     β”‚   (minor if diversified)
β”‚  β€’ Inactivity penalties                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  ETH (Base Asset)                                    β”‚ ← Market risk only
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Each layer ADDS risk. You inherit ALL layers below you.
  ETH holder:     1 risk layer
  wstETH holder:  3 risk layers
  weETH holder:   5 risk layers

Why this matters for DeFi integration:

When you accept an asset as collateral, you must account for ALL risk layers. This directly affects:

  • LTV ratios: ETH might get 85% LTV, wstETH 80%, rETH 75%, weETH 65%
  • Oracle design: More risk layers β†’ more defensive pricing needed
  • Liquidation parameters: Thinner liquidity β†’ higher liquidation bonus needed
  • Debt ceilings: Higher risk β†’ lower maximum exposure

This is not theoretical β€” Aave, Morpho, and every lending protocol that lists these assets goes through exactly this analysis.

The systemic risk: If many AVSes use the same operator set, and that operator set gets slashed on one AVS, the collateral damage cascades β€” all LRTs backed by those operators lose value simultaneously. This correlated slashing risk is the restaking-specific systemic concern.

πŸ“‹ Summary: EigenLayer & Restaking

Covered:

  • Restaking concept β€” recycling economic security, additional yield for additional risk
  • EigenLayer’s 4 core components β€” StrategyManager, EigenPodManager, DelegationManager, AVS
  • The delegation and slashing flow β€” how stakers, operators, and AVSes interact
  • LRTs β€” liquid receipt tokens for restaked positions (weETH, ezETH, rsETH, pufETH)
  • Risk stacking β€” each layer adds risk, directly affecting DeFi integration parameters

Key insight: The risk stacking diagram is what DeFi integration comes down to. Every LTV ratio, oracle design choice, and liquidation parameter for LSTs and LRTs is ultimately a judgment about which risk layers you’re willing to accept and at what discount. This is the analysis that protocol risk teams perform β€” and being able to articulate it is a strong interview signal.

Next: Putting it all together β€” how to actually integrate LSTs into DeFi protocols.

πŸ’Ό Job Market Context

What DeFi teams expect you to know:

  1. β€œWhat are the risks of accepting LRTs as collateral?”
    • Good answer: β€œSmart contract risk, slashing risk, liquidity risk.”
    • Great answer: β€œRisk stacking β€” an LRT like weETH carries five layers of risk: ETH market risk, validator slashing, LST protocol risk, EigenLayer smart contract and AVS slashing risk, and the LRT protocol’s own risk. Each layer compounds. I’d set LTV significantly lower than for plain wstETH (maybe 65% vs 80%), require deeper liquidity on DEX for liquidation viability, set higher liquidation bonus to compensate bidders for the added complexity of selling an LRT, and impose tighter debt ceilings.”

Interview Red Flags:

  • 🚩 Treating LSTs and LRTs as having the same risk profile β€” LRTs stack additional slashing and smart contract layers
  • 🚩 Listing risks without quantifying the impact on protocol parameters (LTV, liquidation bonus, debt ceilings)
  • 🚩 Not mentioning correlated slashing β€” if an AVS slashes, it can affect all LRTs delegated to that operator simultaneously

Pro tip: If asked about EigenLayer/restaking, focus on the risk analysis (risk stacking, correlated slashing, LTV implications) rather than trying to explain the full architecture. Teams care more about how you’d evaluate the risk of accepting restaked assets than about memorizing contract names.


πŸ’‘ LST Integration Patterns

πŸ” Deep Dive: LST Oracle Pricing Pipeline

Pricing LSTs requires a two-step pipeline β€” convert to underlying ETH via exchange rate, then price ETH in USD via Chainlink. This is the same pattern you saw in P2M9’s vault share pricing.

The pipeline:

wstETH pricing (two steps):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  getStETHByWstETH  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Chainlink    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ wstETH   β”‚ ────────────────→  β”‚  ETH equiv β”‚ ────────────→  β”‚ USD value β”‚
  β”‚ (18 dec) β”‚   exchange rate    β”‚  (18 dec)  β”‚   ETH/USD     β”‚ (8 dec)   β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   (8 dec)      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

rETH pricing (two steps):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  getExchangeRate   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Chainlink    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ rETH     β”‚ ────────────────→  β”‚  ETH equiv β”‚ ────────────→  β”‚ USD value β”‚
  β”‚ (18 dec) β”‚   exchange rate    β”‚  (18 dec)  β”‚   ETH/USD     β”‚ (8 dec)   β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   (8 dec)      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Compare to ETH pricing (one step):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    Chainlink     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ ETH      β”‚ ──────────────────────────────→  β”‚ USD value β”‚
  β”‚ (18 dec) β”‚                    ETH/USD       β”‚ (8 dec)   β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    (8 dec)       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”— Connection: This is the exact same two-step pattern from P2M9’s vault share collateral pricing. getStETHByWstETH() is convertToAssets() by another name. The decimal normalization, the manipulation concerns, and the code structure all carry over.

Numeric walkthrough β€” wstETH:

Given:
  wstETH amount    = 10 wstETH              (18 decimals β†’ 10e18)
  stEthPerToken    = 1.19e18                 (exchange rate, 18 decimals)
  ETH/USD price    = $3,200                  (Chainlink 8 decimals β†’ 3200e8)

Step 1: wstETH β†’ ETH equivalent
  ethEquiv = wstETHAmount Γ— stEthPerToken / 1e18
           = 10e18 Γ— 1.19e18 / 1e18
           = 11.9e18 ETH

Step 2: ETH β†’ USD
  valueUSD = ethEquiv Γ— ethPrice / 1e18
           = 11.9e18 Γ— 3200e8 / 1e18
           = 38_080e8

  10 wstETH = $38,080.00 USD

Numeric walkthrough β€” rETH:

Given:
  rETH amount      = 10 rETH                (18 decimals β†’ 10e18)
  rETH exchange    = 1.12e18                 (ETH per rETH, 18 decimals)
  ETH/USD price    = $3,200                  (Chainlink 8 decimals β†’ 3200e8)

Step 1: rETH β†’ ETH equivalent
  ethEquiv = rETHAmount Γ— exchangeRate / 1e18
           = 10e18 Γ— 1.12e18 / 1e18
           = 11.2e18 ETH

Step 2: ETH β†’ USD
  valueUSD = ethEquiv Γ— ethPrice / 1e18
           = 11.2e18 Γ— 3200e8 / 1e18
           = 35_840e8

  10 rETH = $35,840.00 USD

Solidity implementation:

function getLSTValueUSD(
    address lstToken,
    uint256 amount,
    bool isWstETH
) public view returns (uint256 valueUSD) {
    uint256 ethEquivalent;

    if (isWstETH) {
        // wstETH β†’ ETH via Lido exchange rate
        ethEquivalent = IWstETH(lstToken).getStETHByWstETH(amount);
    } else {
        // rETH β†’ ETH via Rocket Pool exchange rate
        uint256 rate = IRocketTokenRETH(lstToken).getExchangeRate();
        ethEquivalent = amount * rate / 1e18;
    }

    // ETH β†’ USD via Chainlink
    (, int256 ethPrice,,uint256 updatedAt,) = ethUsdFeed.latestRoundData();
    require(ethPrice > 0, "Invalid price");
    require(block.timestamp - updatedAt <= STALENESS_THRESHOLD, "Stale price");

    valueUSD = ethEquivalent * uint256(ethPrice) / 1e18;
    // Result in 8 decimals (Chainlink ETH/USD decimals)
}

⚠️ De-Peg Scenarios and the Dual Oracle Pattern

The problem: The exchange rate from Lido/Rocket Pool always reflects the protocol’s view of the backing β€” stETH is always worth ~1 ETH according to the protocol. But the market price can diverge. If stETH trades at 0.95 ETH on Curve, a lending protocol using only the exchange rate would overvalue wstETH collateral by ~5%.

Historical precedent β€” June 2022 stETH de-peg:

Context: 3AC and Celsius facing insolvency, forced to sell stETH for ETH.
Pre-Shapella: No withdrawal queue. Only exit is selling on DEX.

Timeline:
  May 2022:    stETH/ETH β‰ˆ 1.00 (normal)
  June 10:     stETH/ETH β‰ˆ 0.97 (selling pressure begins)
  June 13:     stETH/ETH β‰ˆ 0.93 (peak de-peg, ~7% discount)
  July 2022:   stETH/ETH β‰ˆ 0.97 (partial recovery)
  Post-Shapella: stETH/ETH β‰ˆ 1.00 (withdrawal queue eliminates structural de-peg)

Lending protocols using exchange-rate-only oracle:
  Valued wstETH collateral at 1.00 ETH per stETH
  Actual liquidation value on market: 0.93 ETH per stETH
  Gap: 7% β€” enough to cause undercollateralization in tight positions

The dual oracle pattern:

Use the minimum of the protocol exchange rate and the market price. During normal times, both are ~1.0 and the minimum doesn’t matter. During a de-peg, the market price is lower, and the minimum correctly reflects the actual liquidation value of the collateral.

Normal times:
  Exchange rate:  1 stETH = 1.00 ETH (protocol)
  Market price:   1 stETH = 1.00 ETH (Curve/Chainlink)
  min(1.00, 1.00) = 1.00 ETH  ← no difference

De-peg scenario:
  Exchange rate:  1 stETH = 1.00 ETH (protocol β€” unchanged)
  Market price:   1 stETH = 0.93 ETH (Curve/Chainlink)
  min(1.00, 0.93) = 0.93 ETH  ← safely uses market price

Numeric impact on a lending position:

Position: 100 wstETH collateral, stEthPerToken = 1.19
  = 119 stETH equivalent, borrowing 300,000 stablecoin
  ETH/USD = $3,200, liquidation threshold = 82.5%

Exchange-rate-only valuation:
  collateralUSD = 119 Γ— 1.00 Γ— $3,200 = $380,800
  HF = $380,800 Γ— 0.825 / $300,000 = 1.047  ← looks healthy

Dual oracle during 7% de-peg:
  collateralUSD = 119 Γ— 0.93 Γ— $3,200 = $354,144
  HF = $354,144 Γ— 0.825 / $300,000 = 0.974  ← LIQUIDATABLE

The $26,656 difference is the de-peg discount. Without the dual oracle,
this position appears healthy when it should be liquidated.

Implementation sketch:

function getStETHToETHRate() public view returns (uint256) {
    // Protocol rate: always ~1.0 (stETH is 1:1 with staked ETH by design)
    uint256 protocolRate = 1e18;

    // Market rate: Chainlink stETH/ETH feed
    (, int256 marketRate,,uint256 updatedAt,) = stethEthFeed.latestRoundData();
    require(marketRate > 0, "Invalid stETH price");
    require(block.timestamp - updatedAt <= STETH_STALENESS, "Stale stETH price");

    // Use the lower of the two β€” conservative for collateral valuation
    uint256 safeRate = uint256(marketRate) < protocolRate
        ? uint256(marketRate)
        : protocolRate;

    return safeRate;
}

Note: Chainlink provides a stETH/ETH feed on mainnet. For rETH, Chainlink provides an rETH/ETH feed. Both are used by production protocols (Aave, Morpho) for exactly this dual-oracle pattern.

πŸ’‘ Concept: LSTs as Collateral in Lending

Aave V3 wstETH integration β€” how production does it:

Aave V3 lists wstETH as a collateral asset with specific parameters tuned for its risk profile:

Aave V3 Ethereum β€” wstETH parameters (approximate):
  LTV:                    80%
  Liquidation Threshold:  83%
  Liquidation Bonus:      5%
  Supply Cap:             ~1.2M wstETH

E-Mode (ETH-correlated):
  LTV:                    93%    ← much higher!
  Liquidation Threshold:  95%
  Liquidation Bonus:      1%

E-Mode (Efficiency Mode): Aave V3’s E-Mode allows higher LTV for assets that are highly correlated. wstETH and ETH are correlated β€” wstETH is backed 1:1 by staked ETH. So Aave creates an β€œETH-correlated” E-Mode category where wstETH collateral can borrow ETH (or WETH) at up to 93% LTV instead of 80%.

Why E-Mode works here: The risk of wstETH dropping significantly relative to ETH is low (they’re fundamentally the same asset minus protocol risk). The primary risk is the de-peg scenario, which the dual oracle handles. With the dual oracle and high correlation, 93% LTV is defensible β€” but only for borrowing ETH-denominated assets, not stablecoins (where ETH price risk applies fully).

Liquidation with LSTs:

When a wstETH-collateralized position is liquidated, the liquidator receives wstETH. They have options:

  1. Hold wstETH β€” continue earning staking yield
  2. Sell on DEX β€” swap wstETH β†’ ETH on Curve/Uniswap
  3. Unwrap + sell β€” unwrap wstETH β†’ stETH β†’ request withdrawal (slow but 1:1 rate)

In practice, liquidators sell on DEX for immediate ETH. This is why DEX liquidity depth for wstETH matters for liquidation parameter settings β€” the same concern as P2M9’s liquidation economics section.

πŸ”— Connection: This mirrors exactly the liquidation economics discussion from P2M9 β€” bidder profitability depends on DEX liquidity depth, which determines whether liquidation actually works at the parameters you’ve set.

πŸ’‘ Concept: LSTs in AMMs

The Curve stETH/ETH pool is the most important pool for LST liquidity. It uses Curve’s StableSwap invariant, which is optimized for assets that trade near 1:1.

Why StableSwap and not constant product (Uniswap)?

For assets near 1:1 peg:

Constant product (x Γ— y = k):
  Slippage for 1,000 ETH swap in $500M pool: ~0.4%

StableSwap (Curve):
  Slippage for 1,000 ETH swap in $500M pool: ~0.01%

  ~40x less slippage for correlated assets β€” critical for liquidation efficiency
  (illustrative β€” exact values depend on pool parameters and amplification factor)

πŸ”— Connection: This connects to P2M2’s AMM module. The invariant choice (constant product vs StableSwap vs concentrated liquidity) directly determines slippage, which determines liquidation viability for LST collateral.

Yield-bearing LP positions: LPing in the stETH/ETH pool earns trading fees AND half the position earns staking yield (the stETH side). This β€œyield-bearing LP” concept connects to P2M7’s yield stacking patterns.

πŸ’‘ Concept: LSTs in Vaults

wstETH is a natural fit for ERC-4626 vaults. Since wstETH already has an increasing exchange rate (staking yield), wrapping it in a vault adds another yield layer:

Nested yield stack:
  ETH staking:    ~3.5% APR (base layer β€” beacon chain rewards)
  Vault strategy:  +X% APR (additional yield from vault's strategy)

Example: A vault that deposits wstETH as collateral on Aave,
borrows ETH, and loops the leverage:
  Base yield:     3.5% (staking)
  Leveraged yield: 3.5% Γ— leverage multiplier - borrow cost

wstETH as quasi-ERC-4626: wstETH itself behaves almost like an ERC-4626 vault. It has shares (wstETH tokens), assets (stETH), and an exchange rate (stEthPerToken). The main difference is that ERC-4626 defines deposit()/withdraw() with assets, while wstETH uses wrap()/unwrap(). Some protocols (like Morpho Blue) treat wstETH as an ERC-4626 by using adapter contracts.

πŸ”— Connection: This directly links to P3M3 (Yield Tokenization) β€” Pendle’s most popular markets are wstETH and eETH, where users split LST staking yield into principal and yield tokens. Understanding LSTs as yield-bearing assets is the prerequisite for understanding yield tokenization.

πŸ”— DeFi Pattern Connections

SourceConceptHow It Connects
P2M1Rebasing tokensstETH is the canonical rebasing token β€” the β€œweird token” integration challenge
P2M3Chainlink integrationETH/USD and stETH/ETH feeds for LST pricing pipeline
P2M4Health factor, liquidationLST collateral health factor uses dual oracle, liquidation via DEX
P2M7ERC-4626 share mathwstETH exchange rate = vault share convertToAssets()
P2M7Inflation attackExchange rate manipulation concern applies to LST pricing
P2M8Oracle manipulationDe-peg scenario defense requires dual oracle pattern
P2M9Two-step vault share pricingLST pricing pipeline is the same pattern (exchange rate Γ— underlying price)
P2M9Rate capLido’s oracle sanity check serves the same role as P2M9’s rate cap
P3M3Yield tokenizationPendle splits LST yield into PT/YT β€” LSTs are the primary input
P3M9Capstone (perp exchange)LSTs as margin collateral β€” pricing and liquidation mechanics carry over

🎯 Build Exercise: LST Collateral Lending Pool

Workspace: workspace/src/part3/module1/

Build a simplified lending pool that accepts wstETH as collateral, using the oracle from Exercise 1.

What you’ll implement:

  • depositCollateral(uint256 wstETHAmount) β€” deposit wstETH as collateral
  • borrow(uint256 stablecoinAmount) β€” borrow stablecoin against wstETH collateral
  • repay(uint256 stablecoinAmount) β€” repay borrowed stablecoin
  • withdrawCollateral(uint256 wstETHAmount) β€” withdraw collateral (health check after)
  • liquidate(address user) β€” liquidate unhealthy position, transfer wstETH to liquidator
  • getHealthFactor(address user) β€” calculate HF using safe (dual oracle) valuation
  • E-Mode toggle: when borrowing ETH-denominated assets, use higher LTV

What’s provided:

  • WstETHOracle from Exercise 1 (imported, already deployed)
  • Mock stablecoin ERC-20 for borrowing
  • Mock wstETH with configurable exchange rate
  • Mock Chainlink feeds for both price sources

Tests verify:

  • Full lifecycle: deposit β†’ borrow β†’ repay β†’ withdraw
  • Health factor increases as wstETH exchange rate grows (staking rewards)
  • De-peg scenario: stETH/ETH drops to 0.93, previously healthy position becomes liquidatable
  • Liquidation transfers wstETH to liquidator, burns repaid stablecoin
  • E-Mode allows higher LTV when borrowing ETH-denominated asset
  • Cannot withdraw below minimum health factor
  • Cannot borrow above debt ceiling

🎯 Goal: Practice building a lending integration that correctly handles LST-specific concerns β€” two-step pricing, de-peg risk, and E-Mode for correlated assets. These are production patterns used by every major lending protocol.


πŸ“‹ Summary: LST Integration Patterns

Covered:

  • Oracle pricing pipeline β€” two-step (exchange rate β†’ Chainlink), with full numeric walkthroughs
  • De-peg scenario β€” June 2022 stETH de-peg, numeric impact on lending positions
  • Dual oracle pattern β€” min(protocol rate, market rate) for safe collateral valuation
  • LSTs as collateral β€” Aave V3 parameters, E-Mode for correlated assets, liquidation considerations
  • LSTs in AMMs β€” why StableSwap for correlated assets, yield-bearing LP
  • LSTs in vaults β€” nested yield stacking, wstETH as quasi-ERC-4626

Key insight: LST integration is really about two things: (1) correctly converting to underlying value via the exchange rate, and (2) defensively handling the edge case where market price diverges from exchange rate (de-peg). The dual oracle pattern handles both. Everything else β€” LTV ratios, E-Mode, liquidation parameters β€” follows from understanding these two points.

πŸ’Ό Job Market Context

What DeFi teams expect you to know:

  1. β€œWhat happened during the June 2022 stETH de-peg and what did it teach us?”
    • Good answer: β€œstETH traded below 1 ETH. It was caused by selling pressure.”
    • Great answer: β€œ3AC and Celsius faced insolvency and had to liquidate stETH positions. Pre-Shapella, there was no withdrawal queue β€” the only exit was selling on DEX. Massive sell pressure pushed stETH/ETH to 0.93. This wasn’t a protocol failure β€” Lido’s backing was fine. It was a liquidity/market failure. The lesson: exchange rate and market price can diverge, so lending protocols need dual oracle pricing. Post-Shapella (April 2023), the withdrawal queue creates an arbitrage floor that prevents deep de-pegs.”

Interview Red Flags:

  • 🚩 Saying β€œjust use the exchange rate” for collateral pricing without mentioning de-peg risk and the need for a market price check
  • 🚩 Not knowing the difference between pre-Shapella and post-Shapella withdrawal mechanics
  • 🚩 Treating the June 2022 de-peg as a protocol bug rather than a market/liquidity event

Pro tip: In interviews, when discussing LST integration, always mention the de-peg scenario unprompted. Saying β€œwe’d use a dual oracle pattern because of the June 2022 de-peg risk” signals real-world awareness, not just textbook knowledge. Protocol teams remember June 2022 β€” it shaped how every subsequent LST integration was designed.


← Backward References (where these patterns were introduced):

  • Exchange rate math β†’ P1M1 ShareMath (shares/assets pattern), P2M7 ERC-4626 convertToShares/convertToAssets β€” LSTs use the same shares-proportional-to-underlying model
  • Oracle integration β†’ P2M3 Chainlink patterns, staleness checks, heartbeat monitoring β€” LST oracles add beacon chain finality as an extra trust assumption
  • Lending collateral β†’ P2M4 health factor calculation, liquidation mechanics β€” LST collateral requires dual oracle pricing (exchange rate + market price)
  • Rebasing tokens β†’ P2M1 weird token behaviors β€” stETH rebasing breaks balanceOf assumptions; wstETH wrapping solves this
  • Yield-bearing assets β†’ P2M7 vault shares as collateral, ERC-4626 accounting β€” LSTs are essentially yield-bearing receipt tokens with the same math

β†’ Forward References (where LST concepts appear next in Part 3):

  • Restaking β†’ P3M6 (Governance & Risk) β€” risk stacking from restaked assets, correlated slashing conditions
  • LST as perp collateral β†’ P3M2 (Perpetuals) β€” yield-bearing margin, funding rate interaction with staking yield
  • LST yield tokenization β†’ P3M3 (Yield Tokenization) β€” Pendle PT-stETH, fixed-rate staking exposure via PT/YT split
  • LST price feeds β†’ P3M5 (MEV & Frontrunning) β€” oracle manipulation vectors, sandwich attacks on LST swaps

πŸ“– Production Study Order

Study these codebases in order β€” each builds on the previous one’s patterns:

#RepositoryWhy Study ThisKey Files
1Lido stETH/wstETHThe canonical LST β€” shares accounting, rebase mechanics, wrap/unwrap patterncontracts/0.4.24/Lido.sol, contracts/0.6.12/WstETH.sol
2Lido AccountingOracleBeacon chain reporting, quorum, finalization delay β€” understand the trust modelcontracts/0.8.9/oracle/AccountingOracle.sol, contracts/0.8.9/oracle/HashConsensus.sol
3Aave V3 wstETH integrationE-Mode configuration, oracle adapter wrapping exchange rate + Chainlink feedcontracts/misc/PriceOracleSentinel.sol, Aave wstETH oracle adapter
4EigenLayer StrategyManagerRestaking deposit flow, delegation, withdrawal queue β€” see how risk stackssrc/contracts/core/StrategyManager.sol, src/contracts/core/DelegationManager.sol
5Rocket Pool rETHAlternative exchange rate model β€” decentralized node operator set, minipool architecturecontracts/contract/token/RocketTokenRETH.sol, contracts/contract/deposit/RocketDepositPool.sol

Reading strategy: Start with Lido β€” it’s the most widely integrated LST. Read Lido.sol for the shares/pooledEth accounting, then WstETH.sol for the non-rebasing wrapper (this is what DeFi protocols actually integrate). Study the oracle next to understand the trust assumptions. Then see how Aave wraps the exchange rate into a price feed. EigenLayer shows restaking as a layer on top. Rocket Pool shows the decentralized alternative.


πŸ“š Resources

Production Code

RepositoryWhat to StudyKey Files
Lido stETHShares accounting, oracle, rebaseLido.sol, WstETH.sol, AccountingOracle.sol
Rocket PoolrETH exchange rate, minipool modelRocketTokenRETH.sol, RocketDepositPool.sol
EigenLayerRestaking architectureStrategyManager.sol, DelegationManager.sol
EtherFiLRT implementationweETH.sol, LiquidityPool.sol

Documentation

Further Reading


Navigation: Part 3 Overview | Next: Module 2 β€” Perpetuals & Derivatives β†’