A decentralized token vesting contract built on the Movement Network that enables time-locked token distribution with cliff periods and linear vesting schedules for team members, investors, and contributors.
The Token Vesting smart contract provides a robust solution for managing token distribution over time. The contract locks tokens and releases them gradually according to predefined schedules, enabling:
- Linear Vesting: Tokens unlock proportionally over a specified duration
- Cliff Periods: Initial lockup period before any tokens can be claimed
- Flexible Scheduling: Custom vesting periods and cliff durations per beneficiary
- On-Chain Verification: All vesting schedules stored immutably on-chain
- Granular Claims: Beneficiaries can claim any amount up to their vested balance
This system is ideal for token distribution scenarios such as team allocations, investor vesting, advisor compensation, community rewards, and any situation requiring time-based token release.
- Movement CLI installation script (from l1-migration branch)
- Token Vesting Contract: Production-ready Move module with linear vesting
- Helper Scripts: Easy commands for deployment and testing
- Project Structure: Standard Move project layout
No prerequisites needed! The installation script will download a prebuilt Movement CLI binary.
- Disk Space: ~50MB for the Movement CLI binary
- Platform: Linux x86_64 (Replit compatible)
- Time: Installation takes ~10 seconds
The installation script downloads a prebuilt Movement CLI binary from the l1-migration branch:
bash scripts/install-cli.shNote: This takes about 10 seconds. The script will attempt to configure your PATH automatically.
Set up your Movement CLI configuration for the testnet:
bash scripts/init.shYou'll be prompted to:
- Select custom network
- Enter REST URL:
https://testnet.movementnetwork.xyz/v1 - Enter Faucet URL:
https://faucet.testnet.movementnetwork.xyz/ - Generate a new private key (or provide your own)
Your configuration will be saved in .movement/config.yaml
.movement/config.yaml to git - it contains your private key!
Get testnet MOVE tokens to pay for transactions:
movement account fund-with-faucet --account defaultCompile the token vesting module:
bash scripts/build.shRun the unit tests:
bash scripts/test.shDeploy your module to the Movement testnet:
movement move publish --named-addresses vesting=defaultTo reduce gas costs (omit debug artifacts):
movement move publish --named-addresses vesting=default --included-artifacts noneNote If movement command fails and the cli is installed. install please run
export PATH="$HOME/bin:$PATH".
├── Move.toml # Move package configuration
├── sources/
│ └── vesting.move # Your Move module
├── scripts/
│ ├── install-cli.sh # Install Movement CLI
│ ├── init.sh # Initialize CLI configuration
│ ├── build.sh # Compile the module
│ ├── test.sh # Run tests
│ └── verify.sh # Verify setup
└── tests/ # Additional test files (optional)
Linear Vesting
- Proportional token unlock over time
- Customizable vesting duration per beneficiary
- Smooth, continuous vesting calculations
Cliff Periods
- Optional initial lockup before vesting begins
- Prevents early token access
- Cliff duration configurable per stream
Flexible Claims
- Beneficiaries claim any amount up to vested balance
- Multiple partial claims supported
- Gas-efficient claim operations
Event System
- Stream creation events with full parameters
- Claim events for audit trails
- Complete transparency for all operations
- create_stream: Create a new vesting schedule for a beneficiary (owner only, deposits MOVE tokens)
- claim: Claim vested tokens up to available balance (beneficiary only)
- get_stream: Retrieve complete vesting stream details including total amount, start time, cliff, duration, and claimed amount
- get_vested_amount: Calculate currently vested tokens for a beneficiary at a given timestamp
movement move run \
--function-id 'default::vesting::create_stream' \
--args address:"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1" \
--args u64:100000000 \
--args u64:31536000 \
--args u64:7776000Parameters:
- Beneficiary address
- Total amount (in octas: 100000000 = 1 MOVE)
- Duration in seconds (31536000 = 1 year)
- Cliff in seconds (7776000 = 90 days)
movement move run \
--function-id 'default::vesting::claim' \
--args u64:50000000Parameters:
- Amount to claim in octas (50000000 = 0.5 MOVE)
Modify sources/vesting.move or add new .move files to the sources/ directory.
Edit Move.toml to change dependencies. The default configuration uses the Aptos Framework.
The Move.toml file uses a placeholder address _ for vesting. When compiling or publishing:
# Use the default profile address
movement move compile --named-addresses vesting=default
# Or specify an explicit address
movement move compile --named-addresses vesting=0xYOUR_ADDRESSTip: Edit Move.toml and set vesting = "0xYOUR_ADDRESS" to avoid using --named-addresses every time.
The contract uses a resource account to manage vesting state independently from the deployer:
- VestingContract: Stored under the resource account, contains all streams and token reserves
- State: Holds the signing capability and event handles
- Benefits: Cleaner separation, predictable addresses, better security
The contract implements linear vesting with the following formula:
vested_amount = (elapsed_time / total_duration) * total_amount
Key points:
- Vesting starts after the cliff period passes
- Tokens vest linearly until the end of the duration
- Beneficiaries can claim partial amounts multiple times
- All calculations use seconds for precision
MOVE tokens are deposited into the contract when streams are created:
- Owner deposits tokens during
create_stream - Tokens held in contract's
Coin<AptosCoin>reserve - Beneficiaries withdraw vested amounts via
claim - Unclaimed tokens remain locked in contract
Essential Movement CLI commands for working with your contract:
# Check CLI version
movement --version
# Compile module
movement move compile --named-addresses vesting=default
# Run tests
movement move test
# Publish module
movement move publish --named-addresses vesting=default
# Check account balance
movement account list
# Fund account (testnet only)
movement account fund-with-faucet --account default- Only contract owner can create vesting streams
- Only beneficiaries can claim their vested tokens
- Cliff periods enforce minimum lockup
The contract includes comprehensive error checking:
ERROR_NOT_OWNER: Caller is not the contract ownerERROR_STREAM_EXISTS: Beneficiary already has a vesting streamERROR_STREAM_NOT_FOUND: No stream exists for beneficiaryERROR_INVALID_DURATION: Duration must be greater than zeroERROR_NO_VESTED_TOKENS: No tokens available to claimERROR_CLIFF_EXCEEDS_DURATION: Cliff period longer than total durationERROR_NOTHING_TO_CLAIM: No claimable tokens at current timeERROR_INVALID_AMOUNT: Amount must be greater than zeroERROR_CLIFF_HAS_NOT_PASSED: Attempting to claim before cliff endsERROR_INSUFFICIENT_FUNDS: Owner lacks sufficient tokens for deposit
- Time Calculations: All durations in seconds (use consistent units)
- Token Precision: Use octas (1 MOVE = 100,000,000 octas)
- Cliff Design: Set reasonable cliff periods (typically 30-365 days)
- Owner Funding: Ensure owner has sufficient balance before creating streams
- Gradual Claims: Beneficiaries can claim incrementally to manage gas costs
- Movement Documentation: https://docs.movementnetwork.xyz/
- Movement CLI Guide: https://docs.movementnetwork.xyz/devs/movementcli
- First Move Contract Tutorial: https://docs.movementnetwork.xyz/devs/firstMoveContract
- Movement Testnet Explorer: https://explorer.movementnetwork.xyz/?network=bardock+testnet
- Movement Faucet: https://faucet.movementnetwork.xyz/
- RPC/REST URL: https://testnet.movementnetwork.xyz/v1
- Faucet URL: https://faucet.testnet.movementnetwork.xyz/
- Explorer: https://explorer.movementnetwork.xyz/?network=bardock+testnet
- Chain ID: Check with
movement info
Potential features to add:
- Multiple concurrent streams per beneficiary
- Stream revocation/cancellation by owner
- Non-linear vesting curves (exponential, stepped)
- Stream transfer between addresses
- Batch stream creation
- Emergency pause mechanism
- Vesting templates for common schedules
This project is based on the Movement Labs aptos-core repository and follows the same licensing.
Contributions are welcome! Feel free to:
- Report bugs
- Suggest features
- Submit pull requests
- Share your implementations
Join the Movement community and help build the future of decentralized token vesting!