Platform: Code4rena
Start Date: 08/03/2023
Pot Size: $60,500 USDC
Total HM: 2
Participants: 123
Period: 7 days
Judge: hansfriese
Id: 220
League: ETH
Rank: 44/123
Findings: 1
Award: $154.74
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: rokso
Also found by: 0x52, 0xnev, ABA, BPZ, DadeKuma, Haipls, J4de, Jeiwan, Josiah, Krace, LegendFenGuin, Lirios, MadWookie, RaymondFam, Ruhum, Toshii, UdarTeam, aashar, ak1, anodaram, auditor0517, carlitox477, cccz, jekapi, juancito, kaden, kenzo, minhquanym, nobody2018, rbserver, rokso, ulqiorra
154.74 USDC - $154.74
User can withdraw their LP tokens without affecting their lpPosition.points
. Since the lpPosition.points
could not deducted then and there whenever the LP token is drawn out, user can use the old lpPosition.points
and new lpPosition.points
value to calculate the share vale when staking the LP tokens.
This would result unfair amount of share even if they are not entitled for it. Loss of funds.
User can stake the LP tokens using the function _stakeLP()
PoolData storage pool = _pools[AssetType.LP]; unchecked { uint256 points = amount * 100 / 1e18 * timelockMultiplier / _DIVISOR; // Update the caller's LP token stake. stakerLPPosition[msg.sender].timelockEndTime = block.timestamp + timelockDuration; stakerLPPosition[msg.sender].amount += amount; stakerLPPosition[msg.sender].points += points; // Update the pool point weights for rewards. pool.totalPoints += points; }
stakerLPPosition[msg.sender].points
value is updated based on the points value calculated from uint256 points = amount * 100 / 1e18 * timelockMultiplier / _DIVISOR;
when claiming the reward using the claimReward()
, reward amount will be calculated using getPoolReward()
When we look at the LP token code snip,
} else if (_assetType == AssetType.LP) { unchecked { points += stakerLPPosition[_recipient].points; } } else {
and this points values are used to calculated the share value.
unchecked { uint256 share = points * _PRECISION / pool.totalPoints * totalReward; uint256 daoShare = share * pool.daoTax / (100 * _DIVISOR); share /= _PRECISION; daoShare /= _PRECISION; return ((share - daoShare), daoShare); } }
When we look at the _withdrawLP ()
function, for the given amount, the points value is calculated using,
uint256 points = amount * 100 / 1e18 * lpPosition.multiplier / _DIVISOR;
, It is possible for a user to call this function with input amount
value which would give zero points from above calculation, malicious user can call this function multiple times without affecting their point values. After withdrawing entire staked amount, when they come back for stake, old points value could be used to calculated the share value.
Manual review.
Following suggestion is proposed.
For the given amount
, make sure that the valid amount of points
are deducted.
#0 - c4-judge
2023-03-16T04:37:40Z
hansfriese marked the issue as satisfactory
#1 - c4-judge
2023-03-16T04:37:51Z
hansfriese marked the issue as duplicate of #348
#2 - c4-judge
2023-03-21T09:20:38Z
hansfriese marked the issue as duplicate of #261