Skip to content

Emit investment_made event and mint fraction tokens on invest - #677

Open
GoldenTuxbee wants to merge 1 commit into
StellarState:devfrom
GoldenTuxbee:fix/wave-batch-517-518
Open

GoldenTuxbee wants to merge 1 commit into
StellarState:devfrom
GoldenTuxbee:fix/wave-batch-517-518

Conversation

@GoldenTuxbee

Copy link
Copy Markdown
Contributor

Closes #518
Closes #517

Both issues ask for functionality that was already substantially implemented in this repo under different names: invoice-escrow's invest/finalise_funding (#518's release_to_issuer)/refund (#518's refund_investors)/get_invoice (#518's get_escrow_balance) cover #518's asks, and invoice-token's mint/burn/transfer/balance/events already cover #517's asks as a standalone SEP-41-compliant contract (one deployed instance per invoice, so invoice_id is set once at initialize rather than passed per call). Two real gaps found and fixed:

#518: missing event on the FundingInvoice invest path

Every other state-changing call in invoice-escrow emits an event, but invest() on the multi-investor FundingInvoice flow (created via create_invoice, distinct from the legacy register_invoice/EscrowStatus path) emitted nothing at all. Added events::investment_made, published with the investor, invoice id, amount, and the investor's new total position; wired into invest(). Covered by test_invest_on_funding_invoice_emits_investment_made_event.

#517: invest() never minted fraction tokens

invest() locked the investor's payment into escrow but never minted them any fraction tokens representing their ownership share, because the two contracts were never wired together (invoice-token was only a dev-dependency of invoice-escrow, used in tests, not a real cross-contract call).

The legacy create_escrow_with_tokens path already does this exact mint for its own flow (comment: "Mint invoice tokens to the buyer to represent their ownership share"), invest() on FundingInvoice just never got the same treatment.

Added an optional fraction_token field to FundingInvoice (Option<Address>, additive so it doesn't disturb the existing field layout) set via a new trailing create_invoice parameter; when set, invest() calls the configured invoice-token contract's mint via env.invoke_contract, same pattern as the legacy path. When fraction_token is None, behavior is unchanged (payment-only, no fraction tokens) for invoices that don't need one. Covered by test_invest_mints_fraction_tokens_when_fraction_token_configured, which deploys a real invoice-token instance, configures escrow as its minter, and asserts the investor's fraction balance after two invests.

Scoped smaller than the full "wire every escrow lifecycle state to the token contract" version (burn on refund/partial_refund/finalise_funding is not wired here): the minimal, lowest-risk integration is investor receives fraction tokens on invest, which is the literal ask in #517's acceptance criteria ("Mint issues correct fraction amount proportional to investment"). Burn-on-settlement is a reasonable follow-up but adds more surface (which lifecycle transitions trigger it, whether partial refunds burn partially) that deserves its own review rather than being bundled in here.

Validation

cargo build -p invoice-escrow -p invoice-token builds clean (only pre-existing deprecation warnings).

The crate's own test suite (contracts/invoice-escrow/src/test.rs) fails to compile with 152 pre-existing errors on a clean upstream/dev checkout (confirmed via git stash before/after) due to a soroban-sdk 27.0.2 to 27.0.3 minor-version API drift (Storage::to_xdr removed, StorageKey visibility changed, etc.), unrelated to this change and well outside its scope to fix.

Verified my two new tests compile cleanly in isolation (cargo check -p invoice-escrow --tests, confirmed zero errors in their line range) since the broken pre-existing tests in the same file prevent actually running the suite.

@TS-mfon

TS-mfon commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

⚠️ Merge Conflict Detected

This PR currently has a merge conflict and cannot be merged until it is resolved.

Please rebase or merge the latest changes from the base branch into your branch and push again.

Closes StellarState#518
Closes StellarState#517

Both issues ask for functionality that was already substantially
implemented under different names: invoice-escrow's invest/finalise_funding
(StellarState#518's release_to_issuer)/refund (StellarState#518's refund_investors)/get_invoice
(StellarState#518's get_escrow_balance) cover StellarState#518's asks, and invoice-token's
mint/burn/transfer/balance/events already cover StellarState#517's asks as a standalone
SEP-41-compliant contract (one deployed instance per invoice, so invoice_id
is set once at initialize rather than passed per call). Two real gaps found
and fixed:

invest() on the multi-investor FundingInvoice flow (created via
create_invoice, distinct from the legacy register_invoice/EscrowStatus
path) emitted nothing at all. Added events::investment_made, published
with the investor, invoice id, amount, and the investor's new total
position; wired into invest(). Covered by
test_invest_on_funding_invoice_emits_investment_made_event.

them any fraction tokens representing their ownership share, because the
two contracts were never wired together (invoice-token was only a
dev-dependency of invoice-escrow, used in tests, not a real cross-contract
call). The legacy create_escrow_with_tokens path already does this exact
mint for its own flow ("Mint invoice tokens to the buyer to represent their
ownership share"); invest() on FundingInvoice just never got the same
treatment. Added an optional fraction_token field to FundingInvoice
(Option<Address>, additive so it doesn't disturb the existing field
layout) set via a new trailing create_invoice parameter; when set, invest()
calls the configured invoice-token contract's mint via env.invoke_contract,
same pattern as the legacy path. When fraction_token is None, behavior is
unchanged (payment-only, no fraction tokens) for invoices that don't need
one. Covered by
test_invest_mints_fraction_tokens_when_fraction_token_configured, which
deploys a real invoice-token instance, configures escrow as its minter,
and asserts the investor's fraction balance after two invests.

Scoped smaller than the full "wire every escrow lifecycle state to the
token contract" version (burn on refund/partial_refund/finalise_funding is
not wired here) per discussion: the minimal, lowest-risk integration is
investor receives fraction tokens on invest, which is the literal ask in
proportional to investment"); burn-on-settlement is a reasonable follow-up
but adds more surface (which lifecycle transitions trigger it, whether
partial refunds burn partially) that deserves its own review.

Validation: cargo build -p invoice-escrow -p invoice-token builds clean
(only pre-existing deprecation warnings). The crate's own test suite
(contracts/invoice-escrow/src/test.rs) fails to compile with 152
pre-existing errors on a clean upstream/dev checkout (confirmed via git
stash before/after) due to a soroban-sdk 27.0.2 -> 27.0.3 minor-version
API drift (Storage::to_xdr removed, StorageKey visibility changed, etc.),
unrelated to this change and well outside its scope to fix. Verified my
two new tests compile cleanly in isolation (cargo check -p invoice-escrow
--tests, confirmed zero errors in their line range) since the broken
pre-existing tests in the same file prevent actually running the suite.
@GoldenTuxbee
GoldenTuxbee force-pushed the fix/wave-batch-517-518 branch from 9a96791 to afeb4cc Compare October 31, 2026 23:40
@TS-mfon

TS-mfon commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

✅ PR Ready for Review

Due to a recent malware incident affecting our repositories, all PRs are required to pass automated security checks before being reviewed for merging.

This PR has passed all automated checks:

  • ✅ Security scan — no malicious code detected
  • ✅ No merge conflicts

A maintainer will review and merge this PR shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement invoice escrow contract with fund locking and release logic Build fractional ownership token contract for invoice fractions

2 participants