Refunds
How Gateway refunds work when a swap can't be completed
Overview
Gateway is non-custodial: its contracts never hold user funds between transactions, apart from the X-to-BTC escrow described below. If a swap can't be completed, the user gets their funds back, and Gateway settles every refund itself — there is no refund transaction for a user or an integrator to submit.
Users can always check their order — including refund status — on the Gateway Explorer order page, so you don't need to build refund status UI.
What happens at a glance
| Scenario | What the user receives | Who acts |
|---|---|---|
| BTC to X: swap can't fill at quoted terms | BTC to their refund address, or USDT on Ethereum | Gateway, automatic |
| BTC to X: destination swap or bridge can't land | BTC to their refund address, or USDT on Ethereum | Gateway, automatic |
| X to BTC: payout delayed | BTC (Gateway bumps the fee) | Gateway, automatic |
| X to BTC: payout can't complete (very rare) | Their escrowed USDT back | Gateway, after the on-chain refund delay |
BTC to X refunds
There are two cases where a BTC-to-X swap returns funds instead of the expected output:
-
The swap can't fill at the quoted terms. While waiting for the Bitcoin transaction to confirm, prices can drift until the destination route no longer accepts the submitted amount.
-
The destination swap or bridge can't land. When a route swaps or bridges onwards through a third-party provider, that on-chain call can revert. The payout and the onward call are one atomic transaction, so the whole release reverts with it and the user is never left holding a partial result.
Both cases resolve the same way, automatically, with no action needed from the user or the integrator. The solver simulates the destination call before releasing, then re-quotes and retries the release on an exponential backoff — starting at 15 seconds and doubling — for up to an hour. If the release still can't land, Gateway settles the order as a refund, and the channel is decided by whether the order was created with a Bitcoin refundAddress:
- With a
refundAddress— the order is committed to a Bitcoin refund on-chain, then paid from the solver's Bitcoin wallet to that address. The Bitcoin fee needed to get the refund transaction confirmed is deducted from the amount sent, so the user bears the cost of moving their own coins back. - Without one — USDT on Ethereum to the order owner.
A refunded order earns no fee. Every fee withheld from the fill — solver, protocol and affiliate — is returned to the user along with the deposit.
Pass a refundAddress when you request a quote if you want failed BTC-to-X swaps returned in BTC rather than USDT on Ethereum.
Refunds after a partial recovery
If the destination call was already released and the onward bridge sent funds back to the solver instead of delivering them, the refund is sized against what actually came back, converted at the rate the order was originally quoted at, plus every withheld fee. In practice the user bears only the gas the failed bridge attempt consumed.
A handful of cases can't be settled automatically and are held for manual handling rather than paid out incorrectly: a deposit too small to cover the Bitcoin fee for its own refund, a refund that would be below Bitcoin's dust threshold, or a refund address or order owner flagged by screening.
X to BTC refunds
X-to-BTC refunds are a very rare edge case. The user's USDT is escrowed in the offramp registry when the order is created, and the token side settles before the Bitcoin payout is made — so a refund only comes into play if the payout never happens (for example, a solver going offline). Often a slow payout isn't a refund case at all — it just needs a Bitcoin fee bump, which Gateway handles internally.
The escrow has only two possible destinations, and the contract fixes both: the user, or a solver that has proven on-chain that it already paid the user.
- The solver proves it paid.
finalizeOfframpOrderreleases the escrow only against an SPV proof of the Bitcoin payout, verified on-chain by the Bitcoin Light Client. See the Deep Dive. - Gateway refunds the order. Once the on-chain
refundDelayhas elapsed,refundOrderreturns the full escrowed amount to the user. The delay is configurable on-chain between 12 hours and 7 days, and exists so a Bitcoin payment that was already made can't be refunded on top of it.
No other party can move those funds, and there is no route that pays them anywhere else — the registry owner controls the timing of a refund, not its destination.
refundOrder is owner-only, so users and integrators don't trigger X-to-BTC refunds themselves. If an order looks stuck, contact us on Discord.
Because users cannot submit Bitcoin proofs themselves, an order may be temporarily "stuck" if the relayer is offline. Funds remain safe — the escrow can only be released against a valid proof, and it stays refundable to the user after the refund delay.
Do integrators need to build refund handling?
No. Refunds in both directions are settled by Gateway, and there is nothing for you to submit. Optionally, surface refund status in your app using the API fields below — for example to show "refunded" in an order history.
Refund status in the API
A completed refund shows up as the refunded order status, which lists the refundedTokens actually returned — each with chain, token, amount, and the settlement txHash:
status.refunded.refundedTokens— the completed refund- A BTC refund appears here as a Bitcoin entry, where
txHashis the Bitcoin txid rather than an EVM transaction hash
status.inProgress.refundTx and status.failed.refundTx are always null. The fields remain in the response purely so the shape is unchanged for existing integrators — do not build refund flows on them.