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

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}