Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

init.gno

6.18 Kb · 242 lines
  1package staker
  2
  3import (
  4	"errors"
  5	"time"
  6
  7	"gno.land/r/gnoswap/emission"
  8
  9	sr "gno.land/r/gnoswap/staker"
 10)
 11
 12const (
 13	defaultDepositGnsAmount    = int64(1_000_000_000)
 14	defaultMinimumRewardAmount = int64(1_000_000_000)
 15
 16	// unstakingFee is the fee charged when unstaking positions.
 17	// This parameter can be modified through governance.
 18	defaultUnstakingFee = uint64(100) // 1%
 19
 20	defaultInitialPoolTierPath = "gno.land/r/gnoland/wugnot.wugnot:gno.land/r/gnoswap/gns.GNS:3000"
 21)
 22
 23func init(cur realm) {
 24	registerStakerV1(cur)
 25}
 26
 27func registerStakerV1(cur realm) {
 28	sr.RegisterInitializer(cross(cur), func(_ int, rlm realm, stakerStore sr.IStakerStore, poolAccessor sr.PoolAccessor, emissionAccessor sr.EmissionAccessor, nftAccessor sr.NFTAccessor) sr.IStaker {
 29		if !rlm.IsCurrent() {
 30			panic(errors.New(errSpoofedRealm))
 31		}
 32
 33		err := initStoreData(0, rlm, stakerStore, emissionAccessor)
 34		if err != nil {
 35			panic(err)
 36		}
 37
 38		instance := NewStakerV1(stakerStore, poolAccessor, emissionAccessor, nftAccessor)
 39		instance.setupSwapHooks(0, rlm)
 40		emissionAccessor.SetOnDistributionPctChangeCallback(0, rlm, instance.emissionCacheUpdateHook)
 41
 42		return instance
 43	})
 44}
 45
 46func initStoreData(_ int, rlm realm, stakerStore sr.IStakerStore, emissionAccessor sr.EmissionAccessor) error {
 47	if !stakerStore.HasDepositGnsAmountStoreKey() {
 48		err := stakerStore.SetDepositGnsAmount(0, rlm, defaultDepositGnsAmount)
 49		if err != nil {
 50			return err
 51		}
 52	}
 53
 54	if !stakerStore.HasMinimumRewardAmountStoreKey() {
 55		err := stakerStore.SetMinimumRewardAmount(0, rlm, defaultMinimumRewardAmount)
 56		if err != nil {
 57			return err
 58		}
 59	}
 60
 61	if !stakerStore.HasDepositsStoreKey() {
 62		err := stakerStore.SetDeposits(0, rlm, sr.NewBPTreeN(16))
 63		if err != nil {
 64			return err
 65		}
 66	}
 67
 68	if !stakerStore.HasExternalIncentivesStoreKey() {
 69		err := stakerStore.SetExternalIncentives(0, rlm, sr.NewBPTreeN(16))
 70		if err != nil {
 71			return err
 72		}
 73	}
 74
 75	if !stakerStore.HasTotalEmissionSentStoreKey() {
 76		err := stakerStore.SetTotalEmissionSent(0, rlm, 0)
 77		if err != nil {
 78			return err
 79		}
 80	}
 81
 82	if !stakerStore.HasAllowedTokensStoreKey() {
 83		// Copy the package-level default slice so each store owns its own
 84		// allowed-tokens slice. Storing sr.DefaultAllowedTokens directly would
 85		// alias the shared (sr-owned) slice across every store, leaking
 86		// mutations and tripping the readonly-taint gate on later writes.
 87		err := stakerStore.SetAllowedTokens(0, rlm, sr.DefaultAllowedTokens())
 88		if err != nil {
 89			return err
 90		}
 91	}
 92
 93	if !stakerStore.HasIncentiveCounterStoreKey() {
 94		err := stakerStore.SetIncentiveCounter(0, rlm, sr.NewCounter())
 95		if err != nil {
 96			return err
 97		}
 98	}
 99
100	if !stakerStore.HasTokenSpecificMinimumRewardsStoreKey() {
101		err := stakerStore.SetTokenSpecificMinimumRewards(0, rlm, make(map[string]int64))
102		if err != nil {
103			return err
104		}
105	}
106
107	if !stakerStore.HasUnstakingFeeStoreKey() {
108		err := stakerStore.SetUnstakingFee(0, rlm, defaultUnstakingFee)
109		if err != nil {
110			return err
111		}
112	}
113
114	if !stakerStore.HasPendingProtocolFeesStoreKey() {
115		err := stakerStore.SetPendingProtocolFees(0, rlm, make(map[string]int64))
116		if err != nil {
117			return err
118		}
119	}
120
121	if !stakerStore.HasWarmupTemplateStoreKey() {
122		err := stakerStore.SetWarmupTemplate(0, rlm, sr.DefaultWarmupTemplate())
123		if err != nil {
124			return err
125		}
126	}
127
128	if !stakerStore.HasExternalIncentivesByCreationTimeStoreKey() {
129		err := stakerStore.SetExternalIncentivesByCreationTime(0, rlm, sr.NewUintTree())
130		if err != nil {
131			return err
132		}
133	}
134
135	initializedPoolTier, initializedPools, initialPoolTierTime, initialTierRewards := initializePoolTier(stakerStore)
136
137	previousRealm := rlm.Previous()
138	emitSetPoolTier(
139		previousRealm.Address().String(),
140		previousRealm.PkgPath(),
141		defaultInitialPoolTierPath,
142		uint64(Tier1),
143		initializedPoolTier.currentEmission,
144		initialTierRewards,
145		initializedPoolTier.counts,
146		initialPoolTierTime,
147	)
148
149	if !stakerStore.HasPoolsStoreKey() {
150		err := stakerStore.SetPools(0, rlm, initializedPools.tree)
151		if err != nil {
152			return err
153		}
154	}
155
156	if !stakerStore.HasPoolTierMembershipsStoreKey() {
157		err := stakerStore.SetPoolTierMemberships(0, rlm, initializedPoolTier.membership)
158		if err != nil {
159			return err
160		}
161	}
162
163	if !stakerStore.HasPoolTierRatioStoreKey() {
164		err := stakerStore.SetPoolTierRatio(0, rlm, initializedPoolTier.tierRatio)
165		if err != nil {
166			return err
167		}
168	}
169
170	if !stakerStore.HasPoolTierCountsStoreKey() {
171		err := stakerStore.SetPoolTierCounts(0, rlm, initializedPoolTier.counts)
172		if err != nil {
173			return err
174		}
175	}
176
177	if !stakerStore.HasPoolTierLastRewardCacheTimestampStoreKey() {
178		err := stakerStore.SetPoolTierLastRewardCacheTimestamp(0, rlm, initializedPoolTier.lastRewardCacheTimestamp)
179		if err != nil {
180			return err
181		}
182	}
183
184	if !stakerStore.HasPoolTierCurrentEmissionStoreKey() {
185		err := stakerStore.SetPoolTierCurrentEmission(0, rlm, initializedPoolTier.currentEmission)
186		if err != nil {
187			return err
188		}
189	}
190
191	if !stakerStore.HasPoolTierGetEmissionStoreKey() {
192		getEmissionFn := func() int64 {
193			return emissionAccessor.GetStakerEmissionAmountPerSecond()
194		}
195
196		err := stakerStore.SetPoolTierGetEmission(0, rlm, getEmissionFn)
197		if err != nil {
198			return err
199		}
200	}
201
202	if !stakerStore.HasPoolTierGetHalvingBlocksInRangeStoreKey() {
203		getHalvingBlocksInRangeFn := func(start, end int64) ([]int64, []int64) {
204			return emissionAccessor.GetStakerEmissionAmountPerSecondInRange(start, end)
205		}
206
207		err := stakerStore.SetPoolTierGetHalvingBlocksInRange(0, rlm, getHalvingBlocksInRangeFn)
208		if err != nil {
209			return err
210		}
211	}
212
213	if !stakerStore.HasCurrentSwapBatchStoreKey() {
214		err := stakerStore.SetCurrentSwapBatch(0, rlm, nil)
215		if err != nil {
216			return err
217		}
218	}
219
220	return nil
221}
222
223func initializePoolTier(stakerStore sr.IStakerStore) (*PoolTier, *Pools, int64, map[uint64]int64) {
224	pools := NewPools()
225	currentTime := time.Now().Unix()
226
227	pl := NewPools().GetPoolOrNil(defaultInitialPoolTierPath)
228	if pl == nil {
229		pl = sr.NewPool(defaultInitialPoolTierPath, currentTime)
230		pools.set(defaultInitialPoolTierPath, pl)
231	}
232
233	poolTier := NewPoolTier(
234		pools,
235		currentTime,
236		defaultInitialPoolTierPath,
237		emission.GetStakerEmissionAmountPerSecond,
238		emission.GetStakerEmissionAmountPerSecondInRange,
239	)
240
241	return poolTier, pools, currentTime, poolTier.computeTierRewards(poolTier.currentEmission)
242}