reLP contract can have WETH leftovers while adding liquidity. This amount can be a dust (very small) or can be a considerably big amount depending on the liquidity of the V2 pool and the "reLPFactor" variable. reLP contract has no functionality to handle these leftover WETHs which is lowering the efficiency of the reLP'ing process.
Now we will swap half of the WETH to rDPX:
98.87 988.62 = k
(98.87 + (1.13 / 2)) (988.62 - dx) = k
dx = 5.617 rDPX.
Now the contract holds 0.565WETH and 5.617rDPX which will be added liquidity back to UniV2 pool. UniV2 pool latest reservs were:
99.435WETH
983rDPX
When we follow the add liquidity steps in UniV2 the contract will add liquidity with the following amounts:
full amount of rDPX, which is 5.617 rDPX and 0.563WETH. 0.002WETH will be idle in the contract. This can happen more often if the liquidity to be removen or reLPFactor being very high or very low. Idle WETH should be sweeped to Core contract in these cases.
Tools Used
Recommended Mitigation Steps
Add a sweep functionality for WETH to handle leftover WETH's.
Lines of code
https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/reLP/ReLPContract.sol#L202-L307
Vulnerability details
Impact
reLP contract can have WETH leftovers while adding liquidity. This amount can be a dust (very small) or can be a considerably big amount depending on the liquidity of the V2 pool and the "reLPFactor" variable. reLP contract has no functionality to handle these leftover WETHs which is lowering the efficiency of the reLP'ing process.
Proof of Concept
In UniswapV2 add liquidity is performed as follows: https://github.com/Uniswap/v2-periphery/blob/0335e8f7e1bd1e8d8329fd300aea2ef2f36dd19f/contracts/UniswapV2Router02.sol#L33-L60 https://github.com/Uniswap/v2-core/blob/ee547b17853e71ed4e0101ccfd52e70d5acded58/contracts/UniswapV2Pair.sol#L110-L131
So, if reserves of a hypothetical pool are 100tokenA and 50tokenB and if we need to add 10 tokenA then we exactly need 5 tokenB too. https://github.com/Uniswap/v2-periphery/blob/0335e8f7e1bd1e8d8329fd300aea2ef2f36dd19f/contracts/libraries/UniswapV2Library.sol#L36-L40
Now, let's assume the V2 pool has 1000rDPX, 100WETH, 6 * 1e18 totalSupply and rDPX reserve has 1000rDPX. https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/reLP/ReLPContract.sol#L217-L237 we will calculate the lpToRemove as 0.06 and removing 0.06 LP tokens will give us: 1.13WETH 11.38rDPX
The UniV2 pool now has: 98.87WETH 988.62rDPX
Now we will swap half of the WETH to rDPX: 98.87 988.62 = k (98.87 + (1.13 / 2)) (988.62 - dx) = k dx = 5.617 rDPX.
Now the contract holds 0.565WETH and 5.617rDPX which will be added liquidity back to UniV2 pool. UniV2 pool latest reservs were: 99.435WETH 983rDPX
When we follow the add liquidity steps in UniV2 the contract will add liquidity with the following amounts: full amount of rDPX, which is 5.617 rDPX and 0.563WETH. 0.002WETH will be idle in the contract. This can happen more often if the liquidity to be removen or reLPFactor being very high or very low. Idle WETH should be sweeped to Core contract in these cases.
Tools Used
Recommended Mitigation Steps
Add a sweep functionality for WETH to handle leftover WETH's.
Assessed type
Uniswap