Users can swap at the best price by splitting swap into several small swap
| Title | Users can swap at the best price by splitting swap into several small swap |
|---|---|
| Reward | $1633, 6 dups |
| Contest | Dango Dex - 15 Sep 2025 on Sherlock |
| Author | ami |
| Context | Business Logic |
Alpha: this is one of those findings that comes up when you ask what happens if the same function is called several times with smaller amounts. It applies to any kind of maths, not just swaps.
Here it is more of a business-logic issue than a rounding one, but the thought process that gets you there is the same.
When swapping in a geometric pair, the protocol matches the passive orders against the user's swap order.
However, users can swap at the best price by splitting one swap into several small ones.
The reflect_curve function creates params.limit ask and bid orders.
The bid prices decrease and the ask prices increase.
By splitting the swap into several small swaps, a user can always take the best passive order.
Consider the following scenario:
Initial State
Reserves of token1 and token2: 1000, 1000
1 token1 = 10 USD, 1 token2 = 1 USD
swap_fee_rate is 0, for simplicity
params.spacing: 1
params.limit: 3
params.ratio: 10%
Path 1
Alice is going to swap 300 token1 to token2 in one transaction:
The reflect_curve function creates 3 passive bids, as (price, size): (10, 100), (9, 111.11), (8, 125).
As a result, Alice receives 2712 token2:
Path 2
If Bob instead swaps 300 token1 as three swaps of 100 token1, in a single transaction:
Bob receives 1000 token2 for each swap of 100 token1, so 3000 token2 in total — more than Alice, for the same input.
Conclusion
This finding would earn you $1633, and it is not hard to come up with. The explanation is not deep, but it does its job: always think like an attacker, and try splitting a transaction into smaller ones.