Skip to content

Latest commit

 

History

History
249 lines (190 loc) · 5.03 KB

File metadata and controls

249 lines (190 loc) · 5.03 KB

Net Settlement Quick Reference

One-Line Summary

Batch settle multiple remittances with automatic offsetting of opposing transfers to reduce on-chain execution by 50-100%.

Quick Start

// Create batch
let mut entries = Vec::new(&env);
entries.push_back(BatchSettlementEntry { remittance_id: 1 });
entries.push_back(BatchSettlementEntry { remittance_id: 2 });

// Settle with netting
let result = contract.batch_settle_with_netting(&entries)?;

Function Signature

pub fn batch_settle_with_netting(
    env: Env,
    entries: Vec<BatchSettlementEntry>,
) -> Result<BatchSettlementResult, ContractError>

Parameters

Parameter Type Description
entries Vec<BatchSettlementEntry> List of remittance IDs (1-50)

Returns

Type Description
BatchSettlementResult Contains settled_ids: Vec<u64>

Error Codes

Code Error Cause
3 InvalidAmount Empty or >50 entries
6 RemittanceNotFound Invalid ID
7 InvalidStatus Not pending
12 DuplicateSettlement Duplicate ID
13 ContractPaused Contract paused

Data Types

// Input
struct BatchSettlementEntry {
    remittance_id: u64
}

// Output
struct BatchSettlementResult {
    settled_ids: Vec<u64>
}

Example Scenarios

Simple Offset

Input:  A→B: 100, B→A: 90
Output: A→B: 10 (net)
Savings: 50%

Complete Offset

Input:  A→B: 100, B→A: 100
Output: None (complete offset)
Savings: 100%

Multiple Parties

Input:  A→B: 100, B→C: 50, C→A: 30
Output: 3 net transfers (one per pair)

Key Properties

Deterministic - Same input = same output ✅ Order-independent - Any order = same result ✅ Fee-preserving - All fees collected exactly ✅ Secure - Duplicate prevention, overflow protection ✅ Efficient - 50-100% gas savings

Best Practices

  1. Batch size: 10-30 remittances optimal
  2. Grouping: Group same-party pairs for max netting
  3. Validation: Check status before batching
  4. Monitoring: Track events for verification
  5. Error handling: Handle all error codes

Events Emitted

// Per net transfer
emit_settlement_completed(sender, recipient, token, amount)

// Per remittance
emit_remittance_completed(id, sender, agent, token, amount)

Common Patterns

Pattern 1: Validate Before Batch

// Check all remittances are pending
for id in ids {
    let rem = get_remittance(&env, id)?;
    if rem.status != RemittanceStatus::Pending {
        return Err(ContractError::InvalidStatus);
    }
}

Pattern 2: Remove Duplicates

// Deduplicate IDs
let mut seen = Vec::new(&env);
let mut unique = Vec::new(&env);
for entry in entries {
    if !seen.contains(&entry.remittance_id) {
        seen.push_back(entry.remittance_id);
        unique.push_back(entry);
    }
}

Pattern 3: Calculate Efficiency

fn netting_efficiency(original: u32, net: u32) -> f64 {
    ((original - net) as f64 / original as f64) * 100.0
}

JavaScript Example

const entries = [
  { remittance_id: 1n },
  { remittance_id: 2n }
];

const result = await contract.batch_settle_with_netting({
  entries: entries
});

console.log(`Settled: ${result.settled_ids.length}`);

Troubleshooting

Issue Solution
Error 3 Check batch size (1-50)
Error 12 Remove duplicates
Error 7 Verify all pending
Error 13 Wait for unpause

Performance Metrics

Gas per transfer: ~30,000 units
Batch overhead: ~50,000 units
Typical savings: 50-90%
Max batch size: 50 remittances

Testing

# Run net settlement tests
cargo test net_settlement

# Run specific test
cargo test test_net_settlement_simple_offset

# Run with output
cargo test -- --nocapture

Documentation

  • Full guide: NET_SETTLEMENT.md
  • API reference: NET_SETTLEMENT_API.md
  • Examples: examples/net-settlement-example.js
  • Summary: NET_SETTLEMENT_SUMMARY.md

Security Checklist

  • Duplicate prevention
  • Overflow protection
  • Authorization checks
  • Expiry validation
  • Fee preservation
  • Pause mechanism

Limits

Limit Value
Min batch size 1
Max batch size 50
Max remittance amount i128::MAX
Fee range 0-10000 bps

Algorithm Complexity

Operation Complexity
Netting O(n)
Validation O(n)
Execution O(m) where m ≤ n

Quick Checks

// Is batch valid?
assert!(entries.len() > 0 && entries.len() <= 50);

// Are IDs unique?
let unique_count = entries.iter().collect::<HashSet<_>>().len();
assert_eq!(unique_count, entries.len());

// Are all pending?
for entry in entries {
    let rem = get_remittance(&env, entry.remittance_id)?;
    assert_eq!(rem.status, RemittanceStatus::Pending);
}

Version

  • Implementation: v1.0.0
  • Contract: Check get_version()
  • Last updated: 2026-02-20

Need more details? See full documentation in NET_SETTLEMENT.md