From 825d4e6293e732d213a8059ebd77d4c74715e39b Mon Sep 17 00:00:00 2001 From: andrewnguyen22 Date: Fri, 24 Jul 2026 10:53:07 -0400 Subject: [PATCH] refactor(dex): remove legacy LP migration --- fsm/dex.go | 65 +++---------------------------------------------- fsm/dex_test.go | 36 ++------------------------- 2 files changed, 5 insertions(+), 96 deletions(-) diff --git a/fsm/dex.go b/fsm/dex.go index 89e022ee2c..834840f7ca 100644 --- a/fsm/dex.go +++ b/fsm/dex.go @@ -10,12 +10,8 @@ import ( "strings" ) -const ( - // dexLPEvictionIDDomain separates replacement withdrawal IDs from other deterministic DEX IDs. - dexLPEvictionIDDomain = "dex-lp-eviction-v1" - // dexLPMigrationIDDomain separates migration withdrawal IDs from other deterministic DEX IDs. - dexLPMigrationIDDomain = "dex-lp-migration-v1" -) +// dexLPEvictionIDDomain separates replacement withdrawal IDs from other deterministic DEX IDs. +const dexLPEvictionIDDomain = "dex-lp-eviction-v1" /* Dex.go implements logic to handle AMM style atomic exchanges between root & nested chains not to be confused with 1 way order book swaps implemented in swap.go */ @@ -673,13 +669,9 @@ func (s *StateMachine) handleBatchDeposit(batch *lib.DexBatch, chainId uint64, x return nil } -// handleCappedBatchDeposit migrates legacy pools and deterministically admits the best-funded newcomers. +// handleCappedBatchDeposit deterministically admits the best-funded newcomers. // MaxLiquidityProviders bounds serialized point entries, so the permanent dead address consumes one slot. func (s *StateMachine) handleCappedBatchDeposit(batch *lib.DexBatch, p *Pool, chainId uint64, x, y *uint64, local bool) (bool, lib.ErrorI) { - // execute the one-time legacy migration before processing newcomers - if err := s.migrateLegacyLPs(batch, p, chainId, x, y, local); err != nil { - return true, err - } // initialize vars var err lib.ErrorI type candidate struct { @@ -815,57 +807,6 @@ func liquidityDepositPoints(totalPoints, x, y, amount uint64) (uint64, lib.Error return lib.SafeMulDiv(totalPoints, newK-oldK, oldK), nil } -// migrateLegacyLPs() performs the one-time migration of a pool above the provider limit. -func (s *StateMachine) migrateLegacyLPs(batch *lib.DexBatch, p *Pool, chainId uint64, x, y *uint64, local bool) lib.ErrorI { - // calculate how many legacy providers must be removed to reach the limit - excess := len(p.Points) - lib.MaxLiquidityProviders - if excess <= 0 { - return nil - } - // rank the providers from lowest to highest points - sort.Slice(p.Points, func(i, j int) bool { - // rank by points first - if p.Points[i].Points != p.Points[j].Points { - return p.Points[i].Points < p.Points[j].Points - } - // break equal-point ties deterministically using the receipt hash - return bytes.Compare(liquidityProviderTieBreakHash(batch.ReceiptHash, p.Points[i].Address), liquidityProviderTieBreakHash(batch.ReceiptHash, p.Points[j].Address)) < 0 - }) - // preallocate one full withdrawal for each excess provider - withdrawals := make([]*lib.DexLiquidityWithdraw, 0, excess) - // select the lowest-ranked providers - for _, point := range p.Points { - // the permanent dead address cannot be evicted - if !bytes.Equal(point.Address, deadAddr.Bytes()) { - // create a full withdrawal with a deterministic migration order ID - withdrawals = append(withdrawals, &lib.DexLiquidityWithdraw{Address: point.Address, Percent: 100, - OrderId: crypto.ShortHash(lib.JoinLenPrefix([]byte(dexLPMigrationIDDomain), batch.ReceiptHash, point.Address))}) - } - // stop after selecting exactly the excess providers - if len(withdrawals) == excess { - break - } - } - // ensure the pool contained enough removable providers - if len(withdrawals) != excess { - return ErrInvalidLiquidityPool() - } - // execute and persist the migration through the standard withdrawal path - if err := s.HandleBatchWithdraw(&lib.DexBatch{Withdrawals: withdrawals}, chainId, x, y, local); err != nil { - return err - } - // reload the pool updated by HandleBatchWithdraw() - migrated, err := s.GetPool(chainId + LiquidityPoolAddend) - if err != nil { - return err - } - // refresh the working pool before processing the incoming deposits - p.Amount = migrated.Amount - p.Points = migrated.Points - p.TotalPoolPoints = migrated.TotalPoolPoints - return nil -} - // RotateDexBatches() sets 'next batch' as 'locked batch' and deletes reference for 'next batch' // (1) checks if locked batch is processed yet - if not exit // (2) sets the upcoming 'sell' batch as 'last' sell batch diff --git a/fsm/dex_test.go b/fsm/dex_test.go index c8a5462a6f..ffac4f192b 100644 --- a/fsm/dex_test.go +++ b/fsm/dex_test.go @@ -2780,17 +2780,15 @@ func TestHandleBatchDepositRemoteReplacesLowestProvider(t *testing.T) { newProvider := newTestAddress(t, 2) receiptHash, depositOrderId := []byte("receipt"), []byte{0x22} - points := make([]*lib.PoolPoints, lib.MaxLiquidityProviders+1) + points := make([]*lib.PoolPoints, lib.MaxLiquidityProviders) totalPoints := uint64(100) for i := range points { address, amount := make([]byte, crypto.AddressSize), uint64(1) address[len(address)-2], address[len(address)-1] = byte(i>>8), byte(i) if i == 0 { address, amount = deadAddr.Bytes(), 100 - } else if i < lib.MaxLiquidityProviders { - totalPoints++ } else { - amount = 0 // legacy zero-point holder + totalPoints++ } points[i] = &lib.PoolPoints{Address: address, Points: amount} } @@ -2895,36 +2893,6 @@ func TestHandleBatchDepositRanksNewcomersByProviderTotal(t *testing.T) { require.Error(t, err) } -func TestHandleBatchDepositMigratesPoolBeforeDeposits(t *testing.T) { - sm := newTestStateMachine(t) - chainID := uint64(2) - points := make([]*lib.PoolPoints, 50_000) - var total uint64 - for i := range points { - address := make([]byte, crypto.AddressSize) - address[len(address)-2], address[len(address)-1] = byte(i>>8), byte(i) - amount := uint64(i + 1) - if i == 0 { - address, amount = deadAddr.Bytes(), 100 - } - points[i], total = &lib.PoolPoints{Address: address, Points: amount}, total+amount - } - require.NoError(t, sm.SetPool(&Pool{Id: chainID + LiquidityPoolAddend, Amount: 1_000_000, Points: points, TotalPoolPoints: total})) - - x, y := uint64(1_000_000), uint64(1_000_000) - require.NoError(t, sm.HandleBatchDeposit(&lib.DexBatch{Deposits: []*lib.DexLiquidityDeposit{{ - Address: points[len(points)-1].Address, Amount: 100, - }}}, chainID, &x, &y, false)) - - pool, err := sm.GetPool(chainID + LiquidityPoolAddend) - require.NoError(t, err) - require.Len(t, pool.Points, lib.MaxLiquidityProviders) - for _, evicted := range points[1:3] { - _, err = pool.GetPointsFor(evicted.Address) - require.Error(t, err) - } -} - func TestHandleBatchDepositUsesReceiptHashForEqualStakeTie(t *testing.T) { sm := newTestStateMachine(t) chainID, seed := uint64(2), []byte("receipt")