getTokenPrice can revert and the pool's deposit and withdraw will not work.
Proof of Concept
getTokenPrice returns 1e18 when totalFunds = 0, but the correct condition is totalSupply = 0.
getTokenPrice reverts when totalSupply = 0 at the following line.
return totalValue.divWadDown(totalSupply);
If totalFunds is always 0 when totalSupply = 0, getTokenPrice will return the correct value of 1e18.
if (totalFunds == 0) {
return 1e18;
}
But totalFunds can be a dust value when totalSupply = 0. This situation can be happen in several conditions, and the correct token price is 1e18 instead of reversion. If getTokenPrice reverts, there is no way to deposit and it can result a DOS.
One of the possible senarios is for the first depositor. The first depositor can deposit and withdraw in the same transaction. He will send totalFunds for the first deposit, and the token price will be totalFunds.divWadDown(totalSupply) after that. If he withdraws all liquidity tokens (= total supply), susdToReturn = tokens.mulWadDown(tokenPrice) in withdraw method.
So if totalSupply > 1e18, susdToReturn can be slightly less than totalFunds, and totalFunds can be a non-zero dust value. After this, there is no way to deposit/withdraw and this will result DOS.
Similar thing can be happen in KangarooVault because implementation of getTokenPrice is very similar.
Tools Used
Manual Review
Recommended Mitigation Steps
getTokenPrice should return 1e18 when totalSupply = 0.
Lines of code
https://github.com/code-423n4/2023-03-polynomial/blob/aeecafc8aaceab1ebeb94117459946032ccdff1e/src/LiquidityPool.sol#L340-L365
Vulnerability details
Impact
getTokenPrice
can revert and the pool's deposit and withdraw will not work.Proof of Concept
getTokenPrice
returns 1e18 whentotalFunds
= 0, but the correct condition istotalSupply
= 0.getTokenPrice
reverts whentotalSupply
= 0 at the following line.If
totalFunds
is always 0 whentotalSupply
= 0,getTokenPrice
will return the correct value of 1e18.But
totalFunds
can be a dust value whentotalSupply
= 0. This situation can be happen in several conditions, and the correct token price is 1e18 instead of reversion. IfgetTokenPrice
reverts, there is no way todeposit
and it can result a DOS.One of the possible senarios is for the first depositor. The first depositor can deposit and withdraw in the same transaction. He will send
totalFunds
for the first deposit, and the token price will betotalFunds.divWadDown(totalSupply)
after that. If he withdraws all liquidity tokens (= total supply),susdToReturn = tokens.mulWadDown(tokenPrice)
inwithdraw
method.So if
totalSupply
> 1e18,susdToReturn
can be slightly less thantotalFunds
, andtotalFunds
can be a non-zero dust value. After this, there is no way to deposit/withdraw and this will result DOS.Similar thing can be happen in
KangarooVault
because implementation ofgetTokenPrice
is very similar.Tools Used
Manual Review
Recommended Mitigation Steps
getTokenPrice
should return 1e18 whentotalSupply
= 0.