Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

latefees package

Overview

Realm latefees publishes a graduated late-fee penalty on an overdue invoice held in the live r/invoices. A creditor (an invoice issuer) declares a late-fee SCHEDULE once — a p/tiers schedule over how many blocks an invoice is overdue — and the realm prices the penalty as a function of that overdue duration, escalating by tier. The penalty can be read live (PenaltyNow) or frozen into a sequence-numbered ASSESSMENT the creditor can point a payer to.

It is the fourth consumer of p/tiers and the one that exercises its "progressive fee" reading over TIME rather than quantity: r/meters prices usage, r/payslips prices withholding, and this prices lateness. It is the second consumer of r/invoices after r/receivables, and reads the exact integration surface that realm's header advertises — invoices.InvoiceInfo, invoices.IsOverdue, invoices.HasInvoice — all non-crossing views, no struct slice crossing a realm boundary.

It is a PUBLISHER, not a collector

r/invoices is live and immutable, so this realm CANNOT add a charge to an invoice there, and it holds no coins of its own — no banker, no deposit, no payout, no withdrawal path. A published penalty is a verifiable CLAIM backed by the invoice's own facts and the creditor's declared schedule, exactly as r/receivables publishes a loss provision and r/cashflow a statement. It compels nothing; a debtor who ignores a late fee is in the same position as one who ignores the invoice. A custodial variant that collects the fee is a separate, larger product and is deliberately out of scope.

The pricing axis, and the one it is not

The base handed to p/tiers is the OVERDUE DURATION in blocks (`now - dueHeight`), and each tier's rate is a ugnot accrual per RateScale blocks. So the penalty ESCALATES WITH TIME: the longer an invoice is overdue, the higher the marginal accrual. p/tiers' rate cap makes `penalty <= overdueBlocks` an arithmetic fact — the fee can never exceed one ugnot per overdue block, a natural ceiling.

It is NOT a percentage of the outstanding amount. p/tiers prices one amount against breakpoints — a single dimension — and a fee that is both time-escalating AND balance-scaled is two dimensions it cannot express in one call. The creditor scales the ugnot accrual to their debt magnitudes through the schedule; the assessment records the outstanding beside the penalty so a reader can compute an effective rate. Composing a balance- scaled fee as a single Charge call would be a plausible, wrong number.

The trust boundary, inherited twice over

A penalty is a self-report of a self-report of a self-report: the issuer set the invoice amount in r/invoices, the due height there, AND the late-fee schedule here. This realm computes faithfully from those; it does not validate that any of them is fair. A creditor may only assess their OWN invoices — Assess derives the issuer from `cur.Previous().Address()` and reads invoices.InvoiceInfo under that key, which returns only invoices that address issued.

Function

QuotePenalty

func QuotePenalty(issuer address, overdueBlocks int64) int64
Ask AI Claude ChatGPT

QuotePenalty prices a hypothetical overdue duration against an issuer's current schedule, without reading any invoice — the preview a creditor uses to tune a schedule. Panics if the issuer has no schedule or overdueBlocks is negative.

Params

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/latefees.QuotePenalty(,)"

Result