clone_solana_inflation/
lib.rs1#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
3#[cfg(feature = "serde")]
4use serde_derive::{Deserialize, Serialize};
5
6#[cfg_attr(
7 feature = "frozen-abi",
8 derive(clone_solana_frozen_abi_macro::AbiExample)
9)]
10#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
11#[derive(PartialEq, Clone, Debug, Copy)]
12#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
13pub struct Inflation {
14 pub initial: f64,
16
17 pub terminal: f64,
19
20 pub taper: f64,
23
24 pub foundation: f64,
26 pub foundation_term: f64,
28
29 __unused: f64,
31}
32
33const DEFAULT_INITIAL: f64 = 0.08;
34const DEFAULT_TERMINAL: f64 = 0.015;
35const DEFAULT_TAPER: f64 = 0.15;
36const DEFAULT_FOUNDATION: f64 = 0.05;
37const DEFAULT_FOUNDATION_TERM: f64 = 7.0;
38
39impl Default for Inflation {
40 fn default() -> Self {
41 Self {
42 initial: DEFAULT_INITIAL,
43 terminal: DEFAULT_TERMINAL,
44 taper: DEFAULT_TAPER,
45 foundation: DEFAULT_FOUNDATION,
46 foundation_term: DEFAULT_FOUNDATION_TERM,
47 __unused: 0.0,
48 }
49 }
50}
51
52impl Inflation {
53 pub fn new_disabled() -> Self {
54 Self {
55 initial: 0.0,
56 terminal: 0.0,
57 taper: 0.0,
58 foundation: 0.0,
59 foundation_term: 0.0,
60 __unused: 0.0,
61 }
62 }
63
64 pub fn new_fixed(validator: f64) -> Self {
66 Self {
67 initial: validator,
68 terminal: validator,
69 taper: 1.0,
70 foundation: 0.0,
71 foundation_term: 0.0,
72 __unused: 0.0,
73 }
74 }
75
76 pub fn pico() -> Self {
77 Self::new_fixed(0.0001) }
79
80 pub fn full() -> Self {
81 Self {
82 initial: DEFAULT_INITIAL,
83 terminal: DEFAULT_TERMINAL,
84 taper: DEFAULT_TAPER,
85 foundation: 0.0,
86 foundation_term: 0.0,
87 __unused: 0.0,
88 }
89 }
90
91 pub fn total(&self, year: f64) -> f64 {
93 assert!(year >= 0.0);
94 let tapered = self.initial * ((1.0 - self.taper).powf(year));
95
96 if tapered > self.terminal {
97 tapered
98 } else {
99 self.terminal
100 }
101 }
102
103 pub fn validator(&self, year: f64) -> f64 {
105 self.total(year) - self.foundation(year)
106 }
107
108 pub fn foundation(&self, year: f64) -> f64 {
110 if year < self.foundation_term {
111 self.total(year) * self.foundation
112 } else {
113 0.0
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_inflation_basic() {
124 let inflation = Inflation::default();
125
126 let mut last = inflation.total(0.0);
127
128 for year in &[0.1, 0.5, 1.0, DEFAULT_FOUNDATION_TERM, 100.0] {
129 let total = inflation.total(*year);
130 assert_eq!(
131 total,
132 inflation.validator(*year) + inflation.foundation(*year)
133 );
134 assert!(total < last);
135 assert!(total >= inflation.terminal);
136 last = total;
137 }
138 assert_eq!(last, inflation.terminal);
139 }
140
141 #[test]
142 fn test_inflation_fixed() {
143 let inflation = Inflation::new_fixed(0.001);
144 for year in &[0.1, 0.5, 1.0, DEFAULT_FOUNDATION_TERM, 100.0] {
145 assert_eq!(inflation.total(*year), 0.001);
146 }
147 }
148}