factory_param.gno
3.71 Kb ยท 152 lines
1package v1
2
3import (
4 "strings"
5
6 u256 "gno.land/p/gnoswap/uint256"
7 "gno.land/p/nt/ufmt"
8 "gno.land/r/gnoswap/pool"
9)
10
11var Q192 = u256.Zero().Lsh(u256.One(), 192)
12
13var (
14 minSqrtRatio = u256.MustFromDecimal(MIN_SQRT_RATIO)
15 maxSqrtRatio = u256.MustFromDecimal(MAX_SQRT_RATIO)
16)
17
18const (
19 FeeTier100 uint32 = 100
20 FeeTier500 uint32 = 500
21 FeeTier3000 uint32 = 3000
22 FeeTier10000 uint32 = 10000
23)
24
25const (
26 GNOT_DENOM string = "ugnot"
27 WUGNOT_PATH string = "gno.land/r/gnoland/wugnot"
28)
29
30const (
31 MIN_SQRT_RATIO string = "4295128739"
32 MAX_SQRT_RATIO string = "1461446703485210103287273052203988822378723970342"
33)
34
35// poolCreateConfig holds the essential parameters for creating a new pool.
36type poolCreateConfig struct {
37 token0Path string
38 token1Path string
39 fee uint32
40 sqrtPriceX96 *u256.Uint
41 tickSpacing int32
42 slot0FeeProtocol uint8
43}
44
45// newPoolParams defines the essential parameters for creating a new pool.
46func newPoolParams(
47 token0Path string,
48 token1Path string,
49 fee uint32,
50 sqrtPriceX96 string,
51 tickSpacing int32,
52 slot0FeeProtocol uint8,
53) *poolCreateConfig {
54 price := u256.MustFromDecimal(sqrtPriceX96)
55 return &poolCreateConfig{
56 token0Path: token0Path,
57 token1Path: token1Path,
58 fee: fee,
59 sqrtPriceX96: price,
60 tickSpacing: tickSpacing,
61 slot0FeeProtocol: slot0FeeProtocol,
62 }
63}
64
65func (p *poolCreateConfig) SqrtPriceX96() *u256.Uint { return p.sqrtPriceX96 }
66func (p *poolCreateConfig) TickSpacing() int32 { return p.tickSpacing }
67func (p *poolCreateConfig) Token0Path() string { return p.token0Path }
68func (p *poolCreateConfig) Token1Path() string { return p.token1Path }
69func (p *poolCreateConfig) Fee() uint32 { return p.fee }
70
71func (p *poolCreateConfig) updateWithWrapping() error {
72 token0Path, token1Path := p.wrap()
73
74 // Always validate that the price is within valid range
75 if err := validateSqrtPriceX96(p.sqrtPriceX96); err != nil {
76 return err
77 }
78
79 if !p.isInOrder() {
80 token0Path, token1Path = token1Path, token0Path
81
82 // newPrice = 2^192 / oldPrice
83 newPrice := u256.Zero().Div(Q192, p.sqrtPriceX96)
84
85 // Check if calculated price is within valid range
86 if err := validateSqrtPriceX96(newPrice); err != nil {
87 return err
88 }
89
90 p.sqrtPriceX96 = newPrice
91 }
92
93 p.token0Path = token0Path
94 p.token1Path = token1Path
95
96 return nil
97}
98
99func (p *poolCreateConfig) isSameTokenPath() bool {
100 return p.token0Path == p.token1Path
101}
102
103// isInOrder checks if token paths are in lexicographical (or, alphabetical) order
104func (p *poolCreateConfig) isInOrder() bool {
105 if strings.Compare(p.token0Path, p.token1Path) < 0 {
106 return true
107 }
108 return false
109}
110
111func (p *poolCreateConfig) wrap() (string, string) {
112 if p.token0Path == GNOT_DENOM {
113 p.token0Path = WUGNOT_PATH
114 }
115 if p.token1Path == GNOT_DENOM {
116 p.token1Path = WUGNOT_PATH
117 }
118 return p.token0Path, p.token1Path
119}
120
121func (p *poolCreateConfig) poolPath() string {
122 return pool.GetPoolPath(p.token0Path, p.token1Path, p.fee)
123}
124
125func (p *poolCreateConfig) isSupportedFee(feeTier uint32) bool {
126 switch feeTier {
127 case FeeTier100, FeeTier500, FeeTier3000, FeeTier10000:
128 return true
129 }
130 return false
131}
132
133// validateSqrtPriceX96 validates that the given sqrtPriceX96 is within valid range
134func validateSqrtPriceX96(sqrtPriceX96 *u256.Uint) error {
135 // Valid range is [minSqrtRatio, maxSqrtRatio) - same as TickMathGetTickAtSqrtRatio
136 if sqrtPriceX96.Lt(minSqrtRatio) || sqrtPriceX96.Gte(maxSqrtRatio) {
137 return makeErrorWithDetails(
138 errOutOfRange,
139 ufmt.Sprintf("sqrtPriceX96(%s) is out of range", sqrtPriceX96.ToString()),
140 )
141 }
142 return nil
143}
144
145func isValidFeeTier(feeTier uint32) bool {
146 switch feeTier {
147 case FeeTier100, FeeTier500, FeeTier3000, FeeTier10000:
148 return true
149 }
150
151 return false
152}