From 15e06c45c0d95fdc0dabb9ec4421f1ec52746686 Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Mon, 23 Oct 2023 22:58:20 -0500 Subject: [PATCH] refactor(settlement): move CloseMarket -> admin.go --- x/perp/v2/keeper/admin.go | 31 ++++++++ x/perp/v2/keeper/admin_test.go | 110 ++++++++++++++++++++++++++++ x/perp/v2/keeper/settlement.go | 31 -------- x/perp/v2/keeper/settlement_test.go | 105 -------------------------- 4 files changed, 141 insertions(+), 136 deletions(-) diff --git a/x/perp/v2/keeper/admin.go b/x/perp/v2/keeper/admin.go index ae7e252be..6345f6958 100644 --- a/x/perp/v2/keeper/admin.go +++ b/x/perp/v2/keeper/admin.go @@ -113,3 +113,34 @@ func (k admin) CreateMarket( return nil } + +// CloseMarket closes the market. From now on, no new position can be opened on +// this market or closed. Only the open positions can be settled by calling +// SettlePosition. +func (k admin) CloseMarket(ctx sdk.Context, pair asset.Pair) (err error) { + market, err := k.GetMarket(ctx, pair) + if err != nil { + return err + } + if !market.Enabled { + return types.ErrMarketNotEnabled + } + + amm, err := k.GetAMM(ctx, pair) + if err != nil { + return err + } + + settlementPrice, _, err := amm.ComputeSettlementPrice() + if err != nil { + return + } + + amm.SettlementPrice = settlementPrice + market.Enabled = false + + k.SaveAMM(ctx, amm) + k.SaveMarket(ctx, market) + + return nil +} diff --git a/x/perp/v2/keeper/admin_test.go b/x/perp/v2/keeper/admin_test.go index b401026b3..66fe05d2b 100644 --- a/x/perp/v2/keeper/admin_test.go +++ b/x/perp/v2/keeper/admin_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "testing" + "time" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -15,6 +16,10 @@ import ( "github.com/NibiruChain/nibiru/x/common/testutil/testapp" "github.com/NibiruChain/nibiru/x/perp/v2/keeper" "github.com/NibiruChain/nibiru/x/perp/v2/types" + + . "github.com/NibiruChain/nibiru/x/common/testutil/action" + . "github.com/NibiruChain/nibiru/x/perp/v2/integration/action" + . "github.com/NibiruChain/nibiru/x/perp/v2/integration/assertion" ) func TestAdmin_WithdrawFromInsuranceFund(t *testing.T) { @@ -160,3 +165,108 @@ func TestCreateMarket(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(2), market.Version) } + +func TestCloseMarket(t *testing.T) { + pairBtcUsdc := asset.Registry.Pair(denoms.BTC, denoms.NUSD) + startTime := time.Now() + alice := testutil.AccAddress() + + tc := TestCases{ + TC("market can be disabled"). + Given( + CreateCustomMarket(pairBtcUsdc, WithEnabled(true)), + SetBlockTime(startTime), + MarketShouldBeEqual( + pairBtcUsdc, + Market_EnableShouldBeEqualTo(true), + ), + ). + When( + CloseMarket(pairBtcUsdc), + ). + Then( + MarketShouldBeEqual( + pairBtcUsdc, + Market_EnableShouldBeEqualTo(false), + ), + ), + TC("cannot open position on disabled market"). + Given( + CreateCustomMarket( + pairBtcUsdc, + WithEnabled(true), + WithPricePeg(sdk.OneDec()), + WithSqrtDepth(sdk.NewDec(100_000)), + ), + SetBlockNumber(1), + SetBlockTime(startTime), + + FundAccount(alice, sdk.NewCoins(sdk.NewCoin(denoms.NUSD, sdk.NewInt(1e6)))), + ). + When( + CloseMarket(pairBtcUsdc), + ). + Then( + MarketOrderFails( + alice, + pairBtcUsdc, + types.Direction_LONG, + sdk.NewInt(10_000), + sdk.OneDec(), + sdk.ZeroDec(), + types.ErrMarketNotEnabled, + ), + ), + TC("cannot close position on disabled market").When( + CreateCustomMarket( + pairBtcUsdc, + WithPricePeg(sdk.OneDec()), + WithSqrtDepth(sdk.NewDec(100_000)), + WithEnabled(true), + ), + SetBlockNumber(1), + SetBlockTime(startTime), + FundAccount(alice, sdk.NewCoins(sdk.NewCoin(denoms.NUSD, sdk.NewInt(10_200)))), + MarketOrder( + alice, + pairBtcUsdc, + types.Direction_LONG, + sdk.NewInt(10_000), + sdk.OneDec(), + sdk.ZeroDec(), + ), + ).When( + CloseMarket(pairBtcUsdc), + CloseMarketShouldFail(pairBtcUsdc), + CloseMarketShouldFail("random:pair"), + ).Then( + ClosePositionFails(alice, pairBtcUsdc, types.ErrMarketNotEnabled), + ), + TC("cannot partial close position on disabled market").When( + CreateCustomMarket( + pairBtcUsdc, + WithPricePeg(sdk.OneDec()), + WithSqrtDepth(sdk.NewDec(100_000)), + WithEnabled(true), + ), + SetBlockNumber(1), + SetBlockTime(startTime), + FundAccount(alice, sdk.NewCoins(sdk.NewCoin(denoms.NUSD, sdk.NewInt(10_200)))), + MarketOrder( + alice, + pairBtcUsdc, + types.Direction_LONG, + sdk.NewInt(10_000), + sdk.OneDec(), + sdk.ZeroDec(), + ), + ).When( + CloseMarket(pairBtcUsdc), + AMMShouldBeEqual(pairBtcUsdc, AMM_SettlementPriceShoulBeEqual(sdk.MustNewDecFromStr("1.1"))), + ).Then( + PartialCloseFails(alice, pairBtcUsdc, sdk.NewDec(5_000), types.ErrMarketNotEnabled), + ), + } + + NewTestSuite(t).WithTestCases(tc...).Run() +} diff --git a/x/perp/v2/keeper/settlement.go b/x/perp/v2/keeper/settlement.go index e64394472..970cd3a37 100644 --- a/x/perp/v2/keeper/settlement.go +++ b/x/perp/v2/keeper/settlement.go @@ -7,37 +7,6 @@ import ( "github.com/NibiruChain/nibiru/x/perp/v2/types" ) -// CloseMarket closes the market. From now on, no new position can be opened on -// this market or closed. Only the open positions can be settled by calling -// SettlePosition. -func (k admin) CloseMarket(ctx sdk.Context, pair asset.Pair) (err error) { - market, err := k.GetMarket(ctx, pair) - if err != nil { - return err - } - if !market.Enabled { - return types.ErrMarketNotEnabled - } - - amm, err := k.GetAMM(ctx, pair) - if err != nil { - return err - } - - settlementPrice, _, err := amm.ComputeSettlementPrice() - if err != nil { - return - } - - amm.SettlementPrice = settlementPrice - market.Enabled = false - - k.SaveAMM(ctx, amm) - k.SaveMarket(ctx, market) - - return nil -} - // SettlePosition settles a position and transfer the margin and funding payments to the trader. func (k Keeper) SettlePosition(ctx sdk.Context, pair asset.Pair, version uint64, traderAddr sdk.AccAddress) (resp *types.PositionResp, err error) { market, err := k.GetMarketByPairAndVersion(ctx, pair, version) diff --git a/x/perp/v2/keeper/settlement_test.go b/x/perp/v2/keeper/settlement_test.go index 30a0ef6c8..74b748457 100644 --- a/x/perp/v2/keeper/settlement_test.go +++ b/x/perp/v2/keeper/settlement_test.go @@ -16,111 +16,6 @@ import ( "github.com/NibiruChain/nibiru/x/perp/v2/types" ) -func TestDisableMarket(t *testing.T) { - pairBtcUsdc := asset.Registry.Pair(denoms.BTC, denoms.NUSD) - startTime := time.Now() - alice := testutil.AccAddress() - - tc := TestCases{ - TC("market can be disabled"). - Given( - CreateCustomMarket(pairBtcUsdc, WithEnabled(true)), - SetBlockTime(startTime), - MarketShouldBeEqual( - pairBtcUsdc, - Market_EnableShouldBeEqualTo(true), - ), - ). - When( - CloseMarket(pairBtcUsdc), - ). - Then( - MarketShouldBeEqual( - pairBtcUsdc, - Market_EnableShouldBeEqualTo(false), - ), - ), - TC("cannot open position on disabled market"). - Given( - CreateCustomMarket( - pairBtcUsdc, - WithEnabled(true), - WithPricePeg(sdk.OneDec()), - WithSqrtDepth(sdk.NewDec(100_000)), - ), - SetBlockNumber(1), - SetBlockTime(startTime), - - FundAccount(alice, sdk.NewCoins(sdk.NewCoin(denoms.NUSD, sdk.NewInt(1e6)))), - ). - When( - CloseMarket(pairBtcUsdc), - ). - Then( - MarketOrderFails( - alice, - pairBtcUsdc, - types.Direction_LONG, - sdk.NewInt(10_000), - sdk.OneDec(), - sdk.ZeroDec(), - types.ErrMarketNotEnabled, - ), - ), - TC("cannot close position on disabled market").When( - CreateCustomMarket( - pairBtcUsdc, - WithPricePeg(sdk.OneDec()), - WithSqrtDepth(sdk.NewDec(100_000)), - WithEnabled(true), - ), - SetBlockNumber(1), - SetBlockTime(startTime), - FundAccount(alice, sdk.NewCoins(sdk.NewCoin(denoms.NUSD, sdk.NewInt(10_200)))), - MarketOrder( - alice, - pairBtcUsdc, - types.Direction_LONG, - sdk.NewInt(10_000), - sdk.OneDec(), - sdk.ZeroDec(), - ), - ).When( - CloseMarket(pairBtcUsdc), - CloseMarketShouldFail(pairBtcUsdc), - CloseMarketShouldFail("random:pair"), - ).Then( - ClosePositionFails(alice, pairBtcUsdc, types.ErrMarketNotEnabled), - ), - TC("cannot partial close position on disabled market").When( - CreateCustomMarket( - pairBtcUsdc, - WithPricePeg(sdk.OneDec()), - WithSqrtDepth(sdk.NewDec(100_000)), - WithEnabled(true), - ), - SetBlockNumber(1), - SetBlockTime(startTime), - FundAccount(alice, sdk.NewCoins(sdk.NewCoin(denoms.NUSD, sdk.NewInt(10_200)))), - MarketOrder( - alice, - pairBtcUsdc, - types.Direction_LONG, - sdk.NewInt(10_000), - sdk.OneDec(), - sdk.ZeroDec(), - ), - ).When( - CloseMarket(pairBtcUsdc), - AMMShouldBeEqual(pairBtcUsdc, AMM_SettlementPriceShoulBeEqual(sdk.MustNewDecFromStr("1.1"))), - ).Then( - PartialCloseFails(alice, pairBtcUsdc, sdk.NewDec(5_000), types.ErrMarketNotEnabled), - ), - } - - NewTestSuite(t).WithTestCases(tc...).Run() -} - func TestSettlePosition(t *testing.T) { pairBtcUsdc := asset.Registry.Pair(denoms.BTC, denoms.NUSD) startTime := time.Now()