Files
herolib/lib/threefold/incatokens/vesting.v
2025-11-30 08:59:38 +01:00

83 lines
2.7 KiB
V

module incatokens
import incubaid.herolib.biz.spreadsheet
// Create vesting schedule in spreadsheet
pub fn (mut sim Simulation) create_vesting_schedules() ! {
// Create vesting sheet
mut vesting_sheet := spreadsheet.sheet_new(
name: '${sim.name}_vesting'
nrcol: 60 // 60 months
curr: sim.params.simulation.currency
)!
// Team vesting
team_tokens := sim.params.distribution.total_supply * sim.params.distribution.team_pct
mut team_row := vesting_sheet.row_new(
name: 'team_vesting'
tags: 'category:team type:vesting'
descr: 'Team token vesting schedule'
)!
sim.apply_vesting_schedule(mut team_row, team_tokens, sim.team_vesting)!
// Treasury vesting
treasury_tokens := sim.params.distribution.total_supply * sim.params.distribution.treasury_pct
mut treasury_row := vesting_sheet.row_new(
name: 'treasury_vesting'
tags: 'category:treasury type:vesting'
descr: 'Treasury token vesting schedule'
)!
sim.apply_vesting_schedule(mut treasury_row, treasury_tokens, sim.treasury_vesting)!
// Investor rounds vesting
for round in sim.investor_rounds {
round_tokens := sim.params.distribution.total_supply * round.allocation_pct
mut round_row := vesting_sheet.row_new(
name: '${round.name}_vesting'
tags: 'category:investor round:${round.name} type:vesting'
descr: '${round.name} investor vesting schedule'
)!
sim.apply_vesting_schedule(mut round_row, round_tokens, round.vesting)!
}
// Create total unlocked row
_ := vesting_sheet.group2row(
name: 'total_unlocked'
include: ['type:vesting']
tags: 'summary type:total_vesting'
descr: 'Total tokens unlocked over time'
aggregatetype: .sum
)!
sim.vesting_sheet = vesting_sheet
}
fn (sim Simulation) apply_vesting_schedule(mut row spreadsheet.Row, total_tokens f64, schedule VestingSchedule) ! {
initial_unlocked_tokens := total_tokens * schedule.initial_unlock_pct
remaining_tokens_to_vest := total_tokens - initial_unlocked_tokens
monthly_vesting_amount := if schedule.vesting_months > 0 {
remaining_tokens_to_vest / f64(schedule.vesting_months)
} else {
0.0
}
for month in 0 .. row.sheet.nrcol {
if month == 0 {
// Initial unlock at month 0
row.cells[month].val = initial_unlocked_tokens
} else if month < schedule.cliff_months {
// Before cliff, only initial unlock is available
row.cells[month].val = initial_unlocked_tokens
} else if month < schedule.cliff_months + schedule.vesting_months {
// During vesting period (after cliff)
months_after_cliff := month - schedule.cliff_months + 1
row.cells[month].val = initial_unlocked_tokens +
(monthly_vesting_amount * f64(months_after_cliff))
} else {
// After vesting complete
row.cells[month].val = total_tokens
}
}
}