This document defines the expected behavior of the StellarLend protocol when handling zero, negative, or excessive amounts in state-mutating operations.
All core lending entrypoints (deposit, withdraw, borrow, repay, liquidate) MUST reject zero and negative amounts.
- Providing
amount <= 0results inLendingError::InvalidAmount. - No state is mutated, and the transaction reverts.
When a user repays an amount greater than their outstanding debt (principal + accrued interest):
- The protocol silently clamps the repayment to the exact outstanding balance.
- The remaining debt becomes exactly
0. - Debt balances are never allowed to become negative. A negative debt must not be used to represent a credit balance.
- The
repayfunction returns an expliciti128value indicating the remaining principal debt after repayment:- On exact or overpayment: returns
0. - On partial repayment: returns the positive remaining principal.
- On exact or overpayment: returns
- By clamping rather than rejecting overpayments, the protocol ensures users can easily clear their entire debt even as interest accrues between transaction creation and execution.
If a user calls repay when they have no outstanding debt:
- The protocol treats this as a zero-debt repay and clamps cleanly to
0. - No negative debt (credit balance) is created.
- The return value is
0.
Read-only view functions such as get_position and get_health_factor are guaranteed to never report negative debt balances:
get_position().debtalways returns a value>= 0. If underlying interest arithmetic ever results in a sub-zero calculation, it is clamped to0.get_debt_position().principalreflects the raw stored principal, which is always written as>= 0byrepayandborrow.get_health_factorsimilarly clamps the effective debt to0before the health-factor division.
- The clamp is applied in
debt::repay_amountby comparing the repay amount against the accrual-settled principal; ifamount >= settled.principal, the resulting principal is set to0. - An additional
.max(0)guard is applied inLendingContract::get_positionbefore constructing thePositionSummary, providing defense-in-depth against any future rounding edge case. - The
TotalDebtprotocol counter is decremented byprev_principal - updated.principal(floored at0viasaturating_sub), so it also cannot become negative.