render_example_test.gno
2.03 Kb · 69 lines
1package cliffvestingdemo
2
3// ExampleRender pins the realm's Render output as a testable example.
4func ExampleRender() {
5 print(Render(""))
6 // Output:
7 // # Cliff Vesting
8 //
9 // A pure vesting calculator, demoing the [`p/moul/x/daily/cliffvesting`](/p/nym-moultest123/x/daily/cliffvesting/v0) library.
10 //
11 // ## A 12-month grant with a 3-month cliff
12 //
13 // `1200` tokens, `Start = 0`, `Cliff = 3`, `End = 12`.
14 //
15 // | month | vested | unvested | % |
16 // |---|---|---|---|
17 // | 0 | 0 | 1200 | 0% |
18 // | 1 | 0 | 1200 | 0% |
19 // | 2 | 0 | 1200 | 0% ← nothing yet |
20 // | 3 | 300 | 900 | 25% ← **cliff** |
21 // | 4 | 400 | 800 | 33% |
22 // | 5 | 500 | 700 | 41% |
23 // | 6 | 600 | 600 | 50% |
24 // | 7 | 700 | 500 | 58% |
25 // | 8 | 800 | 400 | 66% |
26 // | 9 | 900 | 300 | 75% |
27 // | 10 | 1000 | 200 | 83% |
28 // | 11 | 1100 | 100 | 91% |
29 // | 12 | 1200 | 0 | 100% ← fully vested |
30 //
31 // The cliff is a **step, not a ramp**: at month 3 a quarter of the term has elapsed, so `300` tokens unlock at once. After that it accrues linearly.
32 //
33 // ## Claiming
34 //
35 // The library tracks no balances — the caller supplies what has already been claimed:
36 //
37 // | at month | already claimed | claimable |
38 // |---|---|---|
39 // | 6 | 0 | 600 |
40 // | 6 | 300 | 300 |
41 // | 6 | 600 | 0 |
42 // | 12 | 600 | 600 |
43 //
44 // ## Integer rounding
45 //
46 // All arithmetic is integer — no float ever reaches consensus state. Rounding is **down**, so nobody is ever paid more than they earned, and the final instalment collects the remainder.
47 //
48 // `1000` over `3` periods:
49 //
50 // | t | vested |
51 // |---|---|
52 // | 0 | 0 |
53 // | 1 | 333 |
54 // | 2 | 666 |
55 // | 3 | 1000 |
56 //
57 // `333 + 333 + 334` — the end is exactly `1000`, never `999`.
58 //
59 // ## The bug this avoids
60 //
61 // When the total is smaller than the duration, computing a per-tick rate first truncates it to zero and **nothing ever vests**. Multiplying before dividing keeps it honest — `7` tokens over `1000` ticks:
62 //
63 // | t | vested |
64 // |---|---|
65 // | 100 | 0 |
66 // | 150 | 1 |
67 // | 500 | 3 |
68 // | 1000 | 7 |
69}