type.gno
6.32 Kb ยท 186 lines
1package v1
2
3import (
4 "time"
5
6 i256 "gno.land/p/gnoswap/int256"
7 u256 "gno.land/p/gnoswap/uint256"
8
9 "gno.land/r/gnoswap/common"
10 pl "gno.land/r/gnoswap/pool"
11)
12
13// ModifyPositionParams repersents the parameters for modifying a liquidity position.
14// This structure is used internally both `Mint` and `Burn` operation to manage
15// the liquidity positions.
16type ModifyPositionParams struct {
17 // owner is the address that owns the position
18 owner address
19
20 // tickLower and atickUpper define the price range
21 // The actual price range is calculated as 1.0001^tick
22 // This allows for precision in price range while using integer math.
23
24 tickLower int32 // lower tick of the position
25 tickUpper int32 // upper tick of the position
26
27 // liquidityDelta represents the change in liquidity
28 // Positive for minting, negative for burning
29 liquidityDelta *i256.Int
30}
31
32// newModifyPositionParams creates a new `ModifyPositionParams` instance.
33// This is used to preare parameters for the `modifyPosition` function,
34// which handles both minting and burning of liquidity positions.
35//
36// Parameters:
37// - owner: address that will own (or owns) the position
38// - tickLower: lower tick bound of the position
39// - tickUpper: upper tick bound of the position
40// - liquidityDelta: amount of liquidity to add (positive) or remove (negative)
41//
42// The tick parameters represent prices as powers of 1.0001:
43// - actual_price = 1.0001^tick
44// - For example, tick = 100 means price = 1.0001^100
45//
46// Returns:
47// - ModifyPositionParams: a new instance of ModifyPositionParams
48func newModifyPositionParams(
49 owner address,
50 tickLower int32,
51 tickUpper int32,
52 liquidityDelta *i256.Int,
53) ModifyPositionParams {
54 return ModifyPositionParams{
55 owner: owner,
56 tickLower: tickLower,
57 tickUpper: tickUpper,
58 liquidityDelta: liquidityDelta,
59 }
60}
61
62// SwapCache holds data that remains constant throughout a swap.
63type SwapCache struct {
64 feeProtocol uint8 // protocol fee for the input token
65 liquidityStart *u256.Uint // liquidity at the beginning of the swap
66 blockTimestamp int64 // current block timestamp
67 tickCumulative int64 // current tick accumulator value
68 secondsPerLiquidityCumulativeX128 *u256.Uint // current seconds per liquidity accumulator
69 computedLatestObservation bool // whether we've computed the above accumulators
70}
71
72func newSwapCache(
73 feeProtocol uint8,
74 liquidityStart *u256.Uint,
75) *SwapCache {
76 return &SwapCache{
77 feeProtocol: feeProtocol,
78 liquidityStart: liquidityStart,
79 blockTimestamp: time.Now().Unix(),
80 tickCumulative: 0,
81 secondsPerLiquidityCumulativeX128: u256.Zero(),
82 computedLatestObservation: false,
83 }
84}
85
86// SwapState tracks the changing values during a swap.
87// This type helps manage the state transitions that occur as the swap progresses
88// across different price ranges.
89type SwapState struct {
90 amountSpecifiedRemaining *i256.Int // amount remaining to be swapped in/out of the input/output token
91 amountCalculated *i256.Int // amount already swapped out/in of the output/input token
92 sqrtPriceX96 *u256.Uint // current sqrt(price)
93 tick int32 // tick associated with the current sqrt(price)
94 feeGrowthGlobalX128 *u256.Uint // global fee growth of the input token
95 protocolFee *u256.Uint // amount of input token paid as protocol fee
96 liquidity *u256.Uint // current liquidity in range
97}
98
99func newSwapState(
100 amountSpecifiedRemaining *i256.Int,
101 feeGrowthGlobalX128 *u256.Uint,
102 liquidity *u256.Uint,
103 slot0 pl.Slot0,
104) SwapState {
105 return SwapState{
106 amountSpecifiedRemaining: amountSpecifiedRemaining,
107 amountCalculated: i256.Zero(),
108 sqrtPriceX96: slot0.SqrtPriceX96(),
109 tick: slot0.Tick(),
110 feeGrowthGlobalX128: feeGrowthGlobalX128,
111 protocolFee: u256.Zero(),
112 liquidity: liquidity,
113 }
114}
115
116func (s *SwapState) setSqrtPriceX96(sqrtPriceX96 *u256.Uint) {
117 s.sqrtPriceX96 = sqrtPriceX96.Clone()
118}
119
120func (s *SwapState) setTick(tick int32) {
121 s.tick = tick
122}
123
124func (s *SwapState) setFeeGrowthGlobalX128(feeGrowthGlobalX128 *u256.Uint) {
125 s.feeGrowthGlobalX128 = feeGrowthGlobalX128
126}
127
128func (s *SwapState) setProtocolFee(fee *u256.Uint) {
129 s.protocolFee = fee
130}
131
132// StepComputations holds intermediate values used during a single step of a swap.
133// Each step represents movement from the current tick to the next initialized tick
134// or the target price, whichever comes first.
135type StepComputations struct {
136 sqrtPriceStartX96 *u256.Uint // price at the beginning of the step
137 tickNext int32 // next tick to swap to from the current tick in the swap direction
138 initialized bool // whether tickNext is initialized
139 sqrtPriceNextX96 *u256.Uint // sqrt(price) for the next tick (token1/token0) Q96
140 amountIn *u256.Uint // how much being swapped in this step
141 amountOut *u256.Uint // how much is being swapped out in this step
142 feeAmount *u256.Uint // how much fee is being paid in this step
143}
144
145// init initializes the computation for a single swap step
146func (step *StepComputations) initSwapStep(state SwapState, p *pl.Pool, zeroForOne bool) {
147 step.sqrtPriceStartX96 = state.sqrtPriceX96
148 step.tickNext, step.initialized = tickBitmapNextInitializedTickWithInOneWord(
149 p,
150 state.tick,
151 p.TickSpacing(),
152 zeroForOne,
153 )
154
155 // prevent overshoot the min/max tick
156 step.clampTickNext()
157
158 // get the price for the next tick
159 step.sqrtPriceNextX96 = common.TickMathGetSqrtRatioAtTick(step.tickNext)
160}
161
162// clampTickNext ensures that `tickNext` stays within the min, max tick boundaries
163// as the tick bitmap is not aware of these bounds
164func (step *StepComputations) clampTickNext() {
165 if step.tickNext < MIN_TICK {
166 step.tickNext = MIN_TICK
167 } else if step.tickNext > MAX_TICK {
168 step.tickNext = MAX_TICK
169 }
170}
171
172func newPool(poolInfo *poolCreateConfig) *pl.Pool {
173 maxLiquidityPerTick := calculateMaxLiquidityPerTick(poolInfo.tickSpacing)
174 tick := common.TickMathGetTickAtSqrtRatio(poolInfo.SqrtPriceX96())
175
176 return pl.NewPool(
177 poolInfo.Token0Path(),
178 poolInfo.Token1Path(),
179 poolInfo.Fee(),
180 poolInfo.SqrtPriceX96(),
181 poolInfo.TickSpacing(),
182 tick,
183 poolInfo.slot0FeeProtocol,
184 maxLiquidityPerTick,
185 )
186}