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