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

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:

  1. Load the swap and market. Revert if the swap doesn't exist (E500) or the market is gone (E300).

  2. Compute timeElapsed, capped at swapTerm. If no time has elapsed (entryTimestamp == block.timestamp), return (0, 1) — no obligation, buyer is the trivial recipient.

  3. Resolve the effective oracle index:

    • Active swap: use getFreshIndex(oracle) — a projected-forward read.

    • Expired swap, in order:

      1. If a post-expiry snapshot exists, use the stored interpolation via rateIndex.getIndexAt(expiry) — the same bracket settlement would use.

      2. Otherwise, try getFreshIndex and interpolate the fresh value back to expiryTimestamp via getIndexAtVirtual — bit-equivalent to what a same-transaction settle would resolve, so a stale view can't mask a pending settlement.

      3. 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, revert E450.

  4. Derive floatingPaymentRate from (entryFloatingIndex, effectiveIndex, rateDuration) using SwapFormulas.deriveRateFromIndex.

  5. Compute the accrued legs. The fixed leg comes from SwapFormulas.accruedFixedLeg using swap.baseRate plus the stored swap.utilFee / swap.riskPremium (re-added explicitly on the fixed leg for BUY_FIXED; on the floating leg for BUY_FLOATING). swap.swapRate is 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.

  6. Net them with SwapFormulas.calculateNetObligation(fixedPayment, floatingPayment). Flip the buyerOwes bit if this is a BUY_FLOATING market (the buyer's side of the swap is the floating leg, not the fixed one).

  7. 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 at swap.collateralBalance. This mirrors exactly what makePayment and liquidateSwap would do.

Returns:

Field
Meaning

netAmount

The net obligation in swapToken decimals. Always non-negative.

netRecipient

0 = LP pool receives, 1 = buyer receives.

Reverts:

Code
Reason

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:

  • E450 fires here even past the settlement grace period, where makePayment itself 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 where block.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)netAmount defaults to 0 and netRecipient defaults to 1 ("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 revert E450 or propagate getFreshIndex failures.) 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 SwapClosed event's netRecipient and amountSettled fields (emitted by every closure path; also returned synchronously as SettlementResult from makePayment / exitSwapEarly). There is no storage getter for netRecipient — it lives only in the event/return.

    • The buyer's remaining on-core claimgetBuyerSettlementValue in one call, or the raw slots settlementPayouts / escrowedCollateral. A losing buyer can still have a nonzero payout, so you can't infer netRecipient from 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:

  1. Reads swap.marketId.

  2. Calls rateIndex.update(market.referenceRateOracle) — a real storage write under normal execution.

  3. 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 full swapPositions struct.

Reverts: like getSwapNetAmountE450 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 makePayment doesn't re-read the oracle for every swap in the batch — though makePayment already 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:

Code
Reason

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 for SpotCompoundRate markets only and is zero on other conventions. It is signed — a zero is a legitimate value, not an absence — so key netting eligibility on weightedInverseIndex instead.

  • Fields 15–23 are the value boxes: per-member parameter ranges that bracket every active member, consumed by BucketBoundsLib for conservative NAV bounds. minFeeSum/maxFeeSum (20–21) are a single merged fee axis — min/max over members of utilFee + 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, while getBaseRate / calculateSwapRate / previewUtilizationFee / viewMarketOracleIndex revert 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 while block.timestamp < vestEndTimestamp.

  • capActivetrue iff block.timestamp < vestEndTimestamp && getPoolBurnPrice(marketId) > entryPrice. When true, a withdrawCollateral right now would burn shares at entryPrice rather than the live (higher) price.

    The comparison is against getPoolBurnPrice — the mark withdrawCollateral actually 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