Inside LiquidationPool.sol users can stake their TST or EURO and earn rewards. The contract has a functionality to store pendingStakes for 24 hours, before officially include them to the user's position mapping. The problem comes from the complexity of the function consolidatePendingStakes, which is crucial for the protocol and the fact that user can call unlimited times increasePosition with 1 wei for amount.
The problem comes from the complexity of consolidatePendingStakes, which iterates over all pending stakes twice if 24 hours has passed.
A user can in one transaction create 200 pending stakes with same timestamp for createdAt, which would make function consolidatePendingStakes massive gas cost exactly 24 hours after user “attack start”. For all 200 pending transactions deletePendingStake would be called, which would read & write > 100 times storage variables. This is close to 100^2 complexity, which for only SSTORE operation = 100^2 * **20,000 = 200 000 000 , when block gas limit for Mainnet is only 30 000 000, which is clearly DoS.**
In the following gist I have provided coded PoC and instructions how to execute it
https://gist.github.com/NicolaMirchev/0322a697c3170958585086f02ce08411
consolidatePendingStakes is used inside: increasePosition , decreasePosition & distributeAssets , which means DoS of those function. And the whole staking system is dependant to those functions, which is really bad. Noone would be able to withdraw his rewards & staked funds.
Gas cost for the attacker is relatively low
Manual Review
Hardhat
Limit pendingStakes per user:
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.