feat: add SELL quote from velora to support bigger quotes#501
feat: add SELL quote from velora to support bigger quotes#501antoncoding merged 7 commits intomasterfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 59 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 Walkthrough📝 Walkthrough🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/hooks/useLeverageQuote.ts`:
- Around line 278-303: Treat zero or insufficient SELL quotes as failures: when
computing borrowAssets (from buyRoute.srcAmount) if borrowAssets <= 0n return
the empty/failure shape, and after fetching sellRoute via fetchVeloraPriceRoute
verify that withSlippageFloor(BigInt(sellRoute.destAmount), slippageBps) meets
or exceeds the required target (targetFlashCollateralTokenAmount); if it does
not, return the same empty/failure response (flashLoanAssetAmount: 0n,
flashLegCollateralTokenAmount: 0n, priceRoute: null) so callers will fallback to
iterative sizing rather than treating an undersized BUY-derived SELL quote as
success.
- Around line 130-147: Validate the Velora route side and exact-amount before
using preview amounts: after calling fetchVeloraPriceRoute and before assigning
latestQuote, assert that sellRoute.side === 'SELL' and that
BigInt(sellRoute.srcAmount) === sellAmount (i.e., the route's source amount
matches the requested sellAmount); if either check fails, log/throw and skip
building latestQuote. Do the analogous checks where you use buy routes (ensure
route.side === 'BUY' and the route's dest/src amount matches the requested exact
amount) before reading sellRoute.destAmount or sellRoute.srcAmount, then only
compute quotedCollateralTokenAmount and call withSlippageFloor(slippageBps) and
set latestQuote when validations pass.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 6b999d7c-b61c-40c5-b760-2183ebf41144
📒 Files selected for processing (1)
src/hooks/useLeverageQuote.ts
There was a problem hiding this comment.
♻️ Duplicate comments (2)
src/hooks/useLeverageQuote.ts (2)
199-221:⚠️ Potential issue | 🟠 MajorCheck the slippage-floored amount before accepting the SELL quote.
Line 206 stops once the gross quote reaches
targetCollateralTokenAmount, but line 201 returns the slippage-floored amount. A quote that barely reaches the target can still return a below-targetflashLegCollateralTokenAmount.Proposed fix
- if (quotedCollateralTokenAmount >= targetCollateralTokenAmount) { + if (latestQuote.flashLegCollateralTokenAmount >= targetCollateralTokenAmount) { break; } @@ - if (latestQuote.quotedCollateralTokenAmount < targetCollateralTokenAmount) { + if (latestQuote.flashLegCollateralTokenAmount < targetCollateralTokenAmount) { throw new Error('Failed to size Velora sell route for target leverage. Try a lower multiplier or refresh the quote.'); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/hooks/useLeverageQuote.ts` around lines 199 - 221, The loop currently accepts a quote when quotedCollateralTokenAmount >= targetCollateralTokenAmount but the code uses the slippage-floored value (withSlippageFloor) as flashLegCollateralTokenAmount; update the acceptance and final checks to use the slippage-floored amount instead of the raw quotedCollateralTokenAmount: when deciding to break and set latestQuote, compare withSlippageFloor(quotedCollateralTokenAmount, slippageBps) (or latestQuote.flashLegCollateralTokenAmount) against targetCollateralTokenAmount, and in the final validation replace the quotedCollateralTokenAmount comparison with a check on latestQuote.flashLegCollateralTokenAmount (or the floored value) to ensure the post-slippage amount meets the target before accepting or throwing.
117-130:⚠️ Potential issue | 🟠 MajorValidate Velora
sideand exact amounts before using route amounts.These tx-critical previews use
buyRoute.srcAmountandsellRoute.destAmountwithout visible checks that the response matches the requested BUY/SELL side and exact amount. If this is not enforced insidefetchVeloraPriceRoute, add local guards before assigning quote values. Based on learnings, “For Velora/Paraswap routes, validate execution-authoritative fields only (trusted target, exact sell amount, min-out/close floor, token identities); do not block on echoed metadata”.Proposed guard
const buyRoute = await fetchVeloraPriceRoute({ srcToken: loanTokenAddress, srcDecimals: loanTokenDecimals, destToken: collateralTokenAddress, destDecimals: collateralTokenDecimals, amount: targetCollateralTokenAmount, network: chainId, userAddress: swapExecutionAddress, side: 'BUY', }); + if (buyRoute.side !== 'BUY') { + throw new Error('Velora returned a non-BUY route for BUY bootstrap.'); + } + const initialSellAmount = BigInt(buyRoute.srcAmount); - if (initialSellAmount > 0n && BigInt(buyRoute.destAmount) >= targetCollateralTokenAmount) { + if (initialSellAmount > 0n && BigInt(buyRoute.destAmount) === targetCollateralTokenAmount) { return initialSellAmount; } @@ const sellRoute = await fetchVeloraPriceRoute({ srcToken: loanTokenAddress, srcDecimals: loanTokenDecimals, destToken: collateralTokenAddress, destDecimals: collateralTokenDecimals, amount: sellAmount, network: chainId, userAddress: swapExecutionAddress, side: 'SELL', }); + if (sellRoute.side !== 'SELL' || BigInt(sellRoute.srcAmount) !== sellAmount) { + throw new Error('Velora returned a SELL route for a different exact input amount.'); + } const quotedCollateralTokenAmount = BigInt(sellRoute.destAmount);To verify whether this is already centralized:
#!/bin/bash # Expect to find side and exact requested-amount validation either in fetchVeloraPriceRoute # or at each tx-critical call site before route amounts are consumed. rg -n -C6 --type=ts 'fetchVeloraPriceRoute|side|srcAmount|destAmount' src/features/swap/api/velora.ts src/hooks/useLeverageQuote.tsAlso applies to: 187-201
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/hooks/useLeverageQuote.ts` around lines 117 - 130, Ensure the Velora route is execution-authoritative before using its amounts: after calling fetchVeloraPriceRoute (referencing buyRoute/sellRoute, srcAmount, destAmount), assert route.side === the requested side ('BUY' or 'SELL'), verify route.srcToken and route.destToken match the expected loanTokenAddress and collateralTokenAddress, and validate the authoritative amount (for BUY ensure BigInt(buyRoute.destAmount) >= targetCollateralTokenAmount and for SELL ensure BigInt(sellRoute.srcAmount) equals the exact requested sell amount or meets the required exact/min-out rules). If any guard fails, throw or reject the quote instead of consuming buyRoute.srcAmount/sellRoute.destAmount; apply the same checks for the other route usage at lines ~187-201.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/hooks/useLeverageQuote.ts`:
- Around line 199-221: The loop currently accepts a quote when
quotedCollateralTokenAmount >= targetCollateralTokenAmount but the code uses the
slippage-floored value (withSlippageFloor) as flashLegCollateralTokenAmount;
update the acceptance and final checks to use the slippage-floored amount
instead of the raw quotedCollateralTokenAmount: when deciding to break and set
latestQuote, compare withSlippageFloor(quotedCollateralTokenAmount, slippageBps)
(or latestQuote.flashLegCollateralTokenAmount) against
targetCollateralTokenAmount, and in the final validation replace the
quotedCollateralTokenAmount comparison with a check on
latestQuote.flashLegCollateralTokenAmount (or the floored value) to ensure the
post-slippage amount meets the target before accepting or throwing.
- Around line 117-130: Ensure the Velora route is execution-authoritative before
using its amounts: after calling fetchVeloraPriceRoute (referencing
buyRoute/sellRoute, srcAmount, destAmount), assert route.side === the requested
side ('BUY' or 'SELL'), verify route.srcToken and route.destToken match the
expected loanTokenAddress and collateralTokenAddress, and validate the
authoritative amount (for BUY ensure BigInt(buyRoute.destAmount) >=
targetCollateralTokenAmount and for SELL ensure BigInt(sellRoute.srcAmount)
equals the exact requested sell amount or meets the required exact/min-out
rules). If any guard fails, throw or reject the quote instead of consuming
buyRoute.srcAmount/sellRoute.destAmount; apply the same checks for the other
route usage at lines ~187-201.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d0978ac4-103a-4cf1-ac33-47f5aeee50bb
📒 Files selected for processing (2)
src/hooks/useDeleverageQuote.tssrc/hooks/useLeverageQuote.ts
✅ Files skipped from review due to trivial changes (1)
- src/hooks/useDeleverageQuote.ts
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/hooks/useLeverageQuote.ts (1)
187-223:⚠️ Potential issue | 🟠 MajorValidate the executable SELL amount and min-out before accepting the route.
Line 207 and Line 221 check the raw quote, but execution uses the slippage floor. This can accept a route whose minimum output is below the leverage target. Also confirm
sellRoute.srcAmountmatchessellAmountbefore storing the route.Proposed fix
const sellRoute = await fetchVeloraPriceRoute({ srcToken: loanTokenAddress, srcDecimals: loanTokenDecimals, destToken: collateralTokenAddress, destDecimals: collateralTokenDecimals, amount: sellAmount, network: chainId, userAddress: swapExecutionAddress, side: 'SELL', }); + const routeSellAmount = BigInt(sellRoute.srcAmount); + if (routeSellAmount !== sellAmount) { + throw new Error('Velora returned a SELL route with a different source amount than requested.'); + } + const quotedCollateralTokenAmount = BigInt(sellRoute.destAmount); + const minCollateralTokenAmount = withSlippageFloor(quotedCollateralTokenAmount, slippageBps); latestQuote = { - flashLoanAssetAmount: sellAmount, - flashLegCollateralTokenAmount: withSlippageFloor(quotedCollateralTokenAmount, slippageBps), + flashLoanAssetAmount: routeSellAmount, + flashLegCollateralTokenAmount: minCollateralTokenAmount, quotedCollateralTokenAmount, priceRoute: sellRoute, }; - if (quotedCollateralTokenAmount >= targetCollateralTokenAmount) { + if (minCollateralTokenAmount >= targetCollateralTokenAmount) { break; } sellAmount = getNextSellAmountForTargetCollateral({ - currentSellAmount: sellAmount, - quotedCollateralAmount: quotedCollateralTokenAmount, + currentSellAmount: routeSellAmount, + quotedCollateralAmount: minCollateralTokenAmount, targetCollateralAmount: targetCollateralTokenAmount, }); } @@ - if (latestQuote.quotedCollateralTokenAmount < targetCollateralTokenAmount) { + if (latestQuote.flashLegCollateralTokenAmount < targetCollateralTokenAmount) { throw new Error('Failed to size Velora sell route for target leverage. Try a lower multiplier or refresh the quote.'); }Based on learnings, Applies to **/{swap,paraswap}.{ts,tsx} : For Velora/Paraswap routes, validate execution-authoritative fields only (trusted target, exact sell amount, min-out/close floor, token identities); do not block on echoed metadata.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/hooks/useLeverageQuote.ts` around lines 187 - 223, Ensure the accepted Velora route is executable by validating execution-authoritative fields: inside the attempt loop (where sellRoute, sellAmount, quotedCollateralTokenAmount and latestQuote are set) verify that sellRoute.srcAmount equals the current sellAmount and that the execution min-out (withSlippageFloor(quotedCollateralTokenAmount, slippageBps)) is >= targetCollateralTokenAmount; also confirm sellRoute.srcToken/destToken match loanTokenAddress/collateralTokenAddress before assigning latestQuote and breaking; if any check fails, treat it as a non-viable quote and continue the loop (so getNextSellAmountForTargetCollateral can run) and only throw after the loop if no route passes these execution checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/hooks/useLeverageQuote.ts`:
- Around line 187-223: Ensure the accepted Velora route is executable by
validating execution-authoritative fields: inside the attempt loop (where
sellRoute, sellAmount, quotedCollateralTokenAmount and latestQuote are set)
verify that sellRoute.srcAmount equals the current sellAmount and that the
execution min-out (withSlippageFloor(quotedCollateralTokenAmount, slippageBps))
is >= targetCollateralTokenAmount; also confirm sellRoute.srcToken/destToken
match loanTokenAddress/collateralTokenAddress before assigning latestQuote and
breaking; if any check fails, treat it as a non-viable quote and continue the
loop (so getNextSellAmountForTargetCollateral can run) and only throw after the
loop if no route passes these execution checks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: c7ba07f9-422b-4096-9946-5989673631f4
📒 Files selected for processing (3)
src/hooks/leverage/velora-quote-errors.tssrc/hooks/useDeleverageQuote.tssrc/hooks/useLeverageQuote.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/hooks/useDeleverageQuote.ts
starksama
left a comment
There was a problem hiding this comment.
Reviewed end-to-end after the follow-up fixes.
Why I'm approving:
- collateral-input leverage quotes now use a price-aware BUY bootstrap when available, and fall back to iterative SELL sizing when BUY fails at size
- this fixes the original regression risk on pairs like USDC -> cbBTC while still handling larger routes like PYUSD -> sUSDe
- user-facing quote failures are now much clearer, including reported impact when Velora returns it
- I re-checked the main CodeRabbit concerns; the earlier blocking ones are addressed
What I validated:
- live quote behavior on PYUSD -> sUSDe, USDC -> cbBTC, and WETH -> wstETH
- top-market scan to separate algorithm issues from plain upstream liquidity / impact failures
- execution safety assumptions remain fail-closed downstream in the leverage/deleverage execution path
Remaining caveat, but not blocking for this PR:
- collateral-input preview still accepts success on raw quoted output rather than slippage-floor >= target. That is worth a follow-up if we want stricter target semantics, but I do not see it as a merge blocker for this fix.
Given the fixes and live verification, this looks good to merge.
integrate paraswap sell quote for better liquidity
Summary by CodeRabbit
Bug Fixes
New Features