When a staker would withdraw full amount of both their position balance (positions[_stake.holder].TST
and positions[_stake.holder].EUROs
), their pending staked-balance of $TST and $EUROs are supposed to be also accounted.
Because if the both staked-balance would be 0
(positions[_stake.holder].TST == 0 && positions[_stake.holder].EUROs == 0
) when the staker would withdraw full staked-balance of both via the LiquidationPool#decreasePosition()
, the staker's position (positions[_stake.holder]
) would be deleted - even if some pending staked-balance would be remained in the pendingStake
array storage.
However, there is no validation to check whether or not the pending stake data (PendingStake
) would be remained in the pendingStake
array storage - when the LiquidationPool#decreasePosition()
would be called.
This lead to losing the staker's pending stake balance.
When a staker would like to decrease their staked-amount of $TST or/and $EUROs, the staker would call the LiquidationPool#decreasePosition()
.
Within the LiquidationPool#decreasePosition()
, the LiquidationPool#consolidatePendingStakes()
would be called.
And then, if the both staked-EUROs balance would be the empty balance (_position.TST == 0 && _position.EUROs == 0
), the caller's position (positions[msg.sender]
) would be deleted via the LiquidationPool#deletePosition()
like this:
(NOTE:The empty balance check would be done via the LiquidationPool#empty()
)
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L150
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L161
Within the LiquidationPool#consolidatePendingStakes()
, if this function would be called after the deadline
(_stake.createdAt < deadline
), the given pending stake data (PendingStake
) would be consolidated to the given staker's staked-balance of $TST and $EUROs (positions[_stake.holder].TST
and positions[_stake.holder].EUROs
) like this:
(NOTE:Since the deadline
would be defined as block.timestamp - 1 days
, the pending stake period would be for 1 day after a staker staked $TST or/and $EUROs via the LiquidationPool#increasePosition()
)
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L120-L127
When a staker would withdraw full amount of both their position balance (positions[_stake.holder].TST
and positions[_stake.holder].EUROs
), their pending staked-balance of $TST and $EUROs are supposed to be also accounted.
Because if the both staked-balance would be 0
(positions[_stake.holder].TST == 0 && positions[_stake.holder].EUROs == 0
) when the staker would withdraw full staked-balance of both via the LiquidationPool#decreasePosition()
, the staker's position (positions[_stake.holder]
) would be deleted - even if some pending staked-balance would be remained in the pendingStake
array storage.
However, there is no validation to check whether or not the pending stake data (PendingStake
) would be remained in the pendingStake
array storage - when the LiquidationPool#decreasePosition()
would be called.
This lead to losing the staker's pending stake balance.
Assumption:
Alice is a staker of $TST and $EUROs in the LiquidationPool.
Scenario:
1/ If Alice, who still has the pending stake balance in the pendingStakes
array storage, would withdraw full amount of both their position's balance (positions[_stake.holder].TST
and positions[_stake.holder].EUROs
) by calling the LiquidationPool#decreasePosition()
with the full amount of both their position's balance (positions[_stake.holder].TST
and positions[_stake.holder].EUROs
) as the _tstVal
and the _eurosVal
, the both balance (positions[_stake.holder].TST
and the positions[_stake.holder].EUROs
) would be 0
(empty
balance) .
And therefore, her position (positions[_stake.holder]
) would be deleted - even if some pending staked-balance would be remained in the pendingStake
array storage.
2/ 1 day later, the Alice's pending period would be end and her pending stake balance would be attempted to be consolidated to her position when someone would call the LiquidationPool#consolidatePendingStakes()
via the following functions.
LiquidationPool#increasePosition()
LiquidationPool#decreasePosition()
LiquidationPoolManager#runLiquidation()
However, at that time, there is no target position for Alice's pending stake to be added (consolidated) - because their position would already be deleted when the step 1/ above.
As a result, her pending stake balance would be lost.
The staker's pending stake balance would be lost.
Manual review
Within the LiquidationPool#empty()
, consider adding a validation to check whether or not the pending stake (PendingStake
) would be remained in the pendingStake
array storage like this:
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.