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