Перейти к основному содержанию

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Вестинг опционален при запуске LaunchLab. Установите vesting_param.total_locked_amount = 0 при инициализации, и раздел ниже не применяется. После активации график фиксируется на весь жизненный цикл запуска; cliff и периоды разблокировки не могут быть изменены задним числом.

Зачем нужен вестинг

Bonding curve продаёт base_supply_graduation токенов во время сбора средств и засевает постградуальный пул оставшимся количеством. Вестинг выделяет дополнительную часть предложения, блокирует её на настраиваемый cliff, а затем линейно высвобождает её одному или нескольким получателям — обычно команде создателя, советникам или партнёрам платформы. Практические варианты использования:
  • Распределение команде. Создатель резервирует, скажем, 5% предложения для основной команды, заблокированное на 6 месяцев и разблокировавшееся линейно в течение следующих 12 месяцев.
  • Распределение платформе. Платформа запуска получает часть каждого токена, который она перечисляет, по той же схеме, через CreatePlatformVestingAccount.
  • Гранты советникам и участникам. Несколько получателей с собственными аккаунтами VestingRecord, каждый отслеживающий свою заявленную сумму независимо.
Заблокированные токены никогда не входят в кривую и не входят в постградуальный LP. Они остаются неактивными в base_vault пула до тех пор, пока каждый получатель не вызовет ClaimVestedToken.

Форма графика

Вестинг для запуска описывается тремя числами, записанными один раз во время инициализации:
ПолеТипСмысл
total_locked_amountu64Сумма всех базовых токенов, заблокированных для всех получателей (создатель + платформа). Должна удовлетворять total_locked_amount <= supply * max_lock_rate / 1_000_000 из GlobalConfig.
cliff_periodu64 (секунды)Время ожидания после окончания сбора средств, прежде чем любые токены будут разблокированы.
unlock_periodu64 (секунды)Длительность окна линейной разблокировки после cliff. 0 означает, что всё разблокируется мгновенно в конце cliff.
Эти три значения находятся на PoolState.vesting_schedule (структура VestingSchedule) плюс on-chain start_time, который программа записывает как block_time + cliff_period в момент, когда сбор средств успешно заканчивается (когда условия выпуска впервые выполняются).
// states/pool.rs
pub struct VestingSchedule {
    pub total_locked_amount:     u64,
    pub cliff_period:            u64,
    pub unlock_period:           u64,
    pub start_time:              u64,   // set by the program at fundraising end
    pub allocated_share_amount:  u64,   // running sum of allocations to vesting records
}
allocated_share_amount — это общая сумма, уже назначенная аккаунтам VestingRecord через CreateVestingAccount / CreatePlatformVestingAccount. Она никогда не должна превышать total_locked_amount. Если создатель переалоцирует, следующий вызов CreateVestingAccount вернёт ошибку InvalidTotalLockedAmount.

Формула линейной разблокировки

После окончания сбора средств программа вычисляет совокупную разблокированную сумму для каждого VestingRecord как:
elapsed         = min(now, start_time + unlock_period) − start_time
unlocked_amount = token_share_amount × elapsed / unlock_period
Если unlock_period == 0, весь token_share_amount становится требуемым в один шаг в start_time. В противном случае кривая представляет собой прямую линию от 0 в start_time до token_share_amount в start_time + unlock_period, ограниченную token_share_amount впоследствии. Сумма, переведённая при каждом вызове ClaimVestedToken, — это разница между вновь рассчитанной совокупной разблокированной суммой и текущим полем claimed_amount в записи.
delta_amount    = unlocked_amount − vesting_record.claimed_amount
vesting_record.claimed_amount = unlocked_amount
Попытка получения до start_time вернёт ошибку VestingNotStarted. Получение после start_time + unlock_period выплатит полный остаток.

Схемы аккаунтов

VestingSchedule

Находится inline на PoolState. См. accounts.

VestingRecord

Запись для каждого получателя. PDA получен как:
seeds = [
  b"pool_vesting",
  pool_state.key(),
  beneficiary.key(),
]
program = LaunchLab program
// states/vesting.rs
#[account]
pub struct VestingRecord {
    pub epoch:               u64,         // recent_epoch tracker
    pub pool:                Pubkey,      // back-pointer to PoolState
    pub beneficiary:         Pubkey,      // who can call ClaimVestedToken
    pub claimed_amount:      u64,         // cumulative claimed
    pub token_share_amount:  u64,         // total allocated to this beneficiary
    pub padding:             [u64; 8],
}
Получатель может иметь только один VestingRecord для каждого запуска. Алоцирование снова одному и тому же получателю при одном запуске вернёт ошибку, так как PDA уже существует.

Инструкции

CreateVestingAccount

Только создатель. Выделяет часть total_locked_amount пула новому получателю путём инициализации свежего PDA VestingRecord. Аргументы
share_amount: u64    // токены для назначения этому получателю
Аккаунты
#ИмяWSПримечания
1creatorWSДолжен равняться pool_state.creator; оплачивает аренду для нового аккаунта.
2beneficiaryWПозже получает разблокированные токены. Pubkey заблокирован здесь — не может быть изменён.
3pool_stateWМутируется для увеличения vesting_schedule.allocated_share_amount.
4vesting_recordWinit; PDA [b"pool_vesting", pool_state, beneficiary].
5system_programТребуется для создания аккаунта.
Предусловия
  • share_amount > 0.
  • pool_state.vesting_schedule.allocated_share_amount + share_amount <= total_locked_amount.
  • Pubkey beneficiary не имеет существующего VestingRecord для этого пула.
Постусловия
  • vesting_record инициализирован с token_share_amount = share_amount, claimed_amount = 0.
  • pool_state.vesting_schedule.allocated_share_amount += share_amount.
Общие ошибкиInvalidTotalLockedAmount, InvalidInput.

CreatePlatformVestingAccount

Вариант CreateVestingAccount для администратора платформы. Кошелёк вестинга платформы (хранящийся на PlatformConfig.platform_vesting_wallet) является получателем, а доля ограничена PlatformConfig.platform_vesting_scale. Подписавший должен равняться platform_config.platform_vesting_wallet. Другие аккаунты зеркалируют CreateVestingAccount. Используйте это, когда платформа контрактует получать фиксированную долю вестинга при каждом запуске, который она перечисляет.

ClaimVestedToken

Только получатель. Переводит любые вновь разблокированные токены из base_vault пула на ATA получателя. Аргументы Нет (программа вычисляет сумму претензии из графика). Аккаунты
#ИмяWSПримечания
1beneficiaryWSДолжен равняться vesting_record.beneficiary.
2authorityPDA [b"vault_auth_seed"]; подписывает перевод из хранилища.
3pool_stateWМутируется только если график нуждается в переподтверждении.
4vesting_recordWclaimed_amount обновляется.
5base_vaultWХранилище базового токена пула; дебетуется.
6beneficiary_ataWПолучает разблокированные токены; init_if_needed.
7base_mintБазовый mint пула.
8token_programПрограмма SPL Token или Token-2022.
9associated_token_programДля создания ATA при необходимости.
10system_programТребуется для создания аккаунта.
Предусловия
  • block_time >= pool_state.vesting_schedule.start_time (иначе VestingNotStarted).
  • pool_state.status == PoolStatus::Migrated — выпуск должен был уже произойти. Вызов перед выпуском вернёт ошибку.
  • Дельта разблокированной суммы больше нуля. Холостой вызов (рассчитанная дельта 0) вернёт ошибку.
Постусловия
  • vesting_record.claimed_amount переходит в новую совокупную разблокированную сумму.
  • delta_amount базового токена переводится на beneficiary_ata.
Общие ошибкиVestingNotStarted, NoAssetsToCollect, MathOverflow.

Практический пример

Запуск устанавливает:
  • supply = 1_000_000_000
  • total_locked_amount = 100_000_000 (10% предложения)
  • cliff_period = 180 * 86400 (180 дней)
  • unlock_period = 365 * 86400 (1 год линейно после cliff)
Создатель выделяет два аккаунта VestingRecord сразу же после инициализации:
  • Получатель A (команда): share_amount = 70_000_000
  • Получатель B (советник): share_amount = 30_000_000
allocated_share_amount = 100_000_000, равно total_locked_amount — дальнейшие алокации невозможны. Сбор средств завершается на 2027-01-01T00:00Z. Программа устанавливает start_time = 2027-01-01 + 180 дней = 2027-06-30. На 2027-09-30 (90 дней после start_time), получатель A вызывает ClaimVestedToken:
elapsed         = min(now, start_time + 365·86400) − start_time
                = 90 · 86400
unlocked_amount = 70_000_000 × (90 / 365) ≈ 17_260_274
delta_amount    = 17_260_274 − 0 = 17_260_274
Кошелёк A получает 17,26 млн базовых токенов. vesting_record.claimed_amount переходит к 17_260_274. Шесть месяцев спустя (2028-03-31, 270 дней после start_time), A получает снова:
unlocked_amount = 70_000_000 × (270 / 365) ≈ 51_780_822
delta_amount    = 51_780_822 − 17_260_274 = 34_520_548
A получает ещё 34,52 млн токенов. После 2028-06-30 (конец unlock_period), следующий вызов передаёт оставшиеся ~18,22 млн и оставляет claimed_amount == token_share_amount.

Граничные случаи

  • Получатель потеряет ключ. Pubkey на VestingRecord.beneficiary — единственный подписавший, который может вызвать ClaimVestedToken. Пути восстановления нет. Установите получателя на multisig, если восстановление важно.
  • Комиссии за передачу Token-2022. Если базовый mint — это mint Token-2022 с расширением комиссии за передачу, получатель получает delta_amount − transfer_fee, а не полную дельту. Хранилище пула всё ещё записывает валовую переданную сумму — разница начисляется на счёт удержанных комиссий mint.
  • Пул не выпущен. Вызов ClaimVestedToken перед выпуском вернёт ошибку. Часы вестинга начинают работать только когда сбор средств действительно завершится; отменённый запуск (который никогда не устанавливает start_time) оставляет заблокированные токены недостижимыми в хранилище.
  • Попытки переалокации. Программа устанавливает allocated_share_amount <= total_locked_amount при каждом CreateVestingAccount. Остаток (если есть) из total_locked_amount, оставшийся неалоцированным, теряется — эти токены остаются в хранилище навсегда после выпуска пула. Алоцируйте полную сумму, если это не намеренно.

Ссылки

Источники:
  • raydium-launch/programs/launchpad/src/states/vesting.rsVestingRecord.
  • raydium-launch/programs/launchpad/src/states/pool.rsVestingSchedule, VestingParams, is_vesting_started, vesting_end_time.
  • raydium-launch/programs/launchpad/src/instructions/create_vesting_account.rs.
  • raydium-launch/programs/launchpad/src/instructions/claim_vested_token.rs.