In the current implementation of the "update_positions" feature, the function decr_position_09293696() that decreases the liquidity is flawed. The problem is that it the function uses the same functionality for increasing / decreasing position that is not correct. Moreover, the function does not check if the provided liquidity is no greater than the current position liquidity.
Proof of Concept
Currently both functions for increasing / decreasing liquidity call the same function - adjust_position_internal() where we calculate the liquidity and update the position. The problem is that the functions should be mirrored - users should provide the amount of liquidity and get the calculated corresponding amounts in return:
There are currently no any checks that check for the requested liquidity to be greater or equal than the liquidity inside of the position as it's done in UniswapV3:
As you can see here, the liquidityDelta in UniV3 is not calculated via get_liquidity_for_amounts() but with amount supplied by the user.
Tools Used
Manual review.
Recommended Mitigation Steps
Consider implementing decrease liquidity functionality correctly including check for the liquidity requested to be greater or equal to the current position liquidity to prevent users from getting more liquidity than they should.
Lines of code
https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/lib.rs#L938
Vulnerability details
Impact
In the current implementation of the "update_positions" feature, the function
decr_position_09293696()
that decreases the liquidity is flawed. The problem is that it the function uses the same functionality for increasing / decreasing position that is not correct. Moreover, the function does not check if the provided liquidity is no greater than the current position liquidity.Proof of Concept
Currently both functions for increasing / decreasing liquidity call the same function -
adjust_position_internal()
where we calculate the liquidity and update the position. The problem is that the functions should be mirrored - users should provide the amount of liquidity and get the calculated corresponding amounts in return:https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/lib.rs#L938-958
Now take a look at the Uniswap implementation:
https://github.com/Uniswap/v3-periphery/blob/main/contracts/NonfungiblePositionManager.sol#L257-264
There are currently no any checks that check for the requested liquidity to be greater or equal than the liquidity inside of the position as it's done in UniswapV3:
https://github.com/Uniswap/v3-periphery/blob/main/contracts/NonfungiblePositionManager.sol#L268-269
Now, as we compare the implementation with the impl of UniswapV3, let's take a look at how amounts are calculated:
https://github.com/Uniswap/v3-periphery/blob/main/contracts/NonfungiblePositionManager.sol#L273
But in the protocol everything is done the same way as for liquidity increase operation:
https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/pool.rs#L265-277
So it's the same algorithm as with increasing liquidity on UniswapV3:
https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/LiquidityManagement.sol#L51-78
https://github.com/Uniswap/v3-periphery/blob/main/contracts/NonfungiblePositionManager.sol#L273
https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L522-530
As you can see here, the
liquidityDelta
in UniV3 is not calculated viaget_liquidity_for_amounts()
but with amount supplied by the user.Tools Used
Manual review.
Recommended Mitigation Steps
Consider implementing decrease liquidity functionality correctly including check for the liquidity requested to be greater or equal to the current position liquidity to prevent users from getting more liquidity than they should.
Assessed type
Other