Skip to content

[3] Add per-installment late fee accrual #3

Description

@EmeditWeb

Problem

The RepaymentInstallment struct in contracts/creditline-contract/src/types.rs carries no due_date, and repay_installment() does not penalize late payments. Borrowers can effectively pay months late with zero consequence, which breaks the reputation score's underlying assumption that on-time payment matters.

Context

Late fees are the protocol's only economic enforcement mechanism short of liquidation. Without them, sponsors price all risk into the base APR, hurting on-time learners. The fee must flow back into the liquidity pool so sponsors are made whole.

Before Starting

Read these context files first:

  • context/architecture-context.md
  • context/code-standards.md
  • context/progress-tracker.md
  • contracts/creditline-contract/src/types.rs
  • contracts/creditline-contract/src/lib.rs

What To Build

  1. Add pub due_date: u64 to RepaymentInstallment in types.rs. Populate at loan creation: due_date = approval_ts + (n+1) * installment_period_secs.
  2. Add pub late_fee_bps: u32 to ProtocolParameters in types.rs, default 500 bps (5%).
  3. In repay_installment(), compute now = env.ledger().timestamp(). If now > installment.due_date, compute late_fee = installment.amount * late_fee_bps / 10_000 and require the caller to transfer installment.amount + late_fee.
  4. Route the late fee to the liquidity pool via cross-contract call, not the borrower's loan balance.
  5. Emit a LATEFEEPAID event with (loan_id, installment_index, fee_amount).
  6. Add 4 unit tests: on-time path (no fee), 1-day-late, exact-due-date boundary, custom-bps test.

Files To Touch

  • contracts/creditline-contract/src/types.rs
  • contracts/creditline-contract/src/lib.rs
  • contracts/creditline-contract/src/storage.rs
  • contracts/creditline-contract/src/events.rs
  • contracts/creditline-contract/src/tests.rs

Acceptance Criteria

  • due_date is set on every installment at loan creation
  • late_fee_bps is configurable and persisted in ProtocolParameters
  • Late fees route to the liquidity pool, not the loan balance
  • On-time payments incur zero fee (exact now == due_date is on-time)
  • 4 new tests pass
  • Migration note added: existing loans without due_date are gracefully handled (assume 0 = on-time)

Mandatory Checks Before PR

  • cargo build passes with zero errors
  • cargo test — all 93 existing tests still pass
  • require_auth() is FIRST line of every mutating function
  • extend_ttl() called after EVERY persistent storage write
  • New unit tests written for every new function
  • context/progress-tracker.md updated

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    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