Skip to content

feat(#29): Add checked math for invoice-token burn operations#58

Closed
caxtonacollins wants to merge 2 commits intoStellarState:mainfrom
caxtonacollins:feature/multi-investor-factoring-payer-role
Closed

feat(#29): Add checked math for invoice-token burn operations#58
caxtonacollins wants to merge 2 commits intoStellarState:mainfrom
caxtonacollins:feature/multi-investor-factoring-payer-role

Conversation

@caxtonacollins
Copy link
Copy Markdown
Contributor

Multi-Investor Factoring with Payer Role Enforcement

Overview

This PR implements four interconnected features for the invoice-escrow contract to support decentralized factoring with multiple investors, explicit discount modeling, and enhanced security through payer role enforcement.

Issues Closed

Closes #29 : Use checked math for invoice-token total_supply on burn
Closes #33 : Enforce correct payer role in invoice-escrow record_payment
Closes #39 : Model factoring discount (face value vs investor purchase price)
Closes #43 : Partial/multi-investor funding (MVP slice)

Key Changes

Issue #29: Checked Math for Burn Operations

  • Replaced plain subtraction with checked_sub() in burn() and burn_from()
  • Returns Overflow error on underflow to prevent edge-case issues
  • Improves defensive programming for smart contracts

Issue #33: Payer Role Enforcement

  • Added debtor field to EscrowData to track authorized invoice payer
  • Added InvalidPayer error type
  • Updated create_escrow() to accept debtor parameter
  • Enforces payer == debtor check in record_payment()
  • Prevents unintended settlement triggers from unauthorized parties

Issue #39: Factoring Discount Model

  • Added face_value field: what the debtor owes (amount to be paid at settlement)
  • Added purchase_price field: what investors pay (discount applied here)
  • Updated create_escrow() signature to accept both values
  • Updated fund_escrow() to use purchase_price for investor funding
  • Updated record_payment() to settle based on face_value
  • Updated refund() to use purchase_price for collateral calculation
  • Events now include both values for indexer reconstruction

Issue #43: Multi-Investor Funding MVP

  • Added funded_amt field to track total funding progress
  • Added funder field (MVP: stores primary funder for distribution)
  • Added FunderAmount storage key for per-funder tracking
  • Updated fund_escrow() to accept amount parameter for partial funding
  • Implemented pro-rata distribution in record_payment() and refund()
  • Multiple investors can fund until purchase_price is reached
  • Status transitions to Funded only when fully subscribed

API Changes

create_escrow

Old: (invoice_id, seller, amount, due_date, payment_token, invoice_token)
New: (invoice_id, seller, debtor, face_value, purchase_price, due_date, payment_token, invoice_token)

fund_escrow

Old: (invoice_id, buyer)
New: (invoice_id, buyer, amount)

Test Coverage

  • 32 tests passing
  • 15 tests updated for new API signatures
  • Tests cover:
    • Checked math for burn operations
    • Payer role enforcement (correct/incorrect payer)
    • Factoring discount scenarios
    • Partial payment lifecycle
    • Multi-investor funding (MVP with single funder)
    • Pro-rata distribution
    • Refund scenarios

Implementation Notes

MVP Design Choice

For the MVP, we support multiple funders with per-address tracking but distribute pro-rata based on contribution. The funder field stores the primary funder for backward compatibility with existing tests. Future phases can extend this to track all funders in a list and distribute individually.

Pro-Rata Distribution Formula

pro_rata_share = (funder_amount / total_funded) * payment_amount

Fee Application

Fees are calculated on the payment amount (not face_value), ensuring consistent economics:

platform_fee = (payment_amount × fee_bps) / 10000
investor_amount = payment_amount - platform_fee

Backward Compatibility

  • Single-funder scenarios work identically to before
  • Tests use seller as debtor (simplified for MVP)
  • All existing functionality preserved

Future Enhancements

  • Track all funders in a list for full multi-investor support
  • Implement invoice token redemption for investor claims
  • Add funder-specific settlement tracking
  • Support partial refunds for multiple funders

…ions

- Replace plain subtraction with checked_sub in burn() and burn_from()
- Return Overflow error on underflow to prevent edge-case issues
- Maintains backward compatibility for valid burn amounts
- Improves defensive programming for smart contracts
@drips-wave
Copy link
Copy Markdown

drips-wave bot commented Mar 27, 2026

@caxtonacollins Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

- Export EscrowStatus from invoice-escrow lib for external use
- Fix payment-distributor integration tests with new API signatures
- Update test debtor parameters to use payer where record_payment is called
- Fix event assertions to match new event signatures
- All invoice-escrow tests passing (47/47)
- Payment-distributor tests have pre-existing auth issues unrelated to these changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant