DEVNETYou are on Solana devnet. Funds are not real. Behavior matches mainnet.

Oracle & valuation

Pricing is the single most consequential off-chain input to a Milky loan. Get it wrong and the protocol either over-lends (pool takes losses) or under-lends (borrowers leave with less liquidity than their cards justify). This section walks through how Milky prices cards, how those prices reach the chain, and what assumptions you're trusting when you take a loan or deposit liquidity.

What is being priced

Milky prices individual graded cards, not collections or floors. Every quote is for a specific physical card identified by:

  • A grading certificate (e.g. a PSA cert number) that uniquely identifies the card.
  • The grading company that issued it (PSA, CGC, Beckett, etc.).
  • The grade that company assigned (PSA 10, PSA 9, etc.).

These three together resolve to a canonical asset identity in Milky's indexer, which is what the oracle's pricing data sources actually price. Two different PSA-cert-numbered copies of the same card at the same grade share the same canonical asset identity for pricing purposes, but remain distinct physical certs for exposure tracking.

This granularity matters: a PSA 10 of a given card is often worth several multiples of a PSA 9 of the same card. Treating them as distinct asset types means the protocol's exposure caps and pricing both reflect that reality.

How prices reach the chain

Off-chain prices reach the chain via signed quotes, not via a continuous price feed. The lifecycle, in brief:

  1. Borrower requests a quote

    The Milky backend is asked to price a specific card for a specific borrow request (pool, term option, principal). It looks up the canonical asset, fetches a fresh price from its data sources, and decides on a fair market value and an LTV.

  2. Backend signs the quote

    The oracle's Ed25519 keypair signs a structured message containing the FMV, LTV, term, expiry, quote ID, and several binding fields (NFT mint, certificate hash, asset type ID, root version, pool).

  3. Borrower submits the quote on-chain

    The borrower's loan-create transaction includes the signed quote and an Ed25519 verify instruction. The Milky program verifies the signature, checks the oracle is allowlisted, and validates every field against the on-chain state.

  4. Quote is consumed and locked

    A UsedQuote PDA is created keyed by (oracle pubkey, quote id). The same quote can never be used again: a second attempt fails because the account already exists.

Quote validity and freshness

Quotes are short-lived by design:

  • The default TTL is 300 seconds (5 minutes).
  • The protocol can configure up to a 3,600-second (1-hour) ceiling for special flows.
  • The on-chain loan_create rejects expired quotes.
  • The on-chain loan_draw re-checks the same quote's expiry before releasing funds, so a borrower can't create-now-draw-later with a stale quote.

Short TTLs trade off two concerns:

  • Long enough that borrower UX is comfortable (sign one transaction and submit it within a few minutes).
  • Short enough that the price the lender receives is close to the current market price.

5 minutes is a deliberate choice that works for both.

What the oracle is not

To set expectations:

  • It is not a continuous price feed like Pyth or Switchboard. There's no on-chain "current price" you can query — prices materialize as signed quotes for specific borrow requests.
  • It is not a collection-floor oracle. Milky doesn't price "the Pokémon Charizard collection"; it prices specific graded copies.
  • It is not marketing data or a discoverable rate sheet. Quotes are generated on demand, signed once, and consumed once.
  • It is not decentralized today. The oracle is a single signing key operated by Milky. Multi-party signing is on the roadmap as protocol maturity warrants it.

Why this design

Compared with continuous on-chain price feeds, the signed-quote model has three concrete advantages for an asset class like graded trading cards:

  • Fits the data shape. Card markets are slower-moving than crypto, with thinner per-cert pricing and more reliance on off-chain analytics to combine pop reports, sale comps, and grading distributions. A bespoke off-chain oracle can integrate this reliably; a generic on-chain feed cannot.
  • No public mark-to-market needed. The protocol doesn't need to publish or maintain a price for every card all the time. Prices only exist when there's a borrowing decision to make.
  • Built-in replay protection. Each quote is uniquely identified and used at most once, eliminating an entire class of stale-price attacks.

The trade-off, of course, is that the oracle is a centralized off-chain service with operational responsibility for not signing bad prices. The trust assumptions page covers this honestly.