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}