Skip to main content

Vesting contract

The vesting contract is a smart contract implementation on the TON blockchain, enabling secure, scheduled distribution of Toncoin assets. This contract provides a robust framework for token management, ensuring the controlled release of funds based on predetermined schedules and conditions.

Core functionality

The contract is a secure escrow service that locks a specified amount of Toncoin for a defined period and gradually releases it according to configurable parameters. This mechanism ensures predictable token distribution while maintaining strict control over asset release schedules.

Contract parameters

During deployment, the system establishes the following parameters, which cannot be changed and remain fixed throughout the entire duration of the contract:

ParameterDescriptionExample Values
vesting_total_amountTotal locked Toncoins (in nanotons)500 TON
vesting_start_timeUnix timestamp marking vesting period beginningCurrent time + delay
vesting_total_durationTotal vesting period duration (seconds)31104000 (one year)
unlock_periodTime interval between releases (seconds)2592000 (monthly)
cliff_durationInitial lock period before first release5184000 (two months)
vesting_sender_addressAuthorized address for locked funds managementConfigurable
owner_addressBeneficiary address for Toncoin distributionConfigurable

You can acquire these specific parameters using the get_vesting_data() method.

The parameters must satisfy these conditions:

vesting_total_duration > 0
vesting_total_duration <= 135 years (2^32 seconds)
unlock_period > 0
unlock_period <= vesting_total_duration
cliff_duration >= 0
cliff_duration < vesting_total_duration
vesting_total_duration mod unlock_period == 0
cliff_duration mod unlock_period == 0

Before sending Toncoins to the deployed smart contract, users can verify parameter compliance using the get method, even though the contract itself does not perform these checks.

Lock mechanism

Before vesting_start_time, the contract locks the entire vesting_total_amount.

Starting at vesting_start_time, it unlocks the amount proportionately. For example, if the vesting_total_duration is 10 months, the unlock_period is 1 month, and the vesting_total_amount is 500 TON, then the contract unlocks 50 TON (500 * 10/100) each month, fully releasing all 500 TON in 10 months.

If a cliff period exists, no amount unlocks during that time. Once the cliff period ends, the contract unlocking according to the same formula. For instance, with a cliff_period of 3 months, the contract unlocks nothing in the first 3 months, then unlocks 150 TON at once, followed by 50 TON each month thereafter.

You can use the get_locked_amount(int at_time) method to calculate how much will be locked at a specific time. The contract allows you to transfer locked Toncoins only to whitelisted addresses or the vesting_sender_address. Once unlocked, you can freely send the Toncoins wherever you like.

Whitelist

A whitelist contains addresses to which you can send Toncoins, even if the coins remain locked.

The get_whitelist() method retrieves all whitelist addresses as a list of (wc, hash_part) tuples. You can use the is_whitelisted(slice address) method to check if a specific address is on the whitelist.

The vesting_sender_address can add new addresses to the whitelist at any time using the op::add_whitelist message, but no addresses can be removed from the whitelist. You can always send locked coins to the vesting_sender_address without adding it to the whitelist.

Top-up

You can send Toncoins to the vesting contract from any address.

Wallet smart contract

This contract is similar to the standard wallet V3 smart contract.

The contract maintains seqno, subwallet_id, and public_key, accepts external messages in the same format, and offers get-methods seqno(), get_subwallet_id(), and get_public_key(). Unlike standard wallets, this vesting contract restricts sending to one message at a time.

Send

The public key owner can initiate the sending of Toncoins from the vesting contract by an external message, just like in standard wallets.

The owner initiates Toncoin transfers by sending an op::send internal message from their owner address. In typical usage, the same user owns both the public key and the owner address.

Whitelist restrictions

The contract restricts messages sent to the vesting_sender_address by allowing only send_mode == 3.

Users typically add addresses to the whitelist to enable validation using locked coins or staking locked coins in pools.

Whitelisted addresses must adhere to these restrictions to prevent Toncoin theft:

  • Only send_mode == 3 is permitted
  • Messages must be bounceable
  • No state_init attachments are allowed

System elector addresses accept only these operations:

  • op::elector_new_stake
  • op::elector_recover_stake
  • op::vote_for_complaint
  • op::vote_for_proposal

System config addresses accept only:

  • op::vote_for_proposal

Other whitelisted destinations permit:

  • Empty messages and empty text messages
  • Text messages starting with "d," "w," "D," or "W"
  • Specific operations:
    • op::single_nominator_pool_withdraw
    • op::single_nominator_pool_change_validator
    • op::ton_stakers_deposit
    • op::jetton_burn
    • op::ton_stakers_vote
    • op::vote_for_proposal
    • op::vote_for_complaint

Addresses outside the whitelist operate without restrictions. Unlocked Toncoins remain unrestricted regardless of destination, including whitelisted addresses and vesting_sender_address.

Project structure

  • contracts - source code of all the smart contracts of the project and their dependencies.
  • wrappers - wrapper classes (implementing Contract from ton-core) for the contracts, including any [de]serialization primitives and compilation functions.
  • tests - tests for the contracts.
  • scripts - scripts used by the project, mainly the deployment scripts.

How to use

Build

npx blueprint build` or `yarn blueprint build`

Test

npx blueprint test` or `yarn blueprint test`

Deploy or run another script

npx blueprint run` or `yarn blueprint run`

Add a new contract

npx blueprint create ContractName` or `yarn blueprint create ContractName`

See also