feat: add VestingWallet contract with linear/cliff vesting and revocation#52
Open
Bosun-Josh121 wants to merge 2 commits into
Open
feat: add VestingWallet contract with linear/cliff vesting and revocation#52Bosun-Josh121 wants to merge 2 commits into
Bosun-Josh121 wants to merge 2 commits into
Conversation
…tion Implements a token vesting wallet for SmartDrop that supports cliff + linear unlocking schedules and optional admin revocation. Beneficiaries claim via release(); admins can revoke unvested tokens while preserving already-vested amounts. Ships with 20 tests covering all acceptance criteria.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the
VestingWalletSoroban contract for time-locked token distributions, closing #33.Tokens are deposited at initialisation and unlock linearly over a configurable ledger range, with an optional cliff period before which nothing is releasable. An optional revocation flag lets an admin cancel the unvested portion at any time while preserving the beneficiary's already-vested balance.
What was implemented
Contract:
soroban/contracts/vesting-wallet/initialize(beneficiary, token, total_amount, start_ledger, cliff_ledger, end_ledger, revocable, admin)total_amountfrom admin into the contractrelease()revoke()revocable = true; returns unvested tokens to admin and freezes the vested capvested_amount()released_amount()releasable()vested_amount() - released_amount()Vesting formula (linear with cliff)
The cliff acts as a lock: nothing is releasable before
cliff_ledger, but the linear calculation still usesstart_ledgeras its origin — so the beneficiary earns the "cliff period" proportionally once the cliff is reached.Revocation behaviour
revoke()→ unvested tokens (total - vested_at_revoke) are returned immediatelyvested_amount()is frozen at the revocation snapshot; beneficiary can stillrelease()whatever was vestedrevoke()call returnsAlreadyRevokedTests (20 passing)
All acceptance criteria are covered:
test_cliff_not_reached_releasable_is_zero— nothing releasable before clifftest_past_end_full_amount_releasable— full amount available after schedule endstest_revoke_midway_beneficiary_keeps_vested_portion— vested portion stays claimable after revocationtest_vested_amount_with_cliff— 0 before cliff, correct proportion at cliff and midpointtest_release_transfers_correct_amount/test_release_twice_respects_already_released— release accountingtest_revoke_sends_unvested_to_admin/test_revoke_after_partial_release_only_returns_unvestedtest_vested_amount_frozen_after_revoke— no further vesting after revocationtest_double_initialize_returns_error/test_revoke_when_not_revocable_returns_error/test_revoke_twice_returns_already_revoked— error guardsChecklist
contracts/vesting-wallet/contract createdreleasetransfers correct amount and updatesreleased_amountrevokeonly callable by admin and only whenrevocable = truevested_amountreturns 0 before cliff, proportional during vesting, total after endCloses #33