store.gno
9.96 Kb · 366 lines
1package protocol_fee
2
3import (
4 "errors"
5
6 "gno.land/p/gnoswap/store"
7 bptree "gno.land/p/nt/bptree/v0"
8 ufmt "gno.land/p/nt/ufmt/v0"
9)
10
11type StoreKey string
12
13func (s StoreKey) String() string {
14 return string(s)
15}
16
17const (
18 // By default, devOps will get 0% of the protocol fee (which means gov/staker will get 100% of the protocol fee)
19 // This percentage can be modified through governance.
20 StoreKeyDevOpsPct StoreKey = "devOpsPct"
21
22 // accumulated amount distributed to gov/staker by token path
23 StoreKeyAccuToGovStaker StoreKey = "accuToGovStaker" // tokenPath -> amount
24 StoreKeyAccuToDevOps StoreKey = "accuToDevOps" // tokenPath -> amount
25
26 // distributedToDevOpsHistory and distributedToGovStakerHistory are used to keep track of the distribution history
27 StoreKeyDistributedToGovStakerHistory StoreKey = "distributedToGovStakerHistory" // tokenPath -> amount
28 StoreKeyDistributedToDevOpsHistory StoreKey = "distributedToDevOpsHistory" // tokenPath -> amount
29
30 // reservedTokens tracks token paths collected but not yet distributed.
31 StoreKeyReservedTokens StoreKey = "reservedTokens"
32)
33
34const (
35 defaultDevOpsPct = int64(0)
36 errSpoofedRealm = "rlm does not match the current crossing frame"
37)
38
39// NewBPTreeN allocates a BP-tree under /r/gnoswap/protocol_fee's realm context
40// so tree.Set leaf-slot writes clear the readonly-taint gate regardless of
41// which realm (protocol_fee/v1, mock, tests) calls Set. Callers must allocate
42// protocol_fee trees through here rather than bptree.NewBPTreeN directly.
43func NewBPTreeN(fanout int) *bptree.BPTree {
44 return bptree.NewBPTreeN(fanout)
45}
46
47type protocolFeeStore struct {
48 kvStore store.KVStore
49}
50
51// handle devOpsPct store data
52func (s *protocolFeeStore) HasDevOpsPctStoreKey() bool {
53 return s.kvStore.Has(StoreKeyDevOpsPct.String())
54}
55
56func (s *protocolFeeStore) InitializeDevOpsPct(_ int, rlm realm) error {
57 if !rlm.IsCurrent() {
58 return errors.New(errSpoofedRealm)
59 }
60
61 return s.kvStore.Set(0, rlm, StoreKeyDevOpsPct.String(), defaultDevOpsPct)
62}
63
64func (s *protocolFeeStore) GetDevOpsPct() int64 {
65 devOpsPct, err := s.kvStore.GetInt64(StoreKeyDevOpsPct.String())
66 if err != nil {
67 panic(err)
68 }
69
70 return devOpsPct
71}
72
73func (s *protocolFeeStore) SetDevOpsPct(_ int, rlm realm, pct int64) error {
74 if !rlm.IsCurrent() {
75 return errors.New(errSpoofedRealm)
76 }
77
78 return s.kvStore.Set(0, rlm, StoreKeyDevOpsPct.String(), pct)
79}
80
81// handle accuToGovStaker store data
82func (s *protocolFeeStore) HasAccuToGovStakerStoreKey() bool {
83 return s.kvStore.Has(StoreKeyAccuToGovStaker.String())
84}
85
86func (s *protocolFeeStore) InitializeAccuToGovStaker(_ int, rlm realm) error {
87 if !rlm.IsCurrent() {
88 return errors.New(errSpoofedRealm)
89 }
90
91 return s.kvStore.Set(0, rlm, StoreKeyAccuToGovStaker.String(), NewBPTreeN(16))
92}
93
94func (s *protocolFeeStore) GetAccuToGovStaker() *bptree.BPTree {
95 accuToGovStaker, err := s.kvStore.GetBPTree(StoreKeyAccuToGovStaker.String())
96 if err != nil {
97 panic(err)
98 }
99
100 return accuToGovStaker
101}
102
103func (s *protocolFeeStore) GetAccuToGovStakerItem(tokenPath string) (int64, bool) {
104 accuToGovStaker, err := s.kvStore.GetBPTree(StoreKeyAccuToGovStaker.String())
105 if err != nil {
106 panic(err)
107 }
108
109 result := accuToGovStaker.Get(tokenPath)
110 if result == nil {
111 return 0, false
112 }
113
114 amount, ok := result.(int64)
115 if !ok {
116 panic(ufmt.Errorf("failed to cast result to int64: %T", result))
117 }
118
119 return amount, true
120}
121
122func (s *protocolFeeStore) SetAccuToGovStakerItem(_ int, rlm realm, tokenPath string, amount int64) error {
123 if !rlm.IsCurrent() {
124 return errors.New(errSpoofedRealm)
125 }
126
127 accuToGovStaker, err := s.kvStore.GetBPTree(StoreKeyAccuToGovStaker.String())
128 if err != nil {
129 return err
130 }
131
132 accuToGovStaker.Set(tokenPath, amount)
133
134 return s.kvStore.Set(0, rlm, StoreKeyAccuToGovStaker.String(), accuToGovStaker)
135}
136
137// handle accuToDevOps store data
138func (s *protocolFeeStore) HasAccuToDevOpsStoreKey() bool {
139 return s.kvStore.Has(StoreKeyAccuToDevOps.String())
140}
141
142func (s *protocolFeeStore) InitializeAccuToDevOps(_ int, rlm realm) error {
143 if !rlm.IsCurrent() {
144 return errors.New(errSpoofedRealm)
145 }
146
147 return s.kvStore.Set(0, rlm, StoreKeyAccuToDevOps.String(), NewBPTreeN(16))
148}
149
150func (s *protocolFeeStore) GetAccuToDevOps() *bptree.BPTree {
151 accuToDevOps, err := s.kvStore.GetBPTree(StoreKeyAccuToDevOps.String())
152 if err != nil {
153 panic(err)
154 }
155
156 return accuToDevOps
157}
158
159func (s *protocolFeeStore) GetAccuToDevOpsItem(tokenPath string) (int64, bool) {
160 accuToDevOps, err := s.kvStore.GetBPTree(StoreKeyAccuToDevOps.String())
161 if err != nil {
162 panic(err)
163 }
164
165 result := accuToDevOps.Get(tokenPath)
166 if result == nil {
167 return 0, false
168 }
169
170 amount, ok := result.(int64)
171 if !ok {
172 panic(ufmt.Errorf("failed to cast result to int64: %T", result))
173 }
174
175 return amount, true
176}
177
178func (s *protocolFeeStore) SetAccuToDevOpsItem(_ int, rlm realm, tokenPath string, amount int64) error {
179 if !rlm.IsCurrent() {
180 return errors.New(errSpoofedRealm)
181 }
182
183 accuToDevOps, err := s.kvStore.GetBPTree(StoreKeyAccuToDevOps.String())
184 if err != nil {
185 return err
186 }
187
188 accuToDevOps.Set(tokenPath, amount)
189
190 return s.kvStore.Set(0, rlm, StoreKeyAccuToDevOps.String(), accuToDevOps)
191}
192
193// handle distributedToGovStakerHistory store data
194func (s *protocolFeeStore) HasDistributedToGovStakerHistoryStoreKey() bool {
195 return s.kvStore.Has(StoreKeyDistributedToGovStakerHistory.String())
196}
197
198func (s *protocolFeeStore) InitializeDistributedToGovStakerHistory(_ int, rlm realm) error {
199 if !rlm.IsCurrent() {
200 return errors.New(errSpoofedRealm)
201 }
202
203 return s.kvStore.Set(0, rlm, StoreKeyDistributedToGovStakerHistory.String(), NewBPTreeN(16))
204}
205
206func (s *protocolFeeStore) GetDistributedToGovStakerHistory() *bptree.BPTree {
207 distributedToGovStakerHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToGovStakerHistory.String())
208 if err != nil {
209 panic(err)
210 }
211
212 return distributedToGovStakerHistory
213}
214
215func (s *protocolFeeStore) GetDistributedToGovStakerHistoryItem(tokenPath string) (int64, bool) {
216 distributedToGovStakerHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToGovStakerHistory.String())
217 if err != nil {
218 panic(err)
219 }
220
221 result := distributedToGovStakerHistory.Get(tokenPath)
222 if result == nil {
223 return 0, false
224 }
225
226 amount, ok := result.(int64)
227 if !ok {
228 panic(ufmt.Errorf("failed to cast result to int64: %T", result))
229 }
230
231 return amount, true
232}
233
234func (s *protocolFeeStore) SetDistributedToGovStakerHistoryItem(_ int, rlm realm, tokenPath string, amount int64) error {
235 if !rlm.IsCurrent() {
236 return errors.New(errSpoofedRealm)
237 }
238
239 distributedToGovStakerHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToGovStakerHistory.String())
240 if err != nil {
241 return err
242 }
243
244 distributedToGovStakerHistory.Set(tokenPath, amount)
245
246 return s.kvStore.Set(0, rlm, StoreKeyDistributedToGovStakerHistory.String(), distributedToGovStakerHistory)
247}
248
249// handle distributedToDevOpsHistory store data
250func (s *protocolFeeStore) HasDistributedToDevOpsHistoryStoreKey() bool {
251 return s.kvStore.Has(StoreKeyDistributedToDevOpsHistory.String())
252}
253
254func (s *protocolFeeStore) InitializeDistributedToDevOpsHistory(_ int, rlm realm) error {
255 if !rlm.IsCurrent() {
256 return errors.New(errSpoofedRealm)
257 }
258
259 return s.kvStore.Set(0, rlm, StoreKeyDistributedToDevOpsHistory.String(), NewBPTreeN(16))
260}
261
262func (s *protocolFeeStore) GetDistributedToDevOpsHistory() *bptree.BPTree {
263 distributedToDevOpsHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToDevOpsHistory.String())
264 if err != nil {
265 panic(err)
266 }
267
268 return distributedToDevOpsHistory
269}
270
271func (s *protocolFeeStore) GetDistributedToDevOpsHistoryItem(tokenPath string) (int64, bool) {
272 distributedToDevOpsHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToDevOpsHistory.String())
273 if err != nil {
274 panic(err)
275 }
276
277 result := distributedToDevOpsHistory.Get(tokenPath)
278 if result == nil {
279 return 0, false
280 }
281
282 amount, ok := result.(int64)
283 if !ok {
284 panic(ufmt.Errorf("failed to cast result to int64: %T", result))
285 }
286
287 return amount, true
288}
289
290func (s *protocolFeeStore) SetDistributedToDevOpsHistoryItem(_ int, rlm realm, tokenPath string, amount int64) error {
291 if !rlm.IsCurrent() {
292 return errors.New(errSpoofedRealm)
293 }
294
295 distributedToDevOpsHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToDevOpsHistory.String())
296 if err != nil {
297 return err
298 }
299
300 distributedToDevOpsHistory.Set(tokenPath, amount)
301
302 return s.kvStore.Set(0, rlm, StoreKeyDistributedToDevOpsHistory.String(), distributedToDevOpsHistory)
303}
304
305// handle reservedTokens store data
306func (s *protocolFeeStore) HasReservedTokensStoreKey() bool {
307 return s.kvStore.Has(StoreKeyReservedTokens.String())
308}
309
310func (s *protocolFeeStore) InitializeReservedTokens(_ int, rlm realm) error {
311 if !rlm.IsCurrent() {
312 return errors.New(errSpoofedRealm)
313 }
314
315 return s.kvStore.Set(0, rlm, StoreKeyReservedTokens.String(), []string{})
316}
317
318func (s *protocolFeeStore) GetReservedTokens() []string {
319 result, err := s.kvStore.Get(StoreKeyReservedTokens.String())
320 if err != nil {
321 panic(err)
322 }
323
324 reservedTokens, ok := result.([]string)
325 if !ok {
326 panic(ufmt.Errorf("failed to cast result to []string: %T", result))
327 }
328
329 return reservedTokens
330}
331
332func (s *protocolFeeStore) SetReservedTokens(_ int, rlm realm, reservedTokens []string) error {
333 if !rlm.IsCurrent() {
334 return errors.New(errSpoofedRealm)
335 }
336
337 if reservedTokens == nil {
338 return errors.New("reservedTokens is nil")
339 }
340
341 return s.kvStore.Set(0, rlm, StoreKeyReservedTokens.String(), reservedTokens)
342}
343
344func (s *protocolFeeStore) AddReservedToken(_ int, rlm realm, tokenPath string) error {
345 if !rlm.IsCurrent() {
346 return errors.New(errSpoofedRealm)
347 }
348
349 reservedTokens := s.GetReservedTokens()
350 for _, reservedToken := range reservedTokens {
351 if reservedToken == tokenPath {
352 return nil
353 }
354 }
355
356 reservedTokens = append(reservedTokens, tokenPath)
357 return s.SetReservedTokens(0, rlm, reservedTokens)
358}
359
360// NewprotocolFeeStore creates a new protocol fee store instance with the provided KV store.
361// This function is used by the upgrade system to create storage instances for each implementation.
362func NewProtocolFeeStore(kvStore store.KVStore) IProtocolFeeStore {
363 return &protocolFeeStore{
364 kvStore: kvStore,
365 }
366}