From 0f7a9b5e01d6730b4249d5742297d77bcd787e6d Mon Sep 17 00:00:00 2001 From: caydyan Date: Mon, 22 Jun 2026 23:59:19 +0800 Subject: [PATCH] Move swap router empty-list guards before folds --- clarity/contracts/dlmm-swap-router-v-1-1.clar | 50 +++++++++++-------- clarity/tests/routers/swap-router.test.ts | 36 +++++++++++-- 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/clarity/contracts/dlmm-swap-router-v-1-1.clar b/clarity/contracts/dlmm-swap-router-v-1-1.clar index 7bd0640..7fd64f8 100644 --- a/clarity/contracts/dlmm-swap-router-v-1-1.clar +++ b/clarity/contracts/dlmm-swap-router-v-1-1.clar @@ -44,12 +44,14 @@ (swaps (list 350 {pool-trait: , x-token-trait: , y-token-trait: , expected-bin-id: int, amount: uint, min-received: uint, x-for-y: bool})) (max-unfavorable-bins uint) ) - (let ( - (swap-result (try! (fold fold-swap-multi swaps (ok {results: (list ), unfavorable: u0})))) - ) + (begin (asserts! (> (len swaps) u0) ERR_EMPTY_SWAPS_LIST) - (asserts! (<= (get unfavorable swap-result) max-unfavorable-bins) ERR_BIN_SLIPPAGE) - (ok swap-result) + (let ( + (swap-result (try! (fold fold-swap-multi swaps (ok {results: (list ), unfavorable: u0})))) + ) + (asserts! (<= (get unfavorable swap-result) max-unfavorable-bins) ERR_BIN_SLIPPAGE) + (ok swap-result) + ) ) ) @@ -59,15 +61,17 @@ (x-token-trait ) (y-token-trait ) (amount uint) (min-y-amount-total uint) (max-unfavorable-bins uint) ) - (let ( - (swap-result (try! (fold fold-swap-x-for-y-same-multi swaps (ok {x-token-trait: x-token-trait, y-token-trait: y-token-trait, results: (list ), x-amount-for-swap: amount, y-amount: u0, unfavorable: u0})))) - (y-amount-total (get y-amount swap-result)) - (unfavorable (get unfavorable swap-result)) - ) + (begin (asserts! (> (len swaps) u0) ERR_EMPTY_SWAPS_LIST) - (asserts! (<= unfavorable max-unfavorable-bins) ERR_BIN_SLIPPAGE) - (asserts! (>= y-amount-total min-y-amount-total) ERR_MINIMUM_Y_AMOUNT) - (ok {results: (get results swap-result), y-amount: y-amount-total, unfavorable: unfavorable}) + (let ( + (swap-result (try! (fold fold-swap-x-for-y-same-multi swaps (ok {x-token-trait: x-token-trait, y-token-trait: y-token-trait, results: (list ), x-amount-for-swap: amount, y-amount: u0, unfavorable: u0})))) + (y-amount-total (get y-amount swap-result)) + (unfavorable (get unfavorable swap-result)) + ) + (asserts! (<= unfavorable max-unfavorable-bins) ERR_BIN_SLIPPAGE) + (asserts! (>= y-amount-total min-y-amount-total) ERR_MINIMUM_Y_AMOUNT) + (ok {results: (get results swap-result), y-amount: y-amount-total, unfavorable: unfavorable}) + ) ) ) @@ -77,15 +81,17 @@ (x-token-trait ) (y-token-trait ) (amount uint) (min-x-amount-total uint) (max-unfavorable-bins uint) ) - (let ( - (swap-result (try! (fold fold-swap-y-for-x-same-multi swaps (ok {x-token-trait: x-token-trait, y-token-trait: y-token-trait, results: (list ), y-amount-for-swap: amount, x-amount: u0, unfavorable: u0})))) - (x-amount-total (get x-amount swap-result)) - (unfavorable (get unfavorable swap-result)) - ) + (begin (asserts! (> (len swaps) u0) ERR_EMPTY_SWAPS_LIST) - (asserts! (<= unfavorable max-unfavorable-bins) ERR_BIN_SLIPPAGE) - (asserts! (>= x-amount-total min-x-amount-total) ERR_MINIMUM_X_AMOUNT) - (ok {results: (get results swap-result), x-amount: x-amount-total, unfavorable: unfavorable}) + (let ( + (swap-result (try! (fold fold-swap-y-for-x-same-multi swaps (ok {x-token-trait: x-token-trait, y-token-trait: y-token-trait, results: (list ), y-amount-for-swap: amount, x-amount: u0, unfavorable: u0})))) + (x-amount-total (get x-amount swap-result)) + (unfavorable (get unfavorable swap-result)) + ) + (asserts! (<= unfavorable max-unfavorable-bins) ERR_BIN_SLIPPAGE) + (asserts! (>= x-amount-total min-x-amount-total) ERR_MINIMUM_X_AMOUNT) + (ok {results: (get results swap-result), x-amount: x-amount-total, unfavorable: unfavorable}) + ) ) ) @@ -289,4 +295,4 @@ ;; Get absolute value of a signed int as uint (define-private (abs-int (value int)) (to-uint (if (>= value 0) value (- value))) -) \ No newline at end of file +) diff --git a/clarity/tests/routers/swap-router.test.ts b/clarity/tests/routers/swap-router.test.ts index b145767..167cf04 100644 --- a/clarity/tests/routers/swap-router.test.ts +++ b/clarity/tests/routers/swap-router.test.ts @@ -261,7 +261,6 @@ describe('DLMM Swap Helper Functions', () => { }); it('should revert on empty swap list', async () => { - // test will fail const swaps: any[] = []; const maxUnfavorableBins = 5n; @@ -270,8 +269,37 @@ describe('DLMM Swap Helper Functions', () => { maxUnfavorableBins ), alice); - // will be changed with specific error code once set - expect(cvToValue(response.result)).toBeGreaterThan(0n); + expect(cvToValue(response.result)).toBe(errors.dlmmSwapRouter.ERR_EMPTY_SWAPS_LIST); + }); + + it('should revert on empty X-for-Y same-multi swap list', async () => { + const swaps: any[] = []; + + const response = txErr(dlmmSwapRouter.swapXForYSameMulti( + swaps, + mockSbtcToken.identifier, + mockUsdcToken.identifier, + 1000000n, + 1n, + 5n + ), alice); + + expect(cvToValue(response.result)).toBe(errors.dlmmSwapRouter.ERR_EMPTY_SWAPS_LIST); + }); + + it('should revert on empty Y-for-X same-multi swap list', async () => { + const swaps: any[] = []; + + const response = txErr(dlmmSwapRouter.swapYForXSameMulti( + swaps, + mockSbtcToken.identifier, + mockUsdcToken.identifier, + 50000000n, + 1n, + 5n + ), alice); + + expect(cvToValue(response.result)).toBe(errors.dlmmSwapRouter.ERR_EMPTY_SWAPS_LIST); }); it('should handle swaps with zero amounts', async () => { @@ -544,4 +572,4 @@ describe('DLMM Swap Helper Functions', () => { expect(cvToValue(response.result)).toBe(errors.dlmmCore.ERR_INVALID_Y_TOKEN); }); }); -}); \ No newline at end of file +});