Skip to content

Add vesting contract for time-locked token releases #33

Description

@prodbycorne

Overview

Token distributions often require vesting schedules — linear or cliff-based unlocking over a ledger period. A VestingWallet contract enables SmartDrop to distribute tokens that unlock progressively, rather than all at once.

Vesting Models

Type Description
Linear Tokens unlock proportionally over vesting_period ledgers
Cliff + Linear No unlock before cliff_ledger; linear thereafter
Step (milestone) Discrete chunks unlock at defined ledgers

Contract Design

VestingWallet
  ├── initialize(beneficiary, token, total_amount, start_ledger, cliff_ledger, end_ledger)
  ├── release()            — transfers vested-but-unclaimed tokens to beneficiary
  ├── revoke(admin)        — admin: cancels unvested portion, returns to admin
  ├── vested_amount() -> i128
  ├── released_amount() -> i128
  └── releasable() -> i128  — vested - released

Vested Amount Formula (linear)

fn vested_amount(env: &Env) -> i128 {
    let current = env.ledger().sequence() as i128;
    let start = get_start_ledger(env) as i128;
    let end = get_end_ledger(env) as i128;
    let cliff = get_cliff_ledger(env) as i128;
    let total = get_total_amount(env);

    if current < cliff { return 0; }
    if current >= end { return total; }

    total * (current - start) / (end - start)
}

Revocation

If revocable flag set at init: admin can call revoke to transfer the unvested balance back. Already-vested (but unclaimed) tokens remain claimable by the beneficiary.

Acceptance Criteria

  • contracts/vesting-wallet/ contract created
  • Linear and cliff vesting implemented
  • release transfers correct amount and updates released_amount
  • revoke only callable by admin and only when revocable = true
  • vested_amount returns 0 before cliff, proportional amount during vesting, total after end
  • Test: cliff not reached → 0 releasable
  • Test: past end → full amount releasable
  • Test: revoke midway → beneficiary keeps vested portion

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignfeatureNew feature or capability

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions