This guide is for contributors who need to understand the settlement math in QuickLendX. It documents the formula implemented in quicklendx-contracts/src/profits.rs, the inputs it consumes, and the policy for when administrative fee updates take effect.
This is written for contributors who are reviewing settlement behavior or tracing an invoice from funding to payout.
The settlement calculation consumes three values:
investment_amount: the principal amount originally funded by the investor.payment_amount: the total amount the business pays toward the invoice during settlement.fee_bps: the active platform fee rate, expressed in basis points, from the current platform-fee configuration.
The important detail is that the fee rate is read at settlement time, not when the investment was first placed.
The contract uses the profit portion of the payment as the fee base:
gross_profit = max(0, payment_amount - investment_amount)
platform_fee = floor(gross_profit * fee_bps / 10_000)
investor_return = payment_amount - platform_fee
If the payment does not exceed the investment, the formula falls back to a no-profit case:
platform_fee = 0
investor_return = payment_amount
The contract intentionally charges fees only on profit, never on principal:
payment_amount <= investment_amountmeans there is no profit to charge a fee on.payment_amount > investment_amountmeans the fee is taken from the positive spread only.- The use of floor division keeps the result deterministic and prevents rounding drift from creating dust.
Suppose the investor funded 1_000 units, the business pays 1_100, and the active fee is 200 bps (2%):
gross_profit = 1_100 - 1_000 = 100
platform_fee = floor(100 * 200 / 10_000) = 2
investor_return = 1_100 - 2 = 1_098
The same logic is expressed in the contract as a pure helper that can be called with explicit values:
let (investor_return, platform_fee) =
PlatformFee::calculate_with_fee_bps(1_000, 1_100, 200);
assert_eq!(platform_fee, 2);
assert_eq!(investor_return, 1_098);The settlement path should preserve these invariants:
investor_return + platform_fee == payment_amountplatform_fee <= gross_profitwhen profit exists- no fee is collected when there is no profit
Those invariants are covered by the settlement-accounting tests in quicklendx-contracts/src/test_settlement_accounting_identity.rs.
Administrative fee updates are applied when settlement runs. The contract reads the current platform-fee configuration inside PlatformFee::calculate, so a fee change becomes effective for the next settlement that uses that configuration.
In practical terms:
- An admin updates the platform fee configuration.
- The new value is written to storage.
- The next settlement call that evaluates the formula uses the updated value.
- Already-funded invoices are not retroactively re-priced; the fee change only affects later settlement calculations.
That means the update is rolled in at settlement time rather than at funding time.
When you change settlement math or fee handling, verify:
- the formula still uses
payment_amount - investment_amountfor the profit base - the fee still uses floor division with the basis-point denominator of
10_000 - the no-dust invariant still holds
- fee updates are documented as taking effect on subsequent settlements, not retroactively