Bubbly Inky Sawfish
Medium
The LenderCommitmentGroup_Smart.getMinInterestRate()
function calculates the minimum APR for borrowing. However, this APR is determined based on the utilization ratio, which includes the newly borrowed amount. This allows borrowers to reduce the APR by dividing a loan into multiple smaller loans.
The LenderCommitmentGroup_Smart.getMinInterestRate()
function calculates the minimum APR for borrowing.
https://github.com/sherlock-audit/2024-11-teller-finance-update/blob/main/teller-protocol-v2-audit-2024/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol#L1017-1023
function getMinInterestRate(uint256 amountDelta) public view returns (uint16) {
return interestRateLowerBound +
uint16( uint256(interestRateUpperBound-interestRateLowerBound)
@> .percent(getPoolUtilizationRatio(amountDelta )
) );
}
However, the APR is calculated based on the utilization ratio, which includes the newly borrowed amount. This allows borrowers to reduce the APR by dividing a loan into multiple smaller loans, creating an unfair advantage for them over other users. https://github.com/sherlock-audit/2024-11-teller-finance-update/blob/main/teller-protocol-v2-audit-2024/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol#L1002-1015
function getPoolUtilizationRatio(uint256 activeLoansAmountDelta ) public view returns (uint16) {
if (getPoolTotalEstimatedValue() == 0) {
return 0;
}
return uint16( Math.min(
MathUpgradeable.mulDiv(
@> (getTotalPrincipalTokensOutstandingInActiveLoans() + activeLoansAmountDelta),
10000 ,
getPoolTotalEstimatedValue() ) ,
10000 ));
}
interestRateLowerBound = 0 interestRateLowerBound = 800 // 8% current total estimated value = $20000 current borrowed value = $5000
none
If Alice borrows $10000 USD at once, the APR is (5000 + 10000) / 20000 * 8% = 6%
However, Alice borrow $10000 as follows.
- Alice is going to borrow $10000.
- Alice borrows $1,000 repeatedly for a total of 10 times.
Then the APR for each 1000 USD is: (5000 + 1000) / 20000 * 8% = 2.4% (6000 + 1000) / 20000 * 8% = 2.8% (7000 + 1000) / 20000 * 8% = 3.2% (8000 + 1000) / 20000 * 8% = 3.6% (9000 + 1000) / 20000 * 8% = 4.0% (10000 + 1000) / 20000 * 8% = 4.4% (11000 + 1000) / 20000 * 8% = 4.8% (12000 + 1000) / 20000 * 8% = 5.2% (13000 + 1000) / 20000 * 8% = 5.6% (14000 + 1000) / 20000 * 8% = 6%
(2.4 + 2.8 + ... + 6) / 10 = 4.2
Therefore, the borrower will only pay an APR of 4.2% on the $10,000 loan. As a result, Alice lowers the interest rate from 6% to 4.2% by splitting a $10,000 loan into ten separate loans of $1,000 each.
Users can lower the interest rate by dividing a loan into multiple smaller loans.
none
Middle value should be used instead of end value.
function getPoolUtilizationRatio(uint256 activeLoansAmountDelta ) public view returns (uint16) {
if (getPoolTotalEstimatedValue() == 0) {
return 0;
}
return uint16( Math.min(
MathUpgradeable.mulDiv(
- (getTotalPrincipalTokensOutstandingInActiveLoans() + activeLoansAmountDelta),
+ (getTotalPrincipalTokensOutstandingInActiveLoans() + (activeLoansAmountDelta + 1) / 2),
10000 ,
getPoolTotalEstimatedValue() ) ,
10000 ));
}