When performing 'swap' and the swap position does not cover 'swap amount', the base price of 'sqrt_price' is set incorrectly. #58
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
M-05
primary issue
Highest quality submission among a set of duplicates
🤖_25_group
AI based duplicate group recommendation
satisfactory
satisfies C4 submission criteria; eligible for awards
selected for report
This submission will be included/highlighted in the audit report
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/pool.rs#L303
Vulnerability details
Impact
When performing a swap, a position is searched and if a position with an appropriate price exists, the swap is performed using the token amount of that position.
If the positions in the current pool do not cover the swap amount requested by the user, the value of
sqrt_price
will not be set accurately, which may cause confusion when the next user swaps.Proof of Concept
https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/pool.rs#L303-L535
When a swap is performed, the 'swap' function in pools.rs is triggered.
https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/pool.rs#L378-L492
When performing a swap, the while statement above iterates through the position that matches the tick and searches for it. If a matching position exists, the token of that position is processed and the state is updated.
The while statement will continue until the
swap amount
requested by the user becomes0
or theprice
reaches theprice_limit
requested by the user.https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/pool.rs#L496
After the while loop is finished, the final
sqrt_price
value is updated to thestate.price
value.If the
swap amount
within theprice_limit
range requested by the user is not covered by the positions in the pool, theposition price
will be set to theprice_limit
value set by the user, not theposition price
that was actuallyswapped
last, which will be different from the last swapped price, and the user requesting the next swap may be confused about theswap price
.Scenario)
Assume that the following positions are currently formed in the pool
pool1 state:
lower = 1000
upper = 2000
amount = 20
pool2 state:
lower = 3000
upper = 4000
amount = 20
Assume that the user sets
swap amount
to100
andprice_limit
to10000
and requests a swapWhen the swap is in progress, it searches for a pool that can be swapped and processes
amount 20
ofpool1
andamount 30
ofpool2
to swap a total of 50 tokens.At this time, the position of the pool within the
price_limit
set by the user cannot process theswap amount
requested by the user, so the while statement is performed untilstate.price == price_limit
, and finally thesqrt_price
value is set to thestate.price
value. (state.price is equal to price_limit
)After the swap routine is finished, the reference
swap price
will be set to10000
, which is theprice_limit
set by the user, and not theswap price
ofpool2
where the last swap was done.Users requesting the next swap may experience confusion when processing the swap because the swap base price starts at the price of the
price_limit set by the previous user
, rather than thebase price
of thepool where the last swap was made
.Test Code
https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/pool.rs#L312-L331
Test Code POC is the code that sets
zero_for_one
totrue
andprice_limit
toU256::MAX
and returns an error return in the above conditional statement when the second swap is performed.Write Test code
write Test Code in
test/lib.rs
fileadd
println!
code line and removedebugassert statement
onswap
function insrc/pool.rs
Run Test
Result
When requesting a second swap, you can see that an error return occurs because
sqrt_price
is set to theprice_limit
set in the previous swap even though the position existed.Tools Used
Visual Studio Code
Recommended Mitigation Steps
Modified to allow setting the value to the price of the last swapped position even if the position amount is insufficient.
Mitigation Test Result
Test Code is same above Test Code
Unlike before, it is set to the tick where the last swap occurred.
Assessed type
Loop
The text was updated successfully, but these errors were encountered: