Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Invalid

[M-01] A user can borrow so much that they could become available for liquidation instantly

Summary

The LendingPool::borrow function allows a user to borrow more than the liquidation threshold health factor, as it lacks additional validations for the borrowers health factor after they get their desired amount, leaving them vulnerable to liquidation right after borrow, in certain cases.

Vulnerability Details

The LendingPool::borrow function allows a user to borrow an amount, that would make them available for a liquidator to initiate a liquidation on the borrower, right after the borrow completes. This can put users funds at risk, without the user realizing it, as they expect to be safe from liquidation right after a borrow, in case there are no drops in their collateral value, which is not true in the code.

Impact

  • Impact: High, as it makes the borrower available for initiating liquidation on him right after a successful borrow

  • Likelihood: Medium, as not every borrow will make the borrower go over the health factor limit

PoC

  1. Add a test similar to the one below inside here :

it("should allow user to borrow enough crvUSD to be instantly liquidated", async function () {
const borrowAmount = ethers.parseEther("105");
await lendingPool.connect(user1).borrow(borrowAmount);
const debtBalance = await debtToken.balanceOf(user1.address);
const health = await lendingPool.calculateHealthFactor(user1.getAddress());
console.log('debt', debtBalance);
console.log('health factor', health);
expect(debtBalance).to.gte(borrowAmount);
// Attempt to initiate liquidation
await expect(lendingPool.connect(user2).initiateLiquidation(user1.getAddress()))
.to.emit(lendingPool, "LiquidationInitiated")
.withArgs(user2.getAddress(), user1.getAddress());
// Verify that the user is under liquidation
expect(await lendingPool.isUnderLiquidation(user1.getAddress())).to.be.true;
const healthFactorLiquidationThreshold = await lendingPool.healthFactorLiquidationThreshold();
expect(health).to.be.lt(healthFactorLiquidationThreshold);
});

Tools Used

  • Manual Review


Recommendations

  1. Add an additional check inside the LendingPool::borrow function, that validates the user health factor will still be above the liquidation threshold after borrowing, by adding something like the following:

uint256 healthFactor = calculateHealthFactor(userAddress);
if (healthFactor >= healthFactorLiquidationThreshold) revert HealthFactorTooLow();
Updates

Lead Judging Commences

inallhonesty Lead Judge
3 months ago
inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.