--- title: Refunds description: When a deposit is returned, what is deducted from it, and the cases where a refund does not happen automatically. --- import { MAX_FULFILL_ATTEMPTS } from "/snippets/vars.mdx"; A deposit that cannot be fulfilled is returned to `refund_address` on the source chain, in the token that was deposited. The router pays it from its own balance, the same way it pays fulfillments. ## What triggers one | Cause | How the order gets there | | --- | --- | | Mismatched deposit | Wrong token, wrong amount, or a quote hash already consumed. The order is created directly in `pending_refund`. | | Exhausted fulfillment | {MAX_FULFILL_ATTEMPTS} failed attempts on the destination chain, for example a destination swap that cannot clear `min_amount_out`. | | Reverted submission | A fulfillment that reverted or had its nonce burnt, once the consistency window resolves against it. | ## What is deducted The refund returns the deposit minus the refund fees committed in the quote: `src_refund_gas` plus any `src_burn_cost` and `dst_burn_cost`, carried on the order as `refund_fee_bridge`. The rest of the breakdown is not charged: no spread, no referrer fee, no gas drop. ``` refunded = deposit_amount - src_side_fees ``` The deduction is fixed at quote time, so the refund does not get more expensive if gas rises afterwards. ## Deferral when gas is high If the live gas price would push the refund's cost above the amount committed for it, the refund is not submitted at a loss and it is not taken out of the user's principal. The order stays in `pending_refund` and is rechecked later, submitting as soon as gas comes back down. An order sitting in `pending_refund` for a while is usually this, not a failure. ## When it does not happen automatically Three terminal states mean no refund was paid and the funds need manual handling. All three are rare and none of them is silent. | State | Cause | | --- | --- | | `refund_skipped` | The committed fees are worth more than the deposit itself, so returning it would send a negative amount. Typical for dust. | | `unsupported_deposit` | The deposited token is not in the registry, or a mismatched deposit was made against a same-chain quote. There is no safe automatic path. | | `refund_failed` | The refund transaction reverted or was burnt. | Surface these distinctly in your interface. A user seeing "failed" with no explanation will assume the funds are gone, when in practice they are in the escrow and recoverable through support. ## Reading refund detail `GetOrder` returns a `refund` message once one exists: ```ts const { refund } = await hular.getOrder({ quoteHash }); refund?.status; // submission status refund?.srcTx; // refund transaction hash on the source chain refund?.attempts; // submissions made refund?.lastError; // last failure reason, when there is one refund?.confirmedAt; // set when the refund has confirmed ``` As with fulfillments, `src_tx` being present means submitted, not confirmed. The order state is the authority; see [Order lifecycle](/concepts/order-lifecycle).