Views
Views
Read-only paths into SwapCore, plus the standalone Views lens contract that batches and previews SwapCore state for UIs and indexers. Everything on this page is safe for off-chain consumers (frontends, indexers) to call via staticCall, with the one documented exception.
Source: SwapCore.sol (core reads and auto-generated getters) and lib/Views.sol — a full read-only lens contract (~25 external functions: batched market/LP/oracle reads and exact supply/withdraw previews) deployed at its own address, wrapping SwapCore's public surface. Call lens functions against the Views address, everything else against SwapCore.
Why two flavors of P&L reads?
SwapCore stores a cumulative rate index per oracle (rateIndex) that is only written when a state-changing function runs — buySwap, supplyCollateral, withdrawCollateral, makePayment, exitSwapEarly, liquidateSwap, or the dedicated updateMarketRateIndex. Between those updates, a pure view read (getSwapNetAmount) projects a fresh index on the fly (via getFreshIndex) so the answer still reflects time elapsed since the last write. For consumers who want the stored index actually written to storage first, getFreshSwapNetAmount runs the update as a side effect, then returns the value — useful when a frontend wants to staticCall a mutable function and know the same number would be used by a subsequent makePayment.
See also updateMarketRateIndex for the standalone index-refresh path.
SwapCore — swap valuation
getSwapNetAmount
function getSwapNetAmount(bytes32 swapId)
public view returns (uint256 netAmount, uint8 netRecipient);Who calls: anyone. Pure view.
What it does: computes the current net payment obligation of an open swap — how much one side would owe the other if it settled right now. Projects the reference rate oracle forward with getFreshIndex (no state mutation) to account for time elapsed since the last index write, then nets the accrued fixed and floating legs.
Mid-term this is an accrued-only valuation, not a settlement simulation. It shares its basis with the liquidation gate (Utils.isSwapLiquidatable), so the view always agrees with what a liquidation would trigger on. Only for an expired swap (timeElapsed == swapTerm) does the accrued value coincide exactly with the full-term math makePayment runs at settlement.
Steps:
Load the swap and market. Revert if the swap doesn't exist (
E500) or the market is gone (E300).Compute
timeElapsed, capped atswapTerm. If no time has elapsed (entryTimestamp == block.timestamp), return(0, 1)— no obligation, buyer is the trivial recipient.Resolve the effective oracle index:
Active swap: use
getFreshIndex(oracle)— a projected-forward read.Expired swap, in order:
If a post-expiry snapshot exists, use the stored interpolation via
rateIndex.getIndexAt(expiry)— the same bracket settlement would use.Otherwise, try
getFreshIndexand interpolate the fresh value back toexpiryTimestampviagetIndexAtVirtual— bit-equivalent to what a same-transaction settle would resolve, so a stale view can't mask a pending settlement.If the fresh oracle read itself reverts (dead/invalid oracle): fall back to the stored
getIndexAt(expiry)only if the last stored update is at or after expiry; with no maturity-bracketing snapshot at all, revertE450.
Derive
floatingPaymentRatefrom(entryFloatingIndex, effectiveIndex, rateDuration)usingSwapFormulas.deriveRateFromIndex.Compute the accrued legs. The fixed leg comes from
SwapFormulas.accruedFixedLegusingswap.baseRateplus the storedswap.utilFee/swap.riskPremium(re-added explicitly on the fixed leg for BUY_FIXED; on the floating leg for BUY_FLOATING).swap.swapRateis never read here. On the Cumulative BUY_FIXED side the fixed leg accrues on the compounded curve implied by the stored full-tenor rate (matching the convex floating leg — straight-line proration would overstate the fixed leg mid-term); every other convention/side accrues straight-line. At expiry the compounded value collapses to the straight line.Net them with
SwapFormulas.calculateNetObligation(fixedPayment, floatingPayment). Flip thebuyerOwesbit if this is a BUY_FLOATING market (the buyer's side of the swap is the floating leg, not the fixed one).Cap by collateral. If the buyer is the one receiving, the net is capped at
swap.poolCollateralBacking. If the buyer is the one paying, it's capped atswap.collateralBalance. This mirrors exactly whatmakePaymentandliquidateSwapwould do.
Returns:
netAmount
The net obligation in swapToken decimals. Always non-negative.
netRecipient
0 = LP pool receives, 1 = buyer receives.
Reverts:
E500
Swap doesn't exist.
E300
Market doesn't exist (swap references a purged market — shouldn't happen in normal operation).
E606
Reference rate oracle returned invalid data during getFreshIndex.
E725
Oracle rate/decimals normalization out of bounds during getFreshIndex (misconfigured feed).
E450
Expired swap, oracle unavailable, and no stored snapshot at or after expiry (step 3.3 above).
Notes:
E450fires here even past the settlement grace period, wheremakePaymentitself would fallback-settle on extrapolated data. The view deliberately stays fail-closed: settle the position (permissionless) to realize its value in that state.Returns
(0, 1)for a swap whereblock.timestamp == entryTimestamp— useful sentinel for "just-opened".Both return fields are only meaningful while the swap is open. Once
swap.settled == true, the net-computing branch is skipped, so this function returns the sentinel(0, 1)—netAmountdefaults to0andnetRecipientdefaults to1("buyer receives") regardless of who actually won. (Even that is best-effort: the index-resolution prelude runs before the settled check, so a settled swap can still revertE450or propagategetFreshIndexfailures.) Do not read either field on a settled swap. To recover settlement data after the fact:Direction + net amount (who received the net, and how much) → the
SwapClosedevent'snetRecipientandamountSettledfields (emitted by every closure path; also returned synchronously asSettlementResultfrommakePayment/exitSwapEarly). There is no storage getter fornetRecipient— it lives only in the event/return.The buyer's remaining on-core claim →
getBuyerSettlementValuein one call, or the raw slotssettlementPayouts/escrowedCollateral. A losing buyer can still have a nonzero payout, so you can't infernetRecipientfrom any of these.
See also: getFreshSwapNetAmount, getBuyerSettlementValue, and the SwapClosed event for post-settlement direction and net amount.
getFreshSwapNetAmount
Who calls: frontends via eth_call / staticCall. Not marked view — this function mutates the global rate index.
What it does:
Reads
swap.marketId.Calls
rateIndex.update(market.referenceRateOracle)— a real storage write under normal execution.Delegates to
getSwapNetAmount(swapId).
The only reason this exists is so a frontend can staticCall a mutable function and receive the exact number makePayment would use in the next block, with zero divergence from the stored index. When called via staticCall, the index update is rolled back at the end of the simulation, so consumers get the fresh number without persisting the write.
⚠️ Do NOT call this on-chain. Every call performs a rateIndex.update, which is wasted gas if you're already about to call a state-changing function (that function will update the index itself). On-chain callers should use getSwapNetAmount directly.
Returns: same as getSwapNetAmount.
Reverts: same as getSwapNetAmount, plus any revert from rateIndex.update (which itself reverts with E606 if the oracle is unhealthy). One ordering quirk: a nonexistent swapId reverts E608 (uninitialized index), not E500 — the zero marketId resolves to a zero oracle address, and rateIndex.update fails on it before getSwapNetAmount's existence check is reached.
See also: getSwapNetAmount, updateMarketRateIndex.
getBuyerSettlementValue
Who calls: anyone — the one-call read for "what would the buyer walk away with if settlement ran this block".
What it does:
Unsettled, live, early-exitable swap: returns the more conservative of the liquidation-aware accrued value and the immediate early-exit closeout value, so an adverse remaining-term base-rate move is reflected.
Unsettled, expired swap: returns the exact settlement-equivalent value — remaining collateral + refunded liquidation bounty + any pool-side receipt (no liquidator can fire after expiry).
Settled (but still tracked) swap: returns
escrowedCollateral[swapId]— the failed-transfer escrow is the only remaining on-core buyer claim; a successful payout has already left to the recipient's balance. This branch reads a single packed slot, so callers can value every tracked swap in one call without decoding the fullswapPositionsstruct.
Reverts: like getSwapNetAmount — E450 for an expired unsettled swap with no maturity-bracketing snapshot, even past the settlement grace period where makePayment would fallback-settle. Settle the position to realize its value in that state.
See also: settlementPayouts, escrowedCollateral, claimEscrow.
SwapCore — pool & vesting reads
For the three share prices themselves (getPoolSharePrice, getPoolBurnPrice, getVirtualSharePrice) and LP position reads (getLpValue, getLpPosition, getLpShares, totalLPAvailableCollateral), see Liquidity provision.
getPoolMintAndBurnPrice
Both transactable share prices in one read, computed off a shared bucket scan: mintPrice is what supplyCollateral mints at (accrued-only conservative upper bound, not vesting-deducted), burnPrice is what withdrawCollateral burns at (== getPoolBurnPrice, before the per-LP profit-vest cap — getLpValue applies that). Returns (1e18, 1e18) for an empty pool. Values are still returned in states where the transactions themselves would revert (underwater floor E414, expired-unsettled E415) — gate on those separately, e.g. via previewSupply / viewMarketPoolState. Reverts E300 if the market doesn't exist.
vestingOutstanding
The market's still-withheld settlement vesting (swap token decimals), decaying linearly to zero at its drip horizon. It is subtracted from every burn/NAV read while nonzero; the tokens themselves stay in pool.totalCollateral and outstanding LP shares keep their pro-rata claim. Integrators valuing a held LP position add shares × vestingOutstanding / totalShares back to the deducted mark (that's what lpVestingClaim computes). Reverts E300.
anyBucketCapBinds
true iff any occupied bucket has a buyer-side collateral cap binding — i.e. a liquidatable buyer whose liquidation would seize collateral into the pool. A non-maskable pending-recovery signal: vault-style integrators use it to gate permissionless deallocation until the liquidation crystallizes. Reverts E300.
SwapCore — oracle index reads
updateMarketRateIndex
Who calls: anyone — typically a keeper, but there's no gate.
What it does: first best-effort pokes any of the market's oracles (referenceRateOracle, baseSwapRateOracle, riskPremiumOracle) that advertised IPokeable at market creation — refreshing their internal state (e.g. TWAR buffers) so the index snapshot reflects the freshest values. Pokes are rate-limited per oracle by admin.pokeMinSpacingSec() (default 3600 seconds, timelocked, hard floor of 60 seconds): a poke attempted inside the spacing window is skipped entirely, and a same-timestamp re-entry is short-circuited. Pokes are best-effort — a failing poke never reverts the call, and its window is rolled back so the next caller can retry. It then calls rateIndex.update(market.referenceRateOracle), writing a fresh cumulative index entry keyed by block.timestamp. Used to:
Force an index snapshot at a specific timestamp (useful when a market has been quiet for a while and a keeper wants to refresh before heavy read activity, and required post-maturity for settlement inside the grace window).
Pre-update the index immediately before batch settlement so
makePaymentdoesn't re-read the oracle for every swap in the batch — thoughmakePaymentalready does this per-call, so it's rarely necessary.
Under normal operation every state-changing function already updates the index, so you typically don't need to call updateMarketRateIndex directly.
Reverts:
E300
Market doesn't exist.
E606
Oracle returned invalid data during the update.
See also: getFreshSwapNetAmount, getPoolSharePrice.
getOracleIndexData
Stored index state for an oracle address (not a market ID — index history is global per oracle and shared by every market using it): last recorded index (RAY), timestamp of the last write, the immutable rate convention, and the cumulative rate-time accumulator (spot conventions only). An oracle that was never initialized returns zeros. This is the raw storage read; for a projected-to-now value use getFreshIndex.
getFreshIndex
Projected-forward oracle index for view-only paths — no state mutation. For Cumulative oracles it reads the adapter live (clamped at the stored floor, mirroring the monotonic clamp rateIndex.update applies); for spot conventions it projects from the stored rate-time accumulator plus the current spot rate. Reverts E606 on an invalid oracle response and E725 if rate/decimals normalization is out of bounds. No market-exists guard — an unknown marketId resolves to a zero oracle address and reverts raw.
getIndexAt
Resolves the historical index of the market's reference oracle at targetTime from stored snapshots: interpolated between bracketing snapshots, extrapolated from the last stored pair beyond them, and returned flat at the oldest value for times before the first snapshot. Pure storage read — no oracle call, so the answer only improves as keepers snapshot more densely (see updateMarketRateIndex).
SwapCore — queue & introspection
getExpiryQueueState
The market's expiry queue length and current pointer in one call. The queue is append-only (one entry per buySwap, in entry order); pointer is the source of truth for "earliest possibly-unsettled entry" — everything before it is settled. Returns (0, 0) for unknown markets.
getExpiryQueueEntry
The swap ID at index in the expiry queue. bytes32(0) means a settled entry that has been zeroed (the array never shrinks). Reverts with an array out-of-bounds panic for index >= length. Keepers walk [pointer, length) with this to find settleable swaps.
isLocked
true while SwapCore is executing under its reentrancy guard — i.e. any state-changing entry point (settlement, liquidation, buys, LP ops) is mid-flight. Exists so contracts receiving tokens during a SwapCore call (e.g. SwapPositionWrapper inside a settlement-token callback) can detect that settlementPayouts / escrowedCollateral are not yet final and defer crediting to a later call. Always false when read from a top-level eth_call.
admin
The protocol Admin contract (fee config, multisig, timelocked parameters such as pokeMinSpacingSec and the settlement grace period). Bound at construction and never reassigned — repointing would require a new SwapCore deployment.
State-variable getters
SwapCore exposes several public mappings and arrays. Solidity auto-generates a getter for each; these are the ones integrators most commonly read.
markets
Returns the full Types.Market struct. Market has no mappings or dynamic arrays, so the auto-getter returns every field (22 in total), including the nested Pool sub-struct (totalShares, totalCollateral, lockedCollateral). Use this for market-config reads: oracles, pool (shares/collateral/locked), fee-curve parameters, earlyExitAllowed, earlyExitFee, liquidationIncentive, terminated, marketOwner, lpWhitelistEnabled, minCollateral, bucketInterval, riskPremiumOracle, numBuckets.
Non-existent markets return the zero-initialized struct with exists = false. Check .exists before treating the response as live data.
swapPositions
Returns the 14-field Types.SwapPosition tuple:
A swapId that doesn't exist returns all zeros — check entryTimestamp != 0 to confirm the swap is real. (Views.viewSwap returns the same data as a named struct.)
settlementPayouts
After settlement, records the amount actually transferred to the buyer for swapId (buyerCollateralReleased). If the buyer-side transfer fails and the payout is escrowed instead, this slot is set to 0 and the amount is recorded in escrowedCollateral — the two are mutually exclusive, never double-counted. So 0 means one of: the swap isn't settled yet, the buyer was due nothing (lost the P&L / was liquidated), or the payout failed to transfer and is now sitting in escrow.
For the buyer's remaining on-core claim, prefer getBuyerSettlementValue — on a settled swap it returns exactly the escrowed remainder in one call (a successfully transferred payout has already left the protocol). If you specifically want the historical credited amount including what was already paid out, read settlementPayouts[swapId] + escrowedCollateral[swapId] — the sum exitSwapEarly uses for its slippage check and the pattern SwapPositionWrapper follows. Neither read is a direction flag: a losing buyer can still have a nonzero payout, so you can't infer netRecipient from it.
escrowedCollateral
Non-zero when a buyer-side settlement or liquidation transfer failed (usually because the recipient became unable to receive the token). The balance is held until the buyer (or an authorized delegate) calls claimEscrow. Funds are earmarked to the original swap.userAddress — no one can redirect them. If the recipient is still blocked, the claimEscrow transfer reverts and the escrow stays in place.
isAuthorized
See Authorization. Returns true only for explicitly-set delegations; the implicit self-path (msg.sender == onBehalfOf) is not stored in this mapping, so code that mirrors SwapCore's auth rule should check operator == owner || isAuthorized[owner][operator].
marketLpWhitelist
Returns whether an address is whitelisted to supply LP collateral in a specific market. Only meaningful when markets[marketId].lpWhitelistEnabled == true. The market creator is auto-whitelisted at createMarket time only if lpWhitelistEnabled was true at creation — enabling the whitelist later does not retroactively whitelist the creator.
pendingMarketOwner
Address that has been designated as the new owner of marketId but has not yet accepted via acceptMarketOwnership. address(0) if no transfer is in flight.
allMarketIds (array)
Positional read by index. Use getAllMarketIds() to fetch the whole array at once, or viewAllMarkets for paginated IDs + full market data.
Bucket aggregates are not readable on-chain
The per-market bucket aggregates (Types.Bucket) that back the share-price calculation live in an internal mapping — there is no auto-generated getter on SwapCore, and no lens function exposes them. No protocol path needs the tuple; tests read buckets through a dedicated harness.
For reference (e.g. offline analysts decoding raw storage), the current Types.Bucket struct has 32 fields in this declaration order:
Notes for anyone rebuilding valuation from these aggregates:
weightedLnIndex(6) is populated forSpotCompoundRatemarkets only and is zero on other conventions. It is signed — a zero is a legitimate value, not an absence — so key netting eligibility onweightedInverseIndexinstead.Fields 15–23 are the value boxes: per-member parameter ranges that bracket every active member, consumed by
BucketBoundsLibfor conservative NAV bounds.minFeeSum/maxFeeSum(20–21) are a single merged fee axis — min/max over members ofutilFee + riskPremium— since every valuation consumes the pair only through its sum. Boxes are ranges, not sums; don't aggregate them like the weighted moments.Fields 24–28 are certified-tightening second moments (they let removal re-certify the boxes from survivor aggregates), and 29–32 are the cap-surplus box/moments tracking each member's paired-collateral sizing headroom.
Types.Bucket in interfaces/Types.sol is the source of truth; treat the list above as a convenience snapshot.
This is mostly of interest to offline analysts rebuilding the share-price calculation. For ordinary consumers, getPoolBurnPrice is the right read for redeemable value and getPoolSharePrice for an informational mark — see The three share prices.
The Views lens contract
lib/Views.sol is a standalone read-only contract deployed at its own address, holding a single immutable pointer to SwapCore (readable via core()). It batches multi-market reads, previews LP operations with exact parity to the live paths, and normalizes oracle reads for UIs. Call everything below against the Views address.
Two conventions to know:
Batched functions (
viewLPPositions,viewLPDashboard, …) silently skip non-existent markets and zero-share positions rather than reverting.Single-market functions guard existence inconsistently: the preview functions revert
E300, whilegetBaseRate/calculateSwapRate/previewUtilizationFee/viewMarketOracleIndexrevert with the string"Market does not exist". Match on both if you need robust error handling.
Swap & market reads
viewSwap
The full SwapPosition as a named struct — same data as SwapCore's positional swapPositions getter, friendlier ABI. Non-existent swaps return a zeroed struct; check entryTimestamp != 0.
getSwapTerm
Just the market's swap term in seconds (gas-optimized single-field read). Returns 0 for unknown markets.
viewAllMarkets
Paginated market listing; onlyActive = true filters out terminated markets. marketIds corresponds 1:1 with markets, and total is the count matching the filter (use it to drive pagination). An offset past the end returns empty arrays plus total.
viewMarkets
Full Market structs for a specific set of IDs, in order. Non-existent IDs yield zeroed structs (exists == false).
viewTotalLPCollateral
Sums pool.totalCollateral across the given markets — but only markets whose swapToken is Base-mainnet USDC (hardcoded filter); other tokens contribute zero. A TVL convenience for the USDC frontend, not a general aggregator.
viewMarketPoolState
Single-call market-page payload: mintPrice, burnPrice (pre-cap), fairPrice, vestingOutstanding, totalShares / totalCollateral / lockedCollateral / availableCollateral, utilizationWad, plus two gate flags — capBinds (anyBucketCapBinds) and lpOpsBlocked (true when supply/withdraw would revert E415 on expired-unsettled swaps). Prices are still returned in states where the transactions themselves revert — gate on lpOpsBlocked / previewSupply. Reverts E300.
Pricing & quote previews
getBaseRate
The market's current base rate (WAD, signed) from its baseSwapRateOracle at the market's full swapTerm tenor — validated and normalized exactly as buySwap reads it. Reverts on unknown markets (string) and on an unhealthy oracle (E611).
calculateSwapRate
Preview of the all-in swap rate buySwap would produce for notionalAmount right now: base rate + seasoned utilization fee + risk premium for BUY_FIXED. For BUY_FLOATING it previews the instantaneous effective rate on spot-convention markets and returns 0 on Cumulative markets — matching the stored swap.swapRate == 0 sentinel, since the floating leg is derived from index growth at settlement. Display only; SwapCore never stores the BUY_FLOATING preview.
previewUtilizationFee
The exact utilization fee rate (WAD) buySwap would charge for notionalAmount, priced against seasoned (EMA) liquidity exactly like the live path. Use this instead of reimplementing the curve: the fee depends on a stored EMA accumulator plus block.timestamp and is not reproducible off-chain from the fee-curve parameters alone.
getCalculatedAvailableLiquidity
Returns the maximum notional a new swap can use right now, given the pool's unlocked collateral and the current base rate. Computed as:
In effect: "how much notional can this pool safely back, given that each notional unit consumes |baseRate| × swapTerm × leverageMultiplier worth of collateral for worst-case LP exposure?"
Use this to size the notionalAmount you pass to buySwap. If notionalAmount > getCalculatedAvailableLiquidity(marketId) at tx execution time, buySwap reverts. Because base rates move, quote-time and execute-time values can differ slightly — if that matters, pair it with buySwap's rateBound slippage guard.
Reverts: can revert with E611 / oracle-related errors if the base rate oracle is unhealthy.
See also: totalLPAvailableCollateral, buySwap.
LP previews & dashboards
previewSupply
Exact shares supplyCollateral would mint for collateralAmount this block, replicating its rounding and amount-math guards — it reverts with the same errors the live call would: E300 (no market), E400 (zero amount / dust deposit), E414 (underwater floor with active swaps), E415 (expired-unsettled swaps), E728 (index at floor). Caller-shaped guards are deliberately not replicated (authorization E206, LP whitelist E201). Parity holds when quote and transaction land in the same block/oracle state; across blocks they can diverge — that's what minSharesOut is for.
previewWithdraw
Exact outcome withdrawCollateral would produce this block, replicating the profit-vest cap, the full/partial rounding split, and every last-LP branch. Pass type(uint256).max (or anything ≥ the position's full value) for a full exit. Reverts with the same errors as the live call: E300, E400, E405 (insufficient available collateral), E407, E413 (same-block deposit), E415, E416, E417 (capped full last-LP exit), E419 (undripped vesting on full last-LP exit). Caller slippage params (minCollateralOut, maxSharesToRedeem) and auth/receiver checks are not replicated — feed this preview's outputs into those params instead. effectivePrice is the price actually applied: min(getPoolBurnPrice, entryPrice).
getLpVestState
Who calls: anyone — primarily frontends that want to warn an LP about the profit-vest cap before they supply or withdraw.
What it does: reports the LP's current profit-vest state for a market. Reads the LP's position via SwapCore.getLpPosition, then returns the vest anchor, the window end, and whether the cap is currently binding:
entryPrice— the profit-vest anchor (share price recorded at the deposit that began the current vest window), WAD.vestEndTimestamp— unix seconds; the cap applies whileblock.timestamp < vestEndTimestamp.capActive—trueiffblock.timestamp < vestEndTimestamp && getPoolBurnPrice(marketId) > entryPrice. Whentrue, awithdrawCollateralright now would burn shares atentryPricerather than the live (higher) price.The comparison is against
getPoolBurnPrice— the markwithdrawCollateralactually burns at. Mirror that price if you reimplement the check; the fair mark sits above it and would report the cap as binding across a band where it does not.
For a fully-exited position (shares == 0), returns (0, 0, false) — stale anchor storage is ignored. See Liquidity provision → Profit-vest cap for the full mechanism.
Reverts: E300 if the market doesn't exist (propagated from SwapCore.getLpPosition).
See also: getLpValue (applies the cap to return the true redeemable amount), withdrawCollateral.
lpVestingClaim
The LP's pro-rata claim (shares / totalShares) on the market's still-withheld settlement vesting (vestingOutstanding), in swap token decimals. Display/valuation data, not a separately claimable balance — the value drips back into the share price on its own. Rounding mirrors the on-chain deduction (floor twice), so burn value + claim never exceeds the undeducted book value. Returns 0 (rather than reverting) for unknown markets and share-less LPs.
viewLPDashboard
Everything an LP position row needs, one entry per market where the LP has shares: the LpPosition, burnValue (full-exit value, per-LP cap applied), fairValue (informational, non-transactable), mintPrice / burnPrice (pre-cap) / fairPrice, capActive, vestingClaim, pool-level vestingOutstanding, the full Market, and the reference oracle's description() (empty string when it reverts). Successor to viewLPPositions — prefer it in new integrations. Skips non-existent markets and zero-share positions.
viewLPPositions
Legacy batched LP read: positions, getLpValue values, fair share prices, market structs, and oracle descriptions for every given market where the LP holds shares. Predates the mint/burn price separation and settlement vesting — it reports only the informational fair midpoint. Use viewLPDashboard instead.
viewLPPoolSharesByAddress
Lightweight filter: for each given market where user holds shares, returns the market ID, share balance, and the fair (informational) share price. Same fair-midpoint caveat as viewLPPositions.
Oracle index reads
viewMarketOracleIndex
getOracleIndexData for the market's reference oracle, wrapped in a struct that includes the oracle address: {oracle, currentIndex, lastUpdate, convention, cumulativeRateTime}. Reverts on unknown markets (string).
viewOracleIndex
Same payload, keyed directly by oracle address. Never-initialized oracles return zeros.
viewAllOracleIndexes
Index data for every unique reference rate oracle found in a page of the market list. Pagination is over markets, not oracles — total is the market count, and a page can return fewer infos than markets scanned (duplicates and non-existent markets are skipped).
viewCurrentReferenceRate
The market's "current" reference rate, normalized to WAD. Spot conventions return the live getRate() reading (windowSeconds ignored); Cumulative markets derive a continuously-compounded annualized rate from index growth over the trailing windowSeconds (using stored snapshots — shorter windows need denser snapshots, i.e. someone calling updateMarketRateIndex regularly). isValid is false for unknown markets, failed/invalid spot reads, a zero or over-long window, or a non-increasing index.
Caveats: isValid is not a staleness gate — past the last snapshot the index is extrapolated, so a stale-but-rising history still reads valid; a window whose start predates the first snapshot is annualized over data that doesn't cover it; and a spot oracle whose decimals() drives normalization out of range reverts the view outright rather than returning (0, false). Callers needing freshness should check viewMarketOracleIndex.lastUpdate themselves.
Base-rate oracle governance aids
maxRequiredTenorForBaseRateOracle
The longest base-rate tenor that markets still backed by oracle require it to serve — a pre-flight check before shortening a timelocked base-rate oracle's tenor curve (shortening below this value makes the oracle fail closed for affected tenors and reverts every base-rate read for those markets with E611, freezing LP pricing/supply/withdraw). A market "constrains" the oracle while it can take new buys (!terminated) or still has locked exposure; fully wound-down terminated markets don't. oracle is matched against the address stored on the market (pass the wrapper address for wrapped deployments). Returns 0 if nothing constrains it. O(number of markets), O(1) memory.
requiredTenorsForBaseRateOracle
Diagnostic companion: the per-market swapTerms that still constrain oracle (a market pair contributes one entry per side), under the same matching rules as above. The paginated overload pages over the raw market-ID index space — a window may return fewer entries than it scanned, or none; limit = 0 scans to the end, and nextOffset == allMarketIds.length signals completion.
core
The SwapCore address this lens reads from. Fixed at deployment — useful for verifying you're pointed at the right protocol instance.
Last updated