# last repayments are calculated incorrectly for "irregular" loan durations

Teller's last-payment-cycle detection misclassifies irregular loan durations, making the second installment demand the full remaining principal and enabling liquidation.

- Payout: Contest reward
- Severity: medium
- Program: Teller
- Credited: immeas
- Disclosed: 2023-03-20
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-03-teller-judging/issues/328
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-03-teller%3AM-11
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:liquidation

**Target:** TellerV2 loan repayment calculation (V2Calculations.sol / NumbersLib.sol)
**Root cause:** isLastPaymentCycle is set when timeLeft < paymentCycle, which for durations not a multiple of the payment cycle triggers one cycle early, so the whole remaining principal becomes due. EMI also uses ceilDiv(loanDuration, cycleDuration), rounding up partial periods.
**Steps:**
1. Submit bid: amount=1000, loanDuration=2500, paymentCycle=1000, interest=0
2. Warp +1000; calculateAmountDue returns principal=400; repayLoanMinimum
3. Warp +1000; calculateAmountDue returns principal=600 instead of expected 400
4. Borrower cannot pay the inflated installment and is liquidated; liquidator pays last installment and seizes collateral
**How found:** Reasoned about expected installment split (400+400+200) for a 2.5-cycle loan, then read V2Calculations.sol's durationLeftOnLoan < paymentCycle check and noticed it marks the last cycle one period early for non-multiple durations; confirmed with a Foundry PoC.
**Exploitation:** Liquidator waits for the second installment of an irregular-duration loan; borrower is unexpectedly billed the full remaining principal, defaults, and liquidator repays the small remaining amount to seize the entire collateral.
**Insight:** When auditing amortization/installment logic, test loan durations that are not exact multiples of the payment cycle; boundary conditions like 'time left < cycle' silently assume divisibility and can front-load the final payment.
