Reading vault state
This page lists the exact view calls the frontend makes, so you can reproduce
its reads in your own integration. All of these are mirrored in
apps/frontend/src/hooks/vaultReads.ts and src/config/abis.ts.
Resolve addresses first
Before any read, resolve the immutable address graph from the vault (see Contracts & addresses):
FUND_MANAGER = vault.FUND_MANAGER()
asset = vault.asset() // USDC
YIELD_POOL = fundManager.YIELD_POOL()
YIELD_ASSET = fundManager.YIELD_ASSET() // USDCx
EXTERNAL_VAULT = fundManager.EXTERNAL_VAULT()
FEE_BPS = fundManager.FEE_BPS()
Vault-level (protocol) reads
From StableYieldSyncVault (ERC-4626 surface):
| Call | Returns |
|---|---|
totalAssets() | Reserve-inclusive NAV of the vault |
totalSupply() | Total shares outstanding |
asset() | Underlying asset address (USDC) |
convertToAssets(shares) | Shares → assets at current NAV |
previewRedeem(shares) | Assets returned for redeeming shares now (spot, no TWAP) |
maxDeposit(receiver) | Binary gate: uint256.max or 0 (paused) |
maxWithdraw(owner) / maxRedeem(owner) | NAV- and liquidity-capped; read 0 under external pause |
DEPOSIT_FEE() | Flat deposit fee in asset atoms (immutable) |
From the FundManager:
| Call | Returns |
|---|---|
totalManagedAssets() | Reserve-inclusive NAV |
stableYieldRate() | Promised rate, basis points |
guaranteedFlowDuration() | Forward-solvency horizon (seconds) |
FEE_BPS() | Protocol fee, basis points |
Per-user position reads
| Call | Returns |
|---|---|
vault.balanceOf(user) | Shares owned |
YIELD_POOL.getUnits(user) | Nominal principal in USDC atoms (granted units) |
vault.previewRedeem(shares) | Position value at today's NAV (floats with external performance) |
vault.maxRedeem(user) | Shares redeemable right now (gated by Morpho liquidity / pause) |
vault.maxWithdraw(user) | Same, denominated in assets |
Stream reads (the live yield)
From the GDA pool (ISuperfluidPool) and forwarder:
| Call | Returns |
|---|---|
getTotalAmountReceivedByMember(user) | Streamed-so-far, USDCx (18-dec). Monotonic; identical connected or not. Use this for "earned" displays. |
getMemberFlowRate(user) | Current per-second stream rate (int96, 18-dec) = flowRatePerUnit × userUnits |
getTotalUnits() / getTotalFlowRate() | Pool-wide units / flow |
getClaimableNow(user) | Reads 0 once the member is connected (accrual claimed at connect) |
GDAv1Forwarder.isMemberConnected(pool, user) | Whether the member's stream counts in their wallet balance |
Decimals gotcha: the vault/asset are USDC (6-dec) but the stream is USDCx (18-dec).
SCALING_FACTOR = 10^12bridges them. Don't mix the two when displaying numbers.
Deriving the displayed rate
The app shows a linearized streaming rate, not the compounding APY. In
src/components/vault/lib.ts the displayed APR is:
displayedRate = ln(1 + MORPHO_APY) × (1 − feeFraction)
i.e. continuous-compounding linearization of the underlying APY, net of fee.
Pause / availability checks
maxDeposit(...) == 0→ deposits gated.maxRedeem(user) == 0while the user holds shares → external pause or no liquidity; the stream still pays from the reserve.- The frontend uses these gates rather than calling the external vault's
max*views (which are hardcoded to 0 and should be ignored).
Next
- Integration guide — the write flows (classic and gasless) that act on this state.