Core Contracts

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

Incorrect Liquidity threshold check in `borrow::LendingPool`

Summary

The borrow function in the LendingPool contract incorrectly checks if 80% of the debt is covered by collateral, allowing borrowing even when the collateral is under-collateralized. The actual requirement is that the 80% of the collateral value should cover the total debt, and if it fails to cover, then borrowing should not be allowed.

Vulnerability Details

The current check in the borrow function is:

if (collateralValue < userTotalDebt.percentMul(liquidationThreshold)) {
revert NotEnoughCollateralToBorrow();
}

This condition allows borrowing if 80% of the debt is covered by collateral, which can lead to under-collateralized loans.

link to issue: https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L344

POC

Copy and paste the below test in the lendingPool.test.js

it.only("should allow user to borrow crvUSD using NFT collateral", async function () {
const borrowAmount = ethers.parseEther("110");
console.log("user collateral value", ethers.formatEther(await lendingPool.getUserCollateralValue(user1.address)));
console.log("user borrowing amount", ethers.formatEther(borrowAmount));
console.log("user urcUSD Balance before borrow", ethers.formatEther(await crvusd.balanceOf(user1.address)));
await lendingPool.connect(user1).borrow(borrowAmount);
console.log("user urcUSD Balance after borrow", ethers.formatEther(await crvusd.balanceOf(user1.address)));
const crvUSDBalance = await crvusd.balanceOf(user1.address);
expect(crvUSDBalance).to.equal(ethers.parseEther("1110"));
const debtBalance = await debtToken.balanceOf(user1.address);
expect(debtBalance).to.gte(borrowAmount);
});

run the test the oputput should be like

user collateral value 100.0
user borrowing amount 110.0
user urcUSD Balance before borrow 1000.0
user urcUSD Balance after borrow 1110.0

Impact

This issue can lead to under-collateralized loans, increasing the risk of defaults and potential losses for the protocol.

Tools Used

Manual code review.

Recommendations

Update the condition to correctly check if the collateral value is sufficient to cover the debt after reducing it to 80% of its actual value. The corrected check should be:

if (collateralValue.percentMul(liquidationThreshold) < userTotalDebt) {
revert NotEnoughCollateralToBorrow();
}

This ensures that borrowing is only allowed if the collateral value, after being reduced to 80%, is still sufficient to cover the user's total debt.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::borrow as well as withdrawNFT() reverses collateralization check, comparing collateral < debt*0.8 instead of collateral*0.8 > debt, allowing 125% borrowing vs intended 80%

Support

FAQs

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

Give us feedback!