In the borrow function of the LendingPool contract where the calculation of the user's scaled debt balance incorrectly uses rayDiv
instead of rayMul
. This error leads to an underestimation of the user's debt, allowing borrowers to take out larger loans than their collateral should permit, potentially resulting in undercollateralized positions and protocol insolvency.
The borrow
function calculates the user's total debt after borrowing (userTotalDebt
) by combining their existing scaled debt balance (converted to actual debt using rayMul
) with the new borrowed amount. However, when updating the user's scaled debt balance, the new amount is divided by the usage index (rayDiv
), which incorrectly scales down the borrowed amount. This results in a lower scaled debt balance than required, causing the actual debt to be inaccurately represented and allowing users to borrow more than their collateral should allow.
Initial Conditions:
reserve.usageIndex
= 1e27 (RAY)
User has 0 debt and collateral worth 200 units.
First Borrow:
User borrows 100 units.
userTotalDebt
= 0 * 1e27 + 100 = 100 (correct).
scaledAmount
= 100.rayDiv(1e27) = 100e18 * 1e27 / 1e27 = 100e18.
user.scaledDebtBalance
becomes 100e18.
Interest Accrual:
Over time, reserve.usageIndex
increases to 2e27 due to interest.
Second Borrow:
User attempts to borrow another 100 units.
userTotalDebt
= (100e18.rayMul(2e27)) + 100 = 200 + 100 = 300.
Collateral check: 200 >= 300 * 80% → 200 < 240 → Should revert. But:
scaledAmount
= 100.rayDiv(2e27) = 100e18 * 1e27 / 2e27 = 50e18.
user.scaledDebtBalance
becomes 100e18 + 50e18 = 150e18.
Actual debt now: 150e18 * 2e27 / 1e27 = 300 units (correct).
The scaled debt were miscalculated (e.g., using rayMul
), users could borrow beyond their collateral limits, leading to bad debt and protocol insolvency.
Manual review
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.