mirror of
https://github.com/luxfi/precompile.git
synced 2026-09-24 00:26:21 +00:00
ONE money path: D-Chain matches, C-Chain 0x9999 SETTLES, C never matches. - 0x9999 swap() routes ONLY to SettleSwap (native C<->D atomic seam): untagged/ DI01 => Phase A intent (lock input, write C->D object, return intent id); DS01 => Phase B settlement (consume a real D->C atomic object once, credit RECORDED amount). No-receipt-no-settle: absent a real object, Phase B reverts ErrNativeNoSettlement (TestDecomplect_NoReceiptNoSettle). - Deleted the embedded matcher: swap_sync*.go, swap_custody.go (maker order book), buildRouter/evmAMMPool in swap_amm_pool.go, and the swapDeposit/withdraw/place/ cancel selectors. A live in-trie matcher forks consensus; deterministic atomic-object consumption is fork-safe inline. - 0x9010 already non-dispatched. 0x9012 (LXRouter) value selectors exactInput*/ exactOutput* now revert ErrPrecompileMoved (PRECOMPILE_MOVED); read-only quote/ route views kept. - Cleanups (dead code removal, all unreachable via any dispatched selector): deleted the legacy engine PoolManager.Swap + LXRouter.Exact*/executeV4Swap*; deleted the vestigial makerLockedVault ledger (0 callers, always 0); deleted the unwired Block-STM scaffolding (AssertWriteSetWithin/AccessCommitment/Predict*). - Activation rides the EXISTING canonical gate 1766708400 (Dec 25 2025 16:20 PST); no new timestamp. Build CGO_ENABLED=0 (pure-Go luxfi/dex path); go.sum zap re-tag checksum refreshed. 327 dex tests PASS / 0 FAIL, go vet clean. RED-reviewed (0 critical, all drain vectors safe, fund-strand cleared, negative invariant falsified-then-restored). Co-authored-by: Hanzo Dev <[email protected]>
566 lines
15 KiB
Go
566 lines
15 KiB
Go
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package dex
|
|
|
|
import (
|
|
"math/big"
|
|
"testing"
|
|
|
|
"github.com/luxfi/geth/common"
|
|
)
|
|
|
|
// Admin address used as protocolFeeController for pause/freeze tests.
|
|
var adminAddr = common.HexToAddress("0xADMN000000000000000000000000000000000001")
|
|
|
|
// nonAdminAddr is an address without admin privileges.
|
|
var nonAdminAddr = common.HexToAddress("0xBEEF000000000000000000000000000000000002")
|
|
|
|
func newPauseTestPoolManager() *PoolManager {
|
|
pm := NewPoolManager(&mockEngine{})
|
|
pm.protocolFeeController = adminAddr
|
|
return pm
|
|
}
|
|
|
|
// =========================================================================
|
|
// Level 2: DEX-Level Pause Tests
|
|
// =========================================================================
|
|
|
|
func TestPauseDEX(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
|
|
// Pause the DEX
|
|
err := pm.PauseDEX(stateDB, adminAddr)
|
|
if err != nil {
|
|
t.Fatalf("PauseDEX failed: %v", err)
|
|
}
|
|
|
|
if !pm.IsPaused(stateDB) {
|
|
t.Fatal("DEX should be paused")
|
|
}
|
|
|
|
// Verify event was emitted
|
|
logs := stateDB.Logs()
|
|
if len(logs) != 1 {
|
|
t.Fatalf("expected 1 log, got %d", len(logs))
|
|
}
|
|
if logs[0].Topics[0] != dexPausedEventSig {
|
|
t.Error("expected DEXPaused event")
|
|
}
|
|
}
|
|
|
|
func TestPauseDEXUnauthorized(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
|
|
err := pm.PauseDEX(stateDB, nonAdminAddr)
|
|
if err != ErrUnauthorized {
|
|
t.Fatalf("expected ErrUnauthorized, got: %v", err)
|
|
}
|
|
|
|
if pm.IsPaused(stateDB) {
|
|
t.Fatal("DEX should not be paused after unauthorized call")
|
|
}
|
|
}
|
|
|
|
func TestPauseDEXAlreadyPaused(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
err := pm.PauseDEX(stateDB, adminAddr)
|
|
if err != ErrAlreadyPaused {
|
|
t.Fatalf("expected ErrAlreadyPaused, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestResumeDEX(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
err := pm.ResumeDEX(stateDB, adminAddr)
|
|
if err != nil {
|
|
t.Fatalf("ResumeDEX failed: %v", err)
|
|
}
|
|
|
|
if pm.IsPaused(stateDB) {
|
|
t.Fatal("DEX should not be paused after resume")
|
|
}
|
|
}
|
|
|
|
func TestResumeDEXNotPaused(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
|
|
err := pm.ResumeDEX(stateDB, adminAddr)
|
|
if err != ErrDEXNotPaused {
|
|
t.Fatalf("expected ErrDEXNotPaused, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestResumeDEXUnauthorized(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
err := pm.ResumeDEX(stateDB, nonAdminAddr)
|
|
if err != ErrUnauthorized {
|
|
t.Fatalf("expected ErrUnauthorized, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDEXPausePreventsModifyLiquidity(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
caller := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
|
|
params := ModifyLiquidityParams{
|
|
TickLower: -120,
|
|
TickUpper: 120,
|
|
LiquidityDelta: big.NewInt(1000),
|
|
Salt: [32]byte{},
|
|
}
|
|
|
|
_, _, err := pm.ModifyLiquidity(stateDB, caller, key, params, nil)
|
|
if err != ErrDEXPaused {
|
|
t.Fatalf("expected ErrDEXPaused, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDEXPausePreventsDonate(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
caller := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
|
|
_, err := pm.Donate(stateDB, caller, key, big.NewInt(100), big.NewInt(200))
|
|
if err != ErrDEXPaused {
|
|
t.Fatalf("expected ErrDEXPaused, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// =========================================================================
|
|
// Level 3: Pool-Level Pause Tests
|
|
// =========================================================================
|
|
|
|
func TestPausePool(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
poolId := key.ID()
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
err := pm.PausePool(stateDB, adminAddr, poolId)
|
|
if err != nil {
|
|
t.Fatalf("PausePool failed: %v", err)
|
|
}
|
|
|
|
if !pm.IsPoolPaused(stateDB, poolId) {
|
|
t.Fatal("pool should be paused")
|
|
}
|
|
}
|
|
|
|
func TestPausePoolUnauthorized(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
poolId := key.ID()
|
|
|
|
err := pm.PausePool(stateDB, nonAdminAddr, poolId)
|
|
if err != ErrUnauthorized {
|
|
t.Fatalf("expected ErrUnauthorized, got: %v", err)
|
|
}
|
|
|
|
if pm.IsPoolPaused(stateDB, poolId) {
|
|
t.Fatal("pool should not be paused after unauthorized call")
|
|
}
|
|
}
|
|
|
|
func TestPausedPoolPreventsModifyLiquidity(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
caller := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
poolId := key.ID()
|
|
pm.PausePool(stateDB, adminAddr, poolId)
|
|
|
|
params := ModifyLiquidityParams{
|
|
TickLower: -120,
|
|
TickUpper: 120,
|
|
LiquidityDelta: big.NewInt(1000),
|
|
Salt: [32]byte{},
|
|
}
|
|
|
|
_, _, err := pm.ModifyLiquidity(stateDB, caller, key, params, nil)
|
|
if err != ErrPoolPaused {
|
|
t.Fatalf("expected ErrPoolPaused, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// =========================================================================
|
|
// Level 3: Pool-Level Freeze Tests
|
|
// =========================================================================
|
|
|
|
func TestFreezePool(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
poolId := key.ID()
|
|
|
|
err := pm.FreezePool(stateDB, adminAddr, poolId)
|
|
if err != nil {
|
|
t.Fatalf("FreezePool failed: %v", err)
|
|
}
|
|
|
|
if !pm.IsPoolFrozen(stateDB, poolId) {
|
|
t.Fatal("pool should be frozen")
|
|
}
|
|
}
|
|
|
|
func TestFreezePoolUnauthorized(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
poolId := key.ID()
|
|
|
|
err := pm.FreezePool(stateDB, nonAdminAddr, poolId)
|
|
if err != ErrUnauthorized {
|
|
t.Fatalf("expected ErrUnauthorized, got: %v", err)
|
|
}
|
|
|
|
if pm.IsPoolFrozen(stateDB, poolId) {
|
|
t.Fatal("pool should not be frozen after unauthorized call")
|
|
}
|
|
}
|
|
|
|
func TestFreezePoolAlreadyFrozen(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
poolId := key.ID()
|
|
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
err := pm.FreezePool(stateDB, adminAddr, poolId)
|
|
if err != ErrAlreadyFrozen {
|
|
t.Fatalf("expected ErrAlreadyFrozen, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFrozenPoolPreventsModifyLiquidity(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
caller := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
poolId := key.ID()
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
params := ModifyLiquidityParams{
|
|
TickLower: -120,
|
|
TickUpper: 120,
|
|
LiquidityDelta: big.NewInt(1000),
|
|
Salt: [32]byte{},
|
|
}
|
|
|
|
_, _, err := pm.ModifyLiquidity(stateDB, caller, key, params, nil)
|
|
if err != ErrPoolFrozen {
|
|
t.Fatalf("expected ErrPoolFrozen, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFrozenPoolPreventsDonate(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
caller := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
poolId := key.ID()
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
_, err := pm.Donate(stateDB, caller, key, big.NewInt(100), big.NewInt(200))
|
|
if err != ErrPoolFrozen {
|
|
t.Fatalf("expected ErrPoolFrozen, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFrozenPoolCannotBeResumed(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
poolId := key.ID()
|
|
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
err := pm.ResumePool(stateDB, adminAddr, poolId)
|
|
if err != ErrFreezeIrreversible {
|
|
t.Fatalf("expected ErrFreezeIrreversible, got: %v", err)
|
|
}
|
|
|
|
// Pool should still be frozen
|
|
if !pm.IsPoolFrozen(stateDB, poolId) {
|
|
t.Fatal("pool should still be frozen")
|
|
}
|
|
}
|
|
|
|
func TestFrozenPoolCannotBePaused(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
poolId := key.ID()
|
|
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
err := pm.PausePool(stateDB, adminAddr, poolId)
|
|
if err != ErrPoolFrozen {
|
|
t.Fatalf("expected ErrPoolFrozen, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFreezeClearsPauseState(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
poolId := key.ID()
|
|
|
|
// Pause first, then freeze
|
|
pm.PausePool(stateDB, adminAddr, poolId)
|
|
if !pm.IsPoolPaused(stateDB, poolId) {
|
|
t.Fatal("pool should be paused")
|
|
}
|
|
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
// Pause state should be cleared (freeze supersedes)
|
|
if pm.IsPoolPaused(stateDB, poolId) {
|
|
t.Fatal("pool pause should be cleared after freeze")
|
|
}
|
|
if !pm.IsPoolFrozen(stateDB, poolId) {
|
|
t.Fatal("pool should be frozen")
|
|
}
|
|
}
|
|
|
|
// =========================================================================
|
|
// Precedence Tests: DEX pause > Pool freeze > Pool pause
|
|
// =========================================================================
|
|
|
|
// =========================================================================
|
|
// Event Emission Tests
|
|
// =========================================================================
|
|
|
|
func TestPauseResumeEmitsEvents(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
poolId := key.ID()
|
|
|
|
// Initialize the pool so per-pool ops have a pool to act on.
|
|
// Under V5 fix, PausePool/ResumePool/FreezePool require an
|
|
// initialized pool (return ErrPoolNotInitialized otherwise).
|
|
if _, err := pm.Initialize(stateDB, key, new(big.Int).Add(MinSqrtRatio, big.NewInt(1)), nil); err != nil {
|
|
t.Fatalf("Initialize: %v", err)
|
|
}
|
|
// Clear init log so the 5 we assert are the pause/resume/freeze ones.
|
|
stateDB.logs = nil
|
|
|
|
// Pause DEX
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
// Resume DEX
|
|
pm.ResumeDEX(stateDB, adminAddr)
|
|
// Pause pool
|
|
pm.PausePool(stateDB, adminAddr, poolId)
|
|
// Resume pool
|
|
pm.ResumePool(stateDB, adminAddr, poolId)
|
|
// Freeze pool
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
logs := stateDB.Logs()
|
|
if len(logs) != 5 {
|
|
t.Fatalf("expected 5 logs, got %d", len(logs))
|
|
}
|
|
|
|
expected := []common.Hash{
|
|
dexPausedEventSig,
|
|
dexResumedEventSig,
|
|
poolPausedEventSig,
|
|
poolResumedEventSig,
|
|
poolFrozenEventSig,
|
|
}
|
|
|
|
for i, sig := range expected {
|
|
if logs[i].Topics[0] != sig {
|
|
t.Errorf("log[%d]: expected topic %s, got %s", i, sig.Hex(), logs[i].Topics[0].Hex())
|
|
}
|
|
}
|
|
}
|
|
|
|
// =========================================================================
|
|
// Read-Only Access Tests: frozen/paused pools are still readable
|
|
// =========================================================================
|
|
|
|
func TestFrozenPoolIsStillReadable(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
poolId := key.ID()
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
// GetPool should still work on frozen pool
|
|
pool, err := pm.GetPool(stateDB, key)
|
|
if err != nil {
|
|
t.Fatalf("GetPool on frozen pool should succeed: %v", err)
|
|
}
|
|
if !pool.IsInitialized() {
|
|
t.Fatal("frozen pool should still be initialized")
|
|
}
|
|
}
|
|
|
|
func TestPausedPoolIsStillReadable(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
|
|
initPoolWithLiquidity(t, pm, stateDB, key, 1_000_000_000)
|
|
|
|
poolId := key.ID()
|
|
pm.PausePool(stateDB, adminAddr, poolId)
|
|
|
|
pool, err := pm.GetPool(stateDB, key)
|
|
if err != nil {
|
|
t.Fatalf("GetPool on paused pool should succeed: %v", err)
|
|
}
|
|
if !pool.IsInitialized() {
|
|
t.Fatal("paused pool should still be initialized")
|
|
}
|
|
}
|
|
|
|
// =========================================================================
|
|
// Initialize is NOT blocked by pause (pools can be created while paused)
|
|
// This is a deliberate design choice: initialization is admin-initiated
|
|
// and does not move funds.
|
|
// =========================================================================
|
|
|
|
func TestInitializeNotBlockedByDEXPause(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
|
|
sqrtPriceX96 := new(big.Int).Set(Q96)
|
|
_, err := pm.Initialize(stateDB, key, sqrtPriceX96, nil)
|
|
if err != nil {
|
|
t.Fatalf("Initialize should succeed during DEX pause: %v", err)
|
|
}
|
|
}
|
|
|
|
// =========================================================================
|
|
// Flash loan is NOT blocked by pause (reads only, no state mutation of pool)
|
|
// =========================================================================
|
|
|
|
func TestFlashBlockedByDEXPause(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
caller := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
|
recipient := common.HexToAddress("0x2222222222222222222222222222222222222222")
|
|
|
|
sqrtPriceX96 := new(big.Int).Set(Q96)
|
|
pm.Initialize(stateDB, key, sqrtPriceX96, nil)
|
|
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
|
|
params := FlashParams{
|
|
Amount0: big.NewInt(100000),
|
|
Amount1: big.NewInt(200000),
|
|
Recipient: recipient,
|
|
Data: nil,
|
|
}
|
|
|
|
// Flash MUST be blocked during DEX pause — an attacker could exploit
|
|
// flash loans during regulatory halts to manipulate external state.
|
|
_, err := pm.Flash(stateDB, caller, key, params, nil)
|
|
if err != ErrDEXPaused {
|
|
t.Fatalf("Flash should be blocked during DEX pause, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFlashBlockedByPoolFreeze(t *testing.T) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
key := newTestPoolKey()
|
|
caller := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
|
recipient := common.HexToAddress("0x2222222222222222222222222222222222222222")
|
|
|
|
sqrtPriceX96 := new(big.Int).Set(Q96)
|
|
pm.Initialize(stateDB, key, sqrtPriceX96, nil)
|
|
|
|
poolId := key.ID()
|
|
pm.FreezePool(stateDB, adminAddr, poolId)
|
|
|
|
params := FlashParams{
|
|
Amount0: big.NewInt(100000),
|
|
Amount1: big.NewInt(200000),
|
|
Recipient: recipient,
|
|
Data: nil,
|
|
}
|
|
|
|
_, err := pm.Flash(stateDB, caller, key, params, nil)
|
|
if err != ErrPoolFrozen {
|
|
t.Fatalf("Flash should be blocked on frozen pool, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// =========================================================================
|
|
// Benchmark: pause check overhead
|
|
// =========================================================================
|
|
|
|
func BenchmarkCheckPauseState(b *testing.B) {
|
|
pm := newPauseTestPoolManager()
|
|
poolId := newTestPoolKey().ID()
|
|
stateDB := NewMockStateDB()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = pm.checkPauseState(stateDB, poolId)
|
|
}
|
|
}
|
|
|
|
func BenchmarkCheckPauseStatePaused(b *testing.B) {
|
|
pm := newPauseTestPoolManager()
|
|
stateDB := NewMockStateDB()
|
|
pm.PauseDEX(stateDB, adminAddr)
|
|
poolId := newTestPoolKey().ID()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = pm.checkPauseState(stateDB, poolId)
|
|
}
|
|
}
|