Protocol
Remainder Handling
Deterministic zero-loss policy awarding remainder stroops to index 0.
Because integer division drops fractional remainders, protocols must have a strict, deterministic rule for fractional tokens (stroops) so that zero funds disappear.
The Rounding Problem
Consider an odd payment of 100 stroops split across 3 members with shares of 3,333 BPS, 3,333 BPS, and 3,334 BPS (total = 10,000 BPS):
- Member 0: 100 * 3,333 / 10,000 = 33 stroops
- Member 1: 100 * 3,333 / 10,000 = 33 stroops
- Member 2: 100 * 3,334 / 10,000 = 33 stroops
- Sum of raw allocations = 99 stroops (1 stroop difference!)
Deterministic Remainder Policy
SplitPay solves this deterministically: the difference between total payment and allocated sum is added to member index 0 (the primary pool member):
rustcontracts/splitpay/src/contract.rs
let remainder = total_amount.checked_sub(allocated_sum)?;if remainder > 0 && !allocations.is_empty() { let first_alloc = allocations.get(0).unwrap(); let new_first = first_alloc.checked_add(remainder)?; allocations.set(0, new_first);}Concrete Math Walkthrough
| Member | Share | Raw Calculation | Remainder Policy | Final Allocation |
|---|---|---|---|---|
| Member 0 | 3,333 BPS | 33 | +1 (Remainder) | 34 stroops |
| Member 1 | 3,333 BPS | 33 | +0 | 33 stroops |
| Member 2 | 3,334 BPS | 33 | +0 | 33 stroops |
| Total | 10,000 BPS | 99 | +1 | 100 stroops (Exact) |