fix(swap): quote-time refund-risk boundaries — fee/slippage gate + route minimums#369
Merged
Merged
Conversation
…ute minimums
A $17.76 BTC→ETH swap was refunded on-chain ('Emit asset less than
price limit') and came back $14.52 — on small amounts the fixed
outbound fee exceeds the slippage allowance, so the emit lands below
the memo's limit and the refund burns another outbound fee. Nothing
gated this at quote time.
Two unit-safe boundaries in getSwapQuote, every route:
- fees.totalBps >= slippageBps → throw 'amount too low' (bps are the
only fee field with integration-independent units; fees.outbound is
base-units-or-decimal depending on swapper).
- minAmountIn enforced for ALL integrations — previously only the NEAR
Intents block checked it, so THORChain routes sailed past their floor.
parseQuoteResponse now also extracts THORChain's
recommended_min_amount_in into minAmountIn (always 1e8 base units of
the sell asset → converted to decimal; gated to THORChain/Maya routes
only, other swappers' units vary). Regression tests pin the units
conversion and the non-THORChain skip (51/51).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A $17.76 BTC→ETH swap (tx
1a642237…) was refunded on-chain with 'Emit asset 0.0083818 less than price limit' and returned $14.52 — an 18% loss for nothing. On small amounts the fixed outbound fee exceeds the slippage allowance, so the emitted amount is guaranteed to land below the memo's price limit, and the refund burns another outbound fee. Nothing gated this at quote time.Boundaries added (
getSwapQuote, every route)fees.totalBps >= slippageBps→ throw "swap amount too low" at quote time. Basis points are the only fee field with integration-independent units —fees.outboundarrives in base units or decimal depending on the swapper (the SwapDialog literally has alooksLikeBaseUnitsheuristic for it), so no gate is built on it.minAmountInwas only enforced inside the NEAR Intents block; THORChain routes sailed past their floor. Now enforced route-agnostically.recommended_min_amount_inextraction (parseQuoteResponse): THORNode publishes exactly this floor — always 1e8 base units of the sell asset — now converted to decimal and folded intominAmountIn, gated to THORChain/Maya routes only (other swappers' units vary; no generic fallback per the no-silent-format-mismatch rule).Tests
Two new regression tests pin the 1e8→decimal conversion and the non-THORChain skip;
bun test __tests__/swap-parsing.test.ts51/51. tsc differential: 0 new errors (2 pre-existing in swap.ts untouched).