The LiquidationPool::consolidatePendingStakes function loops through the pendingStakes array for making checks if they are older than one day. However, the longer the pendingStakes array is, the more checks will be made. This means the gas cost for the staker who stakes earlier will have to pay dramatically less gas than those who stake later.
Even though it consolidates pending stakes into positions and deletes them if they are older than one day, an attacker can create a lot of pendingStakes in a day by calling the increasePosition function continuously by depositing very little TST or EUROs.
Also the decreasePosition ,distributeAssets functions call the consolidateStakes fuction.
An attacker can make the pendingStakes array so big , disrupting the proper functionalities of the protocol.
consolidatePendingStakes function loops through the pendingStakes array:
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L119-L132
function consolidatePendingStakes() private {
uint256 deadline = block.timestamp - 1 days;
for (int256 i = 0; uint256(i) < pendingStakes.length; i++) {
PendingStake memory _stake = pendingStakes[uint256(i)];
if (_stake.createdAt < deadline) {
positions[_stake.holder].holder = _stake.holder;
positions[_stake.holder].TST += _stake.TST;
positions[_stake.holder].EUROs += _stake.EUROs;
deletePendingStake(uint256(i));
// pause iterating on loop because there has been a deletion. "next" item has same index
i--;
}
}
}
increasePosition function is used to increase position:
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L134-L142
function increasePosition(uint256 _tstVal, uint256 _eurosVal) external {
require(_tstVal > 0 || _eurosVal > 0);
consolidatePendingStakes();
ILiquidationPoolManager(manager).distributeFees();
if (_tstVal > 0) IERC20(TST).safeTransferFrom(msg.sender, address(this), _tstVal);
if (_eurosVal > 0) IERC20(EUROs).safeTransferFrom(msg.sender, address(this), _eurosVal);
pendingStakes.push(PendingStake(msg.sender, block.timestamp, _tstVal, _eurosVal));
addUniqueHolder(msg.sender);
}
This causes Denial of Service (DoS).
Manual Review
These are a few recommendations:
1, Allow the stakers to increase their position only after their previous pending stake has been consolidated into their position.
2, Make the increasePosition function accept a minimum amount of TST or EUROs.
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.