Skip to content

Commit

Permalink
feat: add market version to allow disabling markets (#1559)
Browse files Browse the repository at this point in the history
* make market inmutable and include market version

* temp commit after adding market version

* make test pass

* add genesis part

* create changelog

* add option for market creation when another one is closed

* make tests pass

* make linter

* fix bug

* add convenience method for saving market

* add new methods

* remove comments

* fix merge problem
  • Loading branch information
jgimeno authored Sep 19, 2023
1 parent 98d7338 commit cdf86c5
Show file tree
Hide file tree
Showing 48 changed files with 986 additions and 322 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1501](https://github.com/NibiruChain/nibiru/pull/1501) - feat(proto): add Python buf generation logic for py-sdk
* [#1503](https://github.com/NibiruChain/nibiru/pull/1503) - feat(wasm): add Oracle Exchange Rate query for wasm
* [#1543](https://github.com/NibiruChain/nibiru/pull/1543) - epic(devgas): devgas module for incentivizing smart contract
* [#1559](https://github.com/NibiruChain/nibiru/pull/1559) - feat: add versions to markets to allow to disable them

### Bug Fixes

Expand Down
15 changes: 15 additions & 0 deletions proto/nibiru/perp/v2/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ option go_package = "github.com/NibiruChain/nibiru/x/perp/v2/types";
message GenesisState {
repeated Market markets = 2 [ (gogoproto.nullable) = false ];

repeated GenesisMarketLastVersion market_last_versions = 8 [ (gogoproto.nullable) = false ];

repeated AMM amms = 3 [ (gogoproto.nullable) = false ];

repeated Position positions = 4 [ (gogoproto.nullable) = false ];

repeated ReserveSnapshot reserve_snapshots = 5
[ (gogoproto.nullable) = false ];

uint64 dnr_epoch = 6;

repeated TraderVolume trader_volumes = 7 [ (gogoproto.nullable) = false ];

message TraderVolume {
Expand All @@ -30,4 +34,15 @@ message GenesisState {
(gogoproto.nullable) = false
];
}
}

// GenesisMarketLastVersion is the last version including pair only used for genesis
message GenesisMarketLastVersion {
string pair = 1 [
(gogoproto.customtype) =
"github.com/NibiruChain/nibiru/x/common/asset.Pair",
(gogoproto.nullable) = false
];

uint64 version = 2;
}
14 changes: 14 additions & 0 deletions proto/nibiru/perp/v2/state.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ message Market {
// whether or not the market is enabled
bool enabled = 2;

// the version of the Market, only one market can exist per pair, when one is closed it cannot be reactivated,
// so a new market must be created, this is the version of the market
uint64 version = 14;

// the minimum margin ratio which a user must maintain on this market
string maintenance_margin_ratio = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
Expand Down Expand Up @@ -114,6 +118,12 @@ message Market {
];
}

// MarketLastVersion is used to store the last version of the market
message MarketLastVersion {
// version of the market
uint64 version = 1;
}

message AMM {
// identifies the market this AMM belongs to
string pair = 1 [
Expand All @@ -122,6 +132,10 @@ message AMM {
(gogoproto.nullable) = false
];

// the version of the AMM, only one AMM can exist per pair, when one is closed it cannot be reactivated,
// so a new AMM must be created, this is the version of the AMM
uint64 version = 8;

// the amount of base reserves this AMM has
string base_reserve = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
Expand Down
2 changes: 1 addition & 1 deletion x/common/asset/pair.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func NewPair(base string, quote string) Pair {
return Pair(ap)
}

// New returns a new asset pair instance if the pair is valid.
// TryNewPair New returns a new asset pair instance if the pair is valid.
// The form, "token0:token1", is expected for 'pair'.
// Use this function to return an error instead of panicking.
func TryNewPair(pair string) (Pair, error) {
Expand Down
30 changes: 26 additions & 4 deletions x/common/testutil/genesis/perp_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState {
asset.Registry.Pair(denoms.BTC, denoms.NUSD): {
Market: perpv2types.Market{
Pair: asset.NewPair(denoms.BTC, denoms.NUSD),
Version: 1,
Enabled: true,
MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.04"),
MaxLeverage: sdk.MustNewDecFromStr("20"),
Expand All @@ -35,6 +36,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState {
},
Amm: perpv2types.AMM{
Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD),
Version: 1,
BaseReserve: sdk.NewDec(10e6),
QuoteReserve: sdk.NewDec(10e6),
SqrtDepth: sdk.NewDec(10e6),
Expand All @@ -47,6 +49,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState {
Market: perpv2types.Market{
Pair: asset.NewPair(denoms.ATOM, denoms.NUSD),
Enabled: true,
Version: 1,
MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"),
MaxLeverage: sdk.MustNewDecFromStr("15"),
ExchangeFeeRatio: sdk.MustNewDecFromStr("0.0010"),
Expand All @@ -61,6 +64,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState {
},
Amm: perpv2types.AMM{
Pair: asset.Registry.Pair(denoms.ATOM, denoms.NUSD),
Version: 1,
BaseReserve: sdk.NewDec(10e6),
QuoteReserve: sdk.NewDec(10e6),
SqrtDepth: sdk.NewDec(10e6),
Expand All @@ -73,6 +77,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState {
Market: perpv2types.Market{
Pair: asset.NewPair(denoms.OSMO, denoms.NUSD),
Enabled: true,
Version: 1,
MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"),
MaxLeverage: sdk.MustNewDecFromStr("15"),
ExchangeFeeRatio: sdk.MustNewDecFromStr("0.0010"),
Expand All @@ -87,6 +92,7 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState {
},
Amm: perpv2types.AMM{
Pair: asset.Registry.Pair(denoms.OSMO, denoms.NUSD),
Version: 1,
BaseReserve: sdk.NewDec(10e6),
QuoteReserve: sdk.NewDec(10e6),
SqrtDepth: sdk.NewDec(10e6),
Expand All @@ -102,16 +108,22 @@ func AddPerpV2Genesis(gen app.GenesisState) app.GenesisState {

var marketsv2 []perpv2types.Market
var ammsv2 []perpv2types.AMM
var marketLastVersions []perpv2types.GenesisMarketLastVersion
for _, marketAmm := range extraMarketAmms {
marketsv2 = append(marketsv2, marketAmm.Market)
ammsv2 = append(ammsv2, marketAmm.Amm)
marketLastVersions = append(marketLastVersions, perpv2types.GenesisMarketLastVersion{
Pair: marketAmm.Market.Pair,
Version: marketAmm.Market.Version,
})
}

perpV2Gen := &perpv2types.GenesisState{
Markets: marketsv2,
Amms: ammsv2,
Positions: []perpv2types.Position{},
ReserveSnapshots: []perpv2types.ReserveSnapshot{},
Markets: marketsv2,
MarketLastVersions: marketLastVersions,
Amms: ammsv2,
Positions: []perpv2types.Position{},
ReserveSnapshots: []perpv2types.ReserveSnapshot{},
}

gen[perpv2types.ModuleName] = TEST_ENCODING_CONFIG.Marshaler.
Expand All @@ -124,6 +136,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{
Market: perpv2types.Market{
Pair: asset.Registry.Pair(denoms.ETH, denoms.NUSD),
Enabled: true,
Version: 1,
MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"),
MaxLeverage: sdk.MustNewDecFromStr("15"),
LatestCumulativePremiumFraction: sdk.ZeroDec(),
Expand All @@ -138,6 +151,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{
},
Amm: perpv2types.AMM{
Pair: asset.Registry.Pair(denoms.ETH, denoms.NUSD),
Version: 1,
BaseReserve: sdk.NewDec(10e6),
QuoteReserve: sdk.NewDec(10e6),
SqrtDepth: sdk.NewDec(10e6),
Expand All @@ -150,6 +164,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{
Market: perpv2types.Market{
Pair: asset.Registry.Pair(denoms.NIBI, denoms.NUSD),
Enabled: true,
Version: 1,
MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.04"),
MaxLeverage: sdk.MustNewDecFromStr("20"),
LatestCumulativePremiumFraction: sdk.ZeroDec(),
Expand All @@ -164,6 +179,7 @@ var START_MARKETS = map[asset.Pair]perpv2types.AmmMarket{
},
Amm: perpv2types.AMM{
Pair: asset.Registry.Pair(denoms.NIBI, denoms.NUSD),
Version: 1,
BaseReserve: sdk.NewDec(10 * common.TO_MICRO),
QuoteReserve: sdk.NewDec(10 * common.TO_MICRO),
SqrtDepth: common.MustSqrtDec(sdk.NewDec(10 * common.TO_MICRO * 10 * common.TO_MICRO)),
Expand Down Expand Up @@ -193,6 +209,12 @@ func PerpV2Genesis() *perpv2types.GenesisState {
PrepaidBadDebt: sdk.NewCoin(denoms.NUSD, sdk.ZeroInt()),
},
},
MarketLastVersions: []perpv2types.GenesisMarketLastVersion{
{
Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD),
Version: 1,
},
},
Amms: []perpv2types.AMM{
{
Pair: asset.Registry.Pair(denoms.BTC, denoms.NUSD),
Expand Down
1 change: 1 addition & 0 deletions x/common/testutil/mock/perp_amm.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
func TestAMMDefault() *types.AMM {
return &types.AMM{
Pair: asset.NewPair(denoms.BTC, denoms.NUSD),
Version: 1,
BaseReserve: sdk.NewDec(1e12),
QuoteReserve: sdk.NewDec(1e12),
SqrtDepth: sdk.NewDec(1e12),
Expand Down
1 change: 1 addition & 0 deletions x/common/testutil/mock/perp_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func TestMarket() *types.Market {
return &types.Market{
Pair: asset.NewPair(denoms.BTC, denoms.NUSD),
Enabled: true,
Version: 1,
MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"),
MaxLeverage: sdk.MustNewDecFromStr("10"),
LatestCumulativePremiumFraction: sdk.ZeroDec(),
Expand Down
2 changes: 1 addition & 1 deletion x/epochs/types/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func ValidateEpochIdentifierInterface(i interface{}) error {
return ValidateEpochIdentifierString(v)
}

// ValidateEpochIdentifierInterface performs a stateless
// ValidateEpochIdentifierString performs a stateless
// validation of the epoch ID.
func ValidateEpochIdentifierString(s string) error {
s = strings.TrimSpace(s)
Expand Down
12 changes: 7 additions & 5 deletions x/perp/v2/integration/action/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type logger struct {
log string
}

func (e logger) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
func (e logger) Do(_ *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
fmt.Println(e.log)
return ctx, nil, true
}
Expand All @@ -39,8 +39,9 @@ type createMarketAction struct {
}

func (c createMarketAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
app.PerpKeeperV2.Markets.Insert(ctx, c.Market.Pair, c.Market)
app.PerpKeeperV2.AMMs.Insert(ctx, c.AMM.Pair, c.AMM)
app.PerpKeeperV2.MarketLastVersion.Insert(ctx, c.Market.Pair, types.MarketLastVersion{Version: 1})
app.PerpKeeperV2.SaveMarket(ctx, c.Market)
app.PerpKeeperV2.SaveAMM(ctx, c.AMM)

app.PerpKeeperV2.ReserveSnapshots.Insert(ctx, collections.Join(c.AMM.Pair, ctx.BlockTime()), types.ReserveSnapshot{
Amm: c.AMM,
Expand All @@ -55,6 +56,7 @@ func CreateCustomMarket(pair asset.Pair, marketModifiers ...marketModifier) acti
market := types.DefaultMarket(pair)
amm := types.AMM{
Pair: pair,
Version: 1,
BaseReserve: sdk.NewDec(1e12),
QuoteReserve: sdk.NewDec(1e12),
SqrtDepth: sdk.NewDec(1e12),
Expand All @@ -64,11 +66,11 @@ func CreateCustomMarket(pair asset.Pair, marketModifiers ...marketModifier) acti
}

for _, modifier := range marketModifiers {
modifier(market, &amm)
modifier(&market, &amm)
}

return createMarketAction{
Market: *market,
Market: market,
AMM: amm,
}
}
Expand Down
2 changes: 1 addition & 1 deletion x/perp/v2/integration/action/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ 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 {
if types.MarketsAreEqual(expectedMarket, market.Market) == nil {
return nil
}
}
Expand Down
3 changes: 2 additions & 1 deletion x/perp/v2/integration/action/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ type insertReserveSnapshot struct {
}

func (i insertReserveSnapshot) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
amm := app.PerpKeeperV2.AMMs.GetOr(ctx, i.pair, types.AMM{
amm := app.PerpKeeperV2.AMMs.GetOr(ctx, collections.Join(i.pair, uint64(1)), types.AMM{
Pair: i.pair,
Version: uint64(1),
BaseReserve: sdk.ZeroDec(),
QuoteReserve: sdk.ZeroDec(),
SqrtDepth: sdk.ZeroDec(),
Expand Down
2 changes: 1 addition & 1 deletion x/perp/v2/integration/action/withdraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type withdraw struct {
func (w withdraw) Do(app *app.NibiruApp, ctx sdk.Context) (
outCtx sdk.Context, err error, isMandatory bool,
) {
market, err := app.PerpKeeperV2.Markets.Get(ctx, w.Pair)
market, err := app.PerpKeeperV2.GetMarket(ctx, w.Pair)
if err != nil {
return ctx, err, true
}
Expand Down
19 changes: 15 additions & 4 deletions x/perp/v2/integration/assertion/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package assertion
import (
"fmt"

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

sdkmath "cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -20,7 +22,7 @@ type marketShouldBeEqual struct {
}

func (m marketShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
market, err := app.PerpKeeperV2.Markets.Get(ctx, m.Pair)
market, err := app.PerpKeeperV2.GetMarket(ctx, m.Pair)
if err != nil {
return ctx, err, false
}
Expand All @@ -34,7 +36,7 @@ func (m marketShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Contex
return ctx, nil, false
}

func MarketShouldBeEqual(pair asset.Pair, marketCheckers ...MarketChecker) marketShouldBeEqual {
func MarketShouldBeEqual(pair asset.Pair, marketCheckers ...MarketChecker) action.Action {
return marketShouldBeEqual{
Pair: pair,
Checkers: marketCheckers,
Expand Down Expand Up @@ -77,7 +79,7 @@ type ammShouldBeEqual struct {
type AMMChecker func(amm types.AMM) error

func (a ammShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
amm, err := app.PerpKeeperV2.AMMs.Get(ctx, a.Pair)
amm, err := app.PerpKeeperV2.GetAMM(ctx, a.Pair)
if err != nil {
return ctx, err, false
}
Expand All @@ -91,7 +93,7 @@ func (a ammShouldBeEqual) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context,
return ctx, nil, false
}

func AMMShouldBeEqual(pair asset.Pair, ammCheckers ...AMMChecker) ammShouldBeEqual {
func AMMShouldBeEqual(pair asset.Pair, ammCheckers ...AMMChecker) action.Action {
return ammShouldBeEqual{
Pair: pair,
Checkers: ammCheckers,
Expand Down Expand Up @@ -152,3 +154,12 @@ func AMM_BiasShouldBeEqual(expectedBias sdk.Dec) AMMChecker {
return nil
}
}

func AMM_VersionShouldBeEqual(expectedVersion uint64) AMMChecker {
return func(amm types.AMM) error {
if amm.Version != expectedVersion {
return fmt.Errorf("expected version to be %d, got %d", expectedVersion, amm.Version)
}
return nil
}
}
Loading

0 comments on commit cdf86c5

Please sign in to comment.