A lender can have a pool with attractive interest rates to entice potential borrowers. When the lender sees a borrow txt on the mempool, he can frontrun a usurious increase on the interest rates.
The lender is allowed to update his pools interest rate at any time with the Lender.sol functions setPool() or updateInterestRate(). When the borrower calls the borrow() function, he will take the borrow with whatever the current pool interest rate is.
Take this scenario:
ETH price is 1000 USD.
Lender creates a pool with 1% interest rate. The loan token is USDC and the collateral is ETH. Max loan ratio is 50%.
Borrower decides to take a loan of 500 USDC and deposits 1 ETH as collateral.
Lender frontruns the borrow tx and updates the interest rate to 1000%.
Everyday the interest on the repayment on the loan will increase by about 2.7%.
Considering that the price of ETH stays the same, in around 5 weeks the repayment double to 1000 USDC.
Lender starts an auction. It is very likely that the borrower will not repay the loan and no other lender will take the position.
After the auction has ended, the Lender calls seizeLoan() and takes the collateral.
The borrower will have a loan with unexpected high interest rates.
Manual review.
On the borrow() function, the borrower should pass by parameter the interest rate that they accept for the borrow. If the interest rate provided by the borrower is different than the interest on the pool, the function should revert with an error.
diff --git a/src/utils/Structs.sol b/src/utils/Structs.sol
struct Borrow {
@@ -29,6 +29,8 @@ struct Borrow {
uint256 debt;
/// @notice the amount of collateral to put up
uint256 collateral;
+ /// @notice the interest rate per year in BIPs
+ uint256 interestRate;
}
diff --git a/src/Lender.sol b/src/Lender.sol
@@ -242,6 +242,14 @@ contract Lender is Ownable {
if (debt < pool.minLoanSize) revert LoanTooSmall();
if (debt > pool.poolBalance) revert LoanTooLarge();
if (collateral == 0) revert ZeroCollateral();
+ // validate the expected interest rate
+ if (borrows[i].interestRate != pool.interestRate) revert UnexpectedInterest();
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.