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

init.gno

4.16 Kb · 162 lines
  1package pool
  2
  3import (
  4	ufmt "gno.land/p/nt/ufmt/v0"
  5	"gno.land/r/gnoswap/access/v1"
  6	"gno.land/r/gnoswap/emission"
  7	"gno.land/r/gnoswap/pool"
  8)
  9
 10const (
 11	// slot0FeeProtocol is the protocol-fee denominator (0 or 4-10).
 12	// Zero disables protocol fees; 4 routes 1/4 of swap fees to the protocol.
 13	// This parameter can be modified through governance.
 14	defaultSlot0FeeProtocol = uint8(0)
 15
 16	// poolCreationFee is the fee that is charged when a user creates a pool.
 17	// The fee is denominated in GNS tokens.
 18	// This parameter can be modified through governance.
 19	defaultPoolCreationFee = int64(100_000_000) // 100_GNS
 20
 21	// withdrawalFeeBPS is the fee that is charged when a user withdraws their collected fees
 22	// The fee is denominated in BPS (Basis Points)
 23	// Example: 100 BPS = 1%
 24	// This parameter can be modified through governance.
 25	defaultWithdrawalFeeBPS = uint64(100)
 26
 27	defaultUnlocked = true
 28)
 29
 30func init(cur realm) {
 31	registerPoolV1(cur)
 32}
 33
 34func registerPoolV1(cur realm) {
 35	pool.RegisterInitializer(cross(cur), func(_ int, rlm realm, poolStore pool.IPoolStore) pool.IPool {
 36		access.AssertIsRlmCurrent(0, rlm)
 37
 38		err := initStoreData(0, rlm, poolStore)
 39		if err != nil {
 40			panic(err)
 41		}
 42
 43		emission.SetDefaultInitialPoolChecker(cross(rlm), func(poolPath string) bool {
 44			return pool.ExistsPoolPath(poolPath)
 45		})
 46
 47		return NewPoolV1(poolStore)
 48	})
 49}
 50
 51func initStoreData(_ int, rlm realm, poolStore pool.IPoolStore) error {
 52	if !poolStore.HasPools() {
 53		err := poolStore.SetPools(0, rlm, pool.NewPoolsTree())
 54		if err != nil {
 55			return err
 56		}
 57	}
 58
 59	if !poolStore.HasObservations() {
 60		err := poolStore.SetObservations(0, rlm, pool.NewObservationsTree())
 61		if err != nil {
 62			return err
 63		}
 64	}
 65
 66	if err := validatePoolObservations(poolStore); err != nil {
 67		return err
 68	}
 69
 70	if !poolStore.HasFeeAmountTickSpacing() {
 71		err := poolStore.SetFeeAmountTickSpacing(0, rlm, pool.NewDefaultFeeAmountTickSpacing())
 72		if err != nil {
 73			return err
 74		}
 75	}
 76
 77	if !poolStore.HasPoolCreationFee() {
 78		err := poolStore.SetPoolCreationFee(0, rlm, defaultPoolCreationFee)
 79		if err != nil {
 80			return err
 81		}
 82	}
 83
 84	pendingProtocolFees := make(map[string]int64)
 85	if poolStore.HasPendingProtocolFees() {
 86		pendingProtocolFees = poolStore.GetPendingProtocolFees()
 87	}
 88	if err := poolStore.SetPendingProtocolFees(0, rlm, pendingProtocolFees); err != nil {
 89		return err
 90	}
 91
 92	if !poolStore.HasSlot0FeeProtocol() {
 93		err := poolStore.SetSlot0FeeProtocol(0, rlm, defaultSlot0FeeProtocol)
 94		if err != nil {
 95			return err
 96		}
 97	}
 98
 99	if !poolStore.HasWithdrawalFeeBPS() {
100		err := poolStore.SetWithdrawalFeeBPS(0, rlm, defaultWithdrawalFeeBPS)
101		if err != nil {
102			return err
103		}
104	}
105
106	if !poolStore.HasUnlocked() {
107		err := poolStore.SetUnlocked(0, rlm, defaultUnlocked)
108		if err != nil {
109			return err
110		}
111	}
112
113	// Initialize swap start hook with no-op function
114	if !poolStore.HasSwapStartHook() {
115		noopSwapStart := func(cur realm, poolPath string, timestamp int64) {}
116		err := poolStore.SetSwapStartHook(0, rlm, noopSwapStart)
117		if err != nil {
118			return err
119		}
120	}
121
122	// Initialize swap end hook with no-op function
123	if !poolStore.HasSwapEndHook() {
124		noopSwapEnd := func(cur realm, poolPath string) error {
125			return nil
126		}
127		err := poolStore.SetSwapEndHook(0, rlm, noopSwapEnd)
128		if err != nil {
129			return err
130		}
131	}
132
133	// Initialize tick cross hook with no-op function
134	if !poolStore.HasTickCrossHook() {
135		noopTickCross := func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64) {}
136		err := poolStore.SetTickCrossHook(0, rlm, noopTickCross)
137		if err != nil {
138			return err
139		}
140	}
141
142	return nil
143}
144
145// validatePoolObservations ensures every persisted pool owns an observation tree.
146// CreatePool initializes the pair in one transaction; this check catches an
147// implementation or upgrade that would otherwise leave a pool unusable later.
148func validatePoolObservations(poolStore pool.IPoolStore) error {
149	pools := poolStore.GetPools()
150	observations := poolStore.GetObservations()
151
152	var validationErr error
153	pools.Iterate("", "", func(poolPath string, _ any) bool {
154		if !observations.Has(poolPath) {
155			validationErr = ufmt.Errorf("expected observations for poolPath(%s) to exist", poolPath)
156			return true
157		}
158		return false
159	})
160
161	return validationErr
162}