Using tokens lower or higher than 18 decimals can lead to the wrong loan ratio.
borrow() function checks the loan ratio to avoid users borrowing too much than collateral. but the issue is the calculation of the loan ratio only works correctly with 18 decimal tokens and if the user uses tokens like USDT which is 6 decimals can lead to wrong calculation and as a result, lead to borrowing less or more than the true ratio.
function borrow(Borrow[] calldata borrows) public {
for (uint256 i = 0; i < borrows.length; i++) {
bytes32 poolId = borrows[i].poolId;
uint256 debt = borrows[i].debt;
uint256 collateral = borrows[i].collateral;
Pool memory pool = pools[poolId];
if (pool.lender == address(0)) revert PoolConfig();
if (debt < pool.minLoanSize) revert LoanTooSmall();
if (debt > pool.poolBalance) revert LoanTooLarge();
if (collateral == 0) revert ZeroCollateral();
uint256 loanRatio = (debt * 10 ** 18) / collateral;
if (loanRatio > pool.maxLoanRatio) revert RatioTooHigh();
Loan memory loan = Loan({
lender: pool.lender,
borrower: msg.sender,
loanToken: pool.loanToken,
collateralToken: pool.collateralToken,
debt: debt,
collateral: collateral,
interestRate: pool.interestRate,
startTimestamp: block.timestamp,
auctionStartTimestamp: type(uint256).max,
auctionLength: pool.auctionLength
});
_updatePoolBalance(poolId, pools[poolId].poolBalance - debt);
pools[poolId].outstandingLoans += debt;
uint256 fees = (debt * borrowerFee) / 10000;
IERC20(loan.loanToken).transfer(feeReceiver, fees);
IERC20(loan.loanToken).transfer(msg.sender, debt - fees);
IERC20(loan.collateralToken).transferFrom(
msg.sender,
address(this),
collateral
);
loans.push(loan);
emit Borrowed(
msg.sender,
pool.lender,
loans.length - 1,
debt,
collateral,
pool.interestRate,
block.timestamp
);
}
}
Consider get token decimals by interface and implement calculation for avoid this issue.