There is a rounding error when calculating the interest and fees in the Lender::_calculateInterest() if the loan token (debt) has too small decimals. As a result, a borrower (or attacker) can borrow loans without paying interest.
The _calculateInterest() calculates the interest (lenderInterest) and fees (protocolInterest) that a borrower has to pay for their loan. However, the formulas for calculating the interest and fees do not support the case that the loan token (debt) has too small decimals, leading to a rounding error.
interest (lenderInterest): https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L724
fees (protocolInterest): https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L725
Consider the GUSD (Gemini dollar) token, which has 2 decimals.
l.debt: 100 GUSD
l.interestRate: 100 (1%) per year
timeElapsed: 86400 seconds (1 day)
lenderFee: 100 (1%)
As you can see, the resulting interest and fees will become 0 due to the rounding down since Solidity has no fixed-point numbers. Consequently, a borrower does not need to pay the lender interest or protocol interest.
As explained in the Proof of Concept section, a borrower does not need to pay the lender interest or protocol interest if the loan token (debt) has too small decimals (e.g., GUSD (Gemini dollar) has 2 decimals).
An attacker can leverage this vulnerability by borrowing a lot of short-term loan positions with a small debt. In this way, the attacker can borrow a bigger debt without paying interest.
Manual Review
I recommend verifying that the loan token (p.loanToken) must have sufficient decimals when creating a pool, as shown below. Please set the MIN_LOAN_TOKEN_DECIMALS constant with an appropriate value.
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.