Auctions overview
Auctions are how Milky resolves a loan that didn't get repaid in time. The goal of an auction is simple: sell the collateral card for enough to repay the lender, take a protocol cut of any surplus, and do it through a transparent on-chain process anyone can audit.
In production, every default auction is a Dutch auction with a short duration and a defined starting price. The protocol also supports English auctions at the on-chain level — they exist as an option in the program — but the keeper that triggers production defaults uses the Dutch format exclusively.
This page covers the shared lifecycle. Format-specific behavior lives in Dutch auctions and English auctions.
When does an auction start?
An auction can start as soon as a loan becomes eligible for default —
that is, when the current cluster time is greater than maturity_ts + grace_period_secs. Until then, the borrower can still repay on the
original terms.
Once the loan is default-eligible, the loan_mark_default_and_start_auction
instruction can be submitted by anyone. It atomically:
- Marks the loan as
Defaulted. - Initializes a new
Auctionaccount for that loan. - Opens a USDC bid escrow vault tied to the auction.
- Sets the auction's start and end timestamps based on the requested duration parameter.
Because anyone can call this instruction, in practice it is a keeper bot operated by Milky (or a third party) that watches for newly default-eligible loans and submits the transaction. The starter pays the rent for the new accounts, but is reimbursed at settlement (or at no-bid cancel), giving keepers a small economic incentive to be timely.
What an auction account holds
A live Auction account stores:
- A reference to the loan it's resolving (and therefore to the collateral NFT and the pool).
- The reserve price — the full payoff (
principal + fixed_interest_due) the auction must clear to fully repay the lender. - Timing —
start_ts,end_ts,duration_secs. - Format — Dutch or English (
auction_type). - Bid state — for English: highest bidder and amount; for Dutch: whether a bid has landed yet (which immediately ends the auction).
- A bid escrow vault — the USDC vault holding the current high bidder's funds.
- Anti-sniping config (English only) — the window before
end_tsin which a bid extendsend_ts, and a cap on total extensions.
The collateral during the auction
The card stays in the protocol's collateral vault (the loan's collateral
account) for the entire auction. The loan's loan_authority PDA remains
the delegate, so when settlement happens the protocol can sign the
transfer to the auction winner without needing the borrower's signature.
The borrower has no on-chain claim on the card from the moment the default instruction lands — that's the entire point of the default transition.
What ends an auction
There are three ways an auction reaches a terminal state:
- A bid lands and settlement runs (English: at end_ts; Dutch: on bid). The card transfers to the winner; USDC is split per the settlement waterfall; the loan account, locks, and auction account close and refund their rent.
- No bid is received before end_ts and
auction_cancel_if_no_bidsis called. The card moves to a pool-held custody account; loan and auction accounts close. See no-bid outcome. - The auction is "stuck" — for example, if no keeper triggers either settlement or no-bid cancel. The auction account remains open until someone does. The protocol does not have an automatic timeout.
Permissioning
Different auction operations have different signers:
- Starting the auction. Anyone can submit
loan_mark_default_and_start_auctiononce the loan is default-eligible. - Bidding. Anyone can bid (English) or accept the current Dutch price.
- Settlement. The winner must sign the settlement transaction (it transfers the card to them). The Milky app bundles bid + settle in a single Dutch transaction so this is invisible to the bidder.
- No-bid cancellation. Anyone can submit
auction_cancel_if_no_bidsafter the auction expires with zero bids; the rent refund creates a small keeper incentive. - Pause behavior. New bids are blocked while the protocol is globally paused; settlement is intentionally not pause-blocked, so winners can always claim cards they've legitimately bought.
Read next
- Dutch auctions — the format used in production.
- English auctions — the alternative format also supported by the program.
- Settlement & waterfall — how the proceeds are split.
- No-bid outcome — what happens to a card when nobody bids.