When a staker un-stakes during an active pending stake, there is a vulnerability in the LiquidationPool
contract that leads to a loss of liquidation rewards and reward fees. The issue arises when the LiquidationPool::decreasePosition()
function is called, and there is an active PendingStake
for the staker. The staker's address is removed from the holders
array, causing problems during reward consolidation.
The problem lies in the LiquidationPool::decreasePosition()
function, specifically in the check at the end of the function that removes the staker's address from the holders
array if their position is empty. This becomes problematic when there is an active PendingStake
for the staker. As a result, during reward consolidation, the staker's address is not added back to the holders
array and also removed from the pendingStakes
, impacting the calculation and distribution of rewards.
LIquidationPool::decreasePosition(...)
GitHub: 149-162
The LiqudiationPool::consolidatePendingStakes()
function is responsible for consolidating pending stakes, but it fails to add the staker back to the holders
array, leading to the loss of rewards. The only way for the staker to be added to the array is by depositing tokens again using the LiquidationPool::increasePosition()
function.
Additionally, the LiquidationPool::distributeFees()
and LiquidationPool::distributeAssets()
functions depend on both the holders
array and pendingStakes
array to distribute rewards. Since the staker's address is not present in both arrays after stake consolidation, they do not receive any rewards.
LiquidationPool::distributeFees(...)
GitHub: 182-194
LiquidationPool::distributeAssets(...)
GitHub: 205
Let's take an example to understand it better:
There are three users alice
, bob
and mike
.
alice
and bob
both has 1000 EUROs
and 1000 TSTs
. Both deposits that into the LiquidationPool
. So now, there are 2000 EUROs
and 2000 TSTs
is in pending stakes.
Now mike
comes and decides to create a SmartVault
. So he calls the SmartVaultManager
and creates one for himself. Now whenever he mints or burns or swaps any token, there will be fee he will have to pay that will be deposited to the LiquidationPoolManager
that will ultimately be given to Pool Staker (i.e is alice
and bob
).
Now let's say 1 week has passed and both bob
's and alice
's stakes has been consolidated and they have earn some fee rewards and their new balance is 1010 EURO
and 1000 TSTs
each.
bob
stakes 1000 EUROs
more. But on the same day he decides to unstake his consolidated stakes due to some reasons. So he does that and removes 1010 EUROs
and 1000 TSTs
from the pool. But doing this has removed his address from the holders
mapping as the LiquidationPool::empty()
will return true and his address will be removed from the array. Now he has 1000 EUROs
and 1000 TSTs
in pending stakes.
Now he will keep earning his fee rewards on pending stakes. But when his pending stakes in consolidated after the deadline
. his amount will be added to the positions
mapping only and will not be added to the holders
array. And that means any reward after that will not be sent to him as a staker needs to be present in the holders
array to earn rewards as we have seen above. And hence loss of rewards for him as long as he does not stakes again.
Staker will lose rewards.
NOTE
The below given test is written in thefoundry
framework instead ofhardhat
. Please go to the repo given below and follow the steps mentioned in the readme to setup the project. Every tests for the current codebase is given in the repo itself.
Github: Repo
Here is a test for PoC that demonstarates the loss of fee rewards:
Original Test: [Link]
Output:
Manual Review
It is recomended to add one of the following ways to solve the issue:
If there is a pending stake for the staker, do not remove him from the holders
durning the decreasePosition
. Only decrease his position amount.
Call LiquidationPool::addUniqueHolder(...)
in the LiquidationPool::consolidatePendingStakes
.
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.