A user can have a position in LiquidationPool without being in the holders array. Which will lead to discrepancy in getStakeTotal and getTstTotal, since they iterate over the holders array.
User calls increasePosition.
Which pushes his stake as pending:
pendingStakes.push(PendingStake(msg.sender, block.timestamp, _tstVal, _eurosVal)); and adds him as an unique holder
Now since there are other pending stakes and also a user must wait 1 day before his pending stake passes the deadline period in order to be added in a position. He can call decreasePosition immediately after that:
consolidatePendingStakes(); won't add his pending stake in position because it hasn't passed the deadline and also there might be other pending stakes.
In order to pass this require require(_tstVal <= positions[msg.sender].TST && _eurosVal <= positions[msg.sender].EUROs, "invalid-decr-amount"); just set the input amounts to 0.
Then at the end we get to if (empty(positions[msg.sender])) deletePosition(positions[msg.sender]);
Which will return true because our pending stake hasn't been added yet to our position and we will go into the if statement, which will delete our position.
This deletes as a holder and also deletes our position but since we don't have anything added there yet it's not a problem.
Time passes and other users invoke consolidatePendingStakes and finally we get our pending stake added to our position without being in the holders array.
Discrepancy will be made in getStakeTotal and getTstTotal since they assume that only holders can have active positions.
Which in return won't accumulate the correct fees and rewards for stakers, because they are all dependent on these two functions.
Manual Audit
When consolidatePendingStakes is called it may be a good idea to check if a user has been removed as an holder and add him back if that's the case.
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.