Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}