Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

README.md

2.41 Kb · 51 lines

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

Cliff-then-linear vesting calculatorNew, NewLinear, Vested, Unvested, Claimable, PercentVested, CliffAmount, IsFullyVested, Duration, HasCliff.

1import "gno.land/p/moul/x/daily/cliffvesting/v0"
2
3s, _ := cliffvesting.New(1200, 0, 3, 12) // total, start, cliff, end
4s.Vested(2)          // 0   — before the cliff
5s.Vested(3)          // 300 — the cliff releases the elapsed portion at once
6s.Vested(12)         // 1200
7s.Claimable(6, 300)  // 300 — vested minus already claimed

Pure. No state, no balances, no transfers. The arithmetic is the part that is easy to get subtly wrong and easy to test; custody belongs to the realm holding the coins.

The cliff is a step, not a ramp: nothing vests before it, then the whole elapsed portion unlocks at once, and the rest accrues linearly.

All integer arithmetic — no float ever reaches consensus state:

  • total*elapsed/duration, multiplying first. The reverse computes a per-tick rate that truncates to zero whenever total < duration, so nothing would ever vest. That is the classic vesting bug; it has its own test (7 tokens over 1000 ticks).
  • Rounding is down, so a beneficiary is never paid more than they earned, and the final instalment collects the remainder: 1000 over 3 periods is 333 + 333 + 334, and Vested(end) is exactly total, never total-1.
  • Claimable never returns negative, even if the caller's bookkeeping says more was claimed than has vested.

Times are int64, so the caller may use block heights or unix seconds — the unit only has to be consistent.

Live demo: r/moul/x/daily/cliffvestingdemo · render it at /r/moul/x/daily/cliffvestingdemo/v0.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.