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

ETH+

Custom price feed for Reserve Protocol's ETH+ RToken on Ethereum.

Custom price feed for Reserve Protocol's ETH+ RToken. ETH+ is derived from the value of the collateral basket that backs each token, using Reserve Protocol's on-chain basket accounting.

Source: ETHPlus_CustomPriceFeed.sol


Approach

(basketsNeeded / totalSupply) × basket low price — the conservative (low-bound) USD value of the basket backing one ETH+.

Left-to-right flowchart of the ETH+ price feed: rate and Chainlink inputs combine into a USD price, with a staleness gate.
ETH+ price feed — how its oracle inputs compose into a USD price, with the staleness gate.

Price calculation

Input
Source
Description

basketsNeeded

IRToken(ETHPLUS).basketsNeeded()

Basket units the RToken must be backed by (18 dec)

totalSupply

IRToken(ETHPLUS).totalSupply()

ETH+ total supply

basketLow

IBasketHandler.price() (low bound)

Conservative USD value of one basket unit (18 dec)

Computation is carried at 18-decimal precision and divided by 1e10 to yield the 8-decimal USD price. The low price bound from basketHandler.price() is used deliberately for conservative NAV valuation. If basketsNeeded, totalSupply, the per-token basket units, or the basket price is zero, the feed returns stale.


Constructor

Parameter
Description

ethPlus_

The ETH+ RToken address

reserveProtocolHeartbeat_

Max age (seconds) of the worst-case collateral refresh before the price is stale


Staleness

getLatestPrice() enforces two internal checks; no external Chainlink heartbeat is read directly:

  1. Basket statusIBasketHandler.status() must be SOUND. An IFFY or DISABLED basket returns stale, even though the basket may still report a non-zero price.

  2. Refresh ageupdatedAt = min(IAsset.lastSave()) across all components of the active reference basket, read via IBasketHandler.quote(1e18, RoundingMode.CEIL) — the same basket price()/basketsNeeded() are computed over, rather than the governance-configured prime basket. lastSave() is set when a keeper calls refresh() on a collateral plugin (which reads the underlying Chainlink oracle). If block.timestamp − updatedAt ≥ reserveProtocolHeartbeat, the price is stale. Taking the minimum gives the worst-case freshness of the whole basket. Using the active set matters after a default swaps in backup collateral: the active backups differ from the prime config, and checking the prime set would skip the backups' oracle freshness (stale accepted as fresh). The deployed BasketHandler has no basketTokens() getter, so quote is used to read the live basket.

latestRoundData() exposes updatedAt = min(lastSave()) for observability only; staleness is handled entirely in getLatestPrice().


Chains

Deployed on Ethereum mainnet.

Last updated