store.gno
18.38 Kb · 711 lines
1package staker
2
3import (
4 "strconv"
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 StoreKeyDepositGnsAmount StoreKey = "depositGnsAmount"
19 StoreKeyMinimumRewardAmount StoreKey = "minimumRewardAmount"
20 StoreKeyDeposits StoreKey = "deposits"
21 StoreKeyExternalIncentives StoreKey = "externalIncentives"
22 StoreKeyTotalEmissionSent StoreKey = "totalEmissionSent"
23 StoreKeyAllowedTokens StoreKey = "allowedTokens"
24 StoreKeyIncentiveCounter StoreKey = "incentiveCounter"
25 StoreKeyTokenSpecificMinimumRewards StoreKey = "tokenSpecificMinimumRewards"
26 StoreKeyUnstakingFee StoreKey = "unstakingFee"
27 StoreKeyPendingProtocolFees StoreKey = "pendingProtocolFees"
28 StoreKeyPools StoreKey = "pools"
29 StoreKeyPoolTierMemberships StoreKey = "poolTierMemberships"
30 StoreKeyPoolTierRatio StoreKey = "poolTierRatio"
31 StoreKeyPoolTierCounts StoreKey = "poolTierCounts"
32 StoreKeyPoolTierLastRewardCacheTimestamp StoreKey = "poolTierLastRewardCacheTimestamp"
33 StoreKeyPoolTierCurrentEmission StoreKey = "poolTierCurrentEmission"
34 StoreKeyPoolTierGetEmission StoreKey = "poolTierGetEmission"
35 StoreKeyPoolTierGetHalvingBlocksInRange StoreKey = "poolTierGetHalvingBlocksInRange"
36 StoreKeyWarmupTemplate StoreKey = "warmupTemplate"
37 StoreKeyCurrentSwapBatch StoreKey = "currentSwapBatch"
38 StoreKeyExternalIncentivesByCreationTime StoreKey = "externalIncentivesByCreationTime"
39)
40
41type stakerStore struct {
42 kvStore store.KVStore
43}
44
45// DepositGnsAmount
46func (s *stakerStore) HasDepositGnsAmountStoreKey() bool {
47 return s.kvStore.Has(StoreKeyDepositGnsAmount.String())
48}
49
50func (s *stakerStore) GetDepositGnsAmount() int64 {
51 result, err := s.kvStore.Get(StoreKeyDepositGnsAmount.String())
52 if err != nil {
53 panic(err)
54 }
55
56 amount, ok := result.(int64)
57 if !ok {
58 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
59 }
60
61 return amount
62}
63
64func (s *stakerStore) SetDepositGnsAmount(_ int, rlm realm, amount int64) error {
65 if !rlm.IsCurrent() {
66 return ErrSpoofedRealm
67 }
68
69 return s.kvStore.Set(0, rlm, StoreKeyDepositGnsAmount.String(), amount)
70}
71
72// MinimumRewardAmount
73func (s *stakerStore) HasMinimumRewardAmountStoreKey() bool {
74 return s.kvStore.Has(StoreKeyMinimumRewardAmount.String())
75}
76
77func (s *stakerStore) GetMinimumRewardAmount() int64 {
78 result, err := s.kvStore.Get(StoreKeyMinimumRewardAmount.String())
79 if err != nil {
80 panic(err)
81 }
82
83 amount, ok := result.(int64)
84 if !ok {
85 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
86 }
87
88 return amount
89}
90
91func (s *stakerStore) SetMinimumRewardAmount(_ int, rlm realm, amount int64) error {
92 if !rlm.IsCurrent() {
93 return ErrSpoofedRealm
94 }
95
96 return s.kvStore.Set(0, rlm, StoreKeyMinimumRewardAmount.String(), amount)
97}
98
99// Deposits
100func (s *stakerStore) HasDepositsStoreKey() bool {
101 return s.kvStore.Has(StoreKeyDeposits.String())
102}
103
104func (s *stakerStore) GetDeposits() *bptree.BPTree {
105 result, err := s.kvStore.Get(StoreKeyDeposits.String())
106 if err != nil {
107 panic(err)
108 }
109
110 deposits, ok := result.(*bptree.BPTree)
111 if !ok {
112 panic(ufmt.Sprintf("failed to cast result to *bptree.BPTree: %T", result))
113 }
114
115 return deposits
116}
117
118func (s *stakerStore) SetDeposits(_ int, rlm realm, deposits *bptree.BPTree) error {
119 if !rlm.IsCurrent() {
120 return ErrSpoofedRealm
121 }
122
123 return s.kvStore.Set(0, rlm, StoreKeyDeposits.String(), deposits)
124}
125
126// ExternalIncentives
127func (s *stakerStore) HasExternalIncentivesStoreKey() bool {
128 return s.kvStore.Has(StoreKeyExternalIncentives.String())
129}
130
131func (s *stakerStore) GetExternalIncentives() *bptree.BPTree {
132 result, err := s.kvStore.Get(StoreKeyExternalIncentives.String())
133 if err != nil {
134 panic(err)
135 }
136
137 incentives, ok := result.(*bptree.BPTree)
138 if !ok {
139 panic(ufmt.Sprintf("failed to cast result to *bptree.BPTree: %T", result))
140 }
141
142 return incentives
143}
144
145func (s *stakerStore) SetExternalIncentives(_ int, rlm realm, incentives *bptree.BPTree) error {
146 if !rlm.IsCurrent() {
147 return ErrSpoofedRealm
148 }
149
150 return s.kvStore.Set(0, rlm, StoreKeyExternalIncentives.String(), incentives)
151}
152
153// TotalEmissionSent
154func (s *stakerStore) HasTotalEmissionSentStoreKey() bool {
155 return s.kvStore.Has(StoreKeyTotalEmissionSent.String())
156}
157
158func (s *stakerStore) GetTotalEmissionSent() int64 {
159 result, err := s.kvStore.Get(StoreKeyTotalEmissionSent.String())
160 if err != nil {
161 panic(err)
162 }
163
164 amount, ok := result.(int64)
165 if !ok {
166 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
167 }
168
169 return amount
170}
171
172func (s *stakerStore) SetTotalEmissionSent(_ int, rlm realm, amount int64) error {
173 if !rlm.IsCurrent() {
174 return ErrSpoofedRealm
175 }
176
177 return s.kvStore.Set(0, rlm, StoreKeyTotalEmissionSent.String(), amount)
178}
179
180// AllowedTokens
181func (s *stakerStore) HasAllowedTokensStoreKey() bool {
182 return s.kvStore.Has(StoreKeyAllowedTokens.String())
183}
184
185func (s *stakerStore) GetAllowedTokens() []string {
186 result, err := s.kvStore.Get(StoreKeyAllowedTokens.String())
187 if err != nil {
188 panic(err)
189 }
190
191 tokens, ok := result.([]string)
192 if !ok {
193 panic(ufmt.Sprintf("failed to cast result to []string: %T", result))
194 }
195
196 return tokens
197}
198
199func (s *stakerStore) SetAllowedTokens(_ int, rlm realm, tokens []string) error {
200 if !rlm.IsCurrent() {
201 return ErrSpoofedRealm
202 }
203
204 return s.kvStore.Set(0, rlm, StoreKeyAllowedTokens.String(), tokens)
205}
206
207// AddAllowedToken appends tokenPath to the allowed-tokens list when absent.
208// The store-owned slice is cloned before mutation to avoid readonly-taint panics.
209func (s *stakerStore) AddAllowedToken(_ int, rlm realm, tokenPath string) error {
210 if !rlm.IsCurrent() {
211 return ErrSpoofedRealm
212 }
213
214 tokens := s.GetAllowedTokens()
215 if !contains(tokens, tokenPath) {
216 tokens = append(tokens, tokenPath)
217 }
218
219 return s.kvStore.Set(0, rlm, StoreKeyAllowedTokens.String(), tokens)
220}
221
222// RemoveAllowedToken removes tokenPath from the allowed-tokens list when present.
223// The store-owned slice is cloned before mutation to avoid readonly-taint panics.
224func (s *stakerStore) RemoveAllowedToken(_ int, rlm realm, tokenPath string) error {
225 if !rlm.IsCurrent() {
226 return ErrSpoofedRealm
227 }
228
229 tokens := s.GetAllowedTokens()
230 for i, t := range tokens {
231 if t == tokenPath {
232 tokens = append(tokens[:i], tokens[i+1:]...)
233 break
234 }
235 }
236
237 return s.kvStore.Set(0, rlm, StoreKeyAllowedTokens.String(), tokens)
238}
239
240// IncentiveCounter
241func (s *stakerStore) HasIncentiveCounterStoreKey() bool {
242 return s.kvStore.Has(StoreKeyIncentiveCounter.String())
243}
244
245func (s *stakerStore) GetIncentiveCounter() *Counter {
246 result, err := s.kvStore.Get(StoreKeyIncentiveCounter.String())
247 if err != nil {
248 panic(err)
249 }
250
251 counter, ok := result.(*Counter)
252 if !ok {
253 panic(ufmt.Sprintf("failed to cast result to *Counter: %T", result))
254 }
255
256 return counter
257}
258
259func (s *stakerStore) SetIncentiveCounter(_ int, rlm realm, counter *Counter) error {
260 if !rlm.IsCurrent() {
261 return ErrSpoofedRealm
262 }
263
264 return s.kvStore.Set(0, rlm, StoreKeyIncentiveCounter.String(), counter)
265}
266
267func (s *stakerStore) NextIncentiveID(creator address, timestamp int64) string {
268 counter := s.GetIncentiveCounter()
269 return makeIncentiveID(creator, timestamp, counter.Next())
270}
271
272// TokenSpecificMinimumRewards
273func (s *stakerStore) HasTokenSpecificMinimumRewardsStoreKey() bool {
274 return s.kvStore.Has(StoreKeyTokenSpecificMinimumRewards.String())
275}
276
277func (s *stakerStore) GetTokenSpecificMinimumRewards() map[string]int64 {
278 result, err := s.kvStore.Get(StoreKeyTokenSpecificMinimumRewards.String())
279 if err != nil {
280 panic(err)
281 }
282
283 rewards, ok := result.(map[string]int64)
284 if !ok {
285 panic(ufmt.Sprintf("failed to cast result to map[string]int64: %T", result))
286 }
287
288 return rewards
289}
290
291func (s *stakerStore) SetTokenSpecificMinimumRewards(_ int, rlm realm, rewards map[string]int64) error {
292 if !rlm.IsCurrent() {
293 return ErrSpoofedRealm
294 }
295
296 return s.kvStore.Set(0, rlm, StoreKeyTokenSpecificMinimumRewards.String(), rewards)
297}
298
299// SetTokenSpecificMinimumRewardItem sets a single token's minimum reward amount.
300func (s *stakerStore) SetTokenSpecificMinimumRewardItem(_ int, rlm realm, tokenPath string, amount int64) error {
301 if !rlm.IsCurrent() {
302 return ErrSpoofedRealm
303 }
304
305 rewards := s.GetTokenSpecificMinimumRewards()
306
307 owned := make(map[string]int64)
308 for k, v := range rewards {
309 owned[k] = v
310 }
311
312 owned[tokenPath] = amount
313
314 return s.kvStore.Set(0, rlm, StoreKeyTokenSpecificMinimumRewards.String(), owned)
315}
316
317// RemoveTokenSpecificMinimumRewardItem removes a single token's minimum reward entry.
318func (s *stakerStore) RemoveTokenSpecificMinimumRewardItem(_ int, rlm realm, tokenPath string) error {
319 if !rlm.IsCurrent() {
320 return ErrSpoofedRealm
321 }
322
323 rewards := s.GetTokenSpecificMinimumRewards()
324
325 owned := make(map[string]int64)
326 for k, v := range rewards {
327 if k == tokenPath {
328 continue
329 }
330
331 owned[k] = v
332 }
333
334 return s.kvStore.Set(0, rlm, StoreKeyTokenSpecificMinimumRewards.String(), owned)
335}
336
337// UnstakingFee
338func (s *stakerStore) HasUnstakingFeeStoreKey() bool {
339 return s.kvStore.Has(StoreKeyUnstakingFee.String())
340}
341
342func (s *stakerStore) GetUnstakingFee() uint64 {
343 result, err := s.kvStore.Get(StoreKeyUnstakingFee.String())
344 if err != nil {
345 panic(err)
346 }
347
348 fee, ok := result.(uint64)
349 if !ok {
350 panic(ufmt.Sprintf("failed to cast result to uint64: %T", result))
351 }
352
353 return fee
354}
355
356func (s *stakerStore) SetUnstakingFee(_ int, rlm realm, fee uint64) error {
357 if !rlm.IsCurrent() {
358 return ErrSpoofedRealm
359 }
360
361 return s.kvStore.Set(0, rlm, StoreKeyUnstakingFee.String(), fee)
362}
363
364func (s *stakerStore) HasPendingProtocolFeesStoreKey() bool {
365 return s.kvStore.Has(StoreKeyPendingProtocolFees.String())
366}
367
368func (s *stakerStore) GetPendingProtocolFees() map[string]int64 {
369 result, err := s.kvStore.Get(StoreKeyPendingProtocolFees.String())
370 if err != nil {
371 panic(err)
372 }
373
374 fees, ok := result.(map[string]int64)
375 if !ok {
376 panic(ufmt.Sprintf("failed to cast result to map[string]int64: %T", result))
377 }
378
379 return fees
380}
381
382func (s *stakerStore) SetPendingProtocolFees(_ int, rlm realm, fees map[string]int64) error {
383 if !rlm.IsCurrent() {
384 return ErrSpoofedRealm
385 }
386
387 return s.kvStore.Set(0, rlm, StoreKeyPendingProtocolFees.String(), fees)
388}
389
390// Pools
391func (s *stakerStore) HasPoolsStoreKey() bool {
392 return s.kvStore.Has(StoreKeyPools.String())
393}
394
395func (s *stakerStore) GetPools() *bptree.BPTree {
396 result, err := s.kvStore.Get(StoreKeyPools.String())
397 if err != nil {
398 panic(err)
399 }
400
401 pools, ok := result.(*bptree.BPTree)
402 if !ok {
403 panic(ufmt.Sprintf("failed to cast result to *bptree.BPTree: %T", result))
404 }
405
406 return pools
407}
408
409func (s *stakerStore) SetPools(_ int, rlm realm, pools *bptree.BPTree) error {
410 if !rlm.IsCurrent() {
411 return ErrSpoofedRealm
412 }
413
414 return s.kvStore.Set(0, rlm, StoreKeyPools.String(), pools)
415}
416
417// PoolTierMemberships
418func (s *stakerStore) HasPoolTierMembershipsStoreKey() bool {
419 return s.kvStore.Has(StoreKeyPoolTierMemberships.String())
420}
421
422func (s *stakerStore) GetPoolTierMemberships() *bptree.BPTree {
423 result, err := s.kvStore.Get(StoreKeyPoolTierMemberships.String())
424 if err != nil {
425 panic(err)
426 }
427
428 memberships, ok := result.(*bptree.BPTree)
429 if !ok {
430 panic(ufmt.Sprintf("failed to cast result to *bptree.BPTree: %T", result))
431 }
432
433 return memberships
434}
435
436func (s *stakerStore) SetPoolTierMemberships(_ int, rlm realm, memberships *bptree.BPTree) error {
437 if !rlm.IsCurrent() {
438 return ErrSpoofedRealm
439 }
440
441 return s.kvStore.Set(0, rlm, StoreKeyPoolTierMemberships.String(), memberships)
442}
443
444// PoolTierRatio
445func (s *stakerStore) HasPoolTierRatioStoreKey() bool {
446 return s.kvStore.Has(StoreKeyPoolTierRatio.String())
447}
448
449func (s *stakerStore) GetPoolTierRatio() TierRatio {
450 result, err := s.kvStore.Get(StoreKeyPoolTierRatio.String())
451 if err != nil {
452 panic(err)
453 }
454
455 ratio, ok := result.(TierRatio)
456 if !ok {
457 panic(ufmt.Sprintf("failed to cast result to TierRatio: %T", result))
458 }
459
460 return ratio
461}
462
463func (s *stakerStore) SetPoolTierRatio(_ int, rlm realm, ratio TierRatio) error {
464 if !rlm.IsCurrent() {
465 return ErrSpoofedRealm
466 }
467
468 return s.kvStore.Set(0, rlm, StoreKeyPoolTierRatio.String(), ratio)
469}
470
471// PoolTierCounts
472func (s *stakerStore) HasPoolTierCountsStoreKey() bool {
473 return s.kvStore.Has(StoreKeyPoolTierCounts.String())
474}
475
476func (s *stakerStore) GetPoolTierCounts() [AllTierCount]uint64 {
477 result, err := s.kvStore.Get(StoreKeyPoolTierCounts.String())
478 if err != nil {
479 panic(err)
480 }
481
482 counts, ok := result.([AllTierCount]uint64)
483 if !ok {
484 panic(ufmt.Sprintf("failed to cast result to [AllTierCount]uint64: %T", result))
485 }
486
487 return counts
488}
489
490func (s *stakerStore) SetPoolTierCounts(_ int, rlm realm, counts [AllTierCount]uint64) error {
491 if !rlm.IsCurrent() {
492 return ErrSpoofedRealm
493 }
494
495 return s.kvStore.Set(0, rlm, StoreKeyPoolTierCounts.String(), counts)
496}
497
498// PoolTierLastRewardCacheTimestamp
499func (s *stakerStore) HasPoolTierLastRewardCacheTimestampStoreKey() bool {
500 return s.kvStore.Has(StoreKeyPoolTierLastRewardCacheTimestamp.String())
501}
502
503func (s *stakerStore) GetPoolTierLastRewardCacheTimestamp() int64 {
504 result, err := s.kvStore.Get(StoreKeyPoolTierLastRewardCacheTimestamp.String())
505 if err != nil {
506 panic(err)
507 }
508
509 timestamp, ok := result.(int64)
510 if !ok {
511 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
512 }
513
514 return timestamp
515}
516
517func (s *stakerStore) SetPoolTierLastRewardCacheTimestamp(_ int, rlm realm, timestamp int64) error {
518 if !rlm.IsCurrent() {
519 return ErrSpoofedRealm
520 }
521
522 return s.kvStore.Set(0, rlm, StoreKeyPoolTierLastRewardCacheTimestamp.String(), timestamp)
523}
524
525// PoolTierCurrentEmission
526func (s *stakerStore) HasPoolTierCurrentEmissionStoreKey() bool {
527 return s.kvStore.Has(StoreKeyPoolTierCurrentEmission.String())
528}
529
530func (s *stakerStore) GetPoolTierCurrentEmission() int64 {
531 result, err := s.kvStore.Get(StoreKeyPoolTierCurrentEmission.String())
532 if err != nil {
533 panic(err)
534 }
535
536 emission, ok := result.(int64)
537 if !ok {
538 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
539 }
540
541 return emission
542}
543
544func (s *stakerStore) SetPoolTierCurrentEmission(_ int, rlm realm, emission int64) error {
545 if !rlm.IsCurrent() {
546 return ErrSpoofedRealm
547 }
548
549 return s.kvStore.Set(0, rlm, StoreKeyPoolTierCurrentEmission.String(), emission)
550}
551
552// PoolTierGetEmission
553func (s *stakerStore) HasPoolTierGetEmissionStoreKey() bool {
554 return s.kvStore.Has(StoreKeyPoolTierGetEmission.String())
555}
556
557func (s *stakerStore) GetPoolTierGetEmission() func() int64 {
558 result, err := s.kvStore.Get(StoreKeyPoolTierGetEmission.String())
559 if err != nil {
560 panic(err)
561 }
562
563 fn, ok := result.(func() int64)
564 if !ok {
565 panic(ufmt.Sprintf("failed to cast result to func() int64: %T", result))
566 }
567
568 return fn
569}
570
571func (s *stakerStore) SetPoolTierGetEmission(_ int, rlm realm, fn func() int64) error {
572 if !rlm.IsCurrent() {
573 return ErrSpoofedRealm
574 }
575
576 return s.kvStore.Set(0, rlm, StoreKeyPoolTierGetEmission.String(), fn)
577}
578
579// PoolTierGetHalvingBlocksInRange
580func (s *stakerStore) HasPoolTierGetHalvingBlocksInRangeStoreKey() bool {
581 return s.kvStore.Has(StoreKeyPoolTierGetHalvingBlocksInRange.String())
582}
583
584func (s *stakerStore) GetPoolTierGetHalvingBlocksInRange() func(start, end int64) ([]int64, []int64) {
585 result, err := s.kvStore.Get(StoreKeyPoolTierGetHalvingBlocksInRange.String())
586 if err != nil {
587 panic(err)
588 }
589
590 fn, ok := result.(func(start, end int64) ([]int64, []int64))
591 if !ok {
592 panic(ufmt.Sprintf("failed to cast result to func(start, end int64) ([]int64, []int64): %T", result))
593 }
594
595 return fn
596}
597
598func (s *stakerStore) SetPoolTierGetHalvingBlocksInRange(_ int, rlm realm, fn func(start, end int64) ([]int64, []int64)) error {
599 if !rlm.IsCurrent() {
600 return ErrSpoofedRealm
601 }
602
603 return s.kvStore.Set(0, rlm, StoreKeyPoolTierGetHalvingBlocksInRange.String(), fn)
604}
605
606func (s *stakerStore) HasWarmupTemplateStoreKey() bool {
607 return s.kvStore.Has(StoreKeyWarmupTemplate.String())
608}
609
610func (s *stakerStore) GetWarmupTemplate() []Warmup {
611 result, err := s.kvStore.Get(StoreKeyWarmupTemplate.String())
612 if err != nil {
613 panic(err)
614 }
615
616 warmups, ok := result.([]Warmup)
617 if !ok {
618 panic(ufmt.Sprintf("failed to cast result to []Warmup: %T", result))
619 }
620
621 return warmups
622}
623
624func (s *stakerStore) SetWarmupTemplate(_ int, rlm realm, warmups []Warmup) error {
625 if !rlm.IsCurrent() {
626 return ErrSpoofedRealm
627 }
628
629 return s.kvStore.Set(0, rlm, StoreKeyWarmupTemplate.String(), warmups)
630}
631
632// CurrentSwapBatch
633func (s *stakerStore) HasCurrentSwapBatchStoreKey() bool {
634 return s.kvStore.Has(StoreKeyCurrentSwapBatch.String())
635}
636
637func (s *stakerStore) GetCurrentSwapBatch() *SwapBatchProcessor {
638 result, err := s.kvStore.Get(StoreKeyCurrentSwapBatch.String())
639 if err != nil {
640 panic(err)
641 }
642
643 batch, ok := result.(*SwapBatchProcessor)
644 if !ok {
645 panic(ufmt.Sprintf("failed to cast result to *SwapBatchProcessor: %T", result))
646 }
647
648 return batch
649}
650
651func (s *stakerStore) SetCurrentSwapBatch(_ int, rlm realm, batch *SwapBatchProcessor) error {
652 if !rlm.IsCurrent() {
653 return ErrSpoofedRealm
654 }
655
656 return s.kvStore.Set(0, rlm, StoreKeyCurrentSwapBatch.String(), batch)
657}
658
659// ExternalIncentivesByCreationTime
660// key: timestamp -> value: *bptree.BPTree (poolPath -> []string)
661func (s *stakerStore) HasExternalIncentivesByCreationTimeStoreKey() bool {
662 return s.kvStore.Has(StoreKeyExternalIncentivesByCreationTime.String())
663}
664
665func (s *stakerStore) GetExternalIncentivesByCreationTime() *UintTree {
666 result, err := s.kvStore.Get(StoreKeyExternalIncentivesByCreationTime.String())
667 if err != nil {
668 panic(err)
669 }
670
671 tree, ok := result.(*UintTree)
672 if !ok {
673 panic(ufmt.Sprintf("failed to cast result to *UintTree: %T", result))
674 }
675
676 return tree
677}
678
679func (s *stakerStore) SetExternalIncentivesByCreationTime(_ int, rlm realm, tree *UintTree) error {
680 if !rlm.IsCurrent() {
681 return ErrSpoofedRealm
682 }
683
684 return s.kvStore.Set(0, rlm, StoreKeyExternalIncentivesByCreationTime.String(), tree)
685}
686
687// NewStakerStore creates a new staker store instance with the provided KV store.
688// This function is used by the upgrade system to create storage instances for each implementation.
689func NewStakerStore(kvStore store.KVStore) IStakerStore {
690 return &stakerStore{
691 kvStore: kvStore,
692 }
693}
694
695func uint64ToString(id uint64) string {
696 return strconv.FormatUint(id, 10)
697}
698
699func makeIncentiveID(creator address, timestamp int64, index int64) string {
700 return ufmt.Sprintf("%s:%d:%d", creator.String(), timestamp, index)
701}
702
703func contains(items []string, item string) bool {
704 for _, i := range items {
705 if i == item {
706 return true
707 }
708 }
709
710 return false
711}