Open code423n4 opened 1 year ago
kyscott18 marked the issue as sponsor acknowledged
We still think it is better off to pass in the amount of liquidity as part of the input. It won't result in loss of funds for first time depositors because they can know before time if the amount of tokens they supply match up to the amount of liquidity that they specified or not. I will take a look at this formula in more detail.
berndartmueller marked the issue as satisfactory
berndartmueller marked the issue as selected for report
Lines of code
https://github.com/code-423n4/2023-01-numoen/blob/2ad9a73d793ea23a25a381faadc86ae0c8cb5913/src/periphery/LiquidityManager.sol#L135
Vulnerability details
Impact
The first liquidity depositor should supply three input values
amount0Min, amount1Min, liquidity
viaAddLiquidityParams
but these three values should meet an accurate relationship, or else the depositor will suffer from revert or fund lossProof of Concept
The LPs are supposed to use the function
LiquidityManager.addLiquidity(AddLiquidityParams calldata params)
to add liquidity. When the pool is not empty, this function calculates theamount0, amount1
according to the current total liquidity and the requested liquidity. But when the pool is empty, these amounts are supposed to be provided by the caller.Then how does the caller decides these amount? These values should be chosen very carefully as we explain below.
The whole protocol is based on its invariant that is defined in
Pair.invariant()
. The invariant is actually ensuring thata+b-c-d
stays not negative for all trades (interactions regarding reserve/liquidity). Oncea+b-c-d
becomes strictly positive, anyone can callswap()
function to pull thetoken0
of that amount without any cost.So going back to the question, if the LP choose the values
amount0, amount1, liquidity
not accurately, the transaction reverts ora+b-c-d
becomes greater than zero.Generally, liquidity providers do not specify the desired liquidity amount in other protocols. During the conversation with the sponsor team, it is understood that they avoided the calculation of
liquidity
fromamount0, amount1
because it is too complicated. Off-chain calculation will be necessary to help the situation, and this would limit the growth of the protocol. If any other protocol is going to integrate Numoen, they will face the same problem.I did some calculation and got the formula for the liquidity as below.
$ L = \frac{PCy+C^2x+\sqrt{2PC^3xy+C^4x^2}}{2P^2} $ where $C=10^{18}$, $x$ is
amount0
, $y$ isamount1
, $P$ is theupperBound
, $L$ is the liquidity amount that should be used.Because the LP will almost always suffer revert or fund loss without help of off-chain calculation, I submit this as a medium finding. I would like to note that there still exists a mitigation (not that crazy). As a side note, it would be very helpful to add new preview functions.
Tools Used
Manual Review
Recommended Mitigation Steps
Add a functionality to calculate the liquidity for the first deposit on-chain. And it is also recommended to add preview functions.