Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}