EMI last payment not handled perfectly could lead to borrower losing collaterals
The ternary logic of `calculateAmountOwed()` could have the last EMI payment under calculated, leading to borrower not paying the owed principal and possibly losing the collaterals if care has not been given to.\\nSupposing Bob has a loan duration of 100 days such that the payment cycle is evenly spread out, i.e payment due every 10 days, here is a typical scenario:\\nBob has been making his payment due on time to avoid getting marked delinquent. For the last payment due, Bob decides to make it 5 minutes earlier just to make sure he will not miss it.\\nHowever, `duePrincipal_` ends up assigned the minimum of `owedAmount - interest_` and `owedPrincipal_`, where the former is chosen since `oweTime` is less than _bid.terms.paymentCycle:\\n```\\n        } else {\\n            // Default to PaymentType.EMI\\n            // Max payable amount in a cycle\\n            // NOTE: the last cycle could have less than the calculated payment amount\\n            uint256 maxCycleOwed = isLastPaymentCycle\\n                ? owedPrincipal_ + interest_\\n                : _bid.terms.paymentCycleAmount;\\n\\n            // Calculate accrued amount due since last repayment\\n            uint256 owedAmount = (maxCycleOwed * owedTime) /\\n                _bid.terms.paymentCycle;\\n            duePrincipal_ = Math.min(owedAmount - interest_, owedPrincipal_);\\n        }\\n```\\n\\nHence, in `_repayLoan()`, `paymentAmount >= _owedAmount` equals false failing to close the loan to have the collaterals returned to Bob:\\n```\\n        if (paymentAmount >= _owedAmount) {\\n            paymentAmount = _owedAmount;\\n            bid.state = BidState.PAID;\\n\\n            // Remove borrower's active bid\\n            _borrowerBidsActive[bid.borrower].remove(_bidId);\\n\\n            // If loan is is being liquidated and backed by collateral, withdraw and send to borrower\\n            if (_shouldWithdrawCollateral) {\\n                collateralManager.withdraw(_bidId);\\n            }\\n\\n            emit LoanRepaid(_bidId);\\n```\\n\\nWhile lingering and not paying too much attention to the collateral still in escrow, Bob presumes his loan is now settled.\\nNext, Alex the lender has been waiting for this golden opportunity and proceeds to calling `CollateralManager.withdraw()` to claim all collaterals as soon as the loan turns defaulted.
Consider refactoring the affected ternary logic as follows:\\n```\\n        } else {\\n// Add the line below\\n            duePrincipal = isLastPaymentCycle\\n// Add the line below\\n                ? owedPrincipal\\n// Add the line below\\n               : (_bid.terms.paymentCycleAmount * owedTime) / _bid.terms.paymentCycle;\\n\\n            // Default to PaymentType.EMI\\n            // Max payable amount in a cycle\\n            // NOTE: the last cycle could have less than the calculated payment amount\\n// Remove the line below\\n            uint256 maxCycleOwed = isLastPaymentCycle\\n// Remove the line below\\n                ? owedPrincipal_ // Add the line below\\n interest_\\n// Remove the line below\\n                : _bid.terms.paymentCycleAmount;\\n\\n            // Calculate accrued amount due since last repayment\\n// Remove the line below\\n            uint256 owedAmount = (maxCycleOwed * owedTime) /\\n// Remove the line below\\n                _bid.terms.paymentCycle;\\n// Remove the line below\\n            duePrincipal_ = Math.min(owedAmount // Remove the line below\\n interest_, owedPrincipal_);\\n        }\\n```\\n
Bob ended up losing all collaterals for the sake of the minute amount of loan unpaid whereas Alex receives almost all principal plus interests on top of the collaterals.
```\\n        } else {\\n            // Default to PaymentType.EMI\\n            // Max payable amount in a cycle\\n            // NOTE: the last cycle could have less than the calculated payment amount\\n            uint256 maxCycleOwed = isLastPaymentCycle\\n                ? owedPrincipal_ + interest_\\n                : _bid.terms.paymentCycleAmount;\\n\\n            // Calculate accrued amount due since last repayment\\n            uint256 owedAmount = (maxCycleOwed * owedTime) /\\n                _bid.terms.paymentCycle;\\n            duePrincipal_ = Math.min(owedAmount - interest_, owedPrincipal_);\\n        }\\n```\\n