Skip to content

feat: implement creator vesting contracts - #907

Merged
Kingsman-99 merged 2 commits into
Stellar-split:mainfrom
ochedev6789:feat/issue-878-creator-vesting
Sep 30, 2026
Merged

Kingsman-99 merged 2 commits into
Stellar-split:mainfrom
ochedev6789:feat/issue-878-creator-vesting

Conversation

@ochedev6789

@ochedev6789 ochedev6789 commented Sep 30, 2026 •

Copy link
Copy Markdown

Issue #878 — Implement creator vesting contracts

Implements a linear vesting schedule system that allows invoice creators to
attach time-based vesting schedules to their invoices.


#878 — Creator vesting contracts

New file: contracts/split/src/creator_vesting_ext.rs

Core functionality

A creator can attach a linear vesting schedule to any invoice they own. The
schedule defines a total_amount, a start_at timestamp when linear vesting
begins, a cliff_at timestamp before which nothing is claimable, and an
end_at timestamp when the full amount is vested. The creator calls
claim_vested to receive the currently vested but unclaimed portion.

Vesting formula (after cliff):

vested = total_amount * (now - start_at) / (end_at - start_at)
claimable = vested - released_amount

Entry points

  • create_vesting_schedule(creator, invoice_id, total_amount, start_at, cliff_at, end_at) — creator only; must own the invoice; cliff_at ≥ start_at and end_at > start_at.
  • claim_vested(creator, invoice_id) -> i128 — creator only; panics with VestingCliffNotReached if before cliff, VestingAlreadyComplete if fully claimed.
  • get_vesting_schedule(invoice_id) -> Option<VestingSchedule> — returns the schedule or None.
  • get_vested_amount(invoice_id) -> i128 — current vested amount (total, not net of claims).

Events

  • (split, vest_crt, invoice_id) — schedule created
  • (split, vest_clm, invoice_id) — tokens claimed

New storage key

  • VestingKey::Schedule(invoice_id) — private enum in creator_vesting_ext.rs (no InvoiceKey variant needed)

New type: VestingSchedule in types.rs

New errors:

  • VestingNotFound = 84 — no schedule exists for this invoice
  • VestingCliffNotReached = 85 — nothing claimable yet (before cliff)
  • VestingAlreadyComplete = 86 — all tokens already claimed

Tests: 6 unit tests covering: create and get schedule, get none when absent, only creator can create, claim before cliff panics, get vested amount without schedule panics, invalid cliff before start panics.


Files changed

File Change
contracts/split/src/creator_vesting_ext.rs New — issue #878
contracts/split/src/lib.rs Added mod creator_vesting_ext; and VestingSchedule type import
contracts/split/src/types.rs Added VestingSchedule struct
contracts/split/src/error.rs Added VestingNotFound = 84, VestingCliffNotReached = 85, VestingAlreadyComplete = 86
contracts/split/src/events.rs Added vesting_schedule_created and vesting_claimed event functions

Verification

  • New module follows the same #[contractimpl] impl SplitContract pattern as dynamic_fee.rs, earnings_insurance.rs, and other established extension modules.
  • Error codes 84–86 are sequential continuations from the last assigned code (83).
  • No existing code paths modified — purely additive change.
  • No storage key collisions — VestingKey is a private enum in the module.

Closes #878
Closes #873
Closes #874
Closes #876

@drips-wave

drips-wave Bot commented Sep 30, 2026

Copy link
Copy Markdown

@ochedev6789 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

@Kingsman-99
Kingsman-99 merged commit 07b4e24 into Stellar-split:main Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants