The loan lifecycle
A Milky loan moves through five clearly-defined states. The protocol enforces these transitions on-chain, so the same flow applies whether you use the Milky app, a third-party UI, or interact with the program directly.
States and transitions
There is also a sixth, terminal state on the unhappy path: Defaulted / Auction, which the loan enters after maturity plus the grace period. See default and liquidation for the mechanics of that branch.
Walking through each step
Step 1 — Request a signed quote
Before opening anything on-chain, you ask Milky's oracle for a price. The oracle resolves your card's grading certificate to a canonical asset, fetches the current fair market value, and returns a signed quote that includes:
- The fair market value (FMV) in USDC.
- The maximum LTV permitted on this card, in basis points.
- The selected term length and interest rate.
- A unique quote id and an expiry timestamp.
Quotes are short-lived — they expire in 5 minutes by default. If you don't open a loan in that window, you simply request a new one.
Step 2 — Verify the Merkle proof
Milky maintains an allowlist of every card eligible to be used as collateral, hashed into a Merkle tree whose root the protocol stores on-chain. Before you create the loan, you submit a small proof showing your card is in the current tree. This produces a proof receipt account keyed by your card's certificate hash. The next step will consume that receipt.
This is a one-time-per-loan check. The proof itself is a few hundred bytes and the transaction is cheap.
Step 3 — Create the loan
You submit:
- The signed oracle quote (with the proper Ed25519 verify instruction).
- The proof receipt from the previous step.
- The pool you want to borrow from and the term option you want.
The program checks all the on-chain rules in one shot:
- The oracle's signature is valid and the oracle is on the allowlist.
- The Merkle root version on the quote matches a recent root the chain knows.
- The principal you're requesting is within the pool's
[min, max]range and withinFMV × LTVfor the card. - All the per-card and per-asset-type concentration limits are respected.
If everything passes, the loan is recorded in the Created state and a
short pending draw window opens — about 5 minutes — during which you
must complete the next step.
Step 4 — Draw the funds
Drawing is the moment money and collateral actually move:
- Your card-backed NFT transfers into the protocol's collateral vault (frozen, or for programmable NFTs, locked via a delegate slot).
- The pool sends you principal minus the origination fee in USDC.
- Concentration counters update: the pool's outstanding principal goes up, and the running exposure for this asset type increases by the principal.
- The loan transitions to
Active. The maturity clock starts at this moment, not when you created the loan.
Step 5 — Repay before maturity (the happy path)
To repay, you transfer principal plus the full fixed interest in a single transaction. There is no partial-repayment flow that closes the loan; anything less than the full payoff is rejected.
When the repayment lands:
- The pool's outstanding principal decreases by the principal you repaid.
- The loan moves to
Repaid. - A second instruction (often bundled in the same transaction by the app) closes the loan account, unlocks the NFT, and refunds you the rent that was paid for the loan's accounts.
You can repay at any point after drawing, including the same block. The interest is fixed, so there is no benefit to repaying earlier than your plan calls for, but there is no penalty either.
Step 5 (alternate) — Default after maturity
If the maturity timestamp passes plus the grace period, the loan becomes
eligible for default. At that point anyone — typically a keeper bot — can
submit loan_mark_default_and_start_auction, which atomically:
- Marks the loan as
Defaulted. - Initializes a new
Auctionaccount with a reserve price equal to the full payoff (principal + fixed interest). - Starts the bidding window, which is a Dutch auction in production.
The full mechanics of what happens next are covered in default and liquidation and auctions overview.
What you do not do
A handful of things that exist in other lending protocols are intentionally absent here:
- No health-factor monitoring. Default is purely time-based: maturity passes, grace passes, you default. Price movements during the loan don't trigger early liquidation.
- No rolling / refinancing. A repaid loan is a closed loan; if you want to borrow again, you open a fresh loan against the card.
- No rate adjustments mid-loan. The rate you accept at create time is the rate you owe at repay time, regardless of what the pool changes its current term options to.
Read next
- Terms and fees — the actual numbers involved.
- Default and liquidation — what the unhappy path looks like.
- Auctions overview — how a defaulted card is sold.