This document describes the protocol-wide boundary values enforced during invoice creation and related validation.
Protocol limits are stored in contract instance storage and are used to validate:
- Minimum invoice amount on
store_invoiceandupload_invoice - Maximum invoice due-date horizon (how far in the future
due_dateis allowed to be) - Default grace period used to compute default/overdue deadlines
- (Related limits) minimum bid settings and max invoices per business
The on-chain configuration is represented by ProtocolLimits in quicklendx-contracts/src/protocol_limits.rs:
min_invoice_amount(i128): Minimum allowed invoice amount (smallest unit)min_bid_amount(i128): Absolute minimum bid amount (smallest unit)min_bid_bps(u32): Minimum bid amount as a percent of invoice amount (basis points, 10_000 = 100%)max_due_date_days(u64): Maximum allowed future due-date horizon in daysgrace_period_seconds(u64): Grace period added todue_dateto compute default deadlinemax_invoices_per_business(u32): Maximum active invoices allowed per business (0= unlimited)
When limits are not explicitly configured, the contract falls back to defaults:
min_invoice_amount:1_000_000(1 token at 6 decimals; in tests this is10)min_bid_amount:10min_bid_bps:100(1%)max_due_date_days:365grace_period_seconds:604_800(7 days)max_invoices_per_business:100
Invoice creation enforces these limits in the following flows:
QuickLendXContract::store_invoicecallsprotocol_limits::ProtocolLimitsContract::validate_invoiceQuickLendXContract::upload_invoicecallsverification::verify_invoice_data, which also callsvalidate_invoice
Validation rules:
- Amount must be
>= min_invoice_amount due_datemust be in the future (due_date > ledger.timestamp())due_datemust be no later thanledger.timestamp() + max_due_date_days * 86_400
Boundary behavior is inclusive for the maximum due-date (exactly at the computed max is allowed).
Admin-only entrypoints exist on QuickLendXContract:
initialize_protocol_limits(admin, min_invoice_amount, max_due_date_days, grace_period_seconds)set_protocol_limits(admin, min_invoice_amount, max_due_date_days, grace_period_seconds)update_protocol_limits(admin, min_invoice_amount, max_due_date_days, grace_period_seconds)update_limits_max_invoices(admin, min_invoice_amount, max_due_date_days, grace_period_seconds, max_invoices_per_business)
Authorization is enforced via admin::AdminStorage (admin.require_auth() + admin check).
Updates are rejected unless:
min_invoice_amount > 0min_bid_amount > 0min_bid_bps <= 10_0001 <= max_due_date_days <= 730grace_period_seconds <= 2_592_000(30 days)grace_period_seconds <= max_due_date_days * 86_400(sanity check against contradictory horizons)
The last rule prevents inconsistent configurations where the grace period is longer than the allowed due-date horizon.
quicklendx-contracts/src/test_protocol_limits.rs covers:
- admin-only authorization for all limit-update entrypoints
- rejection of invalid bounds (
min_invoice_amount,max_due_date_days,grace_period_seconds) - rejection of invalid parameter combinations (grace period exceeding due-date horizon)
- internal protocol limit update sanity for bid constraints (
min_bid_amount,min_bid_bps) - immediate application of updated limits on invoice validation and default-date computation
- immediate application of
max_invoices_per_businessupdates - initialization failure for invalid limit combinations before state commit
- Admin authorization: limit updates require admin authorization and are checked against the stored admin address.
- Timestamp trust: validation uses
env.ledger().timestamp(); it assumes ledger timestamps are monotonic and within normal network bounds. - Overflow safety: due-date computations use saturating arithmetic (
saturating_add/saturating_mul) to prevent wrap-around. - Configuration coherence: updates reject contradictory limit combinations to avoid misconfigured risk windows.