Skip to content

Commit

Permalink
refactor: remove client interface for liquidate msg (#1164)
Browse files Browse the repository at this point in the history
* remove client interface for liquidate msg

* add a change log
  • Loading branch information
tj327 authored Feb 1, 2023
1 parent b7d30b3 commit 874a9a9
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 792 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Improvements

* [#1164](https://github.com/NibiruChain/nibiru/pull/1164) - refactor: remove client interface for liquidate msg
* [#1156](https://github.com/NibiruChain/nibiru/pull/1156) - refactor: remove lockup & incentivation module
* [#1134](https://github.com/NibiruChain/nibiru/pull/1134) - refactor: remove panics from vpool and spillovers from the perp module. It's now impossible to call functions in x/perp that would panic in vpool.
* [#1127](https://github.com/NibiruChain/nibiru/pull/1127) - refactor: remove unnecessary panics from x/dex and x/stablecoin
Expand Down
20 changes: 0 additions & 20 deletions proto/perp/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ service Msg {
option (google.api.http).post = "/nibiru/perp/add_margin";
}

/* Liquidate is a transaction that allows the caller to fully or partially
liquidate an existing position. */
rpc Liquidate(MsgLiquidate) returns (MsgLiquidateResponse) {
option (google.api.http).post = "/nibiru/perp/liquidate";
}

rpc MultiLiquidate(MsgMultiLiquidate) returns (MsgMultiLiquidateResponse) {
option (google.api.http).post = "/nibiru/perp/multiliquidate";
}
Expand Down Expand Up @@ -94,20 +88,6 @@ message MsgAddMarginResponse {

// -------------------------- Liquidate --------------------------

message MsgLiquidate {
// Sender is the liquidator address
string sender = 1;

// TokenPair is the identifier for the position's virtual pool
string pair = 2 [
(gogoproto.customtype) = "github.com/NibiruChain/nibiru/x/common.AssetPair",
(gogoproto.nullable) = false
];

// Trader is the address of the owner of the position
string trader = 3;
}

message MsgLiquidateResponse {
cosmos.base.v1beta1.Coin fee_to_liquidator = 1 [(gogoproto.nullable) = false];
cosmos.base.v1beta1.Coin fee_to_perp_ecosystem_fund = 2 [(gogoproto.nullable) = false];
Expand Down
52 changes: 0 additions & 52 deletions x/perp/client/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,58 +436,6 @@ func (s *IntegrationTestSuite) TestX_AddMargin() {
}
}

func (s *IntegrationTestSuite) TestLiquidate() {
s.T().Log("liquidate a position that does not exist")
_, err := testutilcli.ExecTx(s.network, cli.LiquidateCmd(), s.users[4], []string{
asset.Registry.Pair(denoms.ETH, denoms.NUSD).String(),
s.users[1].String(),
})
s.Contains(err.Error(), collections.ErrNotFound.Error())

s.T().Log("opening a position with user 1....")
txResp, err := testutilcli.ExecTx(s.network, cli.OpenPositionCmd(), s.users[1], []string{
"buy",
asset.Registry.Pair(denoms.ETH, denoms.NUSD).String(),
"15", // Leverage
"90000", // Quote asset amount
"0",
})
s.NoError(err)
s.EqualValues(abcitypes.CodeTypeOK, txResp.Code)

s.T().Log("liquidate a position that is above maintenance margin mario")
_, err = testutilcli.ExecTx(s.network, cli.LiquidateCmd(), s.users[4], []string{
asset.Registry.Pair(denoms.ETH, denoms.NUSD).String(),
s.users[1].String(),
})
s.Contains(err.Error(), "margin ratio is too healthy to liquidate")

s.T().Log("opening a position with user 2...")
txResp, err = testutilcli.ExecTx(s.network, cli.OpenPositionCmd(), s.users[2], []string{
"sell",
asset.Registry.Pair(denoms.ETH, denoms.NUSD).String(),
"15", // Leverage
"45000000", // Quote asset amount
"0",
})
s.NoError(err)
s.EqualValues(abcitypes.CodeTypeOK, txResp.Code)

s.T().Log("wait 10 blocks")
height, err := s.network.LatestHeight()
s.NoError(err)
_, err = s.network.WaitForHeight(height + 10)
s.NoError(err)

s.T().Log("liquidating user 1...")
txResp, err = testutilcli.ExecTx(s.network, cli.LiquidateCmd(), s.users[4], []string{
asset.Registry.Pair(denoms.ETH, denoms.NUSD).String(),
s.users[1].String(),
})
s.NoError(err)
s.EqualValues(abcitypes.CodeTypeOK, txResp.Code)
}

func (s *IntegrationTestSuite) TestDonateToEcosystemFund() {
s.T().Logf("donate to ecosystem fund")
out, err := testutilcli.ExecTx(s.network, cli.DonateToEcosystemFundCmd(), sdk.MustAccAddressFromBech32("nibi1w89pf5yq8ntjg89048qmtaz929fdxup0a57d8m"), []string{"100unusd"})
Expand Down
45 changes: 0 additions & 45 deletions x/perp/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ func GetTxCmd() *cobra.Command {
txCmd.AddCommand(
RemoveMarginCmd(),
AddMarginCmd(),
LiquidateCmd(),
OpenPositionCmd(),
ClosePositionCmd(),
DonateToEcosystemFundCmd(),
Expand Down Expand Up @@ -219,50 +218,6 @@ func AddMarginCmd() *cobra.Command {
return cmd
}

func LiquidateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "liquidate [vpool] [trader]",
Short: "liquidates the position of 'trader' on 'vpool' if possible",
Long: strings.TrimSpace(
fmt.Sprintf(`
$ %s tx perp liquidate osmo:nusd nibi1zaavvzxez0elundtn32qnk9lkm8kmcsz44g7xl
`, version.AppName),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

traderAddr, err := sdk.AccAddressFromBech32(args[1])
if err != nil {
return err
}

pair, err := common.TryNewAssetPair(args[0])
if err != nil {
return err
}

msg := &types.MsgLiquidate{
Sender: clientCtx.GetFromAddress().String(),
Pair: pair,
Trader: traderAddr.String(),
}
if err = msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

func DonateToEcosystemFundCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "donate-ef [amount]",
Expand Down
3 changes: 0 additions & 3 deletions x/perp/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
case *types.MsgOpenPosition:
res, err := msgServer.OpenPosition(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgLiquidate:
res, err := msgServer.Liquidate(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgClosePosition:
res, err := msgServer.ClosePosition(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
Expand Down
19 changes: 0 additions & 19 deletions x/perp/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,6 @@ func (m msgServer) ClosePosition(goCtx context.Context, position *types.MsgClose
}, nil
}

func (m msgServer) Liquidate(goCtx context.Context, msg *types.MsgLiquidate,
) (*types.MsgLiquidateResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

liquidatorAddr := sdk.MustAccAddressFromBech32(msg.Sender)

traderAddr := sdk.MustAccAddressFromBech32(msg.Trader)

feeToLiquidator, feeToFund, err := m.k.Liquidate(ctx, liquidatorAddr, msg.Pair, traderAddr)
if err != nil {
return nil, err
}

return &types.MsgLiquidateResponse{
FeeToLiquidator: feeToLiquidator,
FeeToPerpEcosystemFund: feeToFund,
}, nil
}

func (m msgServer) MultiLiquidate(goCtx context.Context, req *types.MsgMultiLiquidate) (*types.MsgMultiLiquidateResponse, error) {
positions := make([]MultiLiquidationRequest, len(req.Liquidations))
for i, pos := range req.Liquidations {
Expand Down
82 changes: 0 additions & 82 deletions x/perp/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,88 +424,6 @@ func TestMsgServerClosePosition(t *testing.T) {
}
}

func TestMsgServerLiquidate(t *testing.T) {
tests := []struct {
name string

pair common.AssetPair
liquidator string
trader string

expectedErr error
}{
{
name: "success",
pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD),
liquidator: testutil.AccAddress().String(),
trader: testutil.AccAddress().String(),
expectedErr: nil,
},
}

for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
app, ctx := nibisimapp.NewTestNibiruAppAndContext(true)
ctx = ctx.WithBlockTime(time.Now())
setLiquidator(ctx, app.PerpKeeper, tc.liquidator)
msgServer := keeper.NewMsgServerImpl(app.PerpKeeper)

t.Log("create vpool")
assert.NoError(t, app.VpoolKeeper.CreatePool(
/* ctx */ ctx,
/* pair */ asset.Registry.Pair(denoms.BTC, denoms.NUSD),
/* quoteAssetReserve */ sdk.NewDec(1*common.Precision),
/* baseAssetReserve */ sdk.NewDec(1*common.Precision),
vpooltypes.VpoolConfig{
TradeLimitRatio: sdk.OneDec(),
FluctuationLimitRatio: sdk.OneDec(),
MaxOracleSpreadRatio: sdk.OneDec(),
MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"),
MaxLeverage: sdk.MustNewDecFromStr("15"),
},
))
setPairMetadata(app.PerpKeeper, ctx, types.PairMetadata{
Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD),
LatestCumulativePremiumFraction: sdk.ZeroDec(),
})
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1).WithBlockTime(time.Now().Add(time.Minute))

traderAddr, err := sdk.AccAddressFromBech32(tc.trader)
if err == nil {
t.Log("set oracle price")
app.OracleKeeper.SetPrice(ctx, asset.Registry.Pair(denoms.BTC, denoms.NUSD), sdk.OneDec())

t.Log("create position")
setPosition(app.PerpKeeper, ctx, types.Position{
TraderAddress: traderAddr.String(),
Pair: tc.pair,
Size_: sdk.OneDec(),
Margin: sdk.OneDec(),
OpenNotional: sdk.NewDec(2), // new spot price is 1, so position can be liquidated
LatestCumulativePremiumFraction: sdk.ZeroDec(),
BlockNumber: 1,
})
require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, types.VaultModuleAccount, sdk.NewCoins(sdk.NewInt64Coin(tc.pair.QuoteDenom(), 1))))
}

resp, err := msgServer.Liquidate(sdk.WrapSDKContext(ctx), &types.MsgLiquidate{
Sender: tc.liquidator,
Pair: tc.pair,
Trader: tc.trader,
})

if tc.expectedErr != nil {
require.ErrorContains(t, err, tc.expectedErr.Error())
require.Nil(t, resp)
} else {
require.NoError(t, err)
require.NotNil(t, resp)
}
})
}
}

func setLiquidator(ctx sdk.Context, perpKeeper keeper.Keeper, liquidator string) {
p := perpKeeper.GetParams(ctx)
p.WhitelistedLiquidators = []string{liquidator}
Expand Down
2 changes: 0 additions & 2 deletions x/perp/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
func RegisterCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgRemoveMargin{}, "perp/remove_margin", nil)
cdc.RegisterConcrete(&MsgAddMargin{}, "perp/add_margin", nil)
cdc.RegisterConcrete(&MsgLiquidate{}, "perp/liquidate", nil)
cdc.RegisterConcrete(&MsgClosePosition{}, "perp/close_position", nil)
}

Expand All @@ -20,7 +19,6 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
/* implementations */
&MsgRemoveMargin{},
&MsgAddMargin{},
&MsgLiquidate{},
&MsgOpenPosition{},
&MsgClosePosition{},
&MsgMultiLiquidate{},
Expand Down
31 changes: 0 additions & 31 deletions x/perp/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

var _ sdk.Msg = &MsgRemoveMargin{}
var _ sdk.Msg = &MsgAddMargin{}
var _ sdk.Msg = &MsgLiquidate{}
var _ sdk.Msg = &MsgOpenPosition{}
var _ sdk.Msg = &MsgClosePosition{}
var _ sdk.Msg = &MsgMultiLiquidate{}
Expand Down Expand Up @@ -130,36 +129,6 @@ func (m *MsgOpenPosition) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{signer}
}

// MsgLiquidate

func (m MsgLiquidate) Route() string { return RouterKey }
func (m MsgLiquidate) Type() string { return "liquidate_msg" }

func (m MsgLiquidate) ValidateBasic() (err error) {
if _, err = sdk.AccAddressFromBech32(m.Sender); err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err)
}
if _, err = sdk.AccAddressFromBech32(m.Trader); err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid trader address (%s)", err)
}
if err := m.Pair.Validate(); err != nil {
return err
}
return nil
}

func (m MsgLiquidate) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m))
}

func (m MsgLiquidate) GetSigners() []sdk.AccAddress {
signer, err := sdk.AccAddressFromBech32(m.Sender)
if err != nil {
panic(err)
}
return []sdk.AccAddress{signer}
}

// MsgMultiLiquidate

func (m *MsgMultiLiquidate) ValidateBasic() error {
Expand Down
Loading

0 comments on commit 874a9a9

Please sign in to comment.