For the complete documentation index, see llms.txt. This page is also available as Markdown.

stETH, lsETH & OETH (CrossRate)

Generic custom price feed for an asset Y that has no direct Y/USD feed but is quoted in a base asset X that does.

Generic custom price feed for an asset Y that has no direct Y/USD feed but is quoted in a base asset X that does. The price is the cross-rate of the NAV's own X/USD base price and a Chainlink Y/X feed. The shared CrossRateCustomPriceFeed base is instantiated as one named per-token contract for each asset that needs it. On Ethereum mainnet the primary instances are lsETH (lsETH_CustomPriceFeed, Liquid Collective — Y/X is Chainlink's LsETH/ETH Exchange Rate) and OETH (OETH_CustomPriceFeed) — each Y/USD = ETH/USD × Y/ETH, where the cross-rate is the asset's sole pricing feed.

stETH is not priced by a cross-rate. Its primary is a fundamental unit-rate feed (1.0 × ETH/USD), matching wstETH and eETH; the market stETH/ETH cross-rate is registered as a monitor (stETHCrossRate), deployed from the generic base rather than a named per-token subclass. This page describes how that monitor computes its price — it does not set stETH's NAV value.

Source: CrossRateCustomPriceFeed.sol

The same base also backs divergence monitors for the fundamental LST/LRT primaries — ezETH, ETHx, osETH, and rETH (ezETH/ETHx/osETH/rETH_CrossRateCustomPriceFeed), where the Y/ETH leg is an independent market feed. Those assets are priced by a fundamental protocol-rate primary (ezETH, ETHx, osETH, rETH); the cross-rate is registered as a monitor feed, so a market depeg makes it diverge from the fundamental primary and NAV flags the asset irregular — it never prices NAV. The L2 deployments use the same pattern (e.g. weETHCrossRate, rsETHCrossRate monitors on Arbitrum/Base).


Approach

NAV base X/USD (getPriceDataNoDivergence(WETH)) × Chainlink Y/X

The base/USD term is sourced from the NAV's own selector — see Base/USD from the NAV's own selector.

Left-to-right flowchart of the stETH, lsETH & OETH (CrossRate) price feed: rate and Chainlink inputs combine into a USD price, with a staleness gate.
stETH, lsETH & OETH (CrossRate) price feed — how its oracle inputs compose into a USD price, with the staleness gate.

Price calculation

Input
Source
Description

X/USD

NAV base — getPriceDataNoDivergence(WETH) (8 dec)

the NAV's primary ETH/USD price

Y/X

Chainlink Y/X feed (latestRoundData)

Underlying Y quoted in X

The Y/X leg is a Chainlink feed; the X/USD (ETH/USD) leg is the NAV's primary base price. The divisor is 10 ** yToX.decimals(), which cancels the Y/X feed's decimals so the result keeps the X/USD leg's scale. Output is 8 decimals (inherited from the X/USD leg via _decimals).

For the mainnet instances, X is ETH (ETH/USD via the NAV base) and Y is stETH, lsETH, or OETH respectively (a stETH/ETH, LsETH/ETH, or OETH/ETH feed).


Constructor

Parameter
Description

underlyingAsset_

The asset Y whose USD price is returned (stETH, lsETH, or OETH)

yToXFeed_

Chainlink Y/X aggregator (e.g. stETH/ETH or OETH/ETH)

yToXHeartbeat_

Staleness window (seconds) for the Y/X feed

nav_

NAVCalculator (proxy) — supplies the base asset's USD price via getPriceDataNoDivergence

baseAsset_

The registered base asset whose USD price is read (WETH)


Staleness

The Y/X heartbeat is checked directly. getLatestPrice() returns stale = true if the Y/X feed satisfies block.timestamp − updatedAt ≥ heartbeat, if either leg's answer is ≤ 0, if the Y/X updatedAt is in the future (clamped to block.timestamp), or if the NAV reports the base asset (WETH) primary feed stale. The base leg's updatedAt comes from the NAV's selected feed. The reported updatedAt is the older of the two legs.


Chains

On Ethereum, as primary feeds: lsETH and OETH, each configured with the matching Y/X feed. As monitor feeds (same base contract, market Y/ETH leg), watching their fundamental primaries: stETHCrossRate, ezETHCrossRate, ezETHCrossRateMarket, ETHxCrossRate, osETHCrossRate, and rETHCrossRateezETH carries two because its original monitor's rate leg stopped being a market feed.

On the L2s, all monitors: weETHCrossRate, ezETHCrossRate and rsETHCrossRate on Arbitrum, and weETHCrossRate on Base. Gnosis has no cross-rate instance.

Every one of these takes an external yToXFeed, so each is covered by the pre-deploy rate-feed guard — pair identity where the provider's description() names the pair, and a declared $UNVERIFIABLE exemption plus a plausibility band where it does not.

Last updated