Skip to content

Commit

Permalink
feat(perp): move close market from Wasm Binding to MsgCloseMarket as …
Browse files Browse the repository at this point in the history
…part of #1642 (#1749)

* remove mentions of bindings for closing the market.

* create new message for Closing a Market

* temp commit

* add permissions to call the CloseMarket

* make lint

* it fails when closing market with other user

* update changelog
  • Loading branch information
jgimeno authored Jan 2, 2024
1 parent c2a96d5 commit b4175f1
Show file tree
Hide file tree
Showing 17 changed files with 608 additions and 245 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1718](https://github.com/NibiruChain/nibiru/pull/1718) - fix: fees does not require additional funds
* [#1734](https://github.com/NibiruChain/nibiru/pull/1734) - feat(perp): MsgDonateToPerpFund sudo call as part of #1642
* [#1755](https://github.com/NibiruChain/nibiru/pull/1755) - feat(oracle): Add more events on validator's performance
* [#1749](https://github.com/NibiruChain/nibiru/pull/1749) - feat(perp): move close market from Wasm Binding to MsgCloseMarket


### Non-breaking/Compatible Improvements

Expand Down
20 changes: 20 additions & 0 deletions proto/nibiru/perp/v2/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,13 @@ service Msg {
// account. [SUDO] Only callable by sudoers.
rpc WithdrawFromPerpFund(MsgWithdrawFromPerpFund)
returns (MsgWithdrawFromPerpFundResponse) {}

// CloseMarket: gRPC tx msg for closing a market.
// [Admin] Only callable by sudoers.
rpc CloseMarket(MsgCloseMarket) returns (MsgCloseMarketResponse) {}
}


// -------------------------- Settle Position --------------------------

/* MsgSettlePosition: Msg to remove margin. */
Expand Down Expand Up @@ -451,3 +456,18 @@ message MsgWithdrawFromPerpFund {
}

message MsgWithdrawFromPerpFundResponse {}

// -------------------------- CloseMarket --------------------------

// CloseMarket: gRPC tx msg for closing a market.
// Admin-only.
message MsgCloseMarket {
string sender = 1;
string pair = 2 [
(gogoproto.customtype) =
"github.com/NibiruChain/nibiru/x/common/asset.Pair",
(gogoproto.nullable) = false
];
}

message MsgCloseMarketResponse {}
7 changes: 0 additions & 7 deletions wasmbinding/bindings/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
type NibiruMsg struct {
// bindings-perp ExecuteMsg enum types
// MultiLiquidate *MultiLiquidate `json:"multi_liquidate,omitempty"` // TODO
SetMarketEnabled *SetMarketEnabled `json:"set_market_enabled,omitempty"`

EditOracleParams *EditOracleParams `json:"edit_oracle_params,omitempty"`

// Short for "no operation". A wasm binding payload that does nothing.
Expand All @@ -35,11 +33,6 @@ type EditOracleParams struct {
ValidatorFeeRatio *sdk.Dec `json:"validator_fee_ratio,omitempty"`
}

type SetMarketEnabled struct {
Pair string `json:"pair"`
Enabled bool `json:"enabled"`
}

type MarketParams struct {
Pair string
Enabled bool `json:"enabled,omitempty"`
Expand Down
21 changes: 0 additions & 21 deletions wasmbinding/exec_perp.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package wasmbinding

import (
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/NibiruChain/nibiru/wasmbinding/bindings"
"github.com/NibiruChain/nibiru/x/common/asset"
perpv2keeper "github.com/NibiruChain/nibiru/x/perp/v2/keeper"
perpv2types "github.com/NibiruChain/nibiru/x/perp/v2/types"
)
Expand All @@ -17,19 +12,3 @@ type ExecutorPerp struct {
func (exec *ExecutorPerp) MsgServer() perpv2types.MsgServer {
return perpv2keeper.NewMsgServerImpl(exec.PerpV2)
}

// TODO: rename to CloseMarket
func (exec *ExecutorPerp) SetMarketEnabled(
cwMsg *bindings.SetMarketEnabled, ctx sdk.Context,
) (err error) {
if cwMsg == nil {
return wasmvmtypes.InvalidRequest{Err: "null msg"}
}

pair, err := asset.TryNewPair(cwMsg.Pair)
if err != nil {
return err
}

return exec.PerpV2.Sudo().CloseMarket(ctx, pair)
}
31 changes: 0 additions & 31 deletions wasmbinding/exec_perp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/NibiruChain/nibiru/app"
"github.com/NibiruChain/nibiru/wasmbinding"
"github.com/NibiruChain/nibiru/wasmbinding/bindings"
"github.com/NibiruChain/nibiru/wasmbinding/wasmbin"
"github.com/NibiruChain/nibiru/x/common/asset"
"github.com/NibiruChain/nibiru/x/common/denoms"
Expand Down Expand Up @@ -130,33 +129,3 @@ func (s *TestSuitePerpExecutor) OnSetupEnd() {
s.contractPerp = ContractMap[wasmbin.WasmKeyPerpBinding]
s.ratesMap = SetExchangeRates(&s.Suite, s.nibiru, s.ctx)
}

func (s *TestSuitePerpExecutor) DoSetMarketEnabledTest(
pair asset.Pair, enabled bool,
) error {
cwMsg := &bindings.SetMarketEnabled{
Pair: pair.String(),
Enabled: enabled,
}
err := s.exec.SetMarketEnabled(cwMsg, s.ctx)
if err != nil {
return err
}

market, err := s.nibiru.PerpKeeperV2.GetMarket(s.ctx, pair)
s.NoError(err)
s.Equal(enabled, market.Enabled)
return err
}

func (s *TestSuitePerpExecutor) TestSadPaths_InvalidPair() {
sadPair := asset.Pair("ftt:ust:doge")
pair := sadPair

for _, err := range []error{
s.DoSetMarketEnabledTest(pair, true),
s.DoSetMarketEnabledTest(pair, false),
} {
s.Error(err)
}
}
44 changes: 0 additions & 44 deletions wasmbinding/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/NibiruChain/nibiru/x/common/asset"
"github.com/NibiruChain/nibiru/x/common/denoms"
"github.com/NibiruChain/nibiru/x/common/testutil"
"github.com/NibiruChain/nibiru/x/common/testutil/genesis"
"github.com/NibiruChain/nibiru/x/common/testutil/testapp"
"github.com/NibiruChain/nibiru/x/oracle/types"
perpv2types "github.com/NibiruChain/nibiru/x/perp/v2/types"
Expand Down Expand Up @@ -312,46 +311,3 @@ func (s *TestSuiteExecutor) TestNoOp() {
contractRespBz, err := s.ExecuteAgainstContract(contract, execMsg)
s.NoErrorf(err, "contractRespBz: %s", contractRespBz)
}

func (s *TestSuiteExecutor) TestSetMarketEnabled() {
// admin := s.contractDeployer.String()
perpv2Genesis := genesis.PerpV2Genesis()
contract := s.contractController
var execMsg bindings.NibiruMsg

for testIdx, market := range perpv2Genesis.Markets {
execMsg = bindings.NibiruMsg{
SetMarketEnabled: &bindings.SetMarketEnabled{
Pair: market.Pair.String(),
Enabled: !market.Enabled,
},
}

s.T().Logf("Execute - happy %v: market: %s", testIdx, market.Pair)
s.keeper.SetSudoContracts(
[]string{contract.String()}, s.ctx,
)
contractRespBz, err := s.ExecuteAgainstContract(contract, execMsg)
s.NoErrorf(err, "contractRespBz: %s", contractRespBz)

marketAfter, err := s.nibiru.PerpKeeperV2.GetMarket(s.ctx, market.Pair)
s.NoError(err)
s.Equal(!market.Enabled, marketAfter.Enabled)
}

s.T().Log("Executing without permission should fail")
s.keeper.SetSudoContracts(
[]string{}, s.ctx,
)
contractRespBz, err := s.ExecuteAgainstContract(contract, execMsg)
s.Errorf(err, "contractRespBz: %s", contractRespBz)

s.T().Log("Executing the wrong contract should fail")
contract = s.contractPerp
s.keeper.SetSudoContracts(
[]string{contract.String()}, s.ctx,
)
contractRespBz, err = s.ExecuteAgainstContract(contract, execMsg)
s.Errorf(err, "contractRespBz: %s", contractRespBz)
s.Contains(err.Error(), "Error parsing into type")
}
9 changes: 0 additions & 9 deletions wasmbinding/message_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,6 @@ func (messenger *CustomMessenger) DispatchMsg(
}

switch {
// Perp module | controller
case contractExecuteMsg.ExecuteMsg.SetMarketEnabled != nil:
if err := messenger.Sudo.CheckPermissions(contractAddr, ctx); err != nil {
return events, data, err
}
cwMsg := contractExecuteMsg.ExecuteMsg.SetMarketEnabled
err = messenger.Perp.SetMarketEnabled(cwMsg, ctx)
return events, data, err

// Oracle module
case contractExecuteMsg.ExecuteMsg.EditOracleParams != nil:
if err := messenger.Sudo.CheckPermissions(contractAddr, ctx); err != nil {
Expand Down
18 changes: 10 additions & 8 deletions x/perp/v2/integration/action/settlement.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,40 @@ import (

// closeMarket
type closeMarket struct {
pair asset.Pair
pair asset.Pair
sender sdk.AccAddress
}

func (c closeMarket) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error) {
err := app.PerpKeeperV2.Sudo().CloseMarket(ctx, c.pair)
err := app.PerpKeeperV2.Sudo().CloseMarket(ctx, c.pair, c.sender)
if err != nil {
return ctx, err
}

return ctx, nil
}

func CloseMarket(pair asset.Pair) action.Action {
return closeMarket{pair: pair}
func CloseMarket(pair asset.Pair, adminAccount sdk.AccAddress) action.Action {
return closeMarket{pair: pair, sender: adminAccount}
}

// closeMarketShouldFail
type closeMarketShouldFail struct {
pair asset.Pair
pair asset.Pair
sender sdk.AccAddress
}

func (c closeMarketShouldFail) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error) {
err := app.PerpKeeperV2.Sudo().CloseMarket(ctx, c.pair)
err := app.PerpKeeperV2.Sudo().CloseMarket(ctx, c.pair, c.sender)
if err == nil {
return ctx, err
}

return ctx, nil
}

func CloseMarketShouldFail(pair asset.Pair) action.Action {
return closeMarketShouldFail{pair: pair}
func CloseMarketShouldFail(pair asset.Pair, adminAccount sdk.AccAddress) action.Action {
return closeMarketShouldFail{pair: pair, sender: adminAccount}
}

// settlePosition
Expand Down
5 changes: 4 additions & 1 deletion x/perp/v2/keeper/clearing_house_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ func TestMarketOrder(t *testing.T) {
pairBtcNusd := asset.Registry.Pair(denoms.BTC, denoms.NUSD)
startBlockTime := time.Now()

adminUser, err := sdk.AccAddressFromBech32(testutil.ADDR_SUDO_ROOT)
require.NoError(t, err)

tc := TestCases{
TC("open big short position and then close after reducing swap invariant").
Given(
Expand Down Expand Up @@ -885,7 +888,7 @@ func TestMarketOrder(t *testing.T) {
SetBlockTime(startBlockTime),
SetBlockNumber(1),
FundAccount(alice, sdk.NewCoins(sdk.NewCoin(types.TestingCollateralDenomNUSD, sdk.NewInt(47_714_285_715)))),
CloseMarket(pairBtcNusd),
CloseMarket(pairBtcNusd, adminUser),
).
When(
MarketOrderFails(alice, pairBtcNusd, types.Direction_SHORT, sdk.NewInt(47_619_047_619), sdk.OneDec(), sdk.ZeroDec(),
Expand Down
11 changes: 9 additions & 2 deletions x/perp/v2/keeper/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import (
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/NibiruChain/nibiru/x/common/testutil"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/NibiruChain/nibiru/x/common/asset"
Expand All @@ -21,6 +25,9 @@ func TestAfterEpochEnd(t *testing.T) {
pairBtcUsdc := asset.Registry.Pair(denoms.BTC, denoms.USDC)
startTime := time.Now()

adminUser, err := sdk.AccAddressFromBech32(testutil.ADDR_SUDO_ROOT)
require.NoError(t, err)

tc := TestCases{
TC("index > mark").
Given(
Expand Down Expand Up @@ -122,7 +129,7 @@ func TestAfterEpochEnd(t *testing.T) {
TC("market closed").
Given(
CreateCustomMarket(pairBtcUsdc, WithEnabled(true)),
CloseMarket(pairBtcUsdc),
CloseMarket(pairBtcUsdc, adminUser),
SetBlockTime(startTime),
StartEpoch(epochtypes.ThirtyMinuteEpochID),
InsertOraclePriceSnapshot(pairBtcUsd, startTime.Add(15*time.Minute), sdk.NewDec(2)),
Expand All @@ -137,7 +144,7 @@ func TestAfterEpochEnd(t *testing.T) {
TC("not correct epoch id").
Given(
CreateCustomMarket(pairBtcUsdc, WithEnabled(true)),
CloseMarket(pairBtcUsdc),
CloseMarket(pairBtcUsdc, adminUser),
SetBlockTime(startTime),
StartEpoch(epochtypes.DayEpochID),
InsertOraclePriceSnapshot(pairBtcUsd, startTime.Add(15*time.Minute), sdk.NewDec(2)),
Expand Down
7 changes: 7 additions & 0 deletions x/perp/v2/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,10 @@ func (m msgServer) WithdrawFromPerpFund(
ctx, msg.Amount, sender, toAddr, msg.Denom,
)
}

// CloseMarket closes a market.
func (m msgServer) CloseMarket(ctx context.Context, msg *types.MsgCloseMarket) (*types.MsgCloseMarketResponse, error) {
sender, _ := sdk.AccAddressFromBech32(msg.Sender)
err := m.k.Sudo().CloseMarket(sdk.UnwrapSDKContext(ctx), msg.Pair, sender)
return &types.MsgCloseMarketResponse{}, err
}
5 changes: 4 additions & 1 deletion x/perp/v2/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,14 +408,17 @@ func TestMsgServerSettlePosition(t *testing.T) {
pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD)
alice := testutil.AccAddress()

adminUser, err := sdk.AccAddressFromBech32(testutil.ADDR_SUDO_ROOT)
require.NoError(t, err)

tests := TestCases{
TC("Settleposition").
Given(
CreateCustomMarket(pair, WithEnabled(true)),
FundAccount(alice, sdk.NewCoins(sdk.NewInt64Coin(types.TestingCollateralDenomNUSD, 100))),
MarketOrder(alice, pair, types.Direction_LONG, sdk.OneInt(), sdk.OneDec(), sdk.ZeroDec()),
MoveToNextBlock(),
CloseMarket(pair),
CloseMarket(pair, adminUser),
).
When(
MsgServerSettlePosition(alice, pair, 1),
Expand Down
13 changes: 9 additions & 4 deletions x/perp/v2/keeper/settlement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"testing"
"time"

"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/NibiruChain/nibiru/x/common/asset"
Expand All @@ -23,6 +25,9 @@ func TestSettlePosition(t *testing.T) {
alice := testutil.AccAddress()
bob := testutil.AccAddress()

adminUser, err := sdk.AccAddressFromBech32(testutil.ADDR_SUDO_ROOT)
require.NoError(t, err)

tc := TestCases{
TC("Happy path").When(
CreateCustomMarket(
Expand All @@ -43,7 +48,7 @@ func TestSettlePosition(t *testing.T) {
sdk.ZeroDec(),
),
).When(
CloseMarket(pairBtcUsdc),
CloseMarket(pairBtcUsdc, adminUser),
SettlePosition(pairBtcUsdc, 1, alice),
).Then(
PositionShouldNotExist(alice, pairBtcUsdc, 1),
Expand Down Expand Up @@ -84,7 +89,7 @@ func TestSettlePosition(t *testing.T) {
// Her Realized Pnl is -101.01010101 and her margin is 100, so -1.01010101 is bad debt
// Bob's Realized Pnl is 1010, so he has 1010 more than his margin

CloseMarket(pairBtcUsdc),
CloseMarket(pairBtcUsdc, adminUser),
SettlePosition(
pairBtcUsdc,
1,
Expand Down Expand Up @@ -160,7 +165,7 @@ func TestSettlePosition(t *testing.T) {
sdk.ZeroDec(),
),
).When(
CloseMarket(pairBtcUsdc),
CloseMarket(pairBtcUsdc, adminUser),
CreateCustomMarket(
pairBtcUsdc,
WithPricePeg(sdk.OneDec()),
Expand Down Expand Up @@ -206,7 +211,7 @@ func TestSettlePosition(t *testing.T) {
sdk.ZeroDec(),
),
).When(
CloseMarket(pairBtcUsdc),
CloseMarket(pairBtcUsdc, adminUser),
CreateCustomMarket(
pairBtcUsdc,
WithPricePeg(sdk.OneDec()),
Expand Down
Loading

0 comments on commit b4175f1

Please sign in to comment.