In the LiquidityPool contract, when a liquidity holder withdraws their entire staked amount from the pool, the corresponding position is deleted from the positions mapping, and the holder is removed from the holders array. However, a flaw in the logic exists: positions that are still pendingStake processing after this withdrawal action (entire stake removal) are not considered for reward distribution. This oversight results in potential loss of rewards for affected positions.
empty()
: Checks for stake in the existing positions of the caller.
deleteHolder()
: deletes the holder from holders array.
consolidatePendingStakes()
: Never checks for holder existence in holders array. Which is essential to spread and claim reward tokens.
Scenario:
User 1 opens a new position with 10 TST.
The position is processed the next day.
Scenario:
On the second day, User 1 opens several new positions by calling increasePosition, and they are sent to pendingStakes.
Assuming User 1 took another position with 10 TST.
User 1 wants to decrease the position by the amount of 10 TST (available to redeem as processed from pending to positions).
Outcome:
User 1 assumes that they held a position at LP and earned rewards.
But on the decrease position call, User 1 deleted their address from holders
.
To receive and claim rewards, the code holds the logic to iterate through the holders
array.
Result:
User 1 never acquired rewards for this holding.
Add the below test code to the liquidation pool test
Sample Result:
This is an edge case where a stake-holder assumes to be receiving rewards on their stake but doesn't. Stake-holders fail to receive rewards until they call the increasePosition function which is as rare action as the cause to vulnerability.
Hardhat
If holder holds pending stakes return false
.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.