Core Contracts

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

Debt tracked in `LendingPool` and by `DebtToken` `balanceOf` function are different

Summary

Debt tracked in LendingPool and by DebtToken balanceOf function are different. When borrowing the tokens the user receives the debt tokens and his debt is tracked in LendingPool in userData data structure.

Vulnerability Details

Paste this test file into test/unit/core/pools/LendingPool/LendingPool.test.js and run npx hardhat test test/unit/core/pools/LendingPool/LendingPool.test.js.

describe("PoC Borrow and Repay", function () {
beforeEach(async function () {
const depositAmount = ethers.parseEther("1000");
await crvusd.connect(user2).approve(lendingPool.target, depositAmount);
await lendingPool.connect(user2).deposit(depositAmount);
const tokenId = 1;
await raacNFT.connect(user1).approve(lendingPool.target, tokenId);
await lendingPool.connect(user1).depositNFT(tokenId);
});
it.only("State after borrow", async function () {
const borrowAmount = ethers.parseEther("70");
await lendingPool.connect(user1).borrow(borrowAmount);
const debtBalance = await debtToken.balanceOf(user1.address);
console.log({debtBalance});
const userDebt = await lendingPool.getUserDebt(user1.address);
console.log({userDebt});
await network.provider.send("evm_increaseTime", [3600 * 72]); // Increase time by 72 hours (3600 seconds)
await network.provider.send("evm_mine"); // Mine a new block to apply the time change
const borrowAmount1 = ethers.parseEther("10");
await lendingPool.connect(user1).borrow(borrowAmount1);
const debtBalance1 = await debtToken.balanceOf(user1.address);
console.log({debtBalance1});
const userDebt1 = await lendingPool.getUserDebt(user1.address);
console.log({userDebt1});
});
});

Output should look like this

LendingPool
PoC Borrow and Repay
{ debtBalance: 70000000000000000000n }
{ userDebt: 70000000000000000000n }
{ debtBalance1: 80032550373922748972n }
{ userDebt1: 80016273295388925806n }

We can see that these values differ from each other. This means that the debt is calculated using incorrect value and the user will have to pay wrong amount of intereset.

Impact

The debt is not tracked correctly which leads to a scenario where users has to pay different interest amount than he should in reality.

Tools Used

Manual Review, Hardhat

Recommendations

Fix the debt tracking methods so that they always return the same values and the interest is calculated based on the same values.

Updates

Lead Judging Commences

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

LendingPool::borrow tracks debt as user.scaledDebtBalance += scaledAmount while DebtToken mints amount+interest, leading to accounting mismatch and preventing full debt repayment

Support

FAQs

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