Net settlement is an optimization that offsets opposing transfers between the same two parties, executing only the net difference on-chain. This dramatically reduces transaction costs and blockchain congestion.
Without Net Settlement:
Transaction 1: Alice → Bob: 100 USDC
Transaction 2: Bob → Alice: 90 USDC
Total on-chain transfers: 2
Total volume: 190 USDC
With Net Settlement:
Net Transaction: Alice → Bob: 10 USDC
Total on-chain transfers: 1
Total volume: 10 USDC
Savings: 50% fewer transfers, 95% less volume
use soroban_sdk::{Env, Vec};
// Create batch of remittances to settle
let mut entries = Vec::new(&env);
entries.push_back(BatchSettlementEntry { remittance_id: 1 });
entries.push_back(BatchSettlementEntry { remittance_id: 2 });
// Execute batch settlement with automatic netting
let result = contract.batch_settle_with_netting(&entries)?;
// Check results
println!("Settled {} remittances", result.settled_ids.len());const entries = [
{ remittance_id: 1n },
{ remittance_id: 2n }
];
const result = await contract.batch_settle_with_netting({ entries });
console.log(`Settled: ${result.settled_ids.length} remittances`);| Document | Description |
|---|---|
| NET_SETTLEMENT.md | Complete implementation guide with algorithm details |
| NET_SETTLEMENT_API.md | Detailed API reference and integration examples |
| NET_SETTLEMENT_QUICKREF.md | Quick reference card for developers |
| NET_SETTLEMENT_SUMMARY.md | Executive summary and implementation overview |
| NET_SETTLEMENT_CHECKLIST.md | Deployment and verification checklist |
| examples/net-settlement-example.js | Working code examples |
Same input always produces the same output, regardless of processing order or timing.
Remittances can be processed in any order with identical results.
All fees are collected exactly as calculated - no rounding errors.
- Duplicate prevention
- Overflow protection
- Authorization checks
- Expiry validation
- Pause mechanism
- 50-100% reduction in on-chain transfers
- O(n) algorithm complexity
- Batch processing (1-50 remittances)
- Significant gas savings
- No breaking changes
- All existing functions work unchanged
- Additive functionality only
| Scenario | Transfers Before | Transfers After | Savings |
|---|---|---|---|
| Simple offset (100 vs 90) | 2 | 1 | 50% |
| Complete offset (100 vs 100) | 2 | 0 | 100% |
| 10 alternating transfers | 10 | 1-2 | 80-90% |
| 50 mixed transfers | 50 | 5-25 | 50-90% |
Without netting:
10 remittances × 50,000 gas = 500,000 gas
With netting (2 net transfers):
Batch overhead: 50,000 gas
2 transfers × 30,000 gas = 60,000 gas
Total: 110,000 gas
Savings: 390,000 gas (78%)
-
Netting Module (
src/netting.rs)- Deterministic netting algorithm
- Mathematical validation
- Address normalization
-
Batch Settlement (
src/lib.rs)- Public contract function
- Validation and error handling
- Net transfer execution
-
Data Types (
src/types.rs)- BatchSettlementEntry
- BatchSettlementResult
- MAX_BATCH_SIZE constant
1. Load remittances → 2. Validate → 3. Compute nets → 4. Validate math
↓
8. Mark complete ← 7. Emit events ← 6. Accumulate fees ← 5. Execute transfers
# All tests
cargo test
# Net settlement tests only
cargo test net_settlement
# Specific test
cargo test test_net_settlement_simple_offset
# With output
cargo test -- --nocapture- ✅ 20+ comprehensive unit tests
- ✅ Basic functionality (offset, complete offset, multiple parties)
- ✅ Mathematical correctness (fee preservation, order independence)
- ✅ Edge cases (empty batch, oversized batch, duplicates)
- ✅ Error conditions (paused, expired, invalid status)
- ✅ Performance (large batches, transfer reduction)
- Duplicate Prevention: Checks for duplicate IDs and settlement hashes
- Overflow Protection: All arithmetic uses checked operations
- Authorization: Requires proper authorization for all operations
- Expiry Validation: Checks settlement expiry timestamps
- Fee Integrity: Validates fee preservation mathematically
- Pause Mechanism: Emergency stop capability
| Code | Error | Description |
|---|---|---|
| 3 | InvalidAmount | Empty batch or exceeds MAX_BATCH_SIZE |
| 6 | RemittanceNotFound | Remittance ID doesn't exist |
| 7 | InvalidStatus | Remittance not in Pending status |
| 8 | Overflow | Arithmetic overflow detected |
| 12 | DuplicateSettlement | Duplicate ID or already settled |
| 13 | ContractPaused | Contract is paused |
// Alice sends 100 to Bob
let id1 = contract.create_remittance(&alice, &bob, &100, &None);
// Bob sends 90 to Alice
let id2 = contract.create_remittance(&bob, &alice, &90, &None);
// Batch settle with netting
let mut entries = Vec::new(&env);
entries.push_back(BatchSettlementEntry { remittance_id: id1 });
entries.push_back(BatchSettlementEntry { remittance_id: id2 });
let result = contract.batch_settle_with_netting(&entries)?;
// Result: Single net transfer of 10 from Alice to Bob// Equal opposing transfers
let id1 = contract.create_remittance(&alice, &bob, &100, &None);
let id2 = contract.create_remittance(&bob, &alice, &100, &None);
let mut entries = Vec::new(&env);
entries.push_back(BatchSettlementEntry { remittance_id: id1 });
entries.push_back(BatchSettlementEntry { remittance_id: id2 });
let result = contract.batch_settle_with_netting(&entries)?;
// Result: No net transfer (complete offset), but fees still collected// Create remittances
const id1 = await contract.create_remittance({
sender: alice,
agent: bob,
amount: 100n,
expiry: null
});
const id2 = await contract.create_remittance({
sender: bob,
agent: alice,
amount: 90n,
expiry: null
});
// Batch settle
const entries = [
{ remittance_id: id1 },
{ remittance_id: id2 }
];
const result = await contract.batch_settle_with_netting({ entries });
console.log(`Settled ${result.settled_ids.length} remittances`);- Batch Size: Use 10-30 remittances for optimal gas efficiency
- Party Grouping: Group remittances between same parties for maximum netting
- Validation: Check all remittances are valid before batching
- Monitoring: Track events to verify settlements
- Error Handling: Handle all error codes appropriately
// Net settlement completed
emit_settlement_completed(sender, recipient, token, amount)
// Individual remittance completed
emit_remittance_completed(id, sender, agent, token, amount)- Number of batch settlements
- Average batch size
- Netting efficiency (%)
- Gas savings per batch
- Error rate
- Fee collection accuracy
Start with NET_SETTLEMENT.md for a comprehensive overview.
Check NET_SETTLEMENT_API.md for detailed API reference.
Run the examples in examples/net-settlement-example.js.
Use the Quick Reference for integration.
Follow the Deployment Checklist.
Error: InvalidAmount (Code 3)
- Check batch size is between 1-50
- Ensure entries array is not empty
Error: DuplicateSettlement (Code 12)
- Remove duplicate IDs from batch
- Check remittances haven't been settled already
Error: InvalidStatus (Code 7)
- Verify all remittances are in Pending status
- Don't include completed or cancelled remittances
Error: ContractPaused (Code 13)
- Wait for contract to be unpaused
- Contact admin if pause is unexpected
src/netting.rs- Core netting algorithm (450+ lines)src/lib.rs- Batch settlement function (150+ lines)src/types.rs- Data type definitionssrc/test.rs- Comprehensive tests (600+ lines)
- Implementation guide (2000+ lines)
- API reference (1500+ lines)
- Quick reference card
- Summary document
- Deployment checklist
- This README
- JavaScript/TypeScript examples
- Rust integration examples
- Python examples
- Monitoring examples
The netting algorithm uses:
- Lexicographic address ordering for determinism
- Commutative aggregation for order independence
- Checked arithmetic for overflow protection
- Mathematical validation for correctness
- Conservation: Total fees in = Total fees out
- Correctness: Net flow matches sum of directional flows
- Determinism: Same input → Same output
- Fairness: No party gains or loses from netting
Contributions welcome! Please ensure:
- All tests pass:
cargo test - Code is formatted:
cargo fmt - No warnings:
cargo clippy - Documentation is updated
- Examples are provided
Same as SwiftRemit main project (MIT).
- Documentation: See files listed above
- Examples: Check
examples/directory - Issues: Create GitHub issue
- Questions: See main README
Net settlement for SwiftRemit provides:
✅ 50-100% reduction in on-chain transfers ✅ Deterministic and order-independent calculations ✅ Mathematical correctness with fee preservation ✅ Comprehensive security with multiple protections ✅ Full backwards compatibility with existing code ✅ Production-ready with extensive testing ✅ Well-documented with examples and guides
Start using net settlement today to optimize your remittance operations!
Version: 1.0.0
Status: Production Ready ✅
Last Updated: 2026-02-20