Problem
The Loan struct (types.rs:63-72) tracks separate outstanding buckets —
principal_outstanding, interest_outstanding, service_fee_outstanding
and late_fees_outstanding — but repay_installment() (lib.rs:755-813)
only subtracts the paid amount from remaining_balance. The individual
buckets are never decremented, so after any installment payment the loan's
internal accounting is inconsistent: interest earned by LPs, service-fee
revenue, and default-penalty calculations (which read these buckets) all
operate on stale values.
Before Starting
Read ALL of these before writing any code:
- context/architecture-context.md
- context/code-standards.md
- context/progress-tracker.md
What To Build
A deterministic repayment waterfall applied on every repayment
(repay_installment and repay_loan):
- Allocate the paid amount in fixed priority order:
late fees → accrued interest → service fee → principal.
- Decrement each
*_outstanding bucket accordingly and only report the
principal/interest split (per bucket) to the pool.
- Reject payments that would underflow any bucket; use
safe_math.
- Keep
remaining_balance equal to the sum of all outstanding buckets as
an invariant, asserted in tests.
Files To Touch
- contracts/creditline-contract/src/lib.rs (repayment functions, helper)
- contracts/creditline-contract/src/safe_math.rs (if new helpers needed)
- contracts/creditline-contract/src/tests.rs
Acceptance Criteria
Mandatory Checks Before Opening PR
Problem
The
Loanstruct (types.rs:63-72) tracks separate outstanding buckets —principal_outstanding,interest_outstanding,service_fee_outstandingand
late_fees_outstanding— butrepay_installment()(lib.rs:755-813)only subtracts the paid
amountfromremaining_balance. The individualbuckets are never decremented, so after any installment payment the loan's
internal accounting is inconsistent: interest earned by LPs, service-fee
revenue, and default-penalty calculations (which read these buckets) all
operate on stale values.
Before Starting
Read ALL of these before writing any code:
What To Build
A deterministic repayment waterfall applied on every repayment
(
repay_installmentandrepay_loan):late fees → accrued interest → service fee → principal.
*_outstandingbucket accordingly and only report theprincipal/interest split (per bucket) to the pool.
safe_math.remaining_balanceequal to the sum of all outstanding buckets asan invariant, asserted in tests.
Files To Touch
Acceptance Criteria
*_outstandingbucket decremented correctly per paymentremaining_balance == sum(all outstanding buckets)invariant holdsMandatory Checks Before Opening PR