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