Skip to content

Commit

Permalink
Merge branch 'master' into mat/module-test-perp
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasmatt authored Aug 2, 2023
2 parents 53d5c59 + b1477cd commit 828589a
Show file tree
Hide file tree
Showing 24 changed files with 1,220 additions and 308 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1495](https://github.com/NibiruChain/nibiru/pull/1495) - feat: add genmsg module
* [#1517](https://github.com/NibiruChain/nibiru/pull/1517) - test: add more tests to x/hooks
* [#1518](https://github.com/NibiruChain/nibiru/pull/1518) - test: add more tests to x/perp
* [#1519](https://github.com/NibiruChain/nibiru/pull/1519) - test: add more tests to x/perp keeper
* [#1520](https://github.com/NibiruChain/nibiru/pull/1520) - feat(wasm): no op handler + tests with updated contracts
* [#1521](https://github.com/NibiruChain/nibiru/pull/1521) - test(sudo): increase unit test coverage
* [#1523](https://github.com/NibiruChain/nibiru/pull/1523) - chore: bump cosmos-sdk to v0.47.4
* [#1533](https://github.com/NibiruChain/nibiru/pull/1533) - feat(perp): add differential fields to PositionChangedEvent

### Features

Expand Down
18 changes: 18 additions & 0 deletions proto/nibiru/perp/v2/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,24 @@ message PositionChangedEvent {
// - CHANGE_REASON_CLOSE_POSITION: An existing position was closed.
string change_reason = 9
[ (gogoproto.customtype) = "ChangeReason", (gogoproto.nullable) = false ];

// exchanged_size represent the change in size for an existing position
// after the change. A positive value indicates that the position size
// increased, while a negative value indicates that the position size
// decreased.
string exchanged_size = 10 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];

// exchanged_notional represent the change in notional for an existing
// position after the change. A positive value indicates that the position
// notional increased, while a negative value indicates that the position
// notional decreased.
string exchanged_notional = 11 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}

// Emitted when a position is liquidated. Wraps a PositionChanged event since a
Expand Down
33 changes: 33 additions & 0 deletions x/perp/v2/integration/action/margin.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,39 @@ func (a addMarginAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, e
return ctx, nil, true
}

// AddMarginFail adds margin to the position expecting a fail
func AddMarginFail(
account sdk.AccAddress,
pair asset.Pair,
margin sdkmath.Int,
err error,
) action.Action {
return &addMarginFailAction{
Account: account,
Pair: pair,
Margin: margin,
ExpectedErr: err,
}
}

type addMarginFailAction struct {
Account sdk.AccAddress
Pair asset.Pair
Margin sdkmath.Int
ExpectedErr error
}

func (a addMarginFailAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
_, err := app.PerpKeeperV2.AddMargin(
ctx, a.Pair, a.Account, sdk.NewCoin(a.Pair.QuoteDenom(), a.Margin),
)
if !errors.Is(err, a.ExpectedErr) {
return ctx, err, false
}

return ctx, nil, false
}

func RemoveMargin(
account sdk.AccAddress,
pair asset.Pair,
Expand Down
46 changes: 32 additions & 14 deletions x/perp/v2/integration/action/market.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package action

import (
"fmt"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"

Expand All @@ -14,6 +16,22 @@ import (
"github.com/NibiruChain/nibiru/x/perp/v2/types"
)

// Logger
type logger struct {
log string
}

func (e logger) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
fmt.Println(e.log)
return ctx, nil, true
}

func Log(log string) action.Action {
return logger{
log: log,
}
}

// createMarketAction creates a market
type createMarketAction struct {
Market types.Market
Expand Down Expand Up @@ -63,9 +81,9 @@ func WithPrepaidBadDebt(amount sdkmath.Int) marketModifier {
}
}

func WithPricePeg(multiplier sdk.Dec) marketModifier {
func WithPricePeg(newValue sdk.Dec) marketModifier {
return func(market *types.Market, amm *types.AMM) {
amm.PriceMultiplier = multiplier
amm.PriceMultiplier = newValue
}
}

Expand Down Expand Up @@ -96,36 +114,36 @@ func WithLatestMarketCPF(amount sdk.Dec) marketModifier {
}

type editPriceMultiplier struct {
pair asset.Pair
multiplier sdk.Dec
pair asset.Pair
newValue sdk.Dec
}

func (e editPriceMultiplier) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
err := app.PerpKeeperV2.EditPriceMultiplier(ctx, e.pair, e.multiplier)
err := app.PerpKeeperV2.EditPriceMultiplier(ctx, e.pair, e.newValue)
return ctx, err, true
}

func EditPriceMultiplier(pair asset.Pair, multiplier sdk.Dec) action.Action {
func EditPriceMultiplier(pair asset.Pair, newValue sdk.Dec) action.Action {
return editPriceMultiplier{
pair: pair,
multiplier: multiplier,
pair: pair,
newValue: newValue,
}
}

type editSwapInvariant struct {
pair asset.Pair
multiplier sdk.Dec
pair asset.Pair
newValue sdk.Dec
}

func (e editSwapInvariant) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
err := app.PerpKeeperV2.EditSwapInvariant(ctx, e.pair, e.multiplier)
err := app.PerpKeeperV2.EditSwapInvariant(ctx, e.pair, e.newValue)
return ctx, err, true
}

func EditSwapInvariant(pair asset.Pair, multiplier sdk.Dec) action.Action {
func EditSwapInvariant(pair asset.Pair, newValue sdk.Dec) action.Action {
return editSwapInvariant{
pair: pair,
multiplier: multiplier,
pair: pair,
newValue: newValue,
}
}

Expand Down
91 changes: 91 additions & 0 deletions x/perp/v2/integration/action/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,94 @@ func QueryPositionNotFound(pair asset.Pair, traderAddress sdk.AccAddress) action
traderAddress: traderAddress,
}
}

type queryMarkets struct {
allResponseCheckers []QueryMarketsChecker
}

func (q queryMarkets) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
queryServer := keeper.NewQuerier(app.PerpKeeperV2)

resp, err := queryServer.QueryMarkets(sdk.WrapSDKContext(ctx), &types.QueryMarketsRequest{})
if err != nil {
return ctx, err, false
}

for _, marketsCheckers := range q.allResponseCheckers {
if err := marketsCheckers(resp.AmmMarkets); err != nil {
return ctx, err, false
}
}

return ctx, nil, false
}

func QueryMarkets(responseCheckers ...QueryMarketsChecker) action.Action {
return queryMarkets{
allResponseCheckers: responseCheckers,
}
}

type QueryMarketsChecker func(resp []types.AmmMarket) error

func QueryMarkets_MarketsShouldContain(expectedMarket types.Market) QueryMarketsChecker {
return func(resp []types.AmmMarket) error {
for _, market := range resp {
if types.MarketsAreEqual(&expectedMarket, &market.Market) == nil {
return nil
}
}
marketsStr := make([]string, len(resp))
for i, market := range resp {
marketsStr[i] = market.Market.String()
}
return fmt.Errorf("expected markets to contain %s but found %s", expectedMarket.String(), marketsStr)
}
}

type queryModuleAccounts struct {
allResponseCheckers []QueryModuleAccountsChecker
}

func (q queryModuleAccounts) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
queryServer := keeper.NewQuerier(app.PerpKeeperV2)

resp, err := queryServer.ModuleAccounts(sdk.WrapSDKContext(ctx), &types.QueryModuleAccountsRequest{})
if err != nil {
return ctx, err, false
}

for _, accountsCheckers := range q.allResponseCheckers {
if err := accountsCheckers(resp.Accounts); err != nil {
return ctx, err, false
}
}

return ctx, nil, false
}

func QueryModuleAccounts(responseCheckers ...QueryModuleAccountsChecker) action.Action {
return queryModuleAccounts{allResponseCheckers: responseCheckers}
}

type QueryModuleAccountsChecker func(resp []types.AccountWithBalance) error

func QueryModuleAccounts_ModulesBalanceShouldBe(expectedBalance map[string]sdk.Coins) QueryModuleAccountsChecker {
return func(resp []types.AccountWithBalance) error {
for name, balance := range expectedBalance {
found := false
for _, account := range resp {
if account.Name == name {
found = true
if !account.Balance.IsEqual(balance) {
return fmt.Errorf("expected module %s to have balance %s, got %s", name, balance, account.Balance)
}
}
}
if !found {
return fmt.Errorf("expected module %s to have balance %s but not found", name, balance)
}
}
return nil
}
}
31 changes: 31 additions & 0 deletions x/perp/v2/integration/action/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,37 @@ func MsgServerClosePosition(
}
}

type msgServerPartialClose struct {
pair asset.Pair
traderAddress sdk.AccAddress
size sdk.Dec
}

func (m msgServerPartialClose) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
msgServer := keeper.NewMsgServerImpl(app.PerpKeeperV2)

// don't need to check response because it's already checked in clearing_house tests
_, err := msgServer.PartialClose(sdk.WrapSDKContext(ctx), &types.MsgPartialClose{
Pair: m.pair,
Sender: m.traderAddress.String(),
Size_: m.size,
})

return ctx, err, true
}

func MsgServerPartialClosePosition(
traderAddress sdk.AccAddress,
pair asset.Pair,
size sdk.Dec,
) action.Action {
return msgServerPartialClose{
pair: pair,
traderAddress: traderAddress,
size: size,
}
}

type msgServerAddmargin struct {
pair asset.Pair
traderAddress sdk.AccAddress
Expand Down
12 changes: 0 additions & 12 deletions x/perp/v2/keeper/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,6 @@ func (k admin) WithdrawFromInsuranceFund(
return nil
}

func (k admin) SetMarketEnabled(
ctx sdk.Context, pair asset.Pair, enabled bool,
) (err error) {
market, err := k.Markets.Get(ctx, pair)
if err != nil {
return
}
market.Enabled = enabled
k.Markets.Insert(ctx, pair, market)
return
}

type ArgsCreateMarket struct {
Pair asset.Pair
PriceMultiplier sdk.Dec
Expand Down
62 changes: 37 additions & 25 deletions x/perp/v2/keeper/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/NibiruChain/nibiru/x/common/testutil/mock"
. "github.com/NibiruChain/nibiru/x/perp/v2/integration/action"
. "github.com/NibiruChain/nibiru/x/perp/v2/integration/assertion"
"github.com/NibiruChain/nibiru/x/perp/v2/keeper"

"github.com/NibiruChain/nibiru/app"
"github.com/NibiruChain/nibiru/x/common/asset"
Expand Down Expand Up @@ -109,30 +110,41 @@ func TestEnableMarket(t *testing.T) {
NewTestSuite(t).WithTestCases(tests...).Run()
}

func TestCreateMarket(t *testing.T) {
func TestCreateMarketFail(t *testing.T) {
pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD)

tests := TestCases{
TC("create pool").
Given().
When(
CreateMarket(pair, *mock.TestMarket(), *mock.TestAMMDefault()),
).
Then(
MarketShouldBeEqual(pair,
Market_EnableShouldBeEqualTo(true),
Market_PrepaidBadDebtShouldBeEqualTo(sdk.ZeroInt()),
Market_LatestCPFShouldBeEqualTo(sdk.ZeroDec()),
),
AMMShouldBeEqual(pair,
AMM_BaseReserveShouldBeEqual(sdk.NewDec(1e12)),
AMM_QuoteReserveShouldBeEqual(sdk.NewDec(1e12)),
AMM_BiasShouldBeEqual(sdk.ZeroDec()),
AMM_PriceMultiplierShouldBeEqual(sdk.OneDec()),
AMM_SqrtDepthShouldBeEqual(sdk.NewDec(1e12)),
),
),
}

NewTestSuite(t).WithTestCases(tests...).Run()
amm := *mock.TestAMMDefault()
app, ctx := testapp.NewNibiruTestAppAndContext(true)

// Error because of invalid market
err := app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{
Pair: pair,
PriceMultiplier: amm.PriceMultiplier,
SqrtDepth: amm.SqrtDepth,
Market: types.DefaultMarket(pair).WithMaintenanceMarginRatio(sdk.NewDec(2)), // Invalid maintenance ratio
})
require.ErrorContains(t, err, "maintenance margin ratio ratio must be 0 <= ratio <= 1")

// Error because of invalid amm
err = app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{
Pair: pair,
PriceMultiplier: sdk.NewDec(-1),
SqrtDepth: amm.SqrtDepth,
})
require.ErrorContains(t, err, "init price multiplier must be > 0")

// Set it correctly
err = app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{
Pair: pair,
PriceMultiplier: amm.PriceMultiplier,
SqrtDepth: amm.SqrtDepth,
})
require.NoError(t, err)

// Fail since it already exists
err = app.PerpKeeperV2.Admin().CreateMarket(ctx, keeper.ArgsCreateMarket{
Pair: pair,
PriceMultiplier: amm.PriceMultiplier,
SqrtDepth: amm.SqrtDepth,
})
require.ErrorContains(t, err, "already exists")
}
Loading

0 comments on commit 828589a

Please sign in to comment.