20,000 USDC
View results
Submission Details
Severity: medium

Borrower can set very low collateral when refinancing because there is no minimum value set for maxLoanRatio. .

Summary

There is no check when creating a pool on the minimum ratio between the debt of a borrower and their collateral. This enables a borrower to set a very low collateral when refinancing if the maxLoanRatio is not properly set.

Vulnerability Details

When creating a lending pool by calling Lender.setPool() the only check for maxLoanRatio is if it zero. There should be a check whether it is for example lower than 8 * 10**17, so that the collateral is at least 1.25 the debt of the borrower, in order to secure lenders' money.

So a borrower can call Lender.refinance() and reduce their collateral a lot depending on the value of maxLoanRatio.

function refinance(Refinance[] calldata refinances) public {
.................
// update loan collateral
if (collateral > loan.collateral) {
// transfer the collateral tokens from the borrower to the contract
IERC20(loan.collateralToken).transferFrom(
msg.sender,
address(this),
collateral - loan.collateral // @audit why transfer more collateral to the lender??
); // Can I remove the collateral alltogether??
} else if (collateral < loan.collateral) {
// transfer the collateral tokens from the contract to the borrower
IERC20(loan.collateralToken).transfer(
msg.sender,
loan.collateral - collateral // @audit here
);
}
.............
}
}

Impact

If maxLoanRatio is not properly set (e.g. 2*10**18) then a borrower can get half their collateral back which would not be very ideal for lenders, as it is shown in the test case below:

function test_refinanceLowCollateral() public {
test_borrow();
vm.startPrank(lender2);
Pool memory p = Pool({
lender: lender2,
loanToken: address(loanToken),
collateralToken: address(collateralToken),
minLoanSize: 100*10**18,
poolBalance: 1000*10**18,
maxLoanRatio: 2*10**18, // @audit Very high value for maxLoanRatio - maybe 8*10**17
auctionLength: 1 days,
interestRate: 1000,
outstandingLoans: 0
});
lender.setPool(p);
vm.startPrank(borrower);
Refinance memory r = Refinance({
loanId: 0,
poolId: keccak256(
abi.encode(
address(lender2),
address(loanToken),
address(collateralToken)
)
),
debt: 100*10**18,
collateral: 51*10**18 // @audit The borrower gets almost half their collateral back - reverts
}); // on exactly half i.e 50*10**18
Refinance[] memory rs = new Refinance[](1);
rs[0] = r;
lender.refinance(rs);
}

Tools Used

Manual review

Recommendations

Consider adding a check for a minimum value of maxLoanRatio when setPool() is called or e.g. when borrow()ing e.g.

if ((debt * 10**18 / collateral) < 8 * 10**17) revert LowCollateral();

Support

FAQs

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