Medium Risk
https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/LiquidationPool.sol#L190C12-L192C14
https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/LiquidationPool.sol#L183C9-L183C42
To incentivize TST stakers in the LiquidationPool.sol
contract there is a function distributeFees
in the LiquidationPoolManager
which distribute EUROs to the stakers.
If a user tries to frontrun this by quickly staking TST tokens and steal rewards this will not work since the only way to stake TST is by calling LiquidationPool::increasePosition
which protects from frontrunnning by calling ILiquidationPoolManager(manager).distributeFees();
which will transfer all rewards before he could stake his TST tokens.
However an attacker can still exploit the rewards by frontrunning not the LiquidationPoolManager::distributeFees
but the SmartVaultV3
's mint
or burn
functions.
Lets imagine a scenario where:
mint
function.
If we look at the mint function we see uint256 fee = _amount * ISmartVaultManagerV3(manager).mintFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
which is actually sent to the LiquidationPoolManager
which is the distributed EUROs to the stakers.
EUROs.mint(ISmartVaultManagerV3(manager).protocol(), fee);
protocol here is the LiquidationPoolManager
contract. See: Contract requires the protocol address to be a payable address. This address will be set to the LiquidationPoolManager, which has a receive function from audit details.So the fees sent will be fee = 10000000 * 500 / 1e5 = 50,000 EUROs
which is worth the attack though he can still do it with smaller amounts if he wants to. Or could even be greater amounts.
before this fees could be sent to the LiquidationPoolManager
the attacker quickly frontruns the transaction by calling the LiquidationPool::increasePosition
and stake a large amount of TST tokens which will be added to the pendingStakes.
now since he called LiquidationPool::increasePosition
the current rewards will be distributed which still doesn't include the 50,000 EUROs
from the whale.
After his transaction the mint
transaction gets executed and there is currently new 50,000 EUROs in rewards from mint fees.
Attacker calls the LiquidationPoolManager::distributeFees
after diluting the rewards of honest stakers and gets his share of EUROs rewards and unstake his tokens. An attacker may have to wait one day to unstake his TST tokens but this is not a problem for him because he gets back all his TST tokens + the EUROs rewards stolen.
He can sell his EUROs for and buy more TST tokens and repeat the attack with larger amount of TST tokens.
This is possible because we reward even the pending stakes and assume that rewards could not be mainpulated by frontrunning because we call ILiquidationPoolManager(manager).distributeFees();
everytime a stake is increased.
Loss of EUROs rewards for innocent stakers.
Instead of rewarding both the currently staked and the pendingStakes only reward the currently staked users so that we require atleast one day for stakers to recieve rewards and cannot be manipulated by frontrunning.