Skip to content

core: implement principal-interest-fee repayment waterfall in creditline #58

Description

@EmeditWeb

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):

  1. Allocate the paid amount in fixed priority order:
    late fees → accrued interest → service fee → principal.
  2. Decrement each *_outstanding bucket accordingly and only report the
    principal/interest split (per bucket) to the pool.
  3. Reject payments that would underflow any bucket; use safe_math.
  4. 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

  • Waterfall order enforced: late fee → interest → service fee → principal
  • Each *_outstanding bucket decremented correctly per payment
  • remaining_balance == sum(all outstanding buckets) invariant holds
  • Interest/principal split reported to pool matches allocation
  • Partial and full payments both covered by tests

Mandatory Checks Before Opening PR

  • All context/ files read and understood
  • context/progress-tracker.md updated
  • cargo build passes with zero errors
  • cargo test passes — test count not decreased
  • require_auth() first in every mutating function
  • extend_ttl() after every persistent storage write
  • No .unwrap()/.expect() in user-facing paths
  • PR references this issue number

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions