Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

pool.gno

33.54 Kb · 998 lines
  1package pool
  2
  3import (
  4	bptree "gno.land/p/nt/bptree/v0"
  5	ufmt "gno.land/p/nt/ufmt/v0"
  6
  7	u256 "gno.land/p/gnoswap/uint256/v1"
  8)
  9
 10// Pool describes a single pool's state.
 11// A pool is identified with a unique key (token0, token1, fee), where token0 < token1.
 12type Pool struct {
 13	// token0/token1 path of the pool
 14	token0Path           string
 15	token1Path           string
 16	fee                  uint32 // fee tier of the pool
 17	tickSpacing          int32  // spacing between ticks
 18	slot0                Slot0
 19	balances             TokenPair // balances of the pool
 20	protocolFees         TokenPair
 21	feeGrowthGlobal0X128 *u256.Uint       // uint256
 22	feeGrowthGlobal1X128 *u256.Uint       // uint256
 23	liquidity            *u256.Uint       // total amount of active liquidity in the pool (within current tick range)
 24	ticks                *bptree.BPTree   // tick(int32) -> TickInfo
 25	tickBitmaps          map[int16]string // tick(wordPos)(int16) -> bitMap(tickWord ^ mask)(string)
 26	positions            *bptree.BPTree   // maps encoded lower/upper tick pairs to aggregate pool accounting
 27}
 28
 29// Pool Getters methods
 30// PoolPath returns the canonical pool path derived from token0, token1, and the fee tier.
 31//
 32// Returns:
 33//   - string: pool identifier assembled from the pool's token paths and fee.
 34func (p *Pool) PoolPath() string { return GetPoolPath(p.token0Path, p.token1Path, p.fee) }
 35
 36// Token0Path returns the path of the pool's token0 asset.
 37//
 38// Returns:
 39//   - string: token0 path stored in the pool.
 40func (p *Pool) Token0Path() string { return p.token0Path }
 41
 42// Token1Path returns the path of the pool's token1 asset.
 43//
 44// Returns:
 45//   - string: token1 path stored in the pool.
 46func (p *Pool) Token1Path() string { return p.token1Path }
 47
 48// Fee returns the pool's fee tier.
 49//
 50// Returns:
 51//   - uint32: fee tier used by swaps in this pool.
 52func (p *Pool) Fee() uint32 { return p.fee }
 53
 54// Balances returns the pool's current token balances.
 55//
 56// Returns:
 57//   - TokenPair: token0 and token1 balances tracked by the pool.
 58func (p *Pool) Balances() TokenPair { return p.balances }
 59
 60// BalanceToken0 returns the pool's current token0 balance.
 61//
 62// Returns:
 63//   - int64: token0 balance available in the pool.
 64func (p *Pool) BalanceToken0() int64 { return p.balances.token0 }
 65
 66// BalanceToken1 returns the pool's current token1 balance.
 67//
 68// Returns:
 69//   - int64: token1 balance available in the pool.
 70func (p *Pool) BalanceToken1() int64 { return p.balances.token1 }
 71
 72// TickSpacing returns the permitted spacing between initialized ticks.
 73//
 74// Returns:
 75//   - int32: tick spacing configured for the pool.
 76func (p *Pool) TickSpacing() int32 { return p.tickSpacing }
 77
 78// Slot0 returns the pool's current price, tick, lock, and oracle cursor state.
 79//
 80// Returns:
 81//   - Slot0: current slot0 state, including the price and observation metadata.
 82func (p *Pool) Slot0() Slot0 { return p.slot0 }
 83
 84// Slot0SqrtPriceX96 returns the current square-root price in Q96 fixed-point form.
 85//
 86// Returns:
 87//   - *u256.Uint: stored sqrt(token1/token0) price scaled by 2^96.
 88func (p *Pool) Slot0SqrtPriceX96() *u256.Uint { return p.slot0.sqrtPriceX96 }
 89
 90// Slot0Tick returns the current pool tick.
 91//
 92// Returns:
 93//   - int32: tick corresponding to the current pool price.
 94func (p *Pool) Slot0Tick() int32 { return p.slot0.tick }
 95
 96// Slot0FeeProtocol returns the packed protocol-fee denominators from slot0.
 97//
 98// Returns:
 99//   - uint8: packed token0/token1 protocol-fee denominator configuration.
100func (p *Pool) Slot0FeeProtocol() uint8 { return p.slot0.feeProtocol }
101
102// Slot0Unlocked reports whether the pool is currently available for reentrant operations.
103//
104// Returns:
105//   - bool: true when the pool is unlocked; false while its swap lock is held.
106func (p *Pool) Slot0Unlocked() bool { return p.slot0.unlocked }
107
108// FeeGrowthGlobal0X128 returns cumulative token0 fee growth per unit of liquidity.
109//
110// Returns:
111//   - *u256.Uint: token0 fee-growth accumulator scaled by 2^128.
112func (p *Pool) FeeGrowthGlobal0X128() *u256.Uint { return p.feeGrowthGlobal0X128 }
113
114// FeeGrowthGlobal1X128 returns cumulative token1 fee growth per unit of liquidity.
115//
116// Returns:
117//   - *u256.Uint: token1 fee-growth accumulator scaled by 2^128.
118func (p *Pool) FeeGrowthGlobal1X128() *u256.Uint { return p.feeGrowthGlobal1X128 }
119
120// ProtocolFees returns protocol fees accrued in both pool tokens.
121//
122// Returns:
123//   - TokenPair: token0 and token1 protocol-fee balances.
124func (p *Pool) ProtocolFees() TokenPair { return p.protocolFees }
125
126// ProtocolFeesToken0 returns protocol fees accrued in token0.
127//
128// Returns:
129//   - int64: token0 amount reserved as protocol fees.
130func (p *Pool) ProtocolFeesToken0() int64 { return p.protocolFees.token0 }
131
132// ProtocolFeesToken1 returns protocol fees accrued in token1.
133//
134// Returns:
135//   - int64: token1 amount reserved as protocol fees.
136func (p *Pool) ProtocolFeesToken1() int64 { return p.protocolFees.token1 }
137
138// Liquidity returns the pool's active liquidity for the current tick range.
139//
140// Returns:
141//   - *u256.Uint: active liquidity amount.
142func (p *Pool) Liquidity() *u256.Uint { return p.liquidity }
143
144// Ticks returns the tree containing tick state keyed by encoded tick.
145//
146// Returns:
147//   - *bptree.BPTree: pool tick storage tree.
148func (p *Pool) Ticks() *bptree.BPTree { return p.ticks }
149
150// TickBitmaps returns the map of initialized-tick bitmap words.
151//
152// Returns:
153//   - map[int16]string: bitmap words keyed by signed word position.
154func (p *Pool) TickBitmaps() map[int16]string { return p.tickBitmaps }
155
156// Positions returns the tree containing aggregate position state by range key.
157//
158// Returns:
159//   - *bptree.BPTree: pool position storage tree.
160func (p *Pool) Positions() *bptree.BPTree { return p.positions }
161
162// GetPosition returns the position information for key.
163//
164// Parameters:
165//   - key: encoded lower/upper tick-range key to look up.
166//
167// Returns:
168//   - PositionInfo: stored aggregate position for the key.
169//   - error: non-nil when the key is absent or contains a value of the wrong type.
170func (p *Pool) GetPosition(key string) (PositionInfo, error) {
171	iPositionInfo := p.positions.Get(key)
172	if iPositionInfo == nil {
173		return PositionInfo{}, ufmt.Errorf("position %s not found", key)
174	}
175
176	positionInfo, ok := iPositionInfo.(PositionInfo)
177	if !ok {
178		return PositionInfo{}, ufmt.Errorf("position %s has invalid type", key)
179	}
180
181	return positionInfo, nil
182}
183
184// Pool Setters methods
185// SetToken0Path stores the path of the pool's token0 asset.
186//
187// Parameters:
188//   - token0Path: token0 asset path to store.
189func (p *Pool) SetToken0Path(token0Path string) {
190	p.token0Path = token0Path
191}
192
193// SetToken1Path stores the path of the pool's token1 asset.
194//
195// Parameters:
196//   - token1Path: token1 asset path to store.
197func (p *Pool) SetToken1Path(token1Path string) {
198	p.token1Path = token1Path
199}
200
201// SetFee stores the pool's fee tier.
202//
203// Parameters:
204//   - fee: fee tier to use for swaps in this pool.
205func (p *Pool) SetFee(fee uint32) {
206	p.fee = fee
207}
208
209// SetBalances replaces the pool's tracked balances for both tokens.
210//
211// Parameters:
212//   - balances: token0 and token1 balances to store.
213func (p *Pool) SetBalances(balances TokenPair) {
214	p.balances = balances
215}
216
217// SetBalanceToken0 updates the pool's tracked token0 balance.
218//
219// Parameters:
220//   - token0: new token0 balance.
221func (p *Pool) SetBalanceToken0(token0 int64) {
222	p.balances.token0 = token0
223}
224
225// SetBalanceToken1 updates the pool's tracked token1 balance.
226//
227// Parameters:
228//   - token1: new token1 balance.
229func (p *Pool) SetBalanceToken1(token1 int64) {
230	p.balances.token1 = token1
231}
232
233// SetTickSpacing stores the permitted spacing between initialized ticks.
234//
235// Parameters:
236//   - tickSpacing: tick spacing to configure for the pool.
237func (p *Pool) SetTickSpacing(tickSpacing int32) {
238	p.tickSpacing = tickSpacing
239}
240
241// SetSlot0 replaces the pool's current price, tick, lock, and oracle cursor state.
242//
243// Parameters:
244//   - slot0: slot0 state to store.
245func (p *Pool) SetSlot0(slot0 Slot0) {
246	p.slot0 = slot0
247}
248
249// SetFeeGrowthGlobal0X128 stores the token0 fee-growth accumulator.
250//
251// Parameters:
252//   - feeGrowthGlobal0X128: token0 fee growth per liquidity unit, scaled by 2^128.
253func (p *Pool) SetFeeGrowthGlobal0X128(feeGrowthGlobal0X128 *u256.Uint) {
254	p.feeGrowthGlobal0X128 = u256.Zero().Set(feeGrowthGlobal0X128)
255}
256
257// SetFeeGrowthGlobal1X128 stores the token1 fee-growth accumulator.
258//
259// Parameters:
260//   - feeGrowthGlobal1X128: token1 fee growth per liquidity unit, scaled by 2^128.
261func (p *Pool) SetFeeGrowthGlobal1X128(feeGrowthGlobal1X128 *u256.Uint) {
262	p.feeGrowthGlobal1X128 = u256.Zero().Set(feeGrowthGlobal1X128)
263}
264
265// SetProtocolFees replaces the pool's accrued protocol fees for both tokens.
266//
267// Parameters:
268//   - protocolFees: token0 and token1 protocol-fee balances to store.
269func (p *Pool) SetProtocolFees(protocolFees TokenPair) {
270	p.protocolFees = protocolFees
271}
272
273// SetProtocolFeesToken0 updates the pool's accrued token0 protocol fees.
274//
275// Parameters:
276//   - token0: new token0 protocol-fee balance.
277func (p *Pool) SetProtocolFeesToken0(token0 int64) {
278	p.protocolFees.token0 = token0
279}
280
281// SetProtocolFeesToken1 updates the pool's accrued token1 protocol fees.
282//
283// Parameters:
284//   - token1: new token1 protocol-fee balance.
285func (p *Pool) SetProtocolFeesToken1(token1 int64) {
286	p.protocolFees.token1 = token1
287}
288
289// SetLiquidity stores the pool's active liquidity for the current tick range.
290//
291// Parameters:
292//   - liquidity: active liquidity amount to store.
293func (p *Pool) SetLiquidity(liquidity *u256.Uint) {
294	p.liquidity = u256.Zero().Set(liquidity)
295}
296
297// SetTicks replaces the tree containing pool tick state.
298//
299// Parameters:
300//   - ticks: tick storage tree to use.
301func (p *Pool) SetTicks(ticks *bptree.BPTree) {
302	p.ticks = ticks
303}
304
305// SetTickBitmap stores one initialized-tick bitmap word.
306//
307// Parameters:
308//   - wordPos: signed bitmap word position.
309//   - tickBitmap: encoded bitmap bits for that word.
310func (p *Pool) SetTickBitmap(wordPos int16, tickBitmap string) {
311	p.tickBitmaps[wordPos] = tickBitmap
312}
313
314// DeleteTickBitmap deletes the tick bitmap for the given word position.
315//
316// Parameters:
317//   - wordPos: signed bitmap word position to remove.
318func (p *Pool) DeleteTickBitmap(wordPos int16) {
319	delete(p.tickBitmaps, wordPos)
320}
321
322// SetTickBitmaps replaces the map of initialized-tick bitmap words.
323//
324// Parameters:
325//   - tickBitmaps: bitmap words keyed by signed word position.
326func (p *Pool) SetTickBitmaps(tickBitmaps map[int16]string) {
327	p.tickBitmaps = tickBitmaps
328}
329
330// SetPositions replaces the tree containing aggregate position state.
331//
332// Parameters:
333//   - positions: position storage tree to use.
334func (p *Pool) SetPositions(positions *bptree.BPTree) {
335	p.positions = positions
336}
337
338// SetPosition stores position information under an encoded range key.
339//
340// Parameters:
341//   - posKey: encoded lower/upper tick-range key.
342//   - positionInfo: aggregate position state to store.
343func (p *Pool) SetPosition(posKey string, positionInfo PositionInfo) {
344	p.positions.Set(posKey, positionInfo)
345}
346
347// HasTick reports whether a tick entry exists in the pool's tick tree.
348//
349// Parameters:
350//   - tick: tick index to check.
351//
352// Returns:
353//   - bool: true when the encoded tick is present; false otherwise.
354func (p *Pool) HasTick(tick int32) bool {
355	tickKey := EncodeTickKey(tick)
356	return p.ticks.Has(tickKey)
357}
358
359// GetTick returns the state stored for a tick.
360//
361// Parameters:
362//   - tick: tick index to look up.
363//
364// Returns:
365//   - TickInfo: stored tick state.
366//   - error: non-nil when the tick is absent; a present value of the wrong type causes a panic.
367func (p *Pool) GetTick(tick int32) (TickInfo, error) {
368	tickKey := EncodeTickKey(tick)
369
370	iTickInfo := p.ticks.Get(tickKey)
371	if iTickInfo == nil {
372		return TickInfo{}, ufmt.Errorf("tick %d not found", tick)
373	}
374
375	tickInfo, ok := iTickInfo.(TickInfo)
376	if !ok {
377		panic(ufmt.Sprintf("failed to cast tickInfo to TickInfo: %T", iTickInfo))
378	}
379
380	return tickInfo, nil
381}
382
383// SetTick stores tick state under its encoded tick key.
384//
385// Parameters:
386//   - tick: tick index to store.
387//   - tickInfo: tick state associated with the index.
388func (p *Pool) SetTick(tick int32, tickInfo TickInfo) {
389	tickKey := EncodeTickKey(tick)
390	p.ticks.Set(tickKey, tickInfo)
391}
392
393// DeleteTick removes the tick state for the given tick index.
394//
395// Parameters:
396//   - tick: tick index to remove.
397func (p *Pool) DeleteTick(tick int32) {
398	tickKey := EncodeTickKey(tick)
399	p.ticks.Remove(tickKey)
400}
401
402// IterateTicks visits pool ticks in the inclusive range [startTick, endTick].
403// Iteration stops when the callback returns true.
404//
405// Parameters:
406//   - startTick: first tick index in the inclusive range.
407//   - endTick: last tick index in the inclusive range.
408//   - fn: callback receiving each decoded tick and its state; return true to stop iteration.
409func (p *Pool) IterateTicks(startTick int32, endTick int32, fn func(tick int32, tickInfo TickInfo) bool) {
410	startTickKey := EncodeTickKey(startTick)
411	endTickKey := EncodeTickKey(endTick + 1) // endTick inclusive
412
413	p.ticks.Iterate(startTickKey, endTickKey, func(key string, value any) bool {
414		tick := DecodeTickKey(key)
415
416		tickInfo, ok := value.(TickInfo)
417		if !ok {
418			return false
419		}
420
421		return fn(tick, tickInfo)
422	})
423}
424
425// Clone copies a pool's own fields and leaves its collections nil: ticks,
426// tickBitmaps, and positions are not copied. Oracle observations are stored
427// separately from Pool.
428//
429// The copy is shallow because the read-only pool view clones every entry a
430// caller reads, so copying the collections would walk the whole tick tree for
431// each entry on a page. Read them through their own lookups instead:
432// GetTickInfo / GetInitializedTicksInRange for ticks, GetTickBitmaps for the
433// bitmaps, GetPoolPositions for positions, and GetSlot0 / GetObservationAt for
434// oracle metadata and entries. A caller that needs a working copy of a
435// collection -- DrySwap is the only one -- assembles it from those getters.
436//
437// Returns:
438//   - *Pool: shallow pool copy with scalar state and cloned numeric values; nil when the receiver is nil.
439func (p *Pool) Clone() *Pool {
440	if p == nil {
441		return nil
442	}
443
444	return &Pool{
445		token0Path:           p.token0Path,
446		token1Path:           p.token1Path,
447		fee:                  p.fee,
448		tickSpacing:          p.tickSpacing,
449		slot0:                p.slot0.Clone(),
450		balances:             p.balances,
451		protocolFees:         p.protocolFees,
452		feeGrowthGlobal0X128: p.feeGrowthGlobal0X128.Clone(),
453		feeGrowthGlobal1X128: p.feeGrowthGlobal1X128.Clone(),
454		liquidity:            p.liquidity.Clone(),
455		ticks:                nil,
456		tickBitmaps:          nil,
457		positions:            nil,
458	}
459}
460
461// NewPool constructs a pool with the supplied token pair, fee, price, and tick configuration.
462//
463// Parameters:
464//   - token0Path: path of the pool's token0 asset.
465//   - token1Path: path of the pool's token1 asset.
466//   - fee: fee tier used by swaps.
467//   - sqrtPriceX96: initial sqrt(token1/token0) price scaled by 2^96.
468//   - tickSpacing: spacing between initialized ticks.
469//   - tick: initial current tick.
470//   - slot0FeeProtocol: packed protocol-fee denominator configuration for slot0.
471//
472// Returns:
473//   - *Pool: initialized pool with empty balances, fee growth, ticks, bitmaps, and positions.
474func NewPool(
475	token0Path string,
476	token1Path string,
477	fee uint32,
478	sqrtPriceX96 *u256.Uint,
479	tickSpacing int32,
480	tick int32,
481	slot0FeeProtocol uint8,
482) *Pool {
483	slot0 := NewSlot0(sqrtPriceX96, tick, slot0FeeProtocol, true)
484
485	return &Pool{
486		token0Path:           token0Path,
487		token1Path:           token1Path,
488		balances:             NewTokenPair(),
489		fee:                  fee,
490		tickSpacing:          tickSpacing,
491		slot0:                slot0,
492		feeGrowthGlobal0X128: u256.Zero(),
493		feeGrowthGlobal1X128: u256.Zero(),
494		protocolFees:         NewTokenPair(),
495		liquidity:            u256.Zero(),
496		ticks:                bptree.NewBPTreeN(32),
497		tickBitmaps:          make(map[int16]string),
498		positions:            bptree.NewBPTreeN(16),
499	}
500}
501
502// NewPoolsTree creates the BPTree used to store pools by pool path.
503//
504// Returns:
505//   - *bptree.BPTree: empty pool storage tree with fanout 32.
506func NewPoolsTree() *bptree.BPTree {
507	return bptree.NewBPTreeN(32)
508}
509
510// NewPoolTicksTree creates a BPTree for storing pool tick info (fanout 32),
511// owned by the pool domain realm so leaf-slot writes are not readonly tainted.
512//
513// Returns:
514//   - *bptree.BPTree: empty tick storage tree with fanout 32.
515func NewPoolTicksTree() *bptree.BPTree {
516	return bptree.NewBPTreeN(32)
517}
518
519// NewPoolPositionsTree creates a BPTree for storing pool position info (fanout 16),
520// owned by the pool domain realm so leaf-slot writes are not readonly tainted.
521//
522// Returns:
523//   - *bptree.BPTree: empty position storage tree with fanout 16.
524func NewPoolPositionsTree() *bptree.BPTree {
525	return bptree.NewBPTreeN(16)
526}
527
528type TokenPair struct {
529	token0, token1 int64
530}
531
532// NewTokenPair creates a token-pair balance value initialized to zero.
533//
534// Returns:
535//   - TokenPair: zero token0 and token1 balances.
536func NewTokenPair() TokenPair {
537	return TokenPair{
538		token0: 0,
539		token1: 0,
540	}
541}
542
543// Token0 returns the token0 amount in the pair.
544//
545// Returns:
546//   - int64: stored token0 amount.
547func (p *TokenPair) Token0() int64 { return p.token0 }
548
549// Token1 returns the token1 amount in the pair.
550//
551// Returns:
552//   - int64: stored token1 amount.
553func (p *TokenPair) Token1() int64 { return p.token1 }
554
555// SetToken0 updates the token0 amount in the pair.
556//
557// Parameters:
558//   - token0: token0 amount to store.
559func (p *TokenPair) SetToken0(token0 int64) { p.token0 = token0 }
560
561// SetToken1 updates the token1 amount in the pair.
562//
563// Parameters:
564//   - token1: token1 amount to store.
565func (p *TokenPair) SetToken1(token1 int64) { p.token1 = token1 }
566
567// Slot0 mirrors Uniswap V3's slot0(): current price/tick/protocol-fee/lock
568// state and the oracle cursor/capacity metadata.
569type Slot0 struct {
570	sqrtPriceX96               *u256.Uint // current price of the pool as a sqrt(token1/token0) Q96 value
571	tick                       int32      // current tick of the pool, i.e according to the last tick transition that was run
572	feeProtocol                uint8      // packed protocol-fee denominators: token0 low nibble, token1 high nibble
573	unlocked                   bool       // whether the pool is currently locked to reentrancy
574	observationIndex           uint16     // the index of the most-recently written observation
575	observationCardinality     uint16     // the current maximum number of observations stored
576	observationCardinalityNext uint16     // the next maximum number of observations to store
577}
578
579// SqrtPriceX96 returns a copy of the current sqrt price in Q96 fixed-point form.
580//
581// Returns:
582//   - *u256.Uint: cloned sqrt(token1/token0) price scaled by 2^96.
583func (s *Slot0) SqrtPriceX96() *u256.Uint { return s.sqrtPriceX96.Clone() }
584
585// Tick returns the current pool tick recorded in slot0.
586//
587// Returns:
588//   - int32: current tick.
589func (s *Slot0) Tick() int32 { return s.tick }
590
591// FeeProtocol returns the packed protocol-fee denominators in slot0.
592//
593// Returns:
594//   - uint8: packed token0/token1 protocol-fee denominator configuration.
595func (s *Slot0) FeeProtocol() uint8 { return s.feeProtocol }
596
597// Unlocked reports whether the pool's reentrancy lock is open.
598//
599// Returns:
600//   - bool: true when unlocked and false while the pool is locked.
601func (s *Slot0) Unlocked() bool { return s.unlocked }
602
603// ObservationIndex returns the index of the most recently written observation.
604//
605// Returns:
606//   - uint16: current observation ring-buffer index.
607func (s *Slot0) ObservationIndex() uint16 { return s.observationIndex }
608
609// ObservationCardinality returns the number of observation slots currently available.
610//
611// Returns:
612//   - uint16: current observation capacity.
613func (s *Slot0) ObservationCardinality() uint16 { return s.observationCardinality }
614
615// ObservationCardinalityNext returns the requested future observation capacity.
616//
617// Returns:
618//   - uint16: next observation capacity to use when the ring grows.
619func (s *Slot0) ObservationCardinalityNext() uint16 { return s.observationCardinalityNext }
620
621// Clone returns a value-type copy of Slot0 that shares no mutable state with
622// the original, so callers cannot reach back into pool internals through the
623// returned sqrtPriceX96 pointer.
624//
625// Returns:
626//   - Slot0: value copy with a cloned sqrt-price pointer.
627func (s *Slot0) Clone() Slot0 {
628	return Slot0{
629		sqrtPriceX96:               s.sqrtPriceX96.Clone(),
630		tick:                       s.tick,
631		feeProtocol:                s.feeProtocol,
632		unlocked:                   s.unlocked,
633		observationIndex:           s.observationIndex,
634		observationCardinality:     s.observationCardinality,
635		observationCardinalityNext: s.observationCardinalityNext,
636	}
637}
638
639// SetSqrtPriceX96 updates the slot0 sqrt price.
640//
641// Parameters:
642//   - sqrtPriceX96: sqrt(token1/token0) price scaled by 2^96; it is cloned before storage.
643func (s *Slot0) SetSqrtPriceX96(sqrtPriceX96 *u256.Uint) { s.sqrtPriceX96 = sqrtPriceX96.Clone() }
644
645// SetTick updates the current slot0 tick.
646//
647// Parameters:
648//   - tick: current pool tick to store.
649func (s *Slot0) SetTick(tick int32) { s.tick = tick }
650
651// SetFeeProtocol updates the packed slot0 protocol-fee denominators.
652//
653// Parameters:
654//   - feeProtocol: packed token0/token1 protocol-fee denominator configuration.
655func (s *Slot0) SetFeeProtocol(feeProtocol uint8) { s.feeProtocol = feeProtocol }
656
657// SetUnlocked updates the slot0 reentrancy-lock state.
658//
659// Parameters:
660//   - unlocked: true to mark the pool unlocked, false to mark it locked.
661func (s *Slot0) SetUnlocked(unlocked bool) { s.unlocked = unlocked }
662
663// SetObservationIndex updates the index of the most recently written observation.
664//
665// Parameters:
666//   - observationIndex: observation ring-buffer index to store.
667func (s *Slot0) SetObservationIndex(observationIndex uint16) {
668	s.observationIndex = observationIndex
669}
670
671// SetObservationCardinality updates the current observation capacity.
672//
673// Parameters:
674//   - observationCardinality: current number of observation slots available.
675func (s *Slot0) SetObservationCardinality(observationCardinality uint16) {
676	s.observationCardinality = observationCardinality
677}
678
679// SetObservationCardinalityNext updates the requested future observation capacity.
680//
681// Parameters:
682//   - observationCardinalityNext: next capacity to use when the ring grows.
683func (s *Slot0) SetObservationCardinalityNext(observationCardinalityNext uint16) {
684	s.observationCardinalityNext = observationCardinalityNext
685}
686
687// NewSlot0 constructs slot0 with the supplied price, tick, protocol fee, and lock state.
688// Observation metadata starts with index zero and cardinality one.
689//
690// Parameters:
691//   - sqrtPriceX96: initial sqrt(token1/token0) price scaled by 2^96.
692//   - tick: initial current pool tick.
693//   - feeProtocol: packed token0/token1 protocol-fee denominator configuration.
694//   - unlocked: initial reentrancy-lock state.
695//
696// Returns:
697//   - Slot0: initialized slot0 value with one observation slot.
698func NewSlot0(
699	sqrtPriceX96 *u256.Uint,
700	tick int32,
701	feeProtocol uint8,
702	unlocked bool,
703) Slot0 {
704	return Slot0{
705		sqrtPriceX96:               sqrtPriceX96.Clone(),
706		tick:                       tick,
707		feeProtocol:                feeProtocol,
708		unlocked:                   unlocked,
709		observationIndex:           0,
710		observationCardinality:     1,
711		observationCardinalityNext: 1,
712	}
713}
714
715// TickInfo stores information about a specific tick in the pool.
716// TIcks represent discrete price points that can be used as boundaries for positions.
717type TickInfo struct {
718	liquidityGross string // total position liquidity that references this tick
719	liquidityNet   string // amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left)
720
721	// fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
722	// only has relative meaning, not absolute — the value depends on when the tick is initialized
723	feeGrowthOutside0X128 string
724	feeGrowthOutside1X128 string
725
726	tickCumulativeOutside int64 // cumulative tick value on the other side of the tick
727
728	// the seconds per unit of liquidity on the _other_ side of this tick (relative to the current tick)
729	// only has relative meaning, not absolute — the value depends on when the tick is initialized
730	secondsPerLiquidityOutsideX128 string
731
732	// the seconds spent on the other side of the tick (relative to the current tick)
733	// only has relative meaning, not absolute — the value depends on when the tick is initialized
734	secondsOutside uint32
735
736	initialized bool // whether the tick is initialized
737}
738
739// TickInfo Getters methods
740// LiquidityGross returns total position liquidity referencing this tick.
741//
742// Returns:
743//   - string: gross liquidity encoded as a decimal string.
744func (t *TickInfo) LiquidityGross() string { return t.liquidityGross }
745
746// LiquidityNet returns net liquidity applied when this tick is crossed.
747//
748// Returns:
749//   - string: signed net liquidity encoded as a decimal string.
750func (t *TickInfo) LiquidityNet() string { return t.liquidityNet }
751
752// FeeGrowthOutside0X128 returns token0 fee growth on the side of this tick opposite the current tick.
753//
754// Returns:
755//   - string: token0 outside fee-growth accumulator scaled by 2^128.
756func (t *TickInfo) FeeGrowthOutside0X128() string { return t.feeGrowthOutside0X128 }
757
758// FeeGrowthOutside1X128 returns token1 fee growth on the side of this tick opposite the current tick.
759//
760// Returns:
761//   - string: token1 outside fee-growth accumulator scaled by 2^128.
762func (t *TickInfo) FeeGrowthOutside1X128() string { return t.feeGrowthOutside1X128 }
763
764// SecondsPerLiquidityOutsideX128 returns seconds per liquidity outside this tick.
765//
766// Returns:
767//   - string: outside seconds-per-liquidity accumulator scaled by 2^128.
768func (t *TickInfo) SecondsPerLiquidityOutsideX128() string {
769	return t.secondsPerLiquidityOutsideX128
770}
771
772// SecondsOutside returns the time spent on the side of this tick opposite the current tick.
773//
774// Returns:
775//   - uint32: seconds accumulated outside the tick.
776func (t *TickInfo) SecondsOutside() uint32 { return t.secondsOutside }
777
778// Initialized reports whether this tick has active initialized state.
779//
780// Returns:
781//   - bool: true when the tick is initialized; false otherwise.
782func (t *TickInfo) Initialized() bool { return t.initialized }
783
784// TickCumulativeOutside returns cumulative tick value on the side opposite the current tick.
785//
786// Returns:
787//   - int64: outside cumulative tick value.
788func (t *TickInfo) TickCumulativeOutside() int64 { return t.tickCumulativeOutside }
789
790// TickInfo Setters methods
791// SetLiquidityGross stores total position liquidity referencing this tick.
792//
793// Parameters:
794//   - liquidityGross: gross liquidity encoded as a decimal string.
795func (t *TickInfo) SetLiquidityGross(liquidityGross string) {
796	t.liquidityGross = liquidityGross
797}
798
799// SetLiquidityNet stores the net liquidity change applied when crossing this tick.
800//
801// Parameters:
802//   - liquidityNet: signed net liquidity encoded as a decimal string.
803func (t *TickInfo) SetLiquidityNet(liquidityNet string) {
804	t.liquidityNet = liquidityNet
805}
806
807// SetFeeGrowthOutside0X128 stores token0 outside fee growth for this tick.
808//
809// Parameters:
810//   - feeGrowthOutside0X128: token0 outside fee growth scaled by 2^128, encoded as a decimal string.
811func (t *TickInfo) SetFeeGrowthOutside0X128(feeGrowthOutside0X128 string) {
812	t.feeGrowthOutside0X128 = feeGrowthOutside0X128
813}
814
815// SetFeeGrowthOutside1X128 stores token1 outside fee growth for this tick.
816//
817// Parameters:
818//   - feeGrowthOutside1X128: token1 outside fee growth scaled by 2^128, encoded as a decimal string.
819func (t *TickInfo) SetFeeGrowthOutside1X128(feeGrowthOutside1X128 string) {
820	t.feeGrowthOutside1X128 = feeGrowthOutside1X128
821}
822
823// SetSecondsPerLiquidityOutsideX128 stores outside seconds-per-liquidity growth.
824//
825// Parameters:
826//   - secondsPerLiquidityOutsideX128: outside seconds per liquidity scaled by 2^128, encoded as a decimal string.
827func (t *TickInfo) SetSecondsPerLiquidityOutsideX128(secondsPerLiquidityOutsideX128 string) {
828	t.secondsPerLiquidityOutsideX128 = secondsPerLiquidityOutsideX128
829}
830
831// SetSecondsOutside stores the seconds accumulated outside this tick.
832//
833// Parameters:
834//   - secondsOutside: elapsed seconds outside the tick.
835func (t *TickInfo) SetSecondsOutside(secondsOutside uint32) {
836	t.secondsOutside = secondsOutside
837}
838
839// SetInitialized updates whether this tick is initialized.
840//
841// Parameters:
842//   - initialized: true to mark the tick initialized, false otherwise.
843func (t *TickInfo) SetInitialized(initialized bool) {
844	t.initialized = initialized
845}
846
847// SetTickCumulativeOutside stores cumulative tick value outside this tick.
848//
849// Parameters:
850//   - tickCumulativeOutside: cumulative tick value on the opposite side.
851func (t *TickInfo) SetTickCumulativeOutside(tickCumulativeOutside int64) {
852	t.tickCumulativeOutside = tickCumulativeOutside
853}
854
855// Clone returns an independent value copy of this tick's stored state.
856//
857// Returns:
858//   - TickInfo: copied liquidity, fee-growth, time, and initialization fields.
859func (t *TickInfo) Clone() TickInfo {
860	return TickInfo{
861		feeGrowthOutside0X128:          t.feeGrowthOutside0X128,
862		feeGrowthOutside1X128:          t.feeGrowthOutside1X128,
863		liquidityGross:                 t.liquidityGross,
864		liquidityNet:                   t.liquidityNet,
865		tickCumulativeOutside:          t.tickCumulativeOutside,
866		secondsPerLiquidityOutsideX128: t.secondsPerLiquidityOutsideX128,
867		secondsOutside:                 t.secondsOutside,
868		initialized:                    t.initialized,
869	}
870}
871
872// NewTickInfo creates an uninitialized tick state with zero accumulators.
873//
874// Returns:
875//   - TickInfo: default tick state with all numeric fields zero and Initialized false.
876func NewTickInfo() TickInfo {
877	return TickInfo{
878		liquidityGross:                 "0",
879		liquidityNet:                   "0",
880		feeGrowthOutside0X128:          "0",
881		feeGrowthOutside1X128:          "0",
882		secondsPerLiquidityOutsideX128: "0",
883		secondsOutside:                 0,
884		initialized:                    false,
885		tickCumulativeOutside:          0,
886	}
887}
888
889// PositionInfo stores aggregate liquidity, fee-growth checkpoints, and tokens
890// owed for one pool-scoped lower/upper tick key.
891type PositionInfo struct {
892	liquidity                string // aggregate liquidity for this tick-range key
893	feeGrowthInside0LastX128 string // fee growth per unit of liquidity for token0 as of last update
894	feeGrowthInside1LastX128 string // fee growth per unit of liquidity for token1 as of last update
895
896	// accumulated token0 amount waiting to be collected (principal or swap fee)
897	tokensOwed0 int64
898
899	// accumulated token1 amount waiting to be collected (principal or swap fee)
900	tokensOwed1 int64
901}
902
903// Liquidity returns aggregate liquidity for this position range.
904//
905// Returns:
906//   - string: position liquidity encoded as a decimal string.
907func (p *PositionInfo) Liquidity() string { return p.liquidity }
908
909// FeeGrowthInside0LastX128 returns the token0 fee-growth checkpoint for this position.
910//
911// Returns:
912//   - string: token0 inside fee-growth checkpoint scaled by 2^128.
913func (p *PositionInfo) FeeGrowthInside0LastX128() string { return p.feeGrowthInside0LastX128 }
914
915// FeeGrowthInside1LastX128 returns the token1 fee-growth checkpoint for this position.
916//
917// Returns:
918//   - string: token1 inside fee-growth checkpoint scaled by 2^128.
919func (p *PositionInfo) FeeGrowthInside1LastX128() string { return p.feeGrowthInside1LastX128 }
920
921// TokensOwed0 returns token0 accumulated for this position.
922//
923// Returns:
924//   - int64: token0 principal or fee amount awaiting collection.
925func (p *PositionInfo) TokensOwed0() int64 { return p.tokensOwed0 }
926
927// TokensOwed1 returns token1 accumulated for this position.
928//
929// Returns:
930//   - int64: token1 principal or fee amount awaiting collection.
931func (p *PositionInfo) TokensOwed1() int64 { return p.tokensOwed1 }
932
933// SetLiquidity updates aggregate liquidity for this position range.
934//
935// Parameters:
936//   - liquidity: position liquidity encoded as a decimal string.
937func (p *PositionInfo) SetLiquidity(liquidity string) {
938	p.liquidity = liquidity
939}
940
941// SetFeeGrowthInside0LastX128 updates the token0 fee-growth checkpoint.
942//
943// Parameters:
944//   - feeGrowthInside0LastX128: token0 inside fee-growth checkpoint scaled by 2^128, encoded as a decimal string.
945func (p *PositionInfo) SetFeeGrowthInside0LastX128(feeGrowthInside0LastX128 string) {
946	p.feeGrowthInside0LastX128 = feeGrowthInside0LastX128
947}
948
949// SetFeeGrowthInside1LastX128 updates the token1 fee-growth checkpoint.
950//
951// Parameters:
952//   - feeGrowthInside1LastX128: token1 inside fee-growth checkpoint scaled by 2^128, encoded as a decimal string.
953func (p *PositionInfo) SetFeeGrowthInside1LastX128(feeGrowthInside1LastX128 string) {
954	p.feeGrowthInside1LastX128 = feeGrowthInside1LastX128
955}
956
957// SetTokensOwed0 updates token0 accumulated for this position.
958//
959// Parameters:
960//   - tokensOwed0: token0 principal or fee amount awaiting collection.
961func (p *PositionInfo) SetTokensOwed0(tokensOwed0 int64) {
962	p.tokensOwed0 = tokensOwed0
963}
964
965// SetTokensOwed1 updates token1 accumulated for this position.
966//
967// Parameters:
968//   - tokensOwed1: token1 principal or fee amount awaiting collection.
969func (p *PositionInfo) SetTokensOwed1(tokensOwed1 int64) {
970	p.tokensOwed1 = tokensOwed1
971}
972
973// NewPositionInfo creates a zeroed position state for a tick range.
974//
975// Returns:
976//   - PositionInfo: position with zero liquidity, fee-growth checkpoints, and owed tokens.
977func NewPositionInfo() PositionInfo {
978	return PositionInfo{
979		liquidity:                "0",
980		feeGrowthInside0LastX128: "0",
981		feeGrowthInside1LastX128: "0",
982		tokensOwed0:              0,
983		tokensOwed1:              0,
984	}
985}
986
987// NewDefaultFeeAmountTickSpacing returns the default tick spacing for each supported fee tier.
988//
989// Returns:
990//   - map[uint32]int32: fee-tier to tick-spacing mapping for 100, 500, 3000, and 10000 tiers.
991func NewDefaultFeeAmountTickSpacing() map[uint32]int32 {
992	return map[uint32]int32{
993		100:   1,
994		500:   10,
995		3000:  60,
996		10000: 200,
997	}
998}