Skip to main content
An escrow fill settles in two transactions. The user’s transaction opens an RFQ order onchain that escrows the user’s input, the settlement mint. The maker fills the order in a later transaction. DFlow does not call /swap for an rfqOrder quote.

Selected Quote

DFlow calls POST /selected before it hands the transaction to the user.
The maker checks that quoteId is one of its live quotes and records or queues orderAddress for filling. endorsementSignature may also be present. To refuse, the maker returns 409 (or 422) with { "reason": "<text>" }. Any 2xx accepts. The call is idempotent per quoteId and orderAddress, and has the same 0.9 second budget and retry as a direct fill selection. The notification arrives before the user signs. The order account may not exist yet, and may never exist if the user declines or the transaction fails or expires. The maker does not refuse the notification because the account is missing. It watches the chain for the account until the open transaction’s blockhash expires, about 150 slots after DFlow built it.

Fill Deadline

An order account stores a last_fillable_slot, inclusive. It is the earlier of the slot of the quote’s expiry and the open slot plus up to 150 slots. DFlow sets the quote’s expiry, 60 seconds after the quote by default, and the maker cannot change it. A maker that needs a different window declines the quote. After last_fillable_slot the order can only be closed and refunded.

Fill an Order

The maker fills the order with its own transaction before the deadline. Read the Fill Instruction describes its data and accounts. The fill instruction carries the order’s quoted_in and quoted_out, which the maker reads from the order account. They are the maker’s own quote: quoted_in is the most input the maker receives after any input-side platform fee, and quoted_out is what it pays for quoted_in, before any output-side fee.
  • Input: a fill takes the lesser of the escrowed input and the amount that leaves the maker quoted_in after an input-side platform fee. The maker does not choose a smaller amount.
  • Output: the maker pays received × quoted_out ÷ quoted_in, rounded down, where received is the input its token account gained. The price does not change with the size of the fill. A platform fee or a Token-2022 transfer fee on the input reduces received and so reduces the payment.
  • Result: a fill closes the order. Input the fill does not consume returns to the user in the same transaction. The events report the measured amounts.

Fill Conditions

A fill succeeds only when all of these hold. Otherwise the transaction reverts and nothing moves.
  • The maker signs, and the slot is at or before last_fillable_slot.
  • Every account is the one the order names, apart from the maker’s two token accounts.
  • The fill’s quoted_in and quoted_out equal the order’s.
  • The maker’s input account gains something. A Token-2022 transfer fee or an input-side platform fee cannot take the whole input.
  • The payment is at least one unit: received × quoted_out must be at least quoted_in.
  • The maker’s output account holds the payment, and its balances move by exactly the payment and received.
  • The user’s account receives the whole payment less any output-side platform fee. The destination is not frozen and the output mint has no transfer fee.
  • Any refund, when the escrow exceeds the ceiling, can reach the user’s refund account.
  • Each Token-2022 mint’s transfer hook gets its extra accounts.
A fee account that is missing, frozen, or of another mint never blocks a fill. The fee is skipped and the user keeps it.

Close an Order

Before last_fillable_slot, only the order’s maker can close the order. A close refunds the whole escrow to the user. The maker closes an order it cannot fill, for example when it cannot acquire the equity. The user cannot close an order. After last_fillable_slot, anyone can close it.

Order Events

Each transition of an order emits one RfqOrderEvent: open, fill, cancel (a close before the deadline) and expire (a close after it). The open event names the order and its maker. Onchain Fill Parsing describes how to read the events.