When a vault gets liquidated, the liquidated assets are distributed in LiquidationPool.sol#distributeAssets(). The way rewards are calculated for users in the distributeAssets() function is it loops through the holders.length, caches all the holders' _positionstake and then loops through the list of available liquidated assets to assign portions of to all the holders.
https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/LiquidationPool.sol#L205-L241
The problem here is that the _portion of rewards assigned to users is calculated in the following way:
uint256 _portion = asset.amount * _positionStake / stakeTotal
Where stakeTotal is the total combined amount of staked EUROs/TSTs for all holders in the protocol which could naturally be a huge amount. That large amount combined with a relatively small-medium liquidated vault asset.amount or/and a small enough user's _positionStake could mean that asset.amount * _positionStake < stakeTotal which would round down and return 0 rewards for that user.
This would lead to a loss of rewards for users and since the rewards are distributed proportionally, other users won't receive them either, but instead they will be forwarded back to the protocol owners since the last mechanism of liquidating a vault is forwarding any leftover rewards to the owners in LiquidationPoolManager.sol#runLiquidation():
https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/LiquidationPoolManager.sol#L59-L82
Some user rewards can be lost when a vault is liquidated due to rounding down precision loss.
Manual Review
Revert if _portion == 0 or maybe skip rewards for such users and accrue it to the rest of the users` rewards?
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.