PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/x/daily/cliffvesting/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / x / daily / cliffvesting
Files
3 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/x/daily/cliffvesting/v0
gno
0.9

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • cliffvesting.gnogno
cliffvesting.gnogno
1// Package cliffvesting computes cliff-then-linear vesting schedules as a PURE2// calculator — no state, no balances, no transfers.3//4// The shape is the standard employee/token grant: nothing vests until the5// cliff, the cliff releases the whole elapsed portion at once, and the rest6// accrues linearly until the end of the term. Keeping it pure is deliberate:7// the arithmetic is the part that is easy to get subtly wrong and easy to test,8// while custody belongs to the realm holding the coins.9//10// Everything is integer arithmetic. Vested is computed as11// total*elapsed/duration with the multiplication FIRST, so the usual rounding12// bug — dividing before multiplying and truncating the rate to zero — cannot13// happen. Rounding is always DOWN, which means the beneficiary never receives14// more than they have earned and the final instalment collects the remainder;15// at t >= end the result is exactly total, never total-1.16//17// Times are int64 so the caller can use block heights or unix seconds. The unit18// only has to be consistent.19//20// A live demo of this package is at21// [r/moul/x/daily/cliffvestingdemo](/r/moul/x/daily/cliffvestingdemo/v0).22package cliffvesting2324import "errors"2526var (27	ErrBadTotal    = errors.New("cliffvesting: total must be positive")28	ErrBadDuration = errors.New("cliffvesting: duration must be positive")29	ErrCliffAfter  = errors.New("cliffvesting: cliff must not fall after the end")30	ErrCliffBefore = errors.New("cliffvesting: cliff must not fall before the start")31)3233// Schedule is a cliff-then-linear vesting plan. Construct with New so the34// invariants are checked once.35type Schedule struct {36	Total int64 // total amount to vest37	Start int64 // vesting begins38	Cliff int64 // nothing is claimable before this39	End   int64 // fully vested at or after this40}4142// New validates and returns a Schedule. cliff must lie within [start, end].43// Passing cliff == start means "no cliff".44func New(total, start, cliff, end int64) (Schedule, error) {45	s := Schedule{Total: total, Start: start, Cliff: cliff, End: end}46	if total <= 0 {47		return Schedule{}, ErrBadTotal48	}49	if end <= start {50		return Schedule{}, ErrBadDuration51	}52	if cliff > end {53		return Schedule{}, ErrCliffAfter54	}55	if cliff < start {56		return Schedule{}, ErrCliffBefore57	}58	return s, nil59}6061// NewLinear is New with no cliff.62func NewLinear(total, start, end int64) (Schedule, error) {63	return New(total, start, start, end)64}6566// Duration returns the length of the vesting term.67func (s Schedule) Duration() int64 { return s.End - s.Start }6869// HasCliff reports whether the schedule has a non-trivial cliff.70func (s Schedule) HasCliff() bool { return s.Cliff > s.Start }7172// Vested returns how much has vested at time t. Zero before the cliff, exactly73// Total at or after End, and floor(total*elapsed/duration) in between.74func (s Schedule) Vested(t int64) int64 {75	if t < s.Cliff || t < s.Start {76		return 077	}78	if t >= s.End {79		return s.Total80	}81	elapsed := t - s.Start82	// Multiply BEFORE dividing: the reverse truncates the per-tick rate to83	// zero whenever total < duration, which is the classic vesting bug.84	return s.Total * elapsed / s.Duration()85}8687// Unvested returns the remainder still locked at time t.88func (s Schedule) Unvested(t int64) int64 { return s.Total - s.Vested(t) }8990// Claimable returns what can be withdrawn at time t given how much has already91// been claimed. Never negative, even if claimed somehow exceeds vested.92func (s Schedule) Claimable(t, claimed int64) int64 {93	v := s.Vested(t) - claimed94	if v < 0 {95		return 096	}97	return v98}99100// IsFullyVested reports whether the term has completed at time t.101func (s Schedule) IsFullyVested(t int64) bool { return t >= s.End }102103// PercentVested returns the vested share at t as an integer percentage,104// rounded down. Integer-only: no floats reach consensus state.105func (s Schedule) PercentVested(t int64) int64 {106	return s.Vested(t) * 100 / s.Total107}108109// CliffAmount returns the lump sum released the instant the cliff is reached.110func (s Schedule) CliffAmount() int64 { return s.Vested(s.Cliff) }111

Functions

not supported for pure packages by the node (vm/qfuncs)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.