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

store.gno

21.09 Kb · 606 lines
  1package pool
  2
  3import (
  4	"errors"
  5
  6	"gno.land/p/gnoswap/store/v1"
  7	bptree "gno.land/p/nt/bptree/v0"
  8	ufmt "gno.land/p/nt/ufmt/v0"
  9)
 10
 11// StoreKey defines the keys used for storing pool data in the KV store.
 12// These keys are prefixed with the domain address to ensure namespace isolation.
 13type StoreKey string
 14
 15// Returns:
 16//   - keyText: the textual store key represented by s.
 17func (s StoreKey) String() string {
 18	return string(s)
 19}
 20
 21const (
 22	// Pool data storage keys
 23	StoreKeyPools                StoreKey = "pools"                // Map containing all pools
 24	StoreKeyObservations         StoreKey = "observations"         // poolPath -> observation B+tree
 25	StoreKeyFeeAmountTickSpacing StoreKey = "feeAmountTickSpacing" // Fee tier to tick spacing mapping
 26	StoreKeySlot0FeeProtocol     StoreKey = "slot0FeeProtocol"     // Protocol fee denominator(s)
 27
 28	// Protocol fee storage keys
 29	StoreKeyPoolCreationFee     StoreKey = "poolCreationFee"     // Pool creation fee amount
 30	StoreKeyPendingProtocolFees StoreKey = "pendingProtocolFees" // tokenPath -> amount held locally for protocol_fee
 31	StoreKeyWithdrawalFeeBPS    StoreKey = "withdrawalFeeBPS"    // Withdrawal fee in basis points
 32	StoreKeyUnlocked            StoreKey = "unlocked"            // Global pool reentrancy lock
 33
 34	// Swap hook storage keys
 35	StoreKeySwapStartHook StoreKey = "swapStartHook" // Swap start hook function
 36	StoreKeySwapEndHook   StoreKey = "swapEndHook"   // Swap end hook function
 37	StoreKeyTickCrossHook StoreKey = "tickCrossHook" // Tick cross hook function
 38)
 39
 40// poolStore implements the IPoolStore interface for pool domain storage.
 41// It provides type-safe access to pool data stored in the underlying KV store.
 42type poolStore struct {
 43	kvStore store.KVStore
 44}
 45
 46// Returns:
 47//   - exists: true when the pool collection key is present in the KV store.
 48func (s *poolStore) HasPools() bool {
 49	return s.kvStore.Has(StoreKeyPools.String())
 50}
 51
 52// GetPools retrieves the map containing all pool data.
 53// This is the main data structure that stores all pool instances.
 54// Returns:
 55//   - pools: the B+tree containing all persisted pool instances; panics if the
 56//     KV store cannot read it or the stored value is nil.
 57func (s *poolStore) GetPools() *bptree.BPTree {
 58	pools, err := s.kvStore.GetBPTree(StoreKeyPools.String())
 59	if err != nil {
 60		panic(err)
 61	}
 62
 63	if pools == nil {
 64		panic("pools is nil")
 65	}
 66
 67	return pools
 68}
 69
 70// SetPools stores the map containing all pool data.
 71// Parameters:
 72//   - _: leading realm-call discriminator; callers pass 0.
 73//   - rlm: propagated realm context; it must be the current realm or the method
 74//     returns ErrSpoofedRealm before writing.
 75//   - pools: non-nil B+tree containing the pool instances to persist.
 76//
 77// Returns:
 78//   - err: nil when the pool tree is stored; ErrSpoofedRealm for a non-current
 79//     realm, or the underlying KV-store write error.
 80func (s *poolStore) SetPools(_ int, rlm realm, pools *bptree.BPTree) error {
 81	if !rlm.IsCurrent() {
 82		return errors.New(ErrSpoofedRealm)
 83	}
 84
 85	if pools == nil {
 86		panic("pools is nil")
 87	}
 88
 89	return s.kvStore.Set(0, rlm, StoreKeyPools.String(), pools)
 90}
 91
 92// Returns:
 93//   - exists: true when the observations collection key is present in the KV store.
 94func (s *poolStore) HasObservations() bool {
 95	return s.kvStore.Has(StoreKeyObservations.String())
 96}
 97
 98// Returns:
 99//   - observations: the B+tree containing persisted observation trees; panics if
100//     the KV store cannot read it or the stored value is nil.
101func (s *poolStore) GetObservations() *bptree.BPTree {
102	observations, err := s.kvStore.GetBPTree(StoreKeyObservations.String())
103	if err != nil {
104		panic(err)
105	}
106	if observations == nil {
107		panic("observations is nil")
108	}
109	return observations
110}
111
112// Parameters:
113//   - _: leading realm-call discriminator; callers pass 0.
114//   - rlm: propagated realm context; it must be the current realm or the method
115//     returns ErrSpoofedRealm before writing.
116//   - observations: non-nil B+tree containing the observation data to persist.
117//
118// Returns:
119//   - err: nil when the observation tree is stored; ErrSpoofedRealm for a
120//     non-current realm, or the underlying KV-store write error.
121func (s *poolStore) SetObservations(_ int, rlm realm, observations *bptree.BPTree) error {
122	if !rlm.IsCurrent() {
123		return errors.New(ErrSpoofedRealm)
124	}
125	if observations == nil {
126		panic("observations is nil")
127	}
128	return s.kvStore.Set(0, rlm, StoreKeyObservations.String(), observations)
129}
130
131// Returns:
132//   - exists: true when the fee-tier/tick-spacing mapping key is present in the
133//     KV store.
134func (s *poolStore) HasFeeAmountTickSpacing() bool {
135	return s.kvStore.Has(StoreKeyFeeAmountTickSpacing.String())
136}
137
138// GetFeeAmountTickSpacing retrieves the mapping between fee amounts and tick spacing.
139// This mapping determines the tick spacing for each supported fee tier.
140// Returns:
141//   - feeAmountTickSpacing: a copy of the fee amount to tick-spacing mapping;
142//     panics if the KV value cannot be read, has the wrong type, or is nil.
143func (s *poolStore) GetFeeAmountTickSpacing() map[uint32]int32 {
144	result, err := s.kvStore.Get(StoreKeyFeeAmountTickSpacing.String())
145	if err != nil {
146		panic(err)
147	}
148
149	feeAmountTickSpacing, ok := result.(map[uint32]int32)
150	if !ok {
151		panic(ufmt.Sprintf("failed to cast result to map[uint32]int32: %T", result))
152	}
153
154	if feeAmountTickSpacing == nil {
155		panic("feeAmountTickSpacing is nil")
156	}
157
158	return cloneFeeAmountTickSpacings(feeAmountTickSpacing)
159}
160
161// SetFeeAmountTickSpacing stores the mapping between fee amounts and tick spacing.
162// Parameters:
163//   - _: leading realm-call discriminator; callers pass 0.
164//   - rlm: propagated realm context; it must be the current realm or the method
165//     returns ErrSpoofedRealm before writing.
166//   - feeAmountTickSpacing: non-nil mapping from fee tiers to their required
167//     int32 tick spacing values.
168//
169// Returns:
170//   - err: nil when the mapping is stored; ErrSpoofedRealm for a non-current
171//     realm, or the underlying KV-store write error.
172func (s *poolStore) SetFeeAmountTickSpacing(_ int, rlm realm, feeAmountTickSpacing map[uint32]int32) error {
173	if !rlm.IsCurrent() {
174		return errors.New(ErrSpoofedRealm)
175	}
176
177	if feeAmountTickSpacing == nil {
178		panic("feeAmountTickSpacing is nil")
179	}
180
181	return s.kvStore.Set(0, rlm, StoreKeyFeeAmountTickSpacing.String(), feeAmountTickSpacing)
182}
183
184// Returns:
185//   - exists: true when the slot0 protocol-fee configuration key is present in
186//     the KV store.
187func (s *poolStore) HasSlot0FeeProtocol() bool {
188	return s.kvStore.Has(StoreKeySlot0FeeProtocol.String())
189}
190
191// GetSlot0FeeProtocol retrieves the protocol fee denominator(s) for slot0.
192// Returns:
193//   - slot0FeeProtocol: packed protocol-fee denominator configuration for
194//     slot0; panics if the KV value cannot be read or has the wrong type.
195func (s *poolStore) GetSlot0FeeProtocol() uint8 {
196	result, err := s.kvStore.Get(StoreKeySlot0FeeProtocol.String())
197	if err != nil {
198		panic(err)
199	}
200
201	slot0FeeProtocol, ok := result.(uint8)
202	if !ok {
203		panic(ufmt.Sprintf("failed to cast result to uint8: %T", result))
204	}
205
206	return slot0FeeProtocol
207}
208
209// SetSlot0FeeProtocol stores the protocol fee denominator(s) for slot0.
210// Parameters:
211//   - _: leading realm-call discriminator; callers pass 0.
212//   - rlm: propagated realm context; it must be the current realm or the method
213//     returns ErrSpoofedRealm before writing.
214//   - slot0FeeProtocol: packed uint8 protocol-fee denominators for token0 and
215//     token1.
216//
217// Returns:
218//   - err: nil when the protocol-fee configuration is stored; ErrSpoofedRealm
219//     for a non-current realm, or the underlying KV-store write error.
220func (s *poolStore) SetSlot0FeeProtocol(_ int, rlm realm, slot0FeeProtocol uint8) error {
221	if !rlm.IsCurrent() {
222		return errors.New(ErrSpoofedRealm)
223	}
224
225	return s.kvStore.Set(0, rlm, StoreKeySlot0FeeProtocol.String(), slot0FeeProtocol)
226}
227
228// Returns:
229//   - exists: true when the pool-creation-fee key is present in the KV store.
230func (s *poolStore) HasPoolCreationFee() bool {
231	return s.kvStore.Has(StoreKeyPoolCreationFee.String())
232}
233
234// GetPoolCreationFee retrieves the pool creation fee amount.
235// Returns:
236//   - poolCreationFee: configured pool-creation charge in the chain's smallest
237//     currency unit; panics if the KV value cannot be read or has the wrong type.
238func (s *poolStore) GetPoolCreationFee() int64 {
239	result, err := s.kvStore.Get(StoreKeyPoolCreationFee.String())
240	if err != nil {
241		panic(err)
242	}
243
244	poolCreationFee, ok := result.(int64)
245	if !ok {
246		panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
247	}
248
249	return poolCreationFee
250}
251
252// SetPoolCreationFee stores the pool creation fee amount.
253// Parameters:
254//   - _: leading realm-call discriminator; callers pass 0.
255//   - rlm: propagated realm context; it must be the current realm or the method
256//     returns ErrSpoofedRealm before writing.
257//   - poolCreationFee: pool-creation charge in the chain's smallest currency
258//     unit.
259//
260// Returns:
261//   - err: nil when the fee is stored; ErrSpoofedRealm for a non-current realm,
262//     or the underlying KV-store write error.
263func (s *poolStore) SetPoolCreationFee(_ int, rlm realm, poolCreationFee int64) error {
264	if !rlm.IsCurrent() {
265		return errors.New(ErrSpoofedRealm)
266	}
267
268	return s.kvStore.Set(0, rlm, StoreKeyPoolCreationFee.String(), poolCreationFee)
269}
270
271// Returns:
272//   - exists: true when the pending protocol-fees key is present in the KV store.
273func (s *poolStore) HasPendingProtocolFees() bool {
274	return s.kvStore.Has(StoreKeyPendingProtocolFees.String())
275}
276
277// Returns:
278//   - pendingProtocolFees: mapping from token path to pending protocol-fee
279//     amount in the chain's smallest currency unit; panics if the KV value
280//     cannot be read or has the wrong type.
281func (s *poolStore) GetPendingProtocolFees() map[string]int64 {
282	result, err := s.kvStore.Get(StoreKeyPendingProtocolFees.String())
283	if err != nil {
284		panic(err)
285	}
286
287	pendingProtocolFees, ok := result.(map[string]int64)
288	if !ok {
289		panic(ufmt.Sprintf("failed to cast result to map[string]int64: %T", result))
290	}
291
292	return pendingProtocolFees
293}
294
295// Parameters:
296//   - _: leading realm-call discriminator; callers pass 0.
297//   - rlm: propagated realm context; it must be the current realm or the method
298//     returns ErrSpoofedRealm before writing.
299//   - pendingProtocolFees: token-path-to-amount mapping; amounts are in the
300//     chain's smallest currency unit and are copied before storage.
301//
302// Returns:
303//   - err: nil when the copied mapping is stored; ErrSpoofedRealm for a
304//     non-current realm, or the underlying KV-store write error.
305func (s *poolStore) SetPendingProtocolFees(_ int, rlm realm, pendingProtocolFees map[string]int64) error {
306	if !rlm.IsCurrent() {
307		return errors.New(ErrSpoofedRealm)
308	}
309
310	// The map is copied here so it is allocated by, and therefore mutable from, this realm.
311	owned := make(map[string]int64, len(pendingProtocolFees))
312	for tokenPath, amount := range pendingProtocolFees {
313		owned[tokenPath] = amount
314	}
315
316	return s.kvStore.Set(0, rlm, StoreKeyPendingProtocolFees.String(), owned)
317}
318
319// Parameters:
320//   - tokenPath: token contract path used as the pending-fee map key.
321//
322// Returns:
323//   - amount: pending protocol-fee amount for tokenPath in the chain's smallest
324//     currency unit, or zero when no entry exists.
325func (s *poolStore) GetPendingProtocolFee(tokenPath string) int64 {
326	return s.GetPendingProtocolFees()[tokenPath]
327}
328
329// Parameters:
330//   - _: leading realm-call discriminator; callers pass 0.
331//   - rlm: propagated realm context; it must be the current realm or the method
332//     returns ErrSpoofedRealm before writing.
333//   - tokenPath: token contract path identifying the pending-fee entry.
334//   - amount: pending protocol-fee amount to assign for tokenPath, in the
335//     chain's smallest currency unit.
336//
337// Returns:
338//   - err: nil after the map entry is updated; ErrSpoofedRealm for a non-current
339//     realm, or store.ErrWritePermissionDenied for an unauthorized code realm.
340func (s *poolStore) SetPendingProtocolFee(_ int, rlm realm, tokenPath string, amount int64) error {
341	if !rlm.IsCurrent() {
342		return errors.New(ErrSpoofedRealm)
343	}
344
345	if rlm.IsCode() && !s.kvStore.IsWriteAuthorized(rlm.Address()) {
346		return errors.New(store.ErrWritePermissionDenied)
347	}
348
349	s.GetPendingProtocolFees()[tokenPath] = amount
350
351	return nil
352}
353
354// Parameters:
355//   - _: leading realm-call discriminator; callers pass 0.
356//   - rlm: propagated realm context; it must be the current realm or the method
357//     returns ErrSpoofedRealm before writing.
358//   - tokenPath: token contract path identifying the pending-fee entry to delete.
359//
360// Returns:
361//   - err: nil after the map entry is removed; ErrSpoofedRealm for a non-current
362//     realm, or store.ErrWritePermissionDenied for an unauthorized code realm.
363func (s *poolStore) RemovePendingProtocolFee(_ int, rlm realm, tokenPath string) error {
364	if !rlm.IsCurrent() {
365		return errors.New(ErrSpoofedRealm)
366	}
367
368	if rlm.IsCode() && !s.kvStore.IsWriteAuthorized(rlm.Address()) {
369		return errors.New(store.ErrWritePermissionDenied)
370	}
371
372	delete(s.GetPendingProtocolFees(), tokenPath)
373
374	return nil
375}
376
377// Returns:
378//   - exists: true when the withdrawal-fee key is present in the KV store.
379func (s *poolStore) HasWithdrawalFeeBPS() bool {
380	return s.kvStore.Has(StoreKeyWithdrawalFeeBPS.String())
381}
382
383// GetWithdrawalFeeBPS retrieves the withdrawal fee in basis points.
384// Returns:
385//   - withdrawalFeeBPS: withdrawal fee expressed in basis points (1/100 of a
386//     percent); panics if the KV value cannot be read or has the wrong type.
387func (s *poolStore) GetWithdrawalFeeBPS() uint64 {
388	result, err := s.kvStore.Get(StoreKeyWithdrawalFeeBPS.String())
389	if err != nil {
390		panic(err)
391	}
392
393	withdrawalFeeBPS, ok := result.(uint64)
394	if !ok {
395		panic(ufmt.Sprintf("failed to cast result to uint64: %T", result))
396	}
397
398	return withdrawalFeeBPS
399}
400
401// SetWithdrawalFeeBPS stores the withdrawal fee in basis points.
402// Parameters:
403//   - _: leading realm-call discriminator; callers pass 0.
404//   - rlm: propagated realm context; it must be the current realm or the method
405//     returns ErrSpoofedRealm before writing.
406//   - withdrawalFeeBPS: withdrawal fee in basis points, where 100 basis points
407//     equals one percent.
408//
409// Returns:
410//   - err: nil when the fee is stored; ErrSpoofedRealm for a non-current realm,
411//     or the underlying KV-store write error.
412func (s *poolStore) SetWithdrawalFeeBPS(_ int, rlm realm, withdrawalFeeBPS uint64) error {
413	if !rlm.IsCurrent() {
414		return errors.New(ErrSpoofedRealm)
415	}
416
417	return s.kvStore.Set(0, rlm, StoreKeyWithdrawalFeeBPS.String(), withdrawalFeeBPS)
418}
419
420// Returns:
421//   - exists: true when the global unlocked-state key is present in the KV store.
422func (s *poolStore) HasUnlocked() bool {
423	return s.kvStore.Has(StoreKeyUnlocked.String())
424}
425
426// Returns:
427//   - unlocked: the persisted global reentrancy-lock state; panics if the KV
428//     value cannot be read or has the wrong type.
429func (s *poolStore) GetUnlocked() bool {
430	result, err := s.kvStore.Get(StoreKeyUnlocked.String())
431	if err != nil {
432		panic(err)
433	}
434
435	unlocked, ok := result.(bool)
436	if !ok {
437		panic(ufmt.Sprintf("failed to cast result to bool: %T", result))
438	}
439
440	return unlocked
441}
442
443// Parameters:
444//   - _: leading realm-call discriminator; callers pass 0.
445//   - rlm: propagated realm context; it must be the current realm or the method
446//     returns ErrSpoofedRealm before writing.
447//   - unlocked: true when pool operations may proceed without the global lock.
448//
449// Returns:
450//   - err: nil when the lock state is stored; ErrSpoofedRealm for a non-current
451//     realm, or the underlying KV-store write error.
452func (s *poolStore) SetUnlocked(_ int, rlm realm, unlocked bool) error {
453	if !rlm.IsCurrent() {
454		return errors.New(ErrSpoofedRealm)
455	}
456
457	return s.kvStore.Set(0, rlm, StoreKeyUnlocked.String(), unlocked)
458}
459
460// HasSwapStartHook checks if the swap start hook is set.
461// Returns:
462//   - exists: true when a swap-start hook key is present in the KV store.
463func (s *poolStore) HasSwapStartHook() bool {
464	return s.kvStore.Has(StoreKeySwapStartHook.String())
465}
466
467// GetSwapStartHook retrieves the swap start hook function.
468// Returns:
469//   - swapStartHook: stored callback invoked at swap start with the current
470//     realm, pool path, and block timestamp; panics if the KV value cannot be
471//     read or has the wrong function type.
472func (s *poolStore) GetSwapStartHook() func(cur realm, poolPath string, timestamp int64) {
473	result, err := s.kvStore.Get(StoreKeySwapStartHook.String())
474	if err != nil {
475		panic(err)
476	}
477
478	swapStartHook, ok := result.(func(cur realm, poolPath string, timestamp int64))
479	if !ok {
480		panic(ufmt.Sprintf("failed to cast result to func(poolPath string, timestamp int64): %T", result))
481	}
482
483	return swapStartHook
484}
485
486// SetSwapStartHook stores the swap start hook function.
487// Parameters:
488//   - _: leading realm-call discriminator; callers pass 0.
489//   - rlm: propagated realm context; it must be the current realm or the method
490//     returns ErrSpoofedRealm before writing.
491//   - swapStartHook: callback receiving the current realm, pool path, and
492//     block timestamp when a swap starts.
493//
494// Returns:
495//   - err: nil when the callback is stored; ErrSpoofedRealm for a non-current
496//     realm, or the underlying KV-store write error.
497func (s *poolStore) SetSwapStartHook(_ int, rlm realm, swapStartHook func(cur realm, poolPath string, timestamp int64)) error {
498	if !rlm.IsCurrent() {
499		return errors.New(ErrSpoofedRealm)
500	}
501
502	return s.kvStore.Set(0, rlm, StoreKeySwapStartHook.String(), swapStartHook)
503}
504
505// HasSwapEndHook checks if the swap end hook is set.
506// Returns:
507//   - exists: true when a swap-end hook key is present in the KV store.
508func (s *poolStore) HasSwapEndHook() bool {
509	return s.kvStore.Has(StoreKeySwapEndHook.String())
510}
511
512// GetSwapEndHook retrieves the swap end hook function.
513// Returns:
514//   - swapEndHook: stored callback receiving the current realm and pool path at
515//     swap end and returning an error; panics if the KV value cannot be read or
516//     has the wrong function type.
517func (s *poolStore) GetSwapEndHook() func(cur realm, poolPath string) error {
518	result, err := s.kvStore.Get(StoreKeySwapEndHook.String())
519	if err != nil {
520		panic(err)
521	}
522
523	swapEndHook, ok := result.(func(cur realm, poolPath string) error)
524	if !ok {
525		panic(ufmt.Sprintf("failed to cast result to func(poolPath string): %T", result))
526	}
527
528	return swapEndHook
529}
530
531// SetSwapEndHook stores the swap end hook function.
532// Parameters:
533//   - _: leading realm-call discriminator; callers pass 0.
534//   - rlm: propagated realm context; it must be the current realm or the method
535//     returns ErrSpoofedRealm before writing.
536//   - swapEndHook: callback receiving the current realm and pool path at swap
537//     end and returning any hook error.
538//
539// Returns:
540//   - err: nil when the callback is stored; ErrSpoofedRealm for a non-current
541//     realm, or the underlying KV-store write error.
542func (s *poolStore) SetSwapEndHook(_ int, rlm realm, swapEndHook func(cur realm, poolPath string) error) error {
543	if !rlm.IsCurrent() {
544		return errors.New(ErrSpoofedRealm)
545	}
546
547	return s.kvStore.Set(0, rlm, StoreKeySwapEndHook.String(), swapEndHook)
548}
549
550// HasTickCrossHook checks if the tick cross hook is set.
551// Returns:
552//   - exists: true when a tick-cross hook key is present in the KV store.
553func (s *poolStore) HasTickCrossHook() bool {
554	return s.kvStore.Has(StoreKeyTickCrossHook.String())
555}
556
557// GetTickCrossHook retrieves the tick cross hook function.
558// Returns:
559//   - tickCrossHook: stored callback receiving the current realm, pool path,
560//     crossed tick, swap direction, and block timestamp; panics if the KV value
561//     cannot be read or has the wrong function type.
562func (s *poolStore) GetTickCrossHook() func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64) {
563	result, err := s.kvStore.Get(StoreKeyTickCrossHook.String())
564	if err != nil {
565		panic(err)
566	}
567
568	tickCrossHook, ok := result.(func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64))
569	if !ok {
570		panic(ufmt.Sprintf("failed to cast result to func(poolPath string, tickId int32, zeroForOne bool, timestamp int64): %T", result))
571	}
572
573	return tickCrossHook
574}
575
576// SetTickCrossHook stores the tick cross hook function.
577// Parameters:
578//   - _: leading realm-call discriminator; callers pass 0.
579//   - rlm: propagated realm context; it must be the current realm or the method
580//     returns ErrSpoofedRealm before writing.
581//   - tickCrossHook: callback receiving the current realm, pool path, crossed
582//     tick ID, swap direction, and block timestamp.
583//
584// Returns:
585//   - err: nil when the callback is stored; ErrSpoofedRealm for a non-current
586//     realm, or the underlying KV-store write error.
587func (s *poolStore) SetTickCrossHook(_ int, rlm realm, tickCrossHook func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64)) error {
588	if !rlm.IsCurrent() {
589		return errors.New(ErrSpoofedRealm)
590	}
591
592	return s.kvStore.Set(0, rlm, StoreKeyTickCrossHook.String(), tickCrossHook)
593}
594
595// NewPoolStore creates a new pool store instance with the provided KV store.
596// This function is used by the upgrade system to create storage instances for each implementation.
597// Parameters:
598//   - kvStore: KV store used to persist and retrieve pool-domain state.
599//
600// Returns:
601//   - poolStore: an IPoolStore implementation backed by kvStore.
602func NewPoolStore(kvStore store.KVStore) IPoolStore {
603	return &poolStore{
604		kvStore: kvStore,
605	}
606}