From 47623c85786dab4b7d1bd07cd5288ebc2655bd40 Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Thu, 1 Dec 2022 18:05:52 -0300 Subject: [PATCH 1/8] feat: add tests for stableswap pool (#1093) * feat: add tests for stableswap pool --- CHANGELOG.md | 1 + simapp/app.go | 1 + x/dex/simulation/operations.go | 30 ++++++++++++++++++++++++---- x/dex/spec/10_future_improvements.md | 2 -- x/perp/simulation/operations.go | 4 ++++ 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c13fc3a9..87e4936a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#1080](https://github.com/NibiruChain/nibiru/pull/1080) - feat(perp): Add exchanged notional to the position changed event #1080 * [#1082](https://github.com/NibiruChain/nibiru/pull/1082) - feat(localnet.sh): Set genesis prices based on real BTC and ETH prices * [#1086](https://github.com/NibiruChain/nibiru/pull/1086) - refactor(perp)!: Removed unused field, `LiquidationPenalty`, from `PositionChangedEvent` +* [#1093](https://github.com/NibiruChain/nibiru/pull/1093) - simulation(dex): add simulation tests for stableswap pools * [#1091](https://github.com/NibiruChain/nibiru/pull/1091) - refactor: Use common.Precision instead of 1_000_000 in the codebase ## v0.15.0 diff --git a/simapp/app.go b/simapp/app.go index 2aaff54ef..5123810ad 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -803,6 +803,7 @@ func NewNibiruTestApp( epochsModule, perpModule, vpoolModule, + dexModule, // ibc capability.NewAppModule(appCodec, *app.CapabilityKeeper), evidence.NewAppModule(app.EvidenceKeeper), diff --git a/x/dex/simulation/operations.go b/x/dex/simulation/operations.go index a414af78b..0a91c4491 100644 --- a/x/dex/simulation/operations.go +++ b/x/dex/simulation/operations.go @@ -1,6 +1,7 @@ package simulation import ( + "fmt" "math/rand" "strings" "time" @@ -68,6 +69,11 @@ func SimulateMsgCreatePool(ak types.AccountKeeper, bk types.BankKeeper, k keeper PoolParams: &poolParams, PoolAssets: poolAssets, } + _, err := k.FetchPoolFromPair(ctx, poolAssets[0].Token.Denom, poolAssets[1].Token.Denom) + if err == nil { + // types.ErrPoolWithSameAssetsExists + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "pool already exists for these tokens"), nil, nil + } return simulation.GenAndDeliverTxWithRandFees( simulation.OperationInput{ @@ -284,19 +290,33 @@ func PoolAssetsCoins(assets []types.PoolAsset) sdk.Coins { } // genBalancerPoolParams creates random parameters for the swap and exit fee of the pool +// The pool has 50% chance of being a stableswap pool. func genBalancerPoolParams(r *rand.Rand, blockTime time.Time, assets []types.PoolAsset) types.PoolParams { // swapFeeInt := int64(r.Intn(1e5)) // swapFee := sdk.NewDecWithPrec(swapFeeInt, 6) exitFeeInt := int64(r.Intn(1e5)) exitFee := sdk.NewDecWithPrec(exitFeeInt, 6) + isBalancer := r.Intn(2) + + var poolType types.PoolType + if isBalancer == 0 { + poolType = types.PoolType_BALANCER + } else { + poolType = types.PoolType_STABLESWAP + } + + A := sdk.NewInt(int64(r.Intn(4_000) + 1)) + + // Create swap fee between 0% and 5% + swapFeeFloat := r.Float64() * .05 + swapFee := sdk.MustNewDecFromStr(fmt.Sprintf("%.5f", swapFeeFloat)) - // TODO: Randomly generate LBP params return types.PoolParams{ - // SwapFee: swapFee, - SwapFee: sdk.ZeroDec(), + SwapFee: swapFee, ExitFee: exitFee, - PoolType: types.PoolType_BALANCER, + PoolType: poolType, + A: A, } } @@ -315,6 +335,8 @@ func genPoolAssets( if _, ok := whitelistedAssets[denom]; ok { amt, _ := simtypes.RandPositiveInt(r, coins[denomIndex].Amount.QuoRaw(10)) reserveAmt := sdk.NewCoin(denom, amt) + + // Weight is useless for stableswap pools. weight := sdk.NewInt(r.Int63n(9) + 1) assets = append(assets, types.PoolAsset{Token: reserveAmt, Weight: weight}) diff --git a/x/dex/spec/10_future_improvements.md b/x/dex/spec/10_future_improvements.md index 276007e7e..571b454bc 100644 --- a/x/dex/spec/10_future_improvements.md +++ b/x/dex/spec/10_future_improvements.md @@ -1,5 +1,3 @@ # Future Improvements -- stableswaps () - constant product solver for pools with different weights () -- single asset joins () diff --git a/x/perp/simulation/operations.go b/x/perp/simulation/operations.go index eecc1ccbe..fa3fe6411 100644 --- a/x/perp/simulation/operations.go +++ b/x/perp/simulation/operations.go @@ -187,7 +187,11 @@ func SimulateMsgAddMargin(ak types.AccountKeeper, bk types.BankKeeper, k keeper. spendableCoins := bk.SpendableCoins(ctx, simAccount.Address) + if spendableCoins.AmountOf(common.DenomNUSD).IsZero() { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "no nusd left"), nil, nil + } quoteAmt, _ := simtypes.RandPositiveInt(r, spendableCoins.AmountOf(common.DenomNUSD)) + spentCoin := sdk.NewCoin(common.DenomNUSD, quoteAmt) msg = &types.MsgAddMargin{ From a48bb781e9495f77326c5bdc485170ec0de8c84a Mon Sep 17 00:00:00 2001 From: Oleg Nikonychev Date: Fri, 2 Dec 2022 19:29:50 +0400 Subject: [PATCH 2/8] feat(perp): Add (notional) volume to metrics state (#1105) * feat(perp): Add (notional) volume to metrics state * feat: volumeBase/volumeQuote Co-authored-by: Matthias <97468149+matthiasmatt@users.noreply.github.com> --- CHANGELOG.md | 1 + proto/perp/v1/event.proto | 16 +- proto/perp/v1/state.proto | 12 ++ scripts/localnet.sh | 4 +- x/perp/keeper/clearing_house.go | 12 +- x/perp/keeper/grpc_query.go | 7 +- x/perp/keeper/grpc_query_test.go | 173 +++++++++++++++++--- x/perp/types/event.pb.go | 238 +++++++++++++++++++--------- x/perp/types/state.pb.go | 261 +++++++++++++++++++++---------- 9 files changed, 545 insertions(+), 179 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87e4936a2..2d662decd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#1082](https://github.com/NibiruChain/nibiru/pull/1082) - feat(vpool): Add gov proposal for editing the sswap invariant of a vpool.. * [#1092](https://github.com/NibiruChain/nibiru/pull/1092) - refactor(dex)!: revive dex module using intermediate test app * [#1097](https://github.com/NibiruChain/nibiru/pull/1097) - feat(perp): Track and expose the net size of a pair with a query +* [#1105](https://github.com/NibiruChain/nibiru/pull/1105) - feat(perp): Add (notional) volume to metrics state ### Improvements diff --git a/proto/perp/v1/event.proto b/proto/perp/v1/event.proto index 0e2be3012..e249a359d 100644 --- a/proto/perp/v1/event.proto +++ b/proto/perp/v1/event.proto @@ -251,9 +251,21 @@ message MetricsEvent { (gogoproto.nullable) = false ]; + // Total notional volume for the pair. + string volumeQuote = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // Total size volume for the pair. + string volumeBase = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + // The block number at which metrics were generated. - int64 block_height = 3; + int64 block_height = 5; // The block time in unix milliseconds at which metrics were generated. - int64 block_time_ms = 4; + int64 block_time_ms = 6; } diff --git a/proto/perp/v1/state.proto b/proto/perp/v1/state.proto index 5bdacaad1..3b57f8164 100644 --- a/proto/perp/v1/state.proto +++ b/proto/perp/v1/state.proto @@ -237,4 +237,16 @@ message Metrics { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + + // Total notional volume for the pair. + string volumeQuote = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // Total size volume for the pair. + string volumeBase = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; } diff --git a/scripts/localnet.sh b/scripts/localnet.sh index 1396958fe..30b02b892 100755 --- a/scripts/localnet.sh +++ b/scripts/localnet.sh @@ -235,9 +235,9 @@ add_genesis_param '.app_state.perp.params.partial_liquidation_ratio = "0.25"' add_genesis_param '.app_state.perp.params.funding_rate_interval = "30 min"' add_genesis_param '.app_state.perp.params.twap_lookback_window = "900s"' add_genesis_param '.app_state.perp.pair_metadata[0].pair = {token0:"ubtc",token1:"unusd"}' -add_genesis_param '.app_state.perp.pair_metadata[0].cumulative_premium_fractions = ["0"]' +add_genesis_param '.app_state.perp.pair_metadata[0].latest_cumulative_premium_fraction = "0"' add_genesis_param '.app_state.perp.pair_metadata[1].pair = {token0:"ueth",token1:"unusd"}' -add_genesis_param '.app_state.perp.pair_metadata[1].cumulative_premium_fractions = ["0"]' +add_genesis_param '.app_state.perp.pair_metadata[1].latest_cumulative_premium_fraction = "0"' # x/pricefeed nibid add-genesis-oracle nibi1zaavvzxez0elundtn32qnk9lkm8kmcsz44g7xl diff --git a/x/perp/keeper/clearing_house.go b/x/perp/keeper/clearing_house.go index fd1b97c1a..db15acc38 100644 --- a/x/perp/keeper/clearing_house.go +++ b/x/perp/keeper/clearing_house.go @@ -824,6 +824,9 @@ func (k Keeper) swapBaseForQuote( if err != nil { return sdk.Dec{}, err } + if side == types.Side_SELL { + baseAssetAmount = baseAssetAmount.Neg() + } k.OnSwapEnd(ctx, pair, quoteAssetAmount, baseAssetAmount) return quoteAssetAmount, err } @@ -837,7 +840,14 @@ func (k Keeper) OnSwapEnd( ) { // Update Metrics pairString := pair.String() - metrics := k.Metrics.GetOr(ctx, pairString, types.Metrics{Pair: pairString, NetSize: sdk.ZeroDec()}) + metrics := k.Metrics.GetOr(ctx, pairString, types.Metrics{ + Pair: pairString, + NetSize: sdk.ZeroDec(), + VolumeQuote: sdk.ZeroDec(), + VolumeBase: sdk.ZeroDec(), + }) metrics.NetSize = metrics.NetSize.Add(baseAssetAmount) + metrics.VolumeBase = metrics.VolumeBase.Add(baseAssetAmount.Abs()) + metrics.VolumeQuote = metrics.VolumeQuote.Add(quoteAssetAmount.Abs()) k.Metrics.Insert(ctx, pairString, metrics) } diff --git a/x/perp/keeper/grpc_query.go b/x/perp/keeper/grpc_query.go index ec1af9895..0b8bf8bb8 100644 --- a/x/perp/keeper/grpc_query.go +++ b/x/perp/keeper/grpc_query.go @@ -181,6 +181,11 @@ func (q queryServer) Metrics( if !q.k.VpoolKeeper.ExistsPool(ctx, tokenPair) { return nil, status.Errorf(codes.InvalidArgument, "pool not found: %s", req.Pair) } - metrics := q.k.Metrics.GetOr(ctx, req.Pair, types.Metrics{Pair: req.Pair, NetSize: sdk.NewDec(0)}) + metrics := q.k.Metrics.GetOr(ctx, req.Pair, types.Metrics{ + Pair: req.Pair, + NetSize: sdk.NewDec(0), + VolumeQuote: sdk.NewDec(0), + VolumeBase: sdk.NewDec(0), + }) return &types.QueryMetricsResponse{Metrics: metrics}, nil } diff --git a/x/perp/keeper/grpc_query_test.go b/x/perp/keeper/grpc_query_test.go index cf217b99a..f2cc9f09f 100644 --- a/x/perp/keeper/grpc_query_test.go +++ b/x/perp/keeper/grpc_query_test.go @@ -328,32 +328,156 @@ func TestQueryCumulativePremiumFraction(t *testing.T) { func TestQueryMetrics(t *testing.T) { tests := []struct { - name string - BaseAssetAmounts []sdk.Dec - NetSize sdk.Dec + name string + Positions []*types.Position + NetSize sdk.Dec + VolumeBase sdk.Dec + VolumeQuote sdk.Dec }{ { - name: "zero net_size", - BaseAssetAmounts: []sdk.Dec{}, - NetSize: sdk.ZeroDec(), + name: "no positions", + Positions: []*types.Position{}, + NetSize: sdk.ZeroDec(), + VolumeBase: sdk.ZeroDec(), + VolumeQuote: sdk.ZeroDec(), }, { - name: "positice net_size", - BaseAssetAmounts: []sdk.Dec{ - sdk.NewDec(10), - sdk.NewDec(20), - sdk.NewDec(30), + name: "two longs", + Positions: []*types.Position{ + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + TraderAddress: "SHRIMP", + Pair: common.Pair_BTC_NUSD, + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, }, - NetSize: sdk.NewDec(60), + NetSize: sdk.NewDec(20), + VolumeBase: sdk.NewDec(20), + VolumeQuote: sdk.NewDec(200), }, { - name: "negative net_size", - BaseAssetAmounts: []sdk.Dec{ - sdk.NewDec(10), - sdk.NewDec(-50), - sdk.NewDec(30), + name: "two shorts", + Positions: []*types.Position{ + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(-10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + TraderAddress: "SHRIMP", + Pair: common.Pair_BTC_NUSD, + Size_: sdk.NewDec(-10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, }, - NetSize: sdk.NewDec(-10), + NetSize: sdk.NewDec(-20), + VolumeBase: sdk.NewDec(20), + VolumeQuote: sdk.NewDec(200), + }, + { + name: "one long, one short", + Positions: []*types.Position{ + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + TraderAddress: "SHRIMP", + Pair: common.Pair_BTC_NUSD, + Size_: sdk.NewDec(-10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + }, + NetSize: sdk.NewDec(0), + VolumeBase: sdk.NewDec(20), + VolumeQuote: sdk.NewDec(200), + }, + { + name: "decrease position", + Positions: []*types.Position{ + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(-10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + }, + NetSize: sdk.NewDec(0), + VolumeBase: sdk.NewDec(20), + VolumeQuote: sdk.NewDec(200), + }, + { + name: "swap positions", + Positions: []*types.Position{ + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "SHRIMP", + Size_: sdk.NewDec(-10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(-10), + OpenNotional: sdk.NewDec(100), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "WHALE", + Size_: sdk.NewDec(-20), + OpenNotional: sdk.NewDec(200), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "SHRIMP", + Size_: sdk.NewDec(20), + OpenNotional: sdk.NewDec(200), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + { + Pair: common.Pair_BTC_NUSD, + TraderAddress: "SHRIMP", + Size_: sdk.NewDec(20), + OpenNotional: sdk.NewDec(200), + LatestCumulativePremiumFraction: sdk.ZeroDec(), + }, + }, + NetSize: sdk.NewDec(10), + VolumeBase: sdk.NewDec(90), + VolumeQuote: sdk.NewDec(900), }, } @@ -365,10 +489,15 @@ func TestQueryMetrics(t *testing.T) { /* quoteReserve */ sdk.NewDec(100_000), /* baseReserve */ sdk.NewDec(100_000), ) - t.Log("call OnSwapEnd hook") - for _, baseAssetAmount := range tc.BaseAssetAmounts { - app.PerpKeeper.OnSwapEnd(ctx, common.Pair_BTC_NUSD, sdk.ZeroDec(), baseAssetAmount) + for _, position := range tc.Positions { + // Detect position decrease + app.PerpKeeper.OnSwapEnd( + ctx, + common.Pair_BTC_NUSD, + position.OpenNotional, + position.Size_, + ) } t.Log("query metrics") @@ -382,6 +511,8 @@ func TestQueryMetrics(t *testing.T) { t.Log("assert response") assert.Equal(t, tc.NetSize, resp.Metrics.NetSize) + assert.Equal(t, tc.VolumeQuote, resp.Metrics.VolumeQuote) + assert.Equal(t, tc.VolumeBase, resp.Metrics.VolumeBase) }) } } diff --git a/x/perp/types/event.pb.go b/x/perp/types/event.pb.go index 542a4ce86..5d8092c01 100644 --- a/x/perp/types/event.pb.go +++ b/x/perp/types/event.pb.go @@ -431,10 +431,14 @@ type MetricsEvent struct { Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"` // Sum of all active position sizes for the pair. NetSize github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=net_size,json=netSize,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"net_size"` + // Total notional volume for the pair. + VolumeQuote github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=volumeQuote,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"volumeQuote"` + // Total size volume for the pair. + VolumeBase github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=volumeBase,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"volumeBase"` // The block number at which metrics were generated. - BlockHeight int64 `protobuf:"varint,3,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + BlockHeight int64 `protobuf:"varint,5,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` // The block time in unix milliseconds at which metrics were generated. - BlockTimeMs int64 `protobuf:"varint,4,opt,name=block_time_ms,json=blockTimeMs,proto3" json:"block_time_ms,omitempty"` + BlockTimeMs int64 `protobuf:"varint,6,opt,name=block_time_ms,json=blockTimeMs,proto3" json:"block_time_ms,omitempty"` } func (m *MetricsEvent) Reset() { *m = MetricsEvent{} } @@ -502,71 +506,73 @@ func init() { func init() { proto.RegisterFile("perp/v1/event.proto", fileDescriptor_19b7f9ebcf2fdb5b) } var fileDescriptor_19b7f9ebcf2fdb5b = []byte{ - // 1017 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x97, 0xdf, 0x4e, 0xdc, 0xc6, - 0x17, 0xc7, 0x71, 0xe0, 0x07, 0xcb, 0xec, 0x1f, 0x7e, 0x0c, 0x10, 0x9c, 0x34, 0x5a, 0xa8, 0xd5, - 0x56, 0xa8, 0x52, 0x6c, 0xd1, 0xde, 0xe5, 0x8e, 0x3f, 0x41, 0x54, 0x0a, 0xe9, 0xc6, 0x50, 0x55, - 0x6a, 0xd5, 0xba, 0x63, 0xfb, 0xac, 0x19, 0x61, 0xcf, 0x38, 0x9e, 0x31, 0x02, 0x9e, 0xa0, 0x97, - 0x7d, 0x8e, 0x5e, 0xf7, 0x1d, 0x9a, 0x8b, 0x5e, 0x44, 0xbd, 0xaa, 0xaa, 0x8a, 0x56, 0xf0, 0x06, - 0x7d, 0x82, 0xca, 0x33, 0xde, 0xf5, 0x2e, 0xa8, 0x81, 0x38, 0xf4, 0xca, 0xbb, 0x67, 0x3c, 0x9f, - 0x73, 0xe6, 0xf8, 0x9c, 0xef, 0xcc, 0xa0, 0x85, 0x14, 0xb2, 0xd4, 0x39, 0x5e, 0x77, 0xe0, 0x18, - 0x98, 0xb4, 0xd3, 0x8c, 0x4b, 0x8e, 0x3b, 0x8c, 0xfa, 0x34, 0xcb, 0xed, 0x62, 0xcc, 0x3e, 0x5e, - 0x7f, 0xb8, 0x18, 0xf1, 0x88, 0xab, 0x21, 0xa7, 0xf8, 0xa5, 0xdf, 0x7a, 0xf8, 0x28, 0xe2, 0x3c, - 0x8a, 0xc1, 0x21, 0x29, 0x75, 0x08, 0x63, 0x5c, 0x12, 0x49, 0x39, 0x13, 0xe5, 0x68, 0x37, 0xe0, - 0x22, 0xe1, 0xc2, 0xf1, 0x89, 0x00, 0xe7, 0x78, 0xdd, 0x07, 0x49, 0xd6, 0x9d, 0x80, 0x53, 0x56, - 0x8e, 0x2f, 0x04, 0x3c, 0x49, 0x38, 0x73, 0xf4, 0x63, 0x60, 0x1c, 0x44, 0x23, 0x24, 0x91, 0xa0, - 0x8d, 0xd6, 0xcf, 0x0d, 0xb4, 0xd8, 0xe3, 0x82, 0x16, 0xf4, 0xad, 0x43, 0xc2, 0x22, 0x08, 0x9f, - 0x16, 0xc1, 0x62, 0x8c, 0xa6, 0x52, 0x42, 0x33, 0xd3, 0x58, 0x35, 0xd6, 0x66, 0x5d, 0xf5, 0x1b, - 0x7f, 0x88, 0x3a, 0x32, 0x23, 0x21, 0x64, 0x1e, 0x09, 0xc3, 0x0c, 0x84, 0x30, 0xef, 0xa9, 0xd1, - 0xb6, 0xb6, 0x6e, 0x68, 0x23, 0xde, 0x45, 0xd3, 0x09, 0xc9, 0x22, 0xca, 0xcc, 0xc9, 0x55, 0x63, - 0xad, 0xf9, 0xc9, 0x03, 0x5b, 0x87, 0x6b, 0x17, 0xe1, 0xda, 0x65, 0xb8, 0xf6, 0x16, 0xa7, 0x6c, - 0x73, 0xe9, 0xd5, 0xf9, 0xca, 0xc4, 0xdf, 0xe7, 0x2b, 0xed, 0x53, 0x92, 0xc4, 0x4f, 0x2c, 0x3d, - 0xcd, 0x72, 0xcb, 0xf9, 0xf8, 0x6b, 0x34, 0x9f, 0x96, 0xc1, 0x79, 0x8c, 0x17, 0x0f, 0x12, 0x9b, - 0x53, 0x85, 0xcf, 0x4d, 0xbb, 0x98, 0xf9, 0xfb, 0xf9, 0xca, 0x47, 0x11, 0x95, 0x87, 0xb9, 0x6f, - 0x07, 0x3c, 0x71, 0xca, 0xac, 0xe8, 0xc7, 0x63, 0x11, 0x1e, 0x39, 0xf2, 0x34, 0x05, 0x61, 0x6f, - 0x43, 0xe0, 0xfe, 0x7f, 0x00, 0x7a, 0x5e, 0x72, 0xf0, 0x17, 0xa8, 0x03, 0x27, 0x81, 0x5e, 0xb3, - 0x27, 0xe8, 0x19, 0x98, 0xff, 0xab, 0x45, 0x6e, 0x0f, 0x29, 0xfb, 0xf4, 0x0c, 0xf0, 0x37, 0x08, - 0x57, 0xd8, 0x61, 0xd0, 0xd3, 0xb5, 0xd0, 0xf3, 0x43, 0xd2, 0x30, 0x6a, 0x1f, 0xcd, 0xc9, 0x8c, - 0x30, 0x41, 0x02, 0x95, 0x95, 0x3e, 0x80, 0x39, 0x73, 0x53, 0x96, 0xbb, 0x65, 0x96, 0xef, 0xeb, - 0x2c, 0x5f, 0x99, 0x6f, 0xb9, 0x9d, 0x11, 0xcb, 0x0e, 0x00, 0xde, 0x47, 0xed, 0x61, 0xda, 0x55, - 0x62, 0x1a, 0xb5, 0xa2, 0x6f, 0x0d, 0x20, 0x2a, 0x2f, 0x2f, 0x50, 0x2b, 0x03, 0x12, 0xd3, 0x33, - 0x08, 0xbd, 0x94, 0xc5, 0xe6, 0x6c, 0x2d, 0x66, 0x73, 0xc0, 0xe8, 0xb1, 0x18, 0x7f, 0x87, 0x16, - 0x73, 0x36, 0x0a, 0xf5, 0x48, 0x5f, 0x42, 0x66, 0xa2, 0x5a, 0x68, 0x5c, 0xb1, 0x7a, 0x2c, 0xde, - 0x28, 0x48, 0xf8, 0x09, 0x6a, 0xf8, 0x24, 0xf4, 0x42, 0xf0, 0xa5, 0xd9, 0xbc, 0x29, 0xcd, 0x53, - 0x85, 0x43, 0x77, 0xc6, 0x27, 0xe1, 0x36, 0xf8, 0x12, 0xef, 0x21, 0x94, 0x90, 0xec, 0xc8, 0x4b, - 0x33, 0x1a, 0x80, 0xd9, 0xaa, 0x15, 0xd3, 0x6c, 0x41, 0xe8, 0x15, 0x00, 0xfc, 0x25, 0x9a, 0xeb, - 0xe7, 0x2c, 0xa4, 0x2c, 0xf2, 0x52, 0x72, 0x9a, 0x00, 0x93, 0x66, 0xbb, 0x16, 0xb3, 0x53, 0x62, - 0x7a, 0x9a, 0x82, 0xdf, 0x47, 0x2d, 0x3f, 0xe6, 0xc1, 0x91, 0x77, 0x08, 0x34, 0x3a, 0x94, 0x66, - 0x67, 0xd5, 0x58, 0x9b, 0x74, 0x9b, 0xca, 0xb6, 0xab, 0x4c, 0xd8, 0x42, 0x6d, 0xfd, 0x8a, 0xa4, - 0x09, 0x78, 0x89, 0x30, 0xe7, 0x46, 0xde, 0x39, 0xa0, 0x09, 0xec, 0x09, 0xeb, 0xd7, 0x06, 0x5a, - 0x1e, 0x28, 0xc9, 0x33, 0xfa, 0x32, 0xa7, 0x21, 0x91, 0x77, 0x20, 0x26, 0x21, 0xba, 0x5f, 0xb5, - 0xd3, 0xcb, 0x9c, 0x4b, 0xf0, 0x48, 0xc2, 0x73, 0x26, 0x95, 0xb8, 0xbc, 0xfd, 0xea, 0x17, 0x87, - 0xb4, 0x17, 0x05, 0x6c, 0x43, 0xb1, 0x70, 0x1f, 0x2d, 0x57, 0x5e, 0xc6, 0x6b, 0xbf, 0x9e, 0xdc, - 0x2c, 0x0d, 0x71, 0xbd, 0xd1, 0x26, 0x78, 0x8c, 0x70, 0x5c, 0xe6, 0x86, 0x57, 0x0b, 0x57, 0xba, - 0xe3, 0xce, 0x57, 0x23, 0x83, 0xc5, 0x47, 0x68, 0xbe, 0x0f, 0xe0, 0x49, 0xee, 0x55, 0x63, 0x4a, - 0x4a, 0xde, 0x58, 0x87, 0xab, 0x65, 0xbb, 0x9b, 0xba, 0xdd, 0xaf, 0x11, 0x2c, 0x77, 0xae, 0x0f, - 0x70, 0xc0, 0x9f, 0x0d, 0x2d, 0x38, 0x43, 0x4b, 0xe5, 0x6b, 0x10, 0x70, 0x71, 0x2a, 0x24, 0x24, - 0x5e, 0x51, 0x26, 0x37, 0x6b, 0xcb, 0x07, 0xa5, 0xb3, 0x47, 0x63, 0xce, 0xc6, 0x29, 0x96, 0x8b, - 0x95, 0xc3, 0xa7, 0x03, 0xeb, 0x4e, 0xce, 0xc2, 0xb1, 0xde, 0x6a, 0xbc, 0x65, 0x6f, 0x55, 0x5b, - 0xcc, 0xec, 0x7f, 0xb1, 0xc5, 0xa0, 0x3b, 0xda, 0x62, 0xae, 0x09, 0x69, 0xf3, 0x0e, 0x84, 0xf4, - 0x00, 0xb5, 0xc7, 0x94, 0xaa, 0xa6, 0xb4, 0x8c, 0x43, 0xae, 0xa8, 0x55, 0xfb, 0x5d, 0xd5, 0xea, - 0x8e, 0x44, 0xe5, 0x0f, 0xa3, 0x3a, 0x9e, 0xec, 0x83, 0x94, 0xf1, 0x1d, 0x28, 0xca, 0xf7, 0x06, - 0x6a, 0x0b, 0xcd, 0xf2, 0x8a, 0x33, 0x93, 0x30, 0x27, 0x57, 0x27, 0xdf, 0x5c, 0x43, 0xbb, 0x65, - 0x0d, 0x2d, 0xea, 0x1a, 0x1a, 0x9b, 0x6d, 0xfd, 0xf8, 0xe7, 0xca, 0xda, 0x2d, 0x12, 0x54, 0x80, - 0x84, 0xdb, 0x2a, 0xe7, 0xaa, 0x7f, 0xd6, 0x2f, 0x53, 0x68, 0x79, 0x47, 0xab, 0xb1, 0x4b, 0x24, - 0xdc, 0x78, 0x00, 0x1b, 0xff, 0x48, 0xf7, 0xde, 0xf5, 0x23, 0x7d, 0x8e, 0x9a, 0x94, 0x85, 0x70, - 0x52, 0xf2, 0xea, 0x09, 0x2a, 0x52, 0x08, 0x0d, 0xfc, 0x16, 0x2d, 0xc4, 0x44, 0x82, 0x90, 0xde, - 0x60, 0xab, 0xca, 0x88, 0xac, 0x2b, 0xa1, 0xf3, 0x1a, 0x35, 0x92, 0x9f, 0x42, 0xa6, 0x4b, 0x7e, - 0x9a, 0x41, 0x42, 0xf3, 0xc4, 0xeb, 0x67, 0xfa, 0xd8, 0x52, 0xf3, 0xec, 0xb6, 0xa4, 0x71, 0x3d, - 0x4d, 0xdb, 0x29, 0x61, 0x98, 0xa1, 0xf7, 0x82, 0x3c, 0xc9, 0x63, 0x22, 0xe9, 0x31, 0x5c, 0xf7, - 0x55, 0xef, 0x30, 0xf7, 0xa0, 0x42, 0x5e, 0xf5, 0x77, 0xb5, 0x5b, 0x66, 0x6e, 0xd1, 0x2d, 0x8d, - 0xeb, 0xdd, 0xf2, 0x93, 0x81, 0x5a, 0x7b, 0x20, 0x33, 0x1a, 0x88, 0x7f, 0xaf, 0xa1, 0xcf, 0x50, - 0x83, 0x81, 0xd4, 0x72, 0x54, 0xaf, 0x82, 0x66, 0x18, 0x48, 0xa5, 0x44, 0x57, 0xc3, 0x9e, 0xbc, - 0x45, 0xd8, 0x53, 0xd7, 0xc2, 0xde, 0xdc, 0x7e, 0x75, 0xd1, 0x35, 0x5e, 0x5f, 0x74, 0x8d, 0xbf, - 0x2e, 0xba, 0xc6, 0x0f, 0x97, 0xdd, 0x89, 0xd7, 0x97, 0xdd, 0x89, 0xdf, 0x2e, 0xbb, 0x13, 0x5f, - 0x7d, 0x3c, 0x12, 0xd1, 0x73, 0x75, 0x6d, 0xda, 0x3a, 0x24, 0x94, 0x39, 0xfa, 0x0a, 0xe5, 0x9c, - 0x38, 0xea, 0x4a, 0xa3, 0x22, 0xf3, 0xa7, 0xd5, 0x85, 0xe6, 0xd3, 0x7f, 0x02, 0x00, 0x00, 0xff, - 0xff, 0x0f, 0x00, 0x87, 0xe0, 0x75, 0x0d, 0x00, 0x00, + // 1041 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x97, 0xdd, 0x6e, 0xdc, 0x44, + 0x14, 0xc7, 0xb3, 0x4d, 0x9a, 0x6c, 0x66, 0x3f, 0x42, 0x26, 0x49, 0xe3, 0x96, 0x6a, 0x13, 0x56, + 0x80, 0x22, 0xa4, 0xda, 0x0a, 0xdc, 0xf5, 0x2e, 0x1f, 0x8d, 0x82, 0xd4, 0x84, 0xad, 0x13, 0x84, + 0x04, 0x02, 0x33, 0xb6, 0xcf, 0x3a, 0xa3, 0xd8, 0x33, 0xae, 0x67, 0xbc, 0x4a, 0xf2, 0x04, 0x5c, + 0xf2, 0x1c, 0xbc, 0x08, 0xbd, 0xe0, 0xa2, 0xe2, 0x02, 0x21, 0x84, 0x02, 0x4a, 0xde, 0x80, 0x27, + 0x40, 0x9e, 0xf1, 0xae, 0x77, 0xb3, 0xa2, 0x49, 0xdd, 0xe5, 0xca, 0xbb, 0x67, 0x3c, 0xbf, 0x73, + 0xe6, 0xf8, 0x9c, 0xff, 0xcc, 0xa0, 0xa5, 0x18, 0x92, 0xd8, 0xea, 0x6d, 0x5a, 0xd0, 0x03, 0x26, + 0xcd, 0x38, 0xe1, 0x92, 0xe3, 0x26, 0xa3, 0x2e, 0x4d, 0x52, 0x33, 0x1b, 0x33, 0x7b, 0x9b, 0x8f, + 0x96, 0x03, 0x1e, 0x70, 0x35, 0x64, 0x65, 0xbf, 0xf4, 0x5b, 0x8f, 0x1e, 0x07, 0x9c, 0x07, 0x21, + 0x58, 0x24, 0xa6, 0x16, 0x61, 0x8c, 0x4b, 0x22, 0x29, 0x67, 0x22, 0x1f, 0x6d, 0x79, 0x5c, 0x44, + 0x5c, 0x58, 0x2e, 0x11, 0x60, 0xf5, 0x36, 0x5d, 0x90, 0x64, 0xd3, 0xf2, 0x38, 0x65, 0xf9, 0xf8, + 0x92, 0xc7, 0xa3, 0x88, 0x33, 0x4b, 0x3f, 0xfa, 0xc6, 0x7e, 0x34, 0x42, 0x12, 0x09, 0xda, 0xd8, + 0xfe, 0xb9, 0x8a, 0x96, 0x3b, 0x5c, 0xd0, 0x8c, 0xbe, 0x73, 0x42, 0x58, 0x00, 0xfe, 0xb3, 0x2c, + 0x58, 0x8c, 0xd1, 0x4c, 0x4c, 0x68, 0x62, 0x54, 0xd6, 0x2b, 0x1b, 0xf3, 0xb6, 0xfa, 0x8d, 0x3f, + 0x42, 0x4d, 0x99, 0x10, 0x1f, 0x12, 0x87, 0xf8, 0x7e, 0x02, 0x42, 0x18, 0xf7, 0xd4, 0x68, 0x43, + 0x5b, 0xb7, 0xb4, 0x11, 0xef, 0xa3, 0xd9, 0x88, 0x24, 0x01, 0x65, 0xc6, 0xf4, 0x7a, 0x65, 0xa3, + 0xf6, 0xe9, 0x43, 0x53, 0x87, 0x6b, 0x66, 0xe1, 0x9a, 0x79, 0xb8, 0xe6, 0x0e, 0xa7, 0x6c, 0x7b, + 0xe5, 0xd5, 0xe5, 0xda, 0xd4, 0x3f, 0x97, 0x6b, 0x8d, 0x73, 0x12, 0x85, 0x4f, 0xdb, 0x7a, 0x5a, + 0xdb, 0xce, 0xe7, 0xe3, 0x6f, 0xd0, 0x62, 0x9c, 0x07, 0xe7, 0x30, 0x9e, 0x3d, 0x48, 0x68, 0xcc, + 0x64, 0x3e, 0xb7, 0xcd, 0x6c, 0xe6, 0x1f, 0x97, 0x6b, 0x1f, 0x07, 0x54, 0x9e, 0xa4, 0xae, 0xe9, + 0xf1, 0xc8, 0xca, 0xb3, 0xa2, 0x1f, 0x4f, 0x84, 0x7f, 0x6a, 0xc9, 0xf3, 0x18, 0x84, 0xb9, 0x0b, + 0x9e, 0xfd, 0x5e, 0x1f, 0x74, 0x98, 0x73, 0xf0, 0x97, 0xa8, 0x09, 0x67, 0x9e, 0x5e, 0xb3, 0x23, + 0xe8, 0x05, 0x18, 0xf7, 0x4b, 0x91, 0x1b, 0x03, 0xca, 0x11, 0xbd, 0x00, 0xfc, 0x2d, 0xc2, 0x05, + 0x76, 0x10, 0xf4, 0x6c, 0x29, 0xf4, 0xe2, 0x80, 0x34, 0x88, 0xda, 0x45, 0x0b, 0x32, 0x21, 0x4c, + 0x10, 0x4f, 0x65, 0xa5, 0x0b, 0x60, 0xcc, 0xdd, 0x96, 0xe5, 0x56, 0x9e, 0xe5, 0x07, 0x3a, 0xcb, + 0x37, 0xe6, 0xb7, 0xed, 0xe6, 0x90, 0x65, 0x0f, 0x00, 0x1f, 0xa1, 0xc6, 0x20, 0xed, 0x2a, 0x31, + 0xd5, 0x52, 0xd1, 0xd7, 0xfb, 0x10, 0x95, 0x97, 0x17, 0xa8, 0x9e, 0x00, 0x09, 0xe9, 0x05, 0xf8, + 0x4e, 0xcc, 0x42, 0x63, 0xbe, 0x14, 0xb3, 0xd6, 0x67, 0x74, 0x58, 0x88, 0xbf, 0x47, 0xcb, 0x29, + 0x1b, 0x86, 0x3a, 0xa4, 0x2b, 0x21, 0x31, 0x50, 0x29, 0x34, 0x2e, 0x58, 0x1d, 0x16, 0x6e, 0x65, + 0x24, 0xfc, 0x14, 0x55, 0x5d, 0xe2, 0x3b, 0x3e, 0xb8, 0xd2, 0xa8, 0xdd, 0x96, 0xe6, 0x99, 0xcc, + 0xa1, 0x3d, 0xe7, 0x12, 0x7f, 0x17, 0x5c, 0x89, 0x0f, 0x10, 0x8a, 0x48, 0x72, 0xea, 0xc4, 0x09, + 0xf5, 0xc0, 0xa8, 0x97, 0x8a, 0x69, 0x3e, 0x23, 0x74, 0x32, 0x00, 0xfe, 0x0a, 0x2d, 0x74, 0x53, + 0xe6, 0x53, 0x16, 0x38, 0x31, 0x39, 0x8f, 0x80, 0x49, 0xa3, 0x51, 0x8a, 0xd9, 0xcc, 0x31, 0x1d, + 0x4d, 0xc1, 0x1f, 0xa0, 0xba, 0x1b, 0x72, 0xef, 0xd4, 0x39, 0x01, 0x1a, 0x9c, 0x48, 0xa3, 0xb9, + 0x5e, 0xd9, 0x98, 0xb6, 0x6b, 0xca, 0xb6, 0xaf, 0x4c, 0xb8, 0x8d, 0x1a, 0xfa, 0x15, 0x49, 0x23, + 0x70, 0x22, 0x61, 0x2c, 0x0c, 0xbd, 0x73, 0x4c, 0x23, 0x38, 0x10, 0xed, 0x5f, 0xab, 0x68, 0xb5, + 0xaf, 0x24, 0xcf, 0xe9, 0xcb, 0x94, 0xfa, 0x44, 0x4e, 0x40, 0x4c, 0x7c, 0xf4, 0xa0, 0x68, 0xa7, + 0x97, 0x29, 0x97, 0xe0, 0x90, 0x88, 0xa7, 0x4c, 0x2a, 0x71, 0x79, 0xfb, 0xd5, 0x2f, 0x0f, 0x68, + 0x2f, 0x32, 0xd8, 0x96, 0x62, 0xe1, 0x2e, 0x5a, 0x2d, 0xbc, 0x8c, 0xd6, 0x7e, 0x39, 0xb9, 0x59, + 0x19, 0xe0, 0x3a, 0xc3, 0x4d, 0xf0, 0x04, 0xe1, 0x30, 0xcf, 0x0d, 0x2f, 0x16, 0xae, 0x74, 0xc7, + 0x5e, 0x2c, 0x46, 0xfa, 0x8b, 0x0f, 0xd0, 0x62, 0x17, 0xc0, 0x91, 0xdc, 0x29, 0xc6, 0x94, 0x94, + 0xbc, 0xb1, 0x0e, 0xd7, 0xf3, 0x76, 0x37, 0x74, 0xbb, 0x8f, 0x11, 0xda, 0xf6, 0x42, 0x17, 0xe0, + 0x98, 0x3f, 0x1f, 0x58, 0x70, 0x82, 0x56, 0xf2, 0xd7, 0xc0, 0xe3, 0xe2, 0x5c, 0x48, 0x88, 0x9c, + 0xac, 0x4c, 0x6e, 0xd7, 0x96, 0x0f, 0x73, 0x67, 0x8f, 0x47, 0x9c, 0x8d, 0x52, 0xda, 0x36, 0x56, + 0x0e, 0x9f, 0xf5, 0xad, 0x7b, 0x29, 0xf3, 0x47, 0x7a, 0xab, 0xfa, 0x96, 0xbd, 0x55, 0x6c, 0x31, + 0xf3, 0xff, 0xc7, 0x16, 0x83, 0x26, 0xb4, 0xc5, 0x8c, 0x09, 0x69, 0x6d, 0x02, 0x42, 0x7a, 0x8c, + 0x1a, 0x23, 0x4a, 0x55, 0x52, 0x5a, 0x46, 0x21, 0x37, 0xd4, 0xaa, 0xf1, 0xae, 0x6a, 0x35, 0x21, + 0x51, 0xf9, 0xb3, 0x52, 0x1c, 0x4f, 0x8e, 0x40, 0xca, 0x70, 0x02, 0x8a, 0xf2, 0x43, 0x05, 0x35, + 0x84, 0x66, 0x39, 0xd9, 0x99, 0x49, 0x18, 0xd3, 0xeb, 0xd3, 0x6f, 0xae, 0xa1, 0xfd, 0xbc, 0x86, + 0x96, 0x75, 0x0d, 0x8d, 0xcc, 0x6e, 0xff, 0xf4, 0xd7, 0xda, 0xc6, 0x1d, 0x12, 0x94, 0x81, 0x84, + 0x5d, 0xcf, 0xe7, 0xaa, 0x7f, 0xed, 0x5f, 0x66, 0xd0, 0xea, 0x9e, 0x56, 0x63, 0x9b, 0x48, 0xb8, + 0xf5, 0x00, 0x36, 0xfa, 0x91, 0xee, 0xbd, 0xeb, 0x47, 0xfa, 0x02, 0xd5, 0x28, 0xf3, 0xe1, 0x2c, + 0xe7, 0x95, 0x13, 0x54, 0xa4, 0x10, 0x1a, 0xf8, 0x1d, 0x5a, 0x0a, 0x89, 0x04, 0x21, 0x9d, 0xfe, + 0x56, 0x95, 0x10, 0x59, 0x56, 0x42, 0x17, 0x35, 0x6a, 0x28, 0x3f, 0x99, 0x4c, 0xe7, 0xfc, 0x38, + 0x81, 0x88, 0xa6, 0x91, 0xd3, 0x4d, 0xf4, 0xb1, 0xa5, 0xe4, 0xd9, 0x6d, 0x45, 0xe3, 0x3a, 0x9a, + 0xb6, 0x97, 0xc3, 0x30, 0x43, 0xef, 0x7b, 0x69, 0x94, 0x86, 0x44, 0xd2, 0x1e, 0x8c, 0xfb, 0x2a, + 0x77, 0x98, 0x7b, 0x58, 0x20, 0x6f, 0xfa, 0xbb, 0xd9, 0x2d, 0x73, 0x77, 0xe8, 0x96, 0xea, 0x78, + 0xb7, 0xfc, 0x76, 0x0f, 0xd5, 0x0f, 0x40, 0x26, 0xd4, 0x13, 0xff, 0x5d, 0x43, 0x9f, 0xa3, 0x2a, + 0x03, 0xa9, 0xe5, 0xa8, 0x5c, 0x05, 0xcd, 0x31, 0x90, 0x4a, 0x89, 0x3a, 0xa8, 0xd6, 0xe3, 0x61, + 0x1a, 0x81, 0xda, 0x4a, 0x4b, 0xd6, 0xcf, 0x30, 0x02, 0x1f, 0x22, 0xa4, 0xff, 0x6e, 0x13, 0x51, + 0xb6, 0x6e, 0x86, 0x08, 0x63, 0x89, 0xbd, 0x7f, 0x87, 0xc4, 0xce, 0x8e, 0x25, 0x76, 0x7b, 0xf7, + 0xd5, 0x55, 0xab, 0xf2, 0xfa, 0xaa, 0x55, 0xf9, 0xfb, 0xaa, 0x55, 0xf9, 0xf1, 0xba, 0x35, 0xf5, + 0xfa, 0xba, 0x35, 0xf5, 0xfb, 0x75, 0x6b, 0xea, 0xeb, 0x4f, 0x86, 0x82, 0x3a, 0x54, 0x17, 0xbb, + 0x9d, 0x13, 0x42, 0x99, 0xa5, 0x2f, 0x79, 0xd6, 0x99, 0xa5, 0x2e, 0x5d, 0x2a, 0x38, 0x77, 0x56, + 0x5d, 0xb9, 0x3e, 0xfb, 0x37, 0x00, 0x00, 0xff, 0xff, 0xc4, 0x92, 0x7c, 0x9b, 0x17, 0x0e, 0x00, + 0x00, } func (m *PositionChangedEvent) Marshal() (dAtA []byte, err error) { @@ -1044,13 +1050,33 @@ func (m *MetricsEvent) MarshalToSizedBuffer(dAtA []byte) (int, error) { if m.BlockTimeMs != 0 { i = encodeVarintEvent(dAtA, i, uint64(m.BlockTimeMs)) i-- - dAtA[i] = 0x20 + dAtA[i] = 0x30 } if m.BlockHeight != 0 { i = encodeVarintEvent(dAtA, i, uint64(m.BlockHeight)) i-- - dAtA[i] = 0x18 + dAtA[i] = 0x28 } + { + size := m.VolumeBase.Size() + i -= size + if _, err := m.VolumeBase.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.VolumeQuote.Size() + i -= size + if _, err := m.VolumeQuote.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a { size := m.NetSize.Size() i -= size @@ -1238,6 +1264,10 @@ func (m *MetricsEvent) Size() (n int) { } l = m.NetSize.Size() n += 1 + l + sovEvent(uint64(l)) + l = m.VolumeQuote.Size() + n += 1 + l + sovEvent(uint64(l)) + l = m.VolumeBase.Size() + n += 1 + l + sovEvent(uint64(l)) if m.BlockHeight != 0 { n += 1 + sovEvent(uint64(m.BlockHeight)) } @@ -2830,6 +2860,74 @@ func (m *MetricsEvent) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeQuote", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VolumeQuote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeBase", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VolumeBase.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field BlockHeight", wireType) } @@ -2848,7 +2946,7 @@ func (m *MetricsEvent) Unmarshal(dAtA []byte) error { break } } - case 4: + case 6: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field BlockTimeMs", wireType) } diff --git a/x/perp/types/state.pb.go b/x/perp/types/state.pb.go index f07fa1226..0fdf9ea0c 100644 --- a/x/perp/types/state.pb.go +++ b/x/perp/types/state.pb.go @@ -533,6 +533,10 @@ type Metrics struct { Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"` // Sum of all active position sizes for the pair. NetSize github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=net_size,json=netSize,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"net_size"` + // Total notional volume for the pair. + VolumeQuote github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=volumeQuote,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"volumeQuote"` + // Total size volume for the pair. + VolumeBase github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=volumeBase,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"volumeBase"` } func (m *Metrics) Reset() { *m = Metrics{} } @@ -592,88 +596,89 @@ func init() { func init() { proto.RegisterFile("perp/v1/state.proto", fileDescriptor_0416b6ef16ef80be) } var fileDescriptor_0416b6ef16ef80be = []byte{ - // 1282 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x97, 0xcf, 0x6f, 0xdb, 0x36, - 0x14, 0xc7, 0xa3, 0x38, 0x89, 0xed, 0x97, 0x1f, 0x75, 0x99, 0xa4, 0x75, 0xd3, 0xc2, 0xce, 0x0c, - 0x6c, 0x08, 0xb2, 0xcd, 0x42, 0xb2, 0x01, 0x03, 0x76, 0xf3, 0xaf, 0x14, 0x06, 0x1c, 0x47, 0x93, - 0xd3, 0xb4, 0x6b, 0x0f, 0x1a, 0x25, 0xd1, 0x8e, 0x1a, 0x89, 0x54, 0x25, 0xca, 0x69, 0xba, 0xf3, - 0xee, 0x3b, 0x0d, 0xfb, 0x03, 0xf6, 0x77, 0x6c, 0xd7, 0x1e, 0x7b, 0x1c, 0x76, 0xc8, 0x86, 0x16, - 0xd8, 0x61, 0xc7, 0xfd, 0x05, 0x03, 0x29, 0x59, 0xd1, 0x8a, 0x0c, 0x58, 0x35, 0xec, 0x64, 0x91, - 0x8f, 0xfc, 0xbc, 0x47, 0xf2, 0x7d, 0x1f, 0x69, 0x58, 0xf7, 0x49, 0xe0, 0xab, 0xd3, 0x3d, 0x35, - 0xe4, 0x98, 0x93, 0xa6, 0x1f, 0x30, 0xce, 0xd0, 0x1a, 0x75, 0x4c, 0x27, 0x88, 0x9a, 0xc2, 0xd6, - 0x9c, 0xee, 0x6d, 0x6d, 0x4c, 0xd8, 0x84, 0x49, 0x93, 0x2a, 0xbe, 0xe2, 0x51, 0x5b, 0x35, 0x8b, - 0x85, 0x1e, 0x0b, 0x55, 0x13, 0x87, 0x44, 0x9d, 0xee, 0x99, 0x84, 0xe3, 0x3d, 0xd5, 0x62, 0x0e, - 0x4d, 0xec, 0x77, 0x62, 0xbb, 0x11, 0x4f, 0x8c, 0x1b, 0xb3, 0xa9, 0x13, 0xc6, 0x26, 0x2e, 0x51, - 0x65, 0xcb, 0x8c, 0xc6, 0xaa, 0x1d, 0x05, 0x98, 0x3b, 0x6c, 0x36, 0x75, 0xdd, 0x62, 0x9e, 0xc7, - 0xa8, 0x1a, 0xff, 0xc4, 0x9d, 0x8d, 0x1f, 0x17, 0x61, 0x49, 0xc3, 0x01, 0xf6, 0x42, 0x54, 0x85, - 0x62, 0xc8, 0x99, 0xef, 0x13, 0xbb, 0xaa, 0x6c, 0x2b, 0x3b, 0x25, 0x7d, 0xd6, 0x44, 0x4f, 0x00, - 0x8d, 0x09, 0x31, 0x7c, 0xc6, 0x5c, 0x43, 0x7c, 0x48, 0x6c, 0xb5, 0xb0, 0xad, 0xec, 0x94, 0xdb, - 0xcd, 0x97, 0x97, 0xf5, 0xb9, 0x5f, 0x2e, 0xeb, 0x1f, 0x4c, 0x1c, 0x7e, 0x1a, 0x99, 0x4d, 0x8b, - 0x79, 0x49, 0x58, 0xc9, 0xcf, 0xc7, 0xa1, 0x7d, 0xa6, 0xf2, 0x0b, 0x9f, 0x84, 0xcd, 0x2e, 0xb1, - 0xf4, 0x1b, 0x63, 0x42, 0x34, 0xc6, 0xdc, 0x03, 0x42, 0x74, 0x81, 0x41, 0x13, 0xa8, 0x12, 0x8b, - 0x85, 0x17, 0x21, 0x27, 0x9e, 0x31, 0x8e, 0xa8, 0x9d, 0x71, 0xb1, 0x90, 0xcb, 0xc5, 0x66, 0xca, - 0x3b, 0x88, 0xa8, 0x9d, 0x3a, 0x32, 0x61, 0xd3, 0x75, 0x9e, 0x45, 0x8e, 0x2d, 0x37, 0x25, 0xe3, - 0x65, 0x31, 0x97, 0x97, 0xf5, 0x0c, 0x2c, 0xf5, 0xf1, 0x14, 0xee, 0xf8, 0x38, 0xe0, 0x0e, 0x76, - 0x8d, 0xac, 0xaf, 0xd8, 0xcf, 0x52, 0x2e, 0x3f, 0xb7, 0x13, 0xe0, 0xe0, 0x8a, 0x17, 0xfb, 0xda, - 0x87, 0x4d, 0xb1, 0x5d, 0x0e, 0x9d, 0x08, 0x3e, 0x31, 0x1c, 0xca, 0x49, 0x30, 0xc5, 0x6e, 0xb5, - 0x28, 0xfc, 0xe8, 0xeb, 0x89, 0x51, 0xc7, 0x9c, 0xf4, 0x13, 0x13, 0xfa, 0x4e, 0x81, 0x0d, 0x7e, - 0x8e, 0x7d, 0xc3, 0x65, 0xec, 0xcc, 0xc4, 0xd6, 0x99, 0x71, 0xee, 0x50, 0x9b, 0x9d, 0x57, 0x4b, - 0xdb, 0xca, 0xce, 0xf2, 0xfe, 0x9d, 0x66, 0x9c, 0x43, 0xcd, 0x59, 0x0e, 0x35, 0xbb, 0x49, 0x0e, - 0xb5, 0xfb, 0x22, 0xec, 0x3f, 0x2e, 0xeb, 0xb5, 0xeb, 0xa6, 0x7f, 0xc4, 0x3c, 0x87, 0x13, 0xcf, - 0xe7, 0x17, 0x7f, 0x5e, 0xd6, 0xef, 0x5e, 0x60, 0xcf, 0xfd, 0xbc, 0x71, 0xdd, 0xb8, 0xc6, 0xf7, - 0xbf, 0xd6, 0x15, 0x1d, 0x09, 0xd3, 0x20, 0xb1, 0x3c, 0x94, 0x06, 0xf4, 0x19, 0xdc, 0x3e, 0x3f, - 0x75, 0x38, 0x71, 0x9d, 0x90, 0x13, 0x3b, 0xdd, 0x3c, 0x16, 0x84, 0xd5, 0xf2, 0x76, 0x61, 0xa7, - 0xac, 0xdf, 0xca, 0x98, 0x07, 0x57, 0xd6, 0xc6, 0xef, 0x05, 0x28, 0x69, 0x2c, 0x74, 0x44, 0x90, - 0xe8, 0x7d, 0x58, 0xe3, 0x01, 0xb6, 0x49, 0x60, 0x60, 0xdb, 0x0e, 0x48, 0x18, 0xca, 0x4c, 0x2e, - 0xeb, 0xab, 0x71, 0x6f, 0x2b, 0xee, 0x44, 0xfb, 0xb0, 0xe0, 0x63, 0x27, 0xa8, 0xce, 0xcb, 0x45, - 0x57, 0x9b, 0x89, 0x32, 0x13, 0x61, 0xb4, 0xc2, 0x90, 0x70, 0x0d, 0x3b, 0x41, 0x7b, 0x41, 0xac, - 0x59, 0x97, 0x63, 0x51, 0x1b, 0x16, 0x42, 0xe7, 0x05, 0xc9, 0x99, 0xf5, 0x72, 0x2e, 0x3a, 0x80, - 0x25, 0x0f, 0x07, 0x13, 0x87, 0xe6, 0x4c, 0xec, 0x64, 0x36, 0x1a, 0xc1, 0x2a, 0xf3, 0x09, 0x35, - 0x28, 0x13, 0xab, 0xc6, 0x6e, 0xce, 0x0c, 0x5e, 0x11, 0x90, 0x61, 0xc2, 0x40, 0x5f, 0x43, 0xc3, - 0xc5, 0x9c, 0x84, 0xdc, 0xb0, 0x22, 0x2f, 0x72, 0x31, 0x77, 0xa6, 0xc4, 0xf0, 0x03, 0xe2, 0x39, - 0x91, 0x67, 0x8c, 0x03, 0x6c, 0x89, 0x71, 0x39, 0x73, 0xb8, 0x1e, 0x93, 0x3b, 0x29, 0x58, 0x8b, - 0xb9, 0x07, 0x09, 0x16, 0xbd, 0x07, 0x2b, 0xa6, 0xcb, 0xac, 0x33, 0x83, 0x46, 0x9e, 0x49, 0x02, - 0x99, 0xc2, 0x05, 0x7d, 0x59, 0xf6, 0x0d, 0x65, 0x57, 0xe3, 0x27, 0x05, 0x56, 0xc4, 0xa9, 0x1c, - 0x12, 0x8e, 0x6d, 0xcc, 0x71, 0x7a, 0x8a, 0xca, 0x3b, 0x9c, 0xe2, 0xbf, 0x5b, 0xe4, 0xfc, 0xff, - 0xb2, 0xc8, 0x06, 0x85, 0x35, 0x2d, 0x20, 0x3e, 0x76, 0xec, 0x36, 0xb6, 0xbb, 0xc4, 0xe4, 0x68, - 0x03, 0x16, 0x6d, 0x42, 0x99, 0x97, 0xa4, 0x69, 0xdc, 0x10, 0x69, 0x82, 0x3d, 0x16, 0x51, 0x9e, - 0x23, 0x90, 0x3e, 0xe5, 0x7a, 0x32, 0xbb, 0xf1, 0xc3, 0x12, 0xac, 0xcc, 0xa4, 0xa1, 0x93, 0xd0, - 0x47, 0x9f, 0x42, 0xc9, 0x4f, 0xda, 0x6f, 0xef, 0x5a, 0x72, 0x2b, 0x35, 0xd3, 0xf1, 0xe9, 0x48, - 0x74, 0x0a, 0x55, 0xf2, 0xdc, 0x3a, 0xc5, 0x74, 0x42, 0xec, 0x34, 0xe5, 0x8c, 0x29, 0x76, 0x23, - 0x92, 0x73, 0xa7, 0x6e, 0xa5, 0xbc, 0x59, 0xf6, 0x9d, 0x08, 0x1a, 0x1a, 0xc3, 0xed, 0x2b, 0x4f, - 0x33, 0xff, 0xc6, 0x7f, 0x90, 0xdd, 0x66, 0x8a, 0x9b, 0xad, 0x6b, 0x24, 0x74, 0xd8, 0x87, 0x92, - 0x89, 0x6d, 0xc3, 0x26, 0x26, 0xcf, 0xa9, 0xc4, 0xa2, 0x99, 0x9c, 0xe0, 0x43, 0xb8, 0x31, 0x2b, - 0xc2, 0x3e, 0xbe, 0xf0, 0x08, 0xe5, 0x39, 0xc5, 0xb8, 0x96, 0x60, 0xb4, 0x98, 0x82, 0xbe, 0x80, - 0x95, 0x80, 0x60, 0xd7, 0x79, 0x21, 0xb6, 0x82, 0xba, 0x39, 0x85, 0xb7, 0x3c, 0x63, 0x68, 0xd4, - 0x45, 0x5f, 0xc1, 0x46, 0x44, 0xb3, 0x50, 0x03, 0x8f, 0x79, 0x22, 0xb6, 0x77, 0x47, 0xa3, 0x2b, - 0x96, 0x46, 0xdd, 0x96, 0x20, 0xa1, 0x13, 0xb8, 0x11, 0x97, 0x28, 0x83, 0x33, 0x63, 0x8a, 0x23, - 0x97, 0xcb, 0x8b, 0xe5, 0xdd, 0xe1, 0xab, 0x31, 0xe6, 0x98, 0x9d, 0x08, 0x08, 0x7a, 0x02, 0x37, - 0xd3, 0x74, 0x48, 0x8b, 0x5e, 0x39, 0x17, 0xb9, 0x32, 0x03, 0xcd, 0x52, 0xaf, 0xf1, 0x4d, 0x01, - 0x56, 0x67, 0x37, 0x0a, 0x91, 0x3a, 0xc9, 0xe6, 0x87, 0x92, 0x4b, 0x82, 0x69, 0x7e, 0x3c, 0x86, - 0x9b, 0xe2, 0xa1, 0xc1, 0x59, 0xe6, 0x4a, 0xcb, 0x29, 0x6b, 0xf1, 0x72, 0x3a, 0x66, 0x57, 0x77, - 0x1f, 0x7a, 0x0a, 0x5b, 0x09, 0x5b, 0xa8, 0xd7, 0xf8, 0xfb, 0x2b, 0x2a, 0x87, 0x62, 0x84, 0x93, - 0x5b, 0xd2, 0x89, 0x46, 0x02, 0xbf, 0x97, 0x7d, 0x44, 0xa1, 0x1a, 0x40, 0x66, 0x01, 0x52, 0x34, - 0x7a, 0xa6, 0x07, 0xb5, 0x60, 0x35, 0x3d, 0xa1, 0x80, 0x84, 0xbe, 0x54, 0xc1, 0xf2, 0xfe, 0xbd, - 0x7f, 0xac, 0x2f, 0x24, 0xf4, 0xf5, 0x15, 0x3f, 0xd3, 0x6a, 0x9c, 0x42, 0xf1, 0x90, 0xf0, 0xc0, - 0xb1, 0x42, 0x84, 0x32, 0xa5, 0xbd, 0x9c, 0x94, 0xee, 0x3e, 0x94, 0x28, 0xe1, 0x71, 0x35, 0xc8, - 0x57, 0x76, 0x8a, 0x94, 0x70, 0xa1, 0xff, 0x5d, 0x15, 0x16, 0x46, 0x8e, 0x4d, 0xd0, 0x06, 0x54, - 0x46, 0xfd, 0x6e, 0xcf, 0x78, 0x30, 0x1c, 0x69, 0xbd, 0x4e, 0xff, 0xa0, 0xdf, 0xeb, 0x56, 0xe6, - 0x50, 0x11, 0x0a, 0xed, 0x07, 0x5f, 0x56, 0x14, 0x54, 0x82, 0x85, 0x51, 0x6f, 0x30, 0xa8, 0xcc, - 0xef, 0x9e, 0xc0, 0xaa, 0x46, 0x07, 0x1d, 0xec, 0x5a, 0x47, 0xbe, 0xac, 0x89, 0x75, 0xb8, 0xab, - 0x0d, 0x07, 0x46, 0xa7, 0x35, 0xe8, 0x18, 0x47, 0xda, 0x71, 0xff, 0x68, 0xf8, 0x16, 0x64, 0x0d, - 0x60, 0xa4, 0x1d, 0x1d, 0x1b, 0x9a, 0xde, 0xef, 0xf4, 0x62, 0xd6, 0xf1, 0xc3, 0x96, 0x56, 0x99, - 0x47, 0x00, 0x4b, 0x47, 0x7a, 0xab, 0x33, 0xe8, 0x55, 0x0a, 0xbb, 0xf7, 0x61, 0x5d, 0xa3, 0x03, - 0x2d, 0x20, 0x63, 0x12, 0x10, 0x6a, 0x91, 0x84, 0x5e, 0x83, 0x2d, 0x41, 0xd7, 0xf4, 0xde, 0x41, - 0x4f, 0xef, 0x0d, 0x3b, 0xd7, 0x44, 0x78, 0xd8, 0x7a, 0x54, 0x51, 0xe4, 0x47, 0x7f, 0x58, 0x99, - 0xdf, 0x7d, 0x06, 0xf7, 0x0e, 0xa5, 0x62, 0x44, 0x8c, 0xf2, 0xfa, 0x61, 0x54, 0x0b, 0x9c, 0x94, - 0xa8, 0xc2, 0x87, 0x87, 0x2d, 0xfd, 0x7e, 0x7f, 0x28, 0x43, 0x7e, 0x30, 0x68, 0xc9, 0x90, 0x65, - 0x70, 0xd7, 0xc7, 0x2f, 0xd6, 0xae, 0x1d, 0x1d, 0x57, 0x14, 0x54, 0x86, 0xc5, 0xfe, 0xb0, 0xdb, - 0x7b, 0x54, 0x99, 0x47, 0xcb, 0x50, 0x3c, 0x6c, 0x3d, 0x32, 0xb4, 0xe1, 0xa0, 0x52, 0x68, 0x77, - 0x5f, 0xbe, 0xae, 0x29, 0xaf, 0x5e, 0xd7, 0x94, 0xdf, 0x5e, 0xd7, 0x94, 0x6f, 0xdf, 0xd4, 0xe6, - 0x5e, 0xbd, 0xa9, 0xcd, 0xfd, 0xfc, 0xa6, 0x36, 0xf7, 0x78, 0x37, 0x73, 0x1e, 0x43, 0x79, 0xfc, - 0x9d, 0x53, 0xec, 0x50, 0x35, 0x4e, 0x05, 0xf5, 0xb9, 0x2a, 0xff, 0x1e, 0xc9, 0x73, 0x31, 0x97, - 0xe4, 0x4b, 0xf3, 0x93, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x34, 0xe6, 0x8c, 0x7e, 0x33, 0x0d, - 0x00, 0x00, + // 1312 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x97, 0x4d, 0x6f, 0xdb, 0x46, + 0x13, 0xc7, 0x4d, 0xcb, 0xaf, 0xe3, 0x97, 0x28, 0x6b, 0x3b, 0x51, 0x9c, 0x40, 0xf6, 0x23, 0xe0, + 0x79, 0x60, 0xf8, 0x69, 0x45, 0xd8, 0x2d, 0x50, 0xa0, 0x37, 0x49, 0x96, 0x03, 0x01, 0xb2, 0xcc, + 0xd0, 0x8e, 0x93, 0x26, 0x07, 0x76, 0x45, 0x8e, 0x64, 0xc6, 0xe4, 0x2e, 0x43, 0x2e, 0xe5, 0x38, + 0x3d, 0xf7, 0xd2, 0x53, 0x4f, 0x45, 0x3f, 0x40, 0x3f, 0x47, 0x7b, 0xcd, 0x31, 0xc7, 0xa2, 0x07, + 0xb7, 0x48, 0x80, 0x1e, 0x7a, 0xec, 0x27, 0x28, 0x76, 0x49, 0xd1, 0x6c, 0xe0, 0x02, 0x0d, 0x8b, + 0x9e, 0xc4, 0xdd, 0xd9, 0xfd, 0xcd, 0xec, 0xee, 0x7f, 0x66, 0x57, 0xb0, 0x12, 0x60, 0x18, 0xe8, + 0xa3, 0x1d, 0x3d, 0x12, 0x54, 0x60, 0x3d, 0x08, 0xb9, 0xe0, 0x64, 0x99, 0xb9, 0x7d, 0x37, 0x8c, + 0xeb, 0xd2, 0x56, 0x1f, 0xed, 0xac, 0xaf, 0x0e, 0xf9, 0x90, 0x2b, 0x93, 0x2e, 0xbf, 0x92, 0x51, + 0xeb, 0x55, 0x9b, 0x47, 0x3e, 0x8f, 0xf4, 0x3e, 0x8d, 0x50, 0x1f, 0xed, 0xf4, 0x51, 0xd0, 0x1d, + 0xdd, 0xe6, 0x2e, 0x4b, 0xed, 0x77, 0x12, 0xbb, 0x95, 0x4c, 0x4c, 0x1a, 0xe3, 0xa9, 0x43, 0xce, + 0x87, 0x1e, 0xea, 0xaa, 0xd5, 0x8f, 0x07, 0xba, 0x13, 0x87, 0x54, 0xb8, 0x7c, 0x3c, 0x75, 0xc5, + 0xe6, 0xbe, 0xcf, 0x99, 0x9e, 0xfc, 0x24, 0x9d, 0xb5, 0xef, 0xa7, 0x61, 0xc6, 0xa0, 0x21, 0xf5, + 0x23, 0x52, 0x81, 0xd9, 0x48, 0xf0, 0x20, 0x40, 0xa7, 0xa2, 0x6d, 0x6a, 0x5b, 0x73, 0xe6, 0xb8, + 0x49, 0x9e, 0x02, 0x19, 0x20, 0x5a, 0x01, 0xe7, 0x9e, 0x25, 0x3f, 0x14, 0xb6, 0x52, 0xda, 0xd4, + 0xb6, 0xe6, 0x9b, 0xf5, 0x57, 0x97, 0x1b, 0x13, 0x3f, 0x5d, 0x6e, 0xfc, 0x6f, 0xe8, 0x8a, 0xd3, + 0xb8, 0x5f, 0xb7, 0xb9, 0x9f, 0x86, 0x95, 0xfe, 0x7c, 0x18, 0x39, 0x67, 0xba, 0xb8, 0x08, 0x30, + 0xaa, 0xef, 0xa1, 0x6d, 0xde, 0x18, 0x20, 0x1a, 0x9c, 0x7b, 0xfb, 0x88, 0xa6, 0xc4, 0x90, 0x21, + 0x54, 0xd0, 0xe6, 0xd1, 0x45, 0x24, 0xd0, 0xb7, 0x06, 0x31, 0x73, 0x72, 0x2e, 0xa6, 0x0a, 0xb9, + 0x58, 0xcb, 0x78, 0xfb, 0x31, 0x73, 0x32, 0x47, 0x7d, 0x58, 0xf3, 0xdc, 0xe7, 0xb1, 0xeb, 0xa8, + 0x4d, 0xc9, 0x79, 0x99, 0x2e, 0xe4, 0x65, 0x25, 0x07, 0xcb, 0x7c, 0x3c, 0x83, 0x3b, 0x01, 0x0d, + 0x85, 0x4b, 0x3d, 0x2b, 0xef, 0x2b, 0xf1, 0x33, 0x53, 0xc8, 0xcf, 0xed, 0x14, 0xd8, 0xbd, 0xe2, + 0x25, 0xbe, 0x76, 0x61, 0x4d, 0x6e, 0x97, 0xcb, 0x86, 0x92, 0x8f, 0x96, 0xcb, 0x04, 0x86, 0x23, + 0xea, 0x55, 0x66, 0xa5, 0x1f, 0x73, 0x25, 0x35, 0x9a, 0x54, 0x60, 0x27, 0x35, 0x91, 0x6f, 0x34, + 0x58, 0x15, 0xe7, 0x34, 0xb0, 0x3c, 0xce, 0xcf, 0xfa, 0xd4, 0x3e, 0xb3, 0xce, 0x5d, 0xe6, 0xf0, + 0xf3, 0xca, 0xdc, 0xa6, 0xb6, 0xb5, 0xb0, 0x7b, 0xa7, 0x9e, 0x68, 0xa8, 0x3e, 0xd6, 0x50, 0x7d, + 0x2f, 0xd5, 0x50, 0xb3, 0x23, 0xc3, 0xfe, 0xed, 0x72, 0xa3, 0x7a, 0xdd, 0xf4, 0x0f, 0xb8, 0xef, + 0x0a, 0xf4, 0x03, 0x71, 0xf1, 0xfb, 0xe5, 0xc6, 0xdd, 0x0b, 0xea, 0x7b, 0x9f, 0xd6, 0xae, 0x1b, + 0x57, 0xfb, 0xf6, 0xe7, 0x0d, 0xcd, 0x24, 0xd2, 0xd4, 0x4d, 0x2d, 0x8f, 0x94, 0x81, 0x7c, 0x02, + 0xb7, 0xcf, 0x4f, 0x5d, 0x81, 0x9e, 0x1b, 0x09, 0x74, 0xb2, 0xcd, 0xe3, 0x61, 0x54, 0x99, 0xdf, + 0x2c, 0x6d, 0xcd, 0x9b, 0xb7, 0x72, 0xe6, 0xee, 0x95, 0xb5, 0xf6, 0x6b, 0x09, 0xe6, 0x0c, 0x1e, + 0xb9, 0x32, 0x48, 0xf2, 0x5f, 0x58, 0x16, 0x21, 0x75, 0x30, 0xb4, 0xa8, 0xe3, 0x84, 0x18, 0x45, + 0x4a, 0xc9, 0xf3, 0xe6, 0x52, 0xd2, 0xdb, 0x48, 0x3a, 0xc9, 0x2e, 0x4c, 0x05, 0xd4, 0x0d, 0x2b, + 0x93, 0x6a, 0xd1, 0x95, 0x7a, 0x9a, 0x99, 0x69, 0x62, 0x34, 0xa2, 0x08, 0x85, 0x41, 0xdd, 0xb0, + 0x39, 0x25, 0xd7, 0x6c, 0xaa, 0xb1, 0xa4, 0x09, 0x53, 0x91, 0xfb, 0x12, 0x0b, 0xaa, 0x5e, 0xcd, + 0x25, 0xfb, 0x30, 0xe3, 0xd3, 0x70, 0xe8, 0xb2, 0x82, 0xc2, 0x4e, 0x67, 0x93, 0x23, 0x58, 0xe2, + 0x01, 0x32, 0x8b, 0x71, 0xb9, 0x6a, 0xea, 0x15, 0x54, 0xf0, 0xa2, 0x84, 0xf4, 0x52, 0x06, 0xf9, + 0x02, 0x6a, 0x1e, 0x15, 0x18, 0x09, 0xcb, 0x8e, 0xfd, 0xd8, 0xa3, 0xc2, 0x1d, 0xa1, 0x15, 0x84, + 0xe8, 0xbb, 0xb1, 0x6f, 0x0d, 0x42, 0x6a, 0xcb, 0x71, 0x05, 0x35, 0xbc, 0x91, 0x90, 0x5b, 0x19, + 0xd8, 0x48, 0xb8, 0xfb, 0x29, 0x96, 0xfc, 0x07, 0x16, 0xfb, 0x1e, 0xb7, 0xcf, 0x2c, 0x16, 0xfb, + 0x7d, 0x0c, 0x95, 0x84, 0x4b, 0xe6, 0x82, 0xea, 0xeb, 0xa9, 0xae, 0xda, 0x0f, 0x1a, 0x2c, 0xca, + 0x53, 0x39, 0x40, 0x41, 0x1d, 0x2a, 0x68, 0x76, 0x8a, 0xda, 0x7b, 0x9c, 0xe2, 0xdf, 0x5b, 0xe4, + 0xe4, 0xbf, 0xb2, 0xc8, 0x1a, 0x83, 0x65, 0x23, 0xc4, 0x80, 0xba, 0x4e, 0x93, 0x3a, 0x7b, 0xd8, + 0x17, 0x64, 0x15, 0xa6, 0x1d, 0x64, 0xdc, 0x4f, 0x65, 0x9a, 0x34, 0xa4, 0x4c, 0xa8, 0xcf, 0x63, + 0x26, 0x0a, 0x04, 0xd2, 0x61, 0xc2, 0x4c, 0x67, 0xd7, 0xbe, 0x9b, 0x81, 0xc5, 0x71, 0x6a, 0x98, + 0x18, 0x05, 0xe4, 0x63, 0x98, 0x0b, 0xd2, 0xf6, 0xbb, 0xbb, 0x96, 0xde, 0x4a, 0xf5, 0x6c, 0x7c, + 0x36, 0x92, 0x9c, 0x42, 0x05, 0x5f, 0xd8, 0xa7, 0x94, 0x0d, 0xd1, 0xc9, 0x24, 0x67, 0x8d, 0xa8, + 0x17, 0x63, 0xc1, 0x9d, 0xba, 0x95, 0xf1, 0xc6, 0xea, 0x3b, 0x91, 0x34, 0x32, 0x80, 0xdb, 0x57, + 0x9e, 0xc6, 0xfe, 0xad, 0x7f, 0x90, 0x76, 0x6b, 0x19, 0x6e, 0xbc, 0xae, 0x23, 0x99, 0x87, 0x1d, + 0x98, 0xeb, 0x53, 0xc7, 0x72, 0xb0, 0x2f, 0x0a, 0x66, 0xe2, 0x6c, 0x3f, 0x3d, 0xc1, 0x47, 0x70, + 0x63, 0x5c, 0x84, 0x03, 0x7a, 0xe1, 0x23, 0x13, 0x05, 0x93, 0x71, 0x39, 0xc5, 0x18, 0x09, 0x85, + 0x3c, 0x80, 0xc5, 0x10, 0xa9, 0xe7, 0xbe, 0x94, 0x5b, 0xc1, 0xbc, 0x82, 0x89, 0xb7, 0x30, 0x66, + 0x18, 0xcc, 0x23, 0x9f, 0xc3, 0x6a, 0xcc, 0xf2, 0x50, 0x8b, 0x0e, 0x44, 0x9a, 0x6c, 0xef, 0x8f, + 0x26, 0x57, 0x2c, 0x83, 0x79, 0x0d, 0x49, 0x22, 0x27, 0x70, 0x23, 0x29, 0x51, 0x96, 0xe0, 0xd6, + 0x88, 0xc6, 0x9e, 0x50, 0x17, 0xcb, 0xfb, 0xc3, 0x97, 0x12, 0xcc, 0x31, 0x3f, 0x91, 0x10, 0xf2, + 0x14, 0x6e, 0x66, 0x72, 0xc8, 0x8a, 0xde, 0x7c, 0x21, 0x72, 0x79, 0x0c, 0x1a, 0x4b, 0xaf, 0xf6, + 0x65, 0x09, 0x96, 0xc6, 0x37, 0x0a, 0xaa, 0x3c, 0xc9, 0xeb, 0x43, 0x2b, 0x94, 0x82, 0x99, 0x3e, + 0x9e, 0xc0, 0x4d, 0xf9, 0xd0, 0x10, 0x3c, 0x77, 0xa5, 0x15, 0x4c, 0x6b, 0xf9, 0x72, 0x3a, 0xe6, + 0x57, 0x77, 0x1f, 0x79, 0x06, 0xeb, 0x29, 0x5b, 0x66, 0xaf, 0xf5, 0xe7, 0x57, 0x54, 0x81, 0x8c, + 0x91, 0x4e, 0x6e, 0x29, 0x27, 0x06, 0x86, 0x41, 0x3b, 0xff, 0x88, 0x22, 0x55, 0x80, 0xdc, 0x02, + 0x54, 0xd2, 0x98, 0xb9, 0x1e, 0xd2, 0x80, 0xa5, 0xec, 0x84, 0x42, 0x8c, 0x02, 0x95, 0x05, 0x0b, + 0xbb, 0xf7, 0xfe, 0xb2, 0xbe, 0x60, 0x14, 0x98, 0x8b, 0x41, 0xae, 0x55, 0xfb, 0x6a, 0x12, 0x66, + 0x0f, 0x50, 0x84, 0xae, 0x1d, 0x11, 0x92, 0xab, 0xed, 0xf3, 0x69, 0xed, 0xee, 0xc0, 0x1c, 0x43, + 0x91, 0x94, 0x83, 0x62, 0x75, 0x67, 0x96, 0xa1, 0x50, 0x05, 0xc0, 0x80, 0x85, 0x11, 0xf7, 0x62, + 0x1f, 0x1f, 0xc4, 0x5c, 0x14, 0x2d, 0x2e, 0x79, 0x04, 0xe9, 0x01, 0x24, 0xcd, 0x26, 0x8d, 0xb0, + 0x60, 0x51, 0xc9, 0x11, 0xb6, 0x75, 0x98, 0x3a, 0x72, 0x1d, 0x24, 0xab, 0x50, 0x3e, 0xea, 0xec, + 0xb5, 0xad, 0x87, 0xbd, 0x23, 0xa3, 0xdd, 0xea, 0xec, 0x77, 0xda, 0x7b, 0xe5, 0x09, 0x32, 0x0b, + 0xa5, 0xe6, 0xc3, 0xcf, 0xca, 0x1a, 0x99, 0x83, 0xa9, 0xa3, 0x76, 0xb7, 0x5b, 0x9e, 0xdc, 0x3e, + 0x81, 0x25, 0x83, 0x75, 0x5b, 0xd4, 0xb3, 0x0f, 0x03, 0x55, 0xb6, 0x37, 0xe0, 0xae, 0xd1, 0xeb, + 0x5a, 0xad, 0x46, 0xb7, 0x65, 0x1d, 0x1a, 0xc7, 0x9d, 0xc3, 0xde, 0x3b, 0x90, 0x65, 0x80, 0x23, + 0xe3, 0xf0, 0xd8, 0x32, 0xcc, 0x4e, 0xab, 0x9d, 0xb0, 0x8e, 0x1f, 0x35, 0x8c, 0xf2, 0x24, 0x01, + 0x98, 0x39, 0x34, 0x1b, 0xad, 0x6e, 0xbb, 0x5c, 0xda, 0xbe, 0x0f, 0x2b, 0x06, 0xeb, 0x1a, 0x21, + 0x0e, 0x30, 0x44, 0x66, 0x63, 0x4a, 0xaf, 0xc2, 0xba, 0xa4, 0x1b, 0x66, 0x7b, 0xbf, 0x6d, 0xb6, + 0x7b, 0xad, 0x6b, 0x22, 0x3c, 0x68, 0x3c, 0x2e, 0x6b, 0xea, 0xa3, 0xd3, 0x2b, 0x4f, 0x6e, 0x3f, + 0x87, 0x7b, 0x07, 0x2a, 0xa9, 0x65, 0x8c, 0xea, 0x86, 0xe4, 0xcc, 0x08, 0xdd, 0x8c, 0xa8, 0xc3, + 0xff, 0x0f, 0x1a, 0xe6, 0xfd, 0x4e, 0x4f, 0x85, 0xfc, 0xb0, 0xdb, 0x50, 0x21, 0xab, 0xe0, 0xae, + 0x8f, 0x5f, 0xae, 0xdd, 0x38, 0x3c, 0x2e, 0x6b, 0x64, 0x1e, 0xa6, 0x3b, 0xbd, 0xbd, 0xf6, 0xe3, + 0xf2, 0x24, 0x59, 0x80, 0xd9, 0x83, 0xc6, 0x63, 0xcb, 0xe8, 0x75, 0xcb, 0xa5, 0xe6, 0xde, 0xab, + 0x37, 0x55, 0xed, 0xf5, 0x9b, 0xaa, 0xf6, 0xcb, 0x9b, 0xaa, 0xf6, 0xf5, 0xdb, 0xea, 0xc4, 0xeb, + 0xb7, 0xd5, 0x89, 0x1f, 0xdf, 0x56, 0x27, 0x9e, 0x6c, 0xe7, 0x8e, 0xa4, 0xa7, 0x14, 0xda, 0x3a, + 0xa5, 0x2e, 0xd3, 0x13, 0xb5, 0xea, 0x2f, 0x74, 0xf5, 0x0f, 0x4e, 0x1d, 0x4d, 0x7f, 0x46, 0x3d, + 0x86, 0x3f, 0xfa, 0x23, 0x00, 0x00, 0xff, 0xff, 0x25, 0xdf, 0xec, 0x3f, 0xd6, 0x0d, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -1148,6 +1153,26 @@ func (m *Metrics) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.VolumeBase.Size() + i -= size + if _, err := m.VolumeBase.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.VolumeQuote.Size() + i -= size + if _, err := m.VolumeQuote.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a { size := m.NetSize.Size() i -= size @@ -1329,6 +1354,10 @@ func (m *Metrics) Size() (n int) { } l = m.NetSize.Size() n += 1 + l + sovState(uint64(l)) + l = m.VolumeQuote.Size() + n += 1 + l + sovState(uint64(l)) + l = m.VolumeBase.Size() + n += 1 + l + sovState(uint64(l)) return n } @@ -2817,6 +2846,74 @@ func (m *Metrics) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeQuote", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VolumeQuote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeBase", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VolumeBase.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipState(dAtA[iNdEx:]) From 8f110136c83467e88236a10a2a9875eb6c24a676 Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Mon, 5 Dec 2022 21:41:01 -0300 Subject: [PATCH 3/8] fix: sort tokens in join pool to avoid panic (#1110) * fix: sort tokens in join pool to avoid panic * chore: changelog --- CHANGELOG.md | 1 + x/dex/types/pool.go | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d662decd..05e573495 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug Fixes * [#1100](https://github.com/NibiruChain/nibiru/pull/1100) - fix(oracle): fix flaky oracle test +* [#1110](https://github.com/NibiruChain/nibiru/pull/1110) - fix(dex): fix dex issue on unsorted join pool ## [v0.16.0](https://github.com/NibiruChain/nibiru/releases/tag/v0.16.0) - 2022-11-23 diff --git a/x/dex/types/pool.go b/x/dex/types/pool.go index 14ec0fd72..3505e2492 100644 --- a/x/dex/types/pool.go +++ b/x/dex/types/pool.go @@ -113,6 +113,7 @@ func (pool *Pool) AddTokensToPool(tokensIn sdk.Coins) ( return sdk.ZeroInt(), sdk.Coins{}, err } + tokensIn.Sort() if err := pool.incrementBalances(numShares, tokensIn.Sub(remCoins)); err != nil { return sdk.ZeroInt(), sdk.Coins{}, err } From 16350e840b38d6a6111153d69b3b821992a98da9 Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Tue, 6 Dec 2022 02:22:53 -0300 Subject: [PATCH 4/8] feat: whitelist ubtc and ueth in pricefeed (#1108) * feat: whitelist ubtc and ueth in pricefeed * feat: add uusdc to the lcoalnet * fix(localnet.sh): 1. Move pair initialization calls of 'nibid add_genesis_param' before calls of 'add-genesis-oracle'. 2. Use USDT instead of USDC to match devnet and testnet Co-authored-by: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Co-authored-by: Unique-Divine --- scripts/localnet.sh | 49 +++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/scripts/localnet.sh b/scripts/localnet.sh index 30b02b892..b504ad347 100755 --- a/scripts/localnet.sh +++ b/scripts/localnet.sh @@ -9,25 +9,26 @@ console_log_text_color() { reset=$(tput sgr0) } -if [ console_log_text_color ]; then echo "succesfully toggled console coloring" +if [ console_log_text_color ]; then + echo "succesfully toggled console coloring" else # For Ubuntu and Debian. MacOS has tput by default. apt-get install libncurses5-dbg -y fi -echo_info () { +echo_info() { echo "${blue}" echo "$1" echo "${reset}" } -echo_error () { +echo_error() { echo "${red}" echo "$1" echo "${reset}" } -echo_success () { +echo_success() { echo "${green}" echo "$1" echo "${reset}" @@ -47,8 +48,10 @@ CHAIN_ID="nibiru-localnet-0" RPC_PORT="26657" GRPC_PORT="9090" MNEMONIC="guard cream sadness conduct invite crumble clock pudding hole grit liar hotel maid produce squeeze return argue turtle know drive eight casino maze host" -GENESIS_COINS="1000000000unibi,10000000000000unusd" +GENESIS_COINS="10000000000000unibi,10000000000000unusd,10000000000000uusdt" CHAIN_DIR="$HOME/.nibid" +echo "CHAIN_DIR: $CHAIN_DIR" +echo "CHAIN_ID: $CHAIN_ID" SEDOPTION="" if [[ "$OSTYPE" == "darwin"* ]]; then @@ -56,9 +59,9 @@ if [[ "$OSTYPE" == "darwin"* ]]; then fi # Stop nibid if it is already running -if pgrep -x "$BINARY" > /dev/null; then - echo_error "Terminating $BINARY..." - killall nibid +if pgrep -x "$BINARY" >/dev/null; then + echo_error "Terminating $BINARY..." + killall nibid fi # Remove previous data @@ -79,7 +82,6 @@ else echo_error "Failed to initialize $CHAIN_ID" fi - # Configure keyring-backend to "test" echo_info "Configuring keyring-backend..." if $BINARY config keyring-backend test; then @@ -88,7 +90,6 @@ else echo_error "Failed to configure keyring-backend" fi - # Configure chain-id echo_info "Configuring chain-id..." if $BINARY config chain-id $CHAIN_ID; then @@ -170,7 +171,7 @@ fi add_genesis_param() { echo "jq input $1" # copy param ($1) to tmp_genesis.json - cat $CHAIN_DIR/config/genesis.json | jq "$1" > $CHAIN_DIR/config/tmp_genesis.json + cat $CHAIN_DIR/config/genesis.json | jq "$1" >$CHAIN_DIR/config/tmp_genesis.json # rewrite genesis.json with the contents of tmp_genesis.json mv $CHAIN_DIR/config/tmp_genesis.json $CHAIN_DIR/config/genesis.json } @@ -182,13 +183,13 @@ add_genesis_vpools_with_coingecko_prices() { curl -X 'GET' \ 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin%2Cethereum&vs_currencies=usd' \ -H 'accept: application/json' \ - > $temp_json_fname + >$temp_json_fname local M=1000000 local num_users=24000 - local faucet_nusd_amt=100 - local quote_amt=$(($num_users * $faucet_nusd_amt * $M)) + local faucet_nusd_amt=100 + local quote_amt=$(($num_users * $faucet_nusd_amt * $M)) price_btc=$(cat tmp_vpool_prices.json | jq -r '.bitcoin.usd') price_btc=${price_btc%.*} @@ -201,7 +202,7 @@ add_genesis_vpools_with_coingecko_prices() { nibid add-genesis-vpool ubtc:unusd $base_amt_btc $quote_amt 0.1 0.1 0.1 0.0625 12 nibid add-genesis-vpool ueth:unusd $base_amt_eth $quote_amt 0.1 0.1 0.1 0.04 20 - echo 'tmp_vpool_prices: ' + echo 'tmp_vpool_prices: ' cat $temp_json_fname | jq . rm -f $temp_json_fname } @@ -213,16 +214,16 @@ add_genesis_vpools_default() { local quote_amt=10$KILO$MEGA local base_amt_btc=$(($quote_amt / 16500)) local base_amt_eth=$(($quote_amt / 1200)) - nibid add-genesis-vpool ubtc:unusd $base_amt_btc $quote_amt 0.1 0.1 0.1 0.0625 12 + nibid add-genesis-vpool ubtc:unusd $base_amt_btc $quote_amt 0.1 0.1 0.1 0.0625 12 nibid add-genesis-vpool ueth:unusd $base_amt_eth $quote_amt 0.1 0.1 0.1 0.0625 10 } # x/vpool -if add_genesis_vpools_with_coingecko_prices; then +if add_genesis_vpools_with_coingecko_prices; then echo_success "set vpools with coingecko prices" -elif add_genesis_vpools_default; then - echo_success "set vpools with defaults" -else +elif add_genesis_vpools_default; then + echo_success "set vpools with defaults" +else echo_error "failed to set genesis vpools" fi @@ -240,9 +241,13 @@ add_genesis_param '.app_state.perp.pair_metadata[1].pair = {token0:"ueth",token1 add_genesis_param '.app_state.perp.pair_metadata[1].latest_cumulative_premium_fraction = "0"' # x/pricefeed +add_genesis_param '.app_state.pricefeed.params.pairs[0] = {token0:"ubtc",token1:"unusd"}' +add_genesis_param '.app_state.pricefeed.params.pairs[0] = {token0:"ueth",token1:"unusd"}' +add_genesis_param '.app_state.pricefeed.params.pairs[0] = {token0:"ueth",token1:"unusd"}' +add_genesis_param '.app_state.pricefeed.params.twap_lookback_window = "900s"' nibid add-genesis-oracle nibi1zaavvzxez0elundtn32qnk9lkm8kmcsz44g7xl - -cat $HOME/.nibid/config/genesis.json | jq '.app_state.pricefeed.params.twap_lookback_window = "900s"' > $HOME/.nibid/config/tmp_genesis.json && mv $HOME/.nibid/config/tmp_genesis.json $HOME/.nibid/config/genesis.json +nibid add-genesis-oracle nibi1lptpc0e3upq2n7e4zmqtr0yxyrldp6jzz8z8xm +nibid add-genesis-oracle nibi15cdcxznuwpuk5hw7t678wpyesy78kwy00qcesa # Start the network echo_info "Starting $CHAIN_ID in $CHAIN_DIR..." From 0009e57011bb65ba09b79ad12967b675411a668d Mon Sep 17 00:00:00 2001 From: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Date: Tue, 6 Dec 2022 11:02:10 -0600 Subject: [PATCH 5/8] feat(vpool)!: Use flags and certain default values instead of unnamed args for add-genesis-vpool to improve ease of use (#1111) * feat(vpool)!: use flags and default values for add-genesis-vpool to improve usability" * reflect changes in localnet.sh * temp CHANGELOG * add PR number to changelog * docs: match CLI docs to proto docs --- CHANGELOG.md | 1 + scripts/localnet.sh | 8 +- x/vpool/client/cli/genvpool.go | 119 +++++++++++++++++++++++----- x/vpool/client/cli/genvpool_test.go | 19 ++--- 4 files changed, 113 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05e573495..b00d129a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +* [#1111](https://github.com/NibiruChain/nibiru/pull/1111) - feat(vpool)!: Use flags and certain default values instead of unnamed args for add-genesis-vpool to improve ease of use * [#1046](https://github.com/NibiruChain/nibiru/pull/1046) - remove: feeder. The price feeder was moved to an external repo. * [#1015](https://github.com/NibiruChain/nibiru/pull/1015) - feat(dex): throw error when swap output amount is less than 1 * [#1018](https://github.com/NibiruChain/nibiru/pull/1018) - chore(dex): refactor to match best practice diff --git a/scripts/localnet.sh b/scripts/localnet.sh index b504ad347..94f2661fb 100755 --- a/scripts/localnet.sh +++ b/scripts/localnet.sh @@ -199,8 +199,8 @@ add_genesis_vpools_with_coingecko_prices() { price_eth=${price_eth%.*} base_amt_eth=$(($quote_amt / $price_eth)) - nibid add-genesis-vpool ubtc:unusd $base_amt_btc $quote_amt 0.1 0.1 0.1 0.0625 12 - nibid add-genesis-vpool ueth:unusd $base_amt_eth $quote_amt 0.1 0.1 0.1 0.04 20 + nibid add-genesis-vpool --pair=ubtc:unusd --base-amt=$base_amt_btc --quote-amt=$quote_amt --max-leverage=12 + nibid add-genesis-vpool --pair=ueth:unusd --base-amt=$base_amt_eth --quote-amt=$quote_amt --max-leverage=20 --mmr=0.04 echo 'tmp_vpool_prices: ' cat $temp_json_fname | jq . @@ -214,8 +214,8 @@ add_genesis_vpools_default() { local quote_amt=10$KILO$MEGA local base_amt_btc=$(($quote_amt / 16500)) local base_amt_eth=$(($quote_amt / 1200)) - nibid add-genesis-vpool ubtc:unusd $base_amt_btc $quote_amt 0.1 0.1 0.1 0.0625 12 - nibid add-genesis-vpool ueth:unusd $base_amt_eth $quote_amt 0.1 0.1 0.1 0.0625 10 + nibid add-genesis-vpool --pair=ubtc:unusd --base-amt=$base_amt_btc --quote-amt=$quote_amt --max-leverage=12 + nibid add-genesis-vpool --pair=ueth:unusd --base-amt=$base_amt_eth --quote-amt=$quote_amt --max-leverage=20 --mmr=0.04 } # x/vpool diff --git a/x/vpool/client/cli/genvpool.go b/x/vpool/client/cli/genvpool.go index 8486cfc62..091e6c8a4 100644 --- a/x/vpool/client/cli/genvpool.go +++ b/x/vpool/client/cli/genvpool.go @@ -5,6 +5,8 @@ import ( "fmt" "strings" + flag "github.com/spf13/pflag" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" @@ -17,6 +19,32 @@ import ( "github.com/NibiruChain/nibiru/x/vpool/types" ) +const ( + FlagPair = "pair" + FlagBaseAmt = "base-amt" + FlagQuoteAmt = "quote-amt" + FlagTradeLim = "trade-lim" + FlagFluctLim = "fluct-lim" + FlagMaintenenceMarginRatio = "mmr" + FlagMaxLeverage = "max-leverage" + FlagMaxOracleSpreadRatio = "max-oracle-spread-ratio" +) + +var flagsAddVpoolGenesis = map[string]struct { + flagName string + defaultValue string + usageDocString string +}{ + FlagPair: {"pair", "", "trading pair identifier of the form 'base:quote'. E.g., ueth:unusd"}, + FlagBaseAmt: {"base-amt", "", "amount of base asset reserves"}, + FlagQuoteAmt: {"quote-amt", "", "amount of quote asset reserves"}, + FlagTradeLim: {"trade-lim", "0.1", "percentage applied to reserves in order not to over trade"}, + FlagFluctLim: {"fluct-lim", "0.1", "percentage that a single open or close position can alter the reserves"}, + FlagMaintenenceMarginRatio: {"mmr", "0.0625", "maintenance margin ratio"}, + FlagMaxLeverage: {"max-leverage", "10", "maximum leverage for opening a position"}, + FlagMaxOracleSpreadRatio: {"max-oracle-spread-ratio", "0.1", "max oracle spread ratio"}, +} + // AddVpoolGenesisCmd returns add-vpool-genesis func AddVpoolGenesisCmd(defaultNodeHome string) *cobra.Command { usageExampleTail := strings.Join([]string{ @@ -24,11 +52,22 @@ func AddVpoolGenesisCmd(defaultNodeHome string) *cobra.Command { "fluctuation-limit-ratio", "max-oracle-spread-ratio", "maintenance-margin-ratio", "max-leverage", }, "] [") + + // getCmdFlagSet returns a flag set and list of required flags for the command. + getCmdFlagSet := func() (fs *flag.FlagSet, reqFlags []string) { + fs = flag.NewFlagSet("flags-add-genesis-pool", flag.ContinueOnError) + + for _, flagDefinitionArgs := range flagsAddVpoolGenesis { + args := flagDefinitionArgs + fs.String(args.flagName, args.defaultValue, args.usageDocString) + } + return fs, []string{"pair", "base-amt", "quote-amt"} + } cmd := &cobra.Command{ Use: fmt.Sprintf("add-genesis-vpool [%s]", usageExampleTail), Short: "Add vPools to genesis.json", Long: `Add vPools to genesis.json.`, - Args: cobra.ExactArgs(8), + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { clientCtx := client.GetClientContextFromCmd(cmd) serverCtx := server.GetServerContextFromCmd(cmd) @@ -42,7 +81,7 @@ func AddVpoolGenesisCmd(defaultNodeHome string) *cobra.Command { return err } - vPool, err := parseVpoolParams(args) + vPool, err := newVpoolFromAddVpoolGenesisFlags(cmd.Flags()) if err != nil { return err } @@ -70,50 +109,88 @@ func AddVpoolGenesisCmd(defaultNodeHome string) *cobra.Command { cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") flags.AddQueryFlagsToCmd(cmd) + flagSet, reqFlags := getCmdFlagSet() + cmd.Flags().AddFlagSet(flagSet) + for _, reqFlag := range reqFlags { + _ = cmd.MarkFlagRequired(reqFlag) + } + return cmd } -func parseVpoolParams(args []string) (types.Vpool, error) { - vPair, err := common.NewAssetPair(args[0]) +func newVpoolFromAddVpoolGenesisFlags(flagSet *flag.FlagSet, +) (vpool types.Vpool, err error) { + var flagErrors = []error{} + pairStr, err := flagSet.GetString(FlagPair) + flagErrors = append(flagErrors, err) + + baseAmtStr, err := flagSet.GetString(FlagBaseAmt) + flagErrors = append(flagErrors, err) + + quoteAmtStr, err := flagSet.GetString(FlagQuoteAmt) + flagErrors = append(flagErrors, err) + + tradeLimStr, err := flagSet.GetString(FlagTradeLim) + flagErrors = append(flagErrors, err) + + fluctLimStr, err := flagSet.GetString(FlagFluctLim) + flagErrors = append(flagErrors, err) + + mmrAsString, err := flagSet.GetString(FlagMaintenenceMarginRatio) + flagErrors = append(flagErrors, err) + + maxLeverageStr, err := flagSet.GetString(FlagMaxLeverage) + flagErrors = append(flagErrors, err) + + maxOracleSpreadStr, err := flagSet.GetString(FlagMaxOracleSpreadRatio) + flagErrors = append(flagErrors, err) + + for _, err := range flagErrors { // for brevity's sake + if err != nil { + return vpool, err + } + } + + pair, err := common.NewAssetPair(pairStr) if err != nil { - return types.Vpool{}, err + return } - baseAsset, err := sdk.NewDecFromStr(args[1]) + baseAsset, err := sdk.NewDecFromStr(baseAmtStr) if err != nil { - return types.Vpool{}, err + return } - quoteAsset, err := sdk.NewDecFromStr(args[2]) + quoteAsset, err := sdk.NewDecFromStr(quoteAmtStr) if err != nil { - return types.Vpool{}, err + return } - tradeLimit, err := sdk.NewDecFromStr(args[3]) + tradeLimit, err := sdk.NewDecFromStr(tradeLimStr) if err != nil { - return types.Vpool{}, err + return } - fluctuationLimitRatio, err := sdk.NewDecFromStr(args[4]) + fluctuationLimitRatio, err := sdk.NewDecFromStr(fluctLimStr) if err != nil { - return types.Vpool{}, err + return } - maxOracleSpread, err := sdk.NewDecFromStr(args[5]) + maxOracleSpread, err := sdk.NewDecFromStr(maxOracleSpreadStr) if err != nil { - return types.Vpool{}, err + return } - maintenanceMarginRatio, err := sdk.NewDecFromStr(args[6]) + maintenanceMarginRatio, err := sdk.NewDecFromStr(mmrAsString) if err != nil { - return types.Vpool{}, err + return } - maxLeverage, err := sdk.NewDecFromStr(args[7]) + maxLeverage, err := sdk.NewDecFromStr(maxLeverageStr) if err != nil { return types.Vpool{}, err } - vPool := types.Vpool{ - Pair: vPair, + vpool = types.Vpool{ + Pair: pair, QuoteAssetReserve: quoteAsset, BaseAssetReserve: baseAsset, Config: types.VpoolConfig{ @@ -125,5 +202,5 @@ func parseVpoolParams(args []string) (types.Vpool, error) { }, } - return vPool, vPool.Validate() + return vpool, vpool.Validate() } diff --git a/x/vpool/client/cli/genvpool_test.go b/x/vpool/client/cli/genvpool_test.go index cd06ba15b..84ce33b3e 100644 --- a/x/vpool/client/cli/genvpool_test.go +++ b/x/vpool/client/cli/genvpool_test.go @@ -131,15 +131,16 @@ func TestAddGenesisVpoolCmd(t *testing.T) { cmd := cli.AddVpoolGenesisCmd("home") cmd.SetArgs([]string{ - tc.pairName, - tc.baseAmt, - tc.quoteAmt, - tc.tradeLimit, - tc.flucLimit, - tc.maxOracle, - tc.maintainRatio, - tc.maxLeverage, - fmt.Sprintf("--%s=home", flags.FlagHome)}) + fmt.Sprintf("--%s=%s", cli.FlagPair, tc.pairName), + fmt.Sprintf("--%s=%s", cli.FlagBaseAmt, tc.baseAmt), + fmt.Sprintf("--%s=%s", cli.FlagQuoteAmt, tc.quoteAmt), + fmt.Sprintf("--%s=%s", cli.FlagTradeLim, tc.tradeLimit), + fmt.Sprintf("--%s=%s", cli.FlagFluctLim, tc.flucLimit), + fmt.Sprintf("--%s=%s", cli.FlagMaxOracleSpreadRatio, tc.maxOracle), + fmt.Sprintf("--%s=%s", cli.FlagMaintenenceMarginRatio, tc.maintainRatio), + fmt.Sprintf("--%s=%s", cli.FlagMaxLeverage, tc.maxLeverage), + fmt.Sprintf("--%s=home", flags.FlagHome), + }) if tc.expectError { require.Error(t, cmd.ExecuteContext(ctx)) From 0ebc527f9eca455aacb29f1343da9e044e0ad69e Mon Sep 17 00:00:00 2001 From: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Date: Tue, 6 Dec 2022 11:17:41 -0600 Subject: [PATCH 6/8] refactor(vpool)!: Condense swap SwapXForY and SwapYForX events into SwapOnVpoolEvent (#1109) * run protolint and create SwapOnVpoolEvent * feat(vpool): SwapOnVpoolEvent + executeSwap * refactor,test(vpool): consistency between functions + DRY * rm unused filed. * docs(CHANGELOG) * Update x/vpool/keeper/keeper.go * dependencies: bump collections to v0.1.1 * Update CHANGELOG.md * test(oracle): wrap potential collections panics in require.NotPanics with better error messags --- CHANGELOG.md | 23 +- go.mod | 2 +- go.sum | 4 +- proto/vpool/v1/event.proto | 76 +++---- x/oracle/keeper/tally_fuzz_test.go | 9 +- x/vpool/keeper/keeper.go | 129 +++++------ x/vpool/keeper/prices.go | 9 +- x/vpool/keeper/snapshot.go | 6 +- x/vpool/types/event.pb.go | 340 ++++++++++++++++++++++++++--- x/vpool/types/events.go | 13 -- x/vpool/types/pool.go | 106 ++++----- x/vpool/types/pool_test.go | 70 +++--- 12 files changed, 517 insertions(+), 270 deletions(-) delete mode 100644 x/vpool/types/events.go diff --git a/CHANGELOG.md b/CHANGELOG.md index b00d129a2..794bb0af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,18 +39,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## Unreleased -### State Machine Breaking +* ... -* [#1102](https://github.com/NibiruChain/nibiru/pull/1102) - refactor(perp)!: replace CumulativePremiumFractions array with single value - -### Bug Fixes - -* [#1100](https://github.com/NibiruChain/nibiru/pull/1100) - fix(oracle): fix flaky oracle test -* [#1110](https://github.com/NibiruChain/nibiru/pull/1110) - fix(dex): fix dex issue on unsorted join pool - -## [v0.16.0](https://github.com/NibiruChain/nibiru/releases/tag/v0.16.0) - 2022-11-23 +## [v0.16.0](https://github.com/NibiruChain/nibiru/releases/tag/v0.16.0) - Unreleased ### Features @@ -64,6 +57,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#1097](https://github.com/NibiruChain/nibiru/pull/1097) - feat(perp): Track and expose the net size of a pair with a query * [#1105](https://github.com/NibiruChain/nibiru/pull/1105) - feat(perp): Add (notional) volume to metrics state +### State Machine Breaking + +* [#1102](https://github.com/NibiruChain/nibiru/pull/1102) - refactor(perp)!: replace CumulativePremiumFractions array with single value + ### Improvements * [#1111](https://github.com/NibiruChain/nibiru/pull/1111) - feat(vpool)!: Use flags and certain default values instead of unnamed args for add-genesis-vpool to improve ease of use @@ -87,6 +84,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#1086](https://github.com/NibiruChain/nibiru/pull/1086) - refactor(perp)!: Removed unused field, `LiquidationPenalty`, from `PositionChangedEvent` * [#1093](https://github.com/NibiruChain/nibiru/pull/1093) - simulation(dex): add simulation tests for stableswap pools * [#1091](https://github.com/NibiruChain/nibiru/pull/1091) - refactor: Use common.Precision instead of 1_000_000 in the codebase +* [#1109](https://github.com/NibiruChain/nibiru/pull/1109) - refactor(vpool)!: Condense swap SwapXForY and SwapYForX events into SwapOnVpoolEvent + +### Bug Fixes + +* [#1100](https://github.com/NibiruChain/nibiru/pull/1100) - fix(oracle): fix flaky oracle test +* [#1110](https://github.com/NibiruChain/nibiru/pull/1110) - fix(dex): fix dex issue on unsorted join pool ## v0.15.0 diff --git a/go.mod b/go.mod index c3e6a9188..a39a26825 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/CosmWasm/wasmd v0.29.1 - github.com/NibiruChain/collections v0.1.0 + github.com/NibiruChain/collections v0.1.1 github.com/cosmos/cosmos-sdk v0.45.10 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/ibc-go/v3 v3.4.0 diff --git a/go.sum b/go.sum index 9697e94fc..bcf800cc1 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/NibiruChain/collections v0.1.0 h1:Y+S9IBID5g8tQonVtIhHxIFYgE4EnMs9PZh0y4AlBp0= -github.com/NibiruChain/collections v0.1.0/go.mod h1:ejC9eAI5B6/56mKYagW5T5aIw0yh1yI0ID+/SnqbCYo= +github.com/NibiruChain/collections v0.1.1 h1:6urGw4ephXwNKZ/cg6I5SGBBlIf9UPvRn6mFiAoX8Vk= +github.com/NibiruChain/collections v0.1.1/go.mod h1:uWw2HTT4NxQaqC6Wmwyqbz8Fg7bGShMjZUx5unWRLNk= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= diff --git a/proto/vpool/v1/event.proto b/proto/vpool/v1/event.proto index fb6f1e8d2..934692a71 100644 --- a/proto/vpool/v1/event.proto +++ b/proto/vpool/v1/event.proto @@ -2,77 +2,67 @@ syntax = "proto3"; package nibiru.vpool.v1; -import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; import "google/protobuf/timestamp.proto"; option go_package = "github.com/NibiruChain/nibiru/x/vpool/types"; message ReserveSnapshotSavedEvent { - string pair = 1; - - string quote_reserve = 2 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - - string base_reserve = 3 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - - // MarkPrice at the end of the block. - // (instantaneous) markPrice := quoteReserve / baseReserve - string mark_price = 4 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - - int64 block_height = 5; + string pair = 1; + string quote_reserve = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + string base_reserve = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // MarkPrice at the end of the block. + // (instantaneous) markPrice := quoteReserve / baseReserve + string mark_price = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + int64 block_height = 5; - google.protobuf.Timestamp block_timestamp = 6 [ + google.protobuf.Timestamp block_timestamp = 6 [ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ]; } -message SwapQuoteForBaseEvent { - string pair = 1; - - string quote_amount = 2 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - - string base_amount = 3 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; -} - -message SwapBaseForQuoteEvent { - string pair = 1; +// A swap on the vpool represented by 'pair'. +// Amounts are negative or positive base on the perspective of the pool, i.e. +// a negative quote means the trader has gained quote and the vpool lost quote. +message SwapOnVpoolEvent { + string pair = 1; - string quote_amount = 2 [ + // delta in the quote reserves of the vpool + string quote_amount = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; - string base_amount = 3 [ + // delta in the base reserves of the vpool + string base_amount = 3 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; } message MarkPriceChangedEvent { - string pair = 1; - string price = 2 [ + string pair = 1; + string price = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; - google.protobuf.Timestamp block_timestamp = 3 [ + google.protobuf.Timestamp block_timestamp = 3 [ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ]; diff --git a/x/oracle/keeper/tally_fuzz_test.go b/x/oracle/keeper/tally_fuzz_test.go index 563cb1912..fc10f97c2 100644 --- a/x/oracle/keeper/tally_fuzz_test.go +++ b/x/oracle/keeper/tally_fuzz_test.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" fuzz "github.com/google/gofuzz" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/NibiruChain/nibiru/x/oracle/types" @@ -122,8 +123,10 @@ func TestFuzz_PickReferencePair(t *testing.T) { voteTargets := map[string]struct{}{} f.Fuzz(&voteTargets) - for k := range voteTargets { - input.OracleKeeper.Pairs.Insert(input.Ctx, k) + for key := range voteTargets { + assert.NotPanics(t, func() { + input.OracleKeeper.Pairs.Insert(input.Ctx, key) + }, "attempted to insert key: %s", key) } voteMap := map[string]types.ExchangeRateBallot{} @@ -131,5 +134,5 @@ func TestFuzz_PickReferencePair(t *testing.T) { require.NotPanics(t, func() { input.OracleKeeper.RemoveInvalidBallots(input.Ctx, voteMap) - }) + }, "voteMap: %v", voteMap) } diff --git a/x/vpool/keeper/keeper.go b/x/vpool/keeper/keeper.go index 780e03948..2d1e38c98 100644 --- a/x/vpool/keeper/keeper.go +++ b/x/vpool/keeper/keeper.go @@ -55,12 +55,12 @@ args: - ctx: cosmos-sdk context - pair: a token pair like BTC:NUSD - dir: either add or remove from pool - - baseAssetAmount: the amount of quote asset being traded + - baseAmt: the amount of base asset being traded - quoteAmountLimit: a limiter to ensure the trader doesn't get screwed by slippage - skipFluctuationLimitCheck: whether or not to skip the fluctuation limit check ret: - - quoteAssetAmount: the amount of quote asset swapped + - quoteAmtAbs: the absolute value of the amount swapped in quote assets - err: error */ func (k Keeper) SwapBaseForQuote( @@ -70,7 +70,7 @@ func (k Keeper) SwapBaseForQuote( baseAmt sdk.Dec, quoteLimit sdk.Dec, skipFluctuationLimitCheck bool, -) (quoteAmt sdk.Dec, err error) { +) (quoteAmtAbs sdk.Dec, err error) { if baseAmt.IsZero() { return sdk.ZeroDec(), nil } @@ -84,56 +84,62 @@ func (k Keeper) SwapBaseForQuote( return sdk.Dec{}, types.ErrPairNotSupported } - if !pool.HasEnoughBaseReserve(baseAmt) { - return sdk.Dec{}, types.ErrOverTradingLimit - } - - quoteAmt, err = pool.GetQuoteAmountByBaseAmount(dir, baseAmt) + baseAmtAbs := baseAmt.Abs() + quoteAmtAbs, err = pool.GetQuoteAmountByBaseAmount(baseAmtAbs.MulInt64(dir.ToMultiplier())) if err != nil { return sdk.Dec{}, err } - if !pool.HasEnoughQuoteReserve(quoteAmt) { - // in reality, this if statement should never run because a perturbation in quote reserve assets - // greater than trading limit ratio would have happened when checking for a perturbation in - // base assets, due to x*y=k - // - // e.g. a 10% change in quote asset reserves would have triggered a >10% change in - // base asset reserves - return sdk.Dec{}, types.ErrOverTradingLimit.Wrapf( - "quote amount %s is over trading limit", quoteAmt) + if err := pool.HasEnoughReservesForTrade(quoteAmtAbs, baseAmtAbs); err != nil { + return sdk.Dec{}, err } - err = checkIfLimitIsViolated(quoteLimit, quoteAmt, dir) - if err != nil { + if err := checkIfLimitIsViolated(quoteLimit, quoteAmtAbs, dir); err != nil { return sdk.Dec{}, err } - if dir == types.Direction_ADD_TO_POOL { - pool.IncreaseBaseAssetReserve(baseAmt) - pool.DecreaseQuoteAssetReserve(quoteAmt) - } else if dir == types.Direction_REMOVE_FROM_POOL { - pool.DecreaseBaseAssetReserve(baseAmt) - pool.IncreaseQuoteAssetReserve(quoteAmt) - } + quoteDelta := quoteAmtAbs.Neg().MulInt64(dir.ToMultiplier()) + baseAmt = baseAmtAbs.MulInt64(dir.ToMultiplier()) - if err = k.updatePool(ctx, pool, skipFluctuationLimitCheck); err != nil { + pool, err = k.executeSwap(ctx, pool, quoteDelta, baseAmt, skipFluctuationLimitCheck) + if err != nil { return sdk.Dec{}, fmt.Errorf("error updating reserve: %w", err) } - if err := ctx.EventManager().EmitTypedEvent(&types.MarkPriceChangedEvent{ - Pair: pair.String(), - Price: pool.GetMarkPrice(), + return quoteAmtAbs, err +} + +func (k Keeper) executeSwap( + ctx sdk.Context, vpool types.Vpool, quoteDelta sdk.Dec, baseDelta sdk.Dec, + skipFluctuationLimitCheck bool, +) (newVpool types.Vpool, err error) { + // -------------------- Update reserves + vpool.AddToBaseAssetReserve(baseDelta) + vpool.AddToQuoteAssetReserve(quoteDelta) + + if err = k.updatePool(ctx, vpool, skipFluctuationLimitCheck); err != nil { + return newVpool, fmt.Errorf("error updating reserve: %w", err) + } + + // -------------------- Emit events + if err = ctx.EventManager().EmitTypedEvent(&types.MarkPriceChangedEvent{ + Pair: vpool.Pair.String(), + Price: vpool.GetMarkPrice(), BlockTimestamp: ctx.BlockTime(), }); err != nil { - return sdk.Dec{}, err + return newVpool, err } - return quoteAmt, ctx.EventManager().EmitTypedEvent(&types.SwapBaseForQuoteEvent{ - Pair: pair.String(), - QuoteAmount: quoteAmt, - BaseAmount: baseAmt, - }) + if err = ctx.EventManager().EmitTypedEvent(&types.SwapOnVpoolEvent{ + Pair: vpool.Pair.String(), + QuoteAmount: quoteDelta, + BaseAmount: baseDelta, + }); err != nil { + return newVpool, err + } + + newVpool = vpool + return newVpool, err } /* @@ -161,7 +167,7 @@ func (k Keeper) SwapQuoteForBase( quoteAmt sdk.Dec, baseLimit sdk.Dec, skipFluctuationLimitCheck bool, -) (baseAmt sdk.Dec, err error) { +) (baseAmtAbs sdk.Dec, err error) { if quoteAmt.IsZero() { return sdk.ZeroDec(), nil } @@ -176,57 +182,30 @@ func (k Keeper) SwapQuoteForBase( } // check trade limit ratio on quote in either direction - if !pool.HasEnoughQuoteReserve(quoteAmt) { - return sdk.Dec{}, types.ErrOverTradingLimit.Wrapf( - "quote amount %s is over trading limit", quoteAmt) - } - - baseAmt, err = pool.GetBaseAmountByQuoteAmount(dir, quoteAmt) + quoteAmtAbs := quoteAmt.Abs() + baseAmtAbs, err = pool.GetBaseAmountByQuoteAmount( + quoteAmtAbs.MulInt64(dir.ToMultiplier())) if err != nil { return sdk.Dec{}, err } - if !pool.HasEnoughBaseReserve(baseAmt) { - // in reality, this if statement should never run because a perturbation in base reserve assets - // greater than trading limit ratio would have happened when checking for a perturbation in - // quote assets, due to x*y=k - // - // e.g. a 10% change in base asset reserves would have triggered a >10% change in - // quote asset reserves - return sdk.Dec{}, types.ErrOverTradingLimit.Wrapf( - "base amount %s is over trading limit", baseAmt) + if err := pool.HasEnoughReservesForTrade(quoteAmtAbs, baseAmtAbs); err != nil { + return sdk.Dec{}, err } - err = checkIfLimitIsViolated(baseLimit, baseAmt, dir) - if err != nil { + if err := checkIfLimitIsViolated(baseLimit, baseAmtAbs, dir); err != nil { return sdk.Dec{}, err } - if dir == types.Direction_ADD_TO_POOL { - pool.DecreaseBaseAssetReserve(baseAmt) - pool.IncreaseQuoteAssetReserve(quoteAmt) - } else if dir == types.Direction_REMOVE_FROM_POOL { - pool.IncreaseBaseAssetReserve(baseAmt) - pool.DecreaseQuoteAssetReserve(quoteAmt) - } + quoteAmt = quoteAmtAbs.MulInt64(dir.ToMultiplier()) + baseDelta := baseAmtAbs.Neg().MulInt64(dir.ToMultiplier()) - if err = k.updatePool(ctx, pool, skipFluctuationLimitCheck); err != nil { + pool, err = k.executeSwap(ctx, pool, quoteAmt, baseDelta, skipFluctuationLimitCheck) + if err != nil { return sdk.Dec{}, fmt.Errorf("error updating reserve: %w", err) } - if err := ctx.EventManager().EmitTypedEvent(&types.MarkPriceChangedEvent{ - Pair: pair.String(), - Price: pool.GetMarkPrice(), - BlockTimestamp: ctx.BlockTime(), - }); err != nil { - return sdk.Dec{}, err - } - - return baseAmt, ctx.EventManager().EmitTypedEvent(&types.SwapQuoteForBaseEvent{ - Pair: pair.String(), - QuoteAmount: quoteAmt, - BaseAmount: baseAmt, - }) + return baseAmtAbs, err } // checkIfLimitIsViolated checks if the limit is violated by the amount. diff --git a/x/vpool/keeper/prices.go b/x/vpool/keeper/prices.go index 48117b84f..4ec2c9ca8 100644 --- a/x/vpool/keeper/prices.go +++ b/x/vpool/keeper/prices.go @@ -65,7 +65,7 @@ func (k Keeper) GetBaseAssetPrice( return sdk.ZeroDec(), err } - return pool.GetQuoteAmountByBaseAmount(dir, baseAssetAmount) + return pool.GetQuoteAmountByBaseAmount(baseAssetAmount.MulInt64(dir.ToMultiplier())) } /* @@ -77,7 +77,7 @@ args: - ctx: cosmos-sdk context - pair: the trading token pair - dir: add or remove - - quoteAmount: the amount of quote asset + - quoteAmountAbs: the amount of quote asset ret: - baseAssetAmount: the amount of base assets required to make the desired swap @@ -87,14 +87,15 @@ func (k Keeper) GetQuoteAssetPrice( ctx sdk.Context, pair common.AssetPair, dir types.Direction, - quoteAmount sdk.Dec, + quoteAmountAbs sdk.Dec, ) (baseAssetAmount sdk.Dec, err error) { pool, err := k.Pools.Get(ctx, pair) if err != nil { return sdk.ZeroDec(), err } - return pool.GetBaseAmountByQuoteAmount(dir, quoteAmount) + dirMult := dir.ToMultiplier() + return pool.GetBaseAmountByQuoteAmount(quoteAmountAbs.MulInt64(dirMult)) } /* diff --git a/x/vpool/keeper/snapshot.go b/x/vpool/keeper/snapshot.go index 079a29472..113576d3e 100644 --- a/x/vpool/keeper/snapshot.go +++ b/x/vpool/keeper/snapshot.go @@ -64,7 +64,7 @@ func getPriceWithSnapshot( TradeLimitRatio: sdk.ZeroDec(), // unused }, } - return pool.GetBaseAmountByQuoteAmount(snapshotPriceOpts.direction, snapshotPriceOpts.assetAmount) + return pool.GetBaseAmountByQuoteAmount(snapshotPriceOpts.assetAmount.MulInt64(snapshotPriceOpts.direction.ToMultiplier())) case types.TwapCalcOption_BASE_ASSET_SWAP: pool := &types.Vpool{ @@ -79,7 +79,9 @@ func getPriceWithSnapshot( TradeLimitRatio: sdk.ZeroDec(), // unused }, } - return pool.GetQuoteAmountByBaseAmount(snapshotPriceOpts.direction, snapshotPriceOpts.assetAmount) + return pool.GetQuoteAmountByBaseAmount( + snapshotPriceOpts.assetAmount.MulInt64(snapshotPriceOpts.direction.ToMultiplier()), + ) } return sdk.ZeroDec(), nil diff --git a/x/vpool/types/event.pb.go b/x/vpool/types/event.pb.go index dc68b9426..d6939d108 100644 --- a/x/vpool/types/event.pb.go +++ b/x/vpool/types/event.pb.go @@ -95,6 +95,57 @@ func (m *ReserveSnapshotSavedEvent) GetBlockTimestamp() time.Time { return time.Time{} } +// A swap on the vpool represented by 'pair'. +// Amounts are negative or positive base on the perspective of the pool, i.e. +// a negative quote means the trader has gained quote and the vpool lost quote. +type SwapOnVpoolEvent struct { + Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"` + // delta in the quote reserves of the vpool + QuoteAmount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=quote_amount,json=quoteAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"quote_amount"` + // delta in the base reserves of the vpool + BaseAmount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=base_amount,json=baseAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"base_amount"` +} + +func (m *SwapOnVpoolEvent) Reset() { *m = SwapOnVpoolEvent{} } +func (m *SwapOnVpoolEvent) String() string { return proto.CompactTextString(m) } +func (*SwapOnVpoolEvent) ProtoMessage() {} +func (*SwapOnVpoolEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_faeff0bc76489252, []int{1} +} +func (m *SwapOnVpoolEvent) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SwapOnVpoolEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SwapOnVpoolEvent.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SwapOnVpoolEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_SwapOnVpoolEvent.Merge(m, src) +} +func (m *SwapOnVpoolEvent) XXX_Size() int { + return m.Size() +} +func (m *SwapOnVpoolEvent) XXX_DiscardUnknown() { + xxx_messageInfo_SwapOnVpoolEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_SwapOnVpoolEvent proto.InternalMessageInfo + +func (m *SwapOnVpoolEvent) GetPair() string { + if m != nil { + return m.Pair + } + return "" +} + type SwapQuoteForBaseEvent struct { Pair string `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"` QuoteAmount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=quote_amount,json=quoteAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"quote_amount"` @@ -105,7 +156,7 @@ func (m *SwapQuoteForBaseEvent) Reset() { *m = SwapQuoteForBaseEvent{} } func (m *SwapQuoteForBaseEvent) String() string { return proto.CompactTextString(m) } func (*SwapQuoteForBaseEvent) ProtoMessage() {} func (*SwapQuoteForBaseEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_faeff0bc76489252, []int{1} + return fileDescriptor_faeff0bc76489252, []int{2} } func (m *SwapQuoteForBaseEvent) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -151,7 +202,7 @@ func (m *SwapBaseForQuoteEvent) Reset() { *m = SwapBaseForQuoteEvent{} } func (m *SwapBaseForQuoteEvent) String() string { return proto.CompactTextString(m) } func (*SwapBaseForQuoteEvent) ProtoMessage() {} func (*SwapBaseForQuoteEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_faeff0bc76489252, []int{2} + return fileDescriptor_faeff0bc76489252, []int{3} } func (m *SwapBaseForQuoteEvent) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -197,7 +248,7 @@ func (m *MarkPriceChangedEvent) Reset() { *m = MarkPriceChangedEvent{} } func (m *MarkPriceChangedEvent) String() string { return proto.CompactTextString(m) } func (*MarkPriceChangedEvent) ProtoMessage() {} func (*MarkPriceChangedEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_faeff0bc76489252, []int{3} + return fileDescriptor_faeff0bc76489252, []int{4} } func (m *MarkPriceChangedEvent) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -242,6 +293,7 @@ func (m *MarkPriceChangedEvent) GetBlockTimestamp() time.Time { func init() { proto.RegisterType((*ReserveSnapshotSavedEvent)(nil), "nibiru.vpool.v1.ReserveSnapshotSavedEvent") + proto.RegisterType((*SwapOnVpoolEvent)(nil), "nibiru.vpool.v1.SwapOnVpoolEvent") proto.RegisterType((*SwapQuoteForBaseEvent)(nil), "nibiru.vpool.v1.SwapQuoteForBaseEvent") proto.RegisterType((*SwapBaseForQuoteEvent)(nil), "nibiru.vpool.v1.SwapBaseForQuoteEvent") proto.RegisterType((*MarkPriceChangedEvent)(nil), "nibiru.vpool.v1.MarkPriceChangedEvent") @@ -250,38 +302,39 @@ func init() { func init() { proto.RegisterFile("vpool/v1/event.proto", fileDescriptor_faeff0bc76489252) } var fileDescriptor_faeff0bc76489252 = []byte{ - // 488 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x94, 0x4d, 0x6f, 0xd3, 0x30, - 0x18, 0xc7, 0x6b, 0xba, 0x4d, 0xcc, 0x2d, 0x4c, 0x8a, 0x36, 0x29, 0xeb, 0x21, 0x2d, 0x3b, 0xa0, - 0x4a, 0x88, 0x58, 0x85, 0x4f, 0x40, 0xf7, 0x22, 0x2e, 0x05, 0x9a, 0x72, 0xe2, 0x12, 0x39, 0x99, - 0x49, 0xac, 0x36, 0x79, 0x82, 0xed, 0x04, 0xf8, 0x16, 0x3b, 0xf2, 0x71, 0x38, 0xee, 0xc6, 0x8e, - 0x88, 0xc3, 0x40, 0xed, 0x17, 0x41, 0xb6, 0x93, 0x8a, 0x03, 0x70, 0xc8, 0x6d, 0xa7, 0xd8, 0xfe, - 0x3f, 0xcf, 0xcf, 0xcf, 0x5b, 0x8c, 0x0f, 0xab, 0x02, 0x60, 0x45, 0xaa, 0x09, 0x61, 0x15, 0xcb, - 0x95, 0x5f, 0x08, 0x50, 0xe0, 0x1c, 0xe4, 0x3c, 0xe2, 0xa2, 0xf4, 0x8d, 0xe8, 0x57, 0x93, 0xc1, - 0x61, 0x02, 0x09, 0x18, 0x8d, 0xe8, 0x95, 0x35, 0x1b, 0x78, 0x31, 0xc8, 0x0c, 0x24, 0x89, 0xa8, - 0x64, 0xa4, 0x9a, 0x44, 0x4c, 0xd1, 0x09, 0x89, 0x81, 0xe7, 0xb5, 0x7e, 0x6c, 0xf5, 0xd0, 0x3a, - 0xda, 0x4d, 0x2d, 0x0d, 0x13, 0x80, 0x64, 0xc5, 0x88, 0xd9, 0x45, 0xe5, 0x7b, 0xa2, 0x78, 0xc6, - 0xa4, 0xa2, 0x59, 0x61, 0x0d, 0x4e, 0xbe, 0x74, 0xf1, 0x71, 0xc0, 0x24, 0x13, 0x15, 0x5b, 0xe4, - 0xb4, 0x90, 0x29, 0xa8, 0x05, 0xad, 0xd8, 0xe5, 0xb9, 0x0e, 0xd3, 0x71, 0xf0, 0x4e, 0x41, 0xb9, - 0x70, 0xd1, 0x08, 0x8d, 0xf7, 0x03, 0xb3, 0x76, 0x16, 0xf8, 0xc1, 0x87, 0x12, 0x14, 0x0b, 0x85, - 0x75, 0x73, 0xef, 0x69, 0x71, 0xea, 0x5f, 0xdf, 0x0e, 0x3b, 0x3f, 0x6e, 0x87, 0x8f, 0x13, 0xae, - 0xd2, 0x32, 0xf2, 0x63, 0xc8, 0xea, 0x50, 0xea, 0xcf, 0x53, 0x79, 0xb9, 0x24, 0xea, 0x73, 0xc1, - 0xa4, 0x7f, 0xc6, 0xe2, 0xa0, 0x6f, 0x20, 0xf5, 0xd5, 0xce, 0x1c, 0xf7, 0x75, 0x76, 0x5b, 0x66, - 0xb7, 0x15, 0xb3, 0xa7, 0x19, 0x0d, 0x72, 0x86, 0x71, 0x46, 0xc5, 0x32, 0x2c, 0x04, 0x8f, 0x99, - 0xbb, 0xd3, 0x0a, 0xb8, 0xaf, 0x09, 0x6f, 0x34, 0xc0, 0x79, 0x84, 0xfb, 0xd1, 0x0a, 0xe2, 0x65, - 0x98, 0x32, 0x9e, 0xa4, 0xca, 0xdd, 0x1d, 0xa1, 0x71, 0x37, 0xe8, 0x99, 0xb3, 0x97, 0xe6, 0xc8, - 0x99, 0xe1, 0x03, 0x6b, 0xb2, 0x2d, 0xb2, 0xbb, 0x37, 0x42, 0xe3, 0xde, 0xb3, 0x81, 0x6f, 0xdb, - 0xe0, 0x37, 0x6d, 0xf0, 0xdf, 0x36, 0x16, 0xd3, 0xfb, 0x3a, 0xa4, 0xab, 0x9f, 0x43, 0x14, 0x3c, - 0x34, 0xce, 0x5b, 0xe5, 0xe4, 0x1b, 0xc2, 0x47, 0x8b, 0x8f, 0xb4, 0x98, 0xeb, 0x42, 0x5d, 0x80, - 0x98, 0x52, 0xc9, 0xfe, 0xdd, 0x96, 0x39, 0xb6, 0x15, 0x0d, 0x69, 0x06, 0x65, 0xae, 0x5a, 0x76, - 0xa5, 0x67, 0x18, 0x2f, 0x0c, 0xc2, 0x79, 0x8d, 0x4d, 0x41, 0x1b, 0x62, 0xbb, 0x9e, 0x60, 0x8d, - 0xb0, 0xc0, 0x6d, 0x46, 0x3a, 0x93, 0x0b, 0x10, 0x26, 0xb1, 0xbb, 0x9d, 0xd1, 0x57, 0x84, 0x8f, - 0x66, 0xcd, 0x8c, 0x9c, 0xa6, 0x34, 0x4f, 0xfe, 0xf7, 0xeb, 0x9c, 0xe1, 0x5d, 0x3b, 0x8d, 0xed, - 0x52, 0xb1, 0xce, 0x7f, 0x1b, 0xb3, 0x6e, 0xfb, 0x31, 0x9b, 0x9e, 0x5f, 0xaf, 0x3d, 0x74, 0xb3, - 0xf6, 0xd0, 0xaf, 0xb5, 0x87, 0xae, 0x36, 0x5e, 0xe7, 0x66, 0xe3, 0x75, 0xbe, 0x6f, 0xbc, 0xce, - 0xbb, 0x27, 0x7f, 0xc4, 0xf5, 0xca, 0xbc, 0x54, 0xa7, 0x29, 0xe5, 0x39, 0xb1, 0xaf, 0x16, 0xf9, - 0x44, 0xec, 0xa3, 0x66, 0x02, 0x8c, 0xf6, 0xcc, 0xa5, 0xcf, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, - 0x61, 0xf5, 0x5c, 0x01, 0xea, 0x04, 0x00, 0x00, + // 504 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x94, 0xcd, 0x8e, 0xd3, 0x30, + 0x10, 0xc7, 0x6b, 0xba, 0xbb, 0x62, 0xdd, 0xc2, 0xa2, 0x68, 0x57, 0xca, 0xf6, 0x90, 0x96, 0x1e, + 0x50, 0x25, 0x44, 0xac, 0xc2, 0x13, 0xd0, 0xfd, 0x10, 0x97, 0xb2, 0x34, 0x45, 0x1c, 0xb8, 0x44, + 0x4e, 0xd6, 0x24, 0x51, 0x9b, 0x4c, 0xb0, 0x9d, 0x00, 0x6f, 0xb1, 0x47, 0x1e, 0x87, 0xe3, 0x8a, + 0x0b, 0x7b, 0x44, 0x1c, 0x0a, 0x6a, 0x5f, 0x04, 0xd9, 0x4e, 0x2a, 0x0e, 0xc0, 0x21, 0x37, 0x38, + 0x25, 0x9e, 0xf1, 0xfc, 0x3c, 0x7f, 0x8f, 0x67, 0xf0, 0x61, 0x99, 0x03, 0x2c, 0x49, 0x39, 0x26, + 0xac, 0x64, 0x99, 0x74, 0x73, 0x0e, 0x12, 0xac, 0x83, 0x2c, 0x09, 0x12, 0x5e, 0xb8, 0xda, 0xe9, + 0x96, 0xe3, 0x9e, 0x13, 0x82, 0x48, 0x41, 0x90, 0x80, 0x0a, 0x46, 0xca, 0x71, 0xc0, 0x24, 0x1d, + 0x93, 0x10, 0x92, 0xcc, 0x04, 0xf4, 0x8e, 0x8d, 0xdf, 0xd7, 0x2b, 0x62, 0x16, 0x95, 0xeb, 0x30, + 0x82, 0x08, 0x8c, 0x5d, 0xfd, 0x55, 0xd6, 0x7e, 0x04, 0x10, 0x2d, 0x19, 0xd1, 0xab, 0xa0, 0x78, + 0x43, 0x64, 0x92, 0x32, 0x21, 0x69, 0x9a, 0x9b, 0x0d, 0xc3, 0x8f, 0x6d, 0x7c, 0xec, 0x31, 0xc1, + 0x78, 0xc9, 0xe6, 0x19, 0xcd, 0x45, 0x0c, 0x72, 0x4e, 0x4b, 0x76, 0x79, 0xa6, 0xd2, 0xb4, 0x2c, + 0xbc, 0x93, 0xd3, 0x84, 0xdb, 0x68, 0x80, 0x46, 0xfb, 0x9e, 0xfe, 0xb7, 0xe6, 0xf8, 0xce, 0xdb, + 0x02, 0x24, 0xf3, 0xb9, 0x09, 0xb3, 0x6f, 0x29, 0xe7, 0xc4, 0xbd, 0x5e, 0xf5, 0x5b, 0xdf, 0x56, + 0xfd, 0x07, 0x51, 0x22, 0xe3, 0x22, 0x70, 0x43, 0x48, 0xab, 0x04, 0xab, 0xcf, 0x23, 0x71, 0xb9, + 0x20, 0xf2, 0x43, 0xce, 0x84, 0x7b, 0xca, 0x42, 0xaf, 0xab, 0x21, 0xd5, 0xd1, 0xd6, 0x0c, 0x77, + 0x95, 0xe6, 0x2d, 0xb3, 0xdd, 0x88, 0xd9, 0x51, 0x8c, 0x1a, 0x39, 0xc5, 0x38, 0xa5, 0x7c, 0xe1, + 0xe7, 0x3c, 0x09, 0x99, 0xbd, 0xd3, 0x08, 0xb8, 0xaf, 0x08, 0x2f, 0x14, 0xc0, 0xba, 0x8f, 0xbb, + 0xc1, 0x12, 0xc2, 0x85, 0x1f, 0xb3, 0x24, 0x8a, 0xa5, 0xbd, 0x3b, 0x40, 0xa3, 0xb6, 0xd7, 0xd1, + 0xb6, 0x67, 0xda, 0x64, 0x4d, 0xf1, 0x81, 0xd9, 0xb2, 0xbd, 0x64, 0x7b, 0x6f, 0x80, 0x46, 0x9d, + 0xc7, 0x3d, 0xd7, 0x94, 0xc1, 0xad, 0xcb, 0xe0, 0xbe, 0xac, 0x77, 0x4c, 0x6e, 0xab, 0x94, 0xae, + 0xbe, 0xf7, 0x91, 0x77, 0x57, 0x07, 0x6f, 0x3d, 0xc3, 0xcf, 0x08, 0xdf, 0x9b, 0xbf, 0xa3, 0xf9, + 0x45, 0xf6, 0x4a, 0xbd, 0x8f, 0x3f, 0x57, 0x64, 0x86, 0xcd, 0x65, 0xfa, 0x34, 0x85, 0x22, 0x93, + 0x0d, 0x0b, 0xd2, 0xd1, 0x8c, 0xa7, 0x1a, 0x61, 0x5d, 0x60, 0x7d, 0x97, 0x35, 0xb1, 0x59, 0x39, + 0xb0, 0x42, 0x18, 0xe0, 0xf0, 0x0b, 0xc2, 0x47, 0x4a, 0xcc, 0x4c, 0x1d, 0x72, 0x0e, 0x7c, 0x42, + 0x05, 0xfb, 0x3f, 0x14, 0x29, 0x25, 0xe7, 0xc0, 0xb5, 0xb0, 0x7f, 0x5b, 0xd1, 0x27, 0x84, 0x8f, + 0xa6, 0xf5, 0x83, 0x3f, 0x89, 0x69, 0x16, 0xfd, 0x6d, 0x0e, 0x9c, 0xe2, 0x5d, 0xd3, 0x5a, 0xcd, + 0xa4, 0x98, 0xe0, 0xdf, 0xf5, 0x4c, 0xbb, 0x79, 0xcf, 0x4c, 0xce, 0xae, 0xd7, 0x0e, 0xba, 0x59, + 0x3b, 0xe8, 0xc7, 0xda, 0x41, 0x57, 0x1b, 0xa7, 0x75, 0xb3, 0x71, 0x5a, 0x5f, 0x37, 0x4e, 0xeb, + 0xf5, 0xc3, 0x5f, 0xf2, 0x7a, 0xae, 0xc7, 0xee, 0x49, 0x4c, 0x93, 0x8c, 0x98, 0x11, 0x4c, 0xde, + 0x13, 0x33, 0xa1, 0x75, 0x82, 0xc1, 0x9e, 0x3e, 0xf4, 0xc9, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xc3, 0x20, 0x4c, 0xa4, 0xb7, 0x05, 0x00, 0x00, } func (m *ReserveSnapshotSavedEvent) Marshal() (dAtA []byte, err error) { @@ -357,6 +410,56 @@ func (m *ReserveSnapshotSavedEvent) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *SwapOnVpoolEvent) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SwapOnVpoolEvent) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SwapOnVpoolEvent) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.BaseAmount.Size() + i -= size + if _, err := m.BaseAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size := m.QuoteAmount.Size() + i -= size + if _, err := m.QuoteAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Pair) > 0 { + i -= len(m.Pair) + copy(dAtA[i:], m.Pair) + i = encodeVarintEvent(dAtA, i, uint64(len(m.Pair))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *SwapQuoteForBaseEvent) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -540,6 +643,23 @@ func (m *ReserveSnapshotSavedEvent) Size() (n int) { return n } +func (m *SwapOnVpoolEvent) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Pair) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = m.QuoteAmount.Size() + n += 1 + l + sovEvent(uint64(l)) + l = m.BaseAmount.Size() + n += 1 + l + sovEvent(uint64(l)) + return n +} + func (m *SwapQuoteForBaseEvent) Size() (n int) { if m == nil { return 0 @@ -833,6 +953,156 @@ func (m *ReserveSnapshotSavedEvent) Unmarshal(dAtA []byte) error { } return nil } +func (m *SwapOnVpoolEvent) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SwapOnVpoolEvent: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SwapOnVpoolEvent: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pair", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pair = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QuoteAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.QuoteAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BaseAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvent(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvent + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *SwapQuoteForBaseEvent) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/vpool/types/events.go b/x/vpool/types/events.go deleted file mode 100644 index a83a0f1e5..000000000 --- a/x/vpool/types/events.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -const ( - EventSnapshotSaved = "reserve_snapshot_saved" - AttributeBlockHeight = "block_height" - AttributeQuoteReserve = "quote_reserve" - AttributeBaseReserve = "base_reserve" - - EventSwapQuoteForBase = "swap_input" - EventSwapBaseForQuote = "swap_output" - AttributeQuoteAssetAmount = "quote_asset_amount" - AttributeBaseAssetAmount = "base_asset_amount" -) diff --git a/x/vpool/types/pool.go b/x/vpool/types/pool.go index c09686707..28a02eafe 100644 --- a/x/vpool/types/pool.go +++ b/x/vpool/types/pool.go @@ -9,13 +9,28 @@ import ( // HasEnoughQuoteReserve returns true if there is enough quote reserve based on // quoteReserve * tradeLimitRatio func (vpool *Vpool) HasEnoughQuoteReserve(quoteAmount sdk.Dec) bool { - return vpool.QuoteAssetReserve.Mul(vpool.Config.TradeLimitRatio).GTE(quoteAmount) + return vpool.QuoteAssetReserve.Mul(vpool.Config.TradeLimitRatio).GTE(quoteAmount.Abs()) } // HasEnoughBaseReserve returns true if there is enough base reserve based on // baseReserve * tradeLimitRatio func (vpool *Vpool) HasEnoughBaseReserve(baseAmount sdk.Dec) bool { - return vpool.BaseAssetReserve.Mul(vpool.Config.TradeLimitRatio).GTE(baseAmount) + return vpool.BaseAssetReserve.Mul(vpool.Config.TradeLimitRatio).GTE(baseAmount.Abs()) +} + +func (vpool *Vpool) HasEnoughReservesForTrade( + quoteAmtAbs sdk.Dec, baseAmtAbs sdk.Dec, +) (err error) { + if !vpool.HasEnoughQuoteReserve(quoteAmtAbs) { + return ErrOverTradingLimit.Wrapf( + "quote amount %s is over trading limit", quoteAmtAbs) + } + if !vpool.HasEnoughBaseReserve(baseAmtAbs) { + return ErrOverTradingLimit.Wrapf( + "base amount %s is over trading limit", baseAmtAbs) + } + + return nil } /* @@ -23,39 +38,32 @@ GetBaseAmountByQuoteAmount returns the amount of base asset you will get out by giving a specified amount of quote asset args: - - dir: add to pool or remove from pool - - quoteAmount: the amount of quote asset to add to/remove from the pool + - quoteDelta: the amount of quote asset to add to/remove from the pool. + Adding to the quote reserves is synonymous with positive 'quoteDelta'. ret: - - baseAmountOut: the amount of base assets required to make this hypothetical swap + - baseOutAbs: the amount of base assets required to make this hypothetical swap always an absolute value - err: error */ func (vpool *Vpool) GetBaseAmountByQuoteAmount( - dir Direction, - quoteAmount sdk.Dec, -) (baseAmount sdk.Dec, err error) { - if quoteAmount.IsZero() { + quoteDelta sdk.Dec, +) (baseOutAbs sdk.Dec, err error) { + if quoteDelta.IsZero() { return sdk.ZeroDec(), nil } invariant := vpool.QuoteAssetReserve.Mul(vpool.BaseAssetReserve) // x * y = k - var quoteAssetsAfter sdk.Dec - if dir == Direction_ADD_TO_POOL { - quoteAssetsAfter = vpool.QuoteAssetReserve.Add(quoteAmount) - } else { - quoteAssetsAfter = vpool.QuoteAssetReserve.Sub(quoteAmount) - } - - if quoteAssetsAfter.LTE(sdk.ZeroDec()) { + quoteReservesAfter := vpool.QuoteAssetReserve.Add(quoteDelta) + if quoteReservesAfter.LTE(sdk.ZeroDec()) { return sdk.Dec{}, ErrQuoteReserveAtZero } - baseAssetsAfter := invariant.Quo(quoteAssetsAfter) - baseAmount = baseAssetsAfter.Sub(vpool.BaseAssetReserve).Abs() + baseReservesAfter := invariant.Quo(quoteReservesAfter) + baseOutAbs = baseReservesAfter.Sub(vpool.BaseAssetReserve).Abs() - return baseAmount, nil + return baseOutAbs, nil } /* @@ -67,56 +75,43 @@ args: - baseAmount: the amount of base asset to add to/remove from the pool ret: - - quoteAmountOut: the amount of quote assets required to make this hypothetical swap + - quoteOutAbs: the amount of quote assets required to make this hypothetical swap always an absolute value - err: error */ func (vpool *Vpool) GetQuoteAmountByBaseAmount( - dir Direction, baseAmount sdk.Dec, -) (quoteAmount sdk.Dec, err error) { - if baseAmount.IsZero() { + baseDelta sdk.Dec, +) (quoteOutAbs sdk.Dec, err error) { + if baseDelta.IsZero() { return sdk.ZeroDec(), nil } invariant := vpool.QuoteAssetReserve.Mul(vpool.BaseAssetReserve) // x * y = k - var baseAssetsAfter sdk.Dec - if dir == Direction_ADD_TO_POOL { - baseAssetsAfter = vpool.BaseAssetReserve.Add(baseAmount) - } else { - baseAssetsAfter = vpool.BaseAssetReserve.Sub(baseAmount) - } - - if baseAssetsAfter.LTE(sdk.ZeroDec()) { + baseReservesAfter := vpool.BaseAssetReserve.Add(baseDelta) + if baseReservesAfter.LTE(sdk.ZeroDec()) { return sdk.Dec{}, ErrBaseReserveAtZero.Wrapf( "base assets below zero after trying to swap %s base assets", - baseAmount.String(), + baseDelta.String(), ) } - quoteAssetsAfter := invariant.Quo(baseAssetsAfter) - quoteAmount = quoteAssetsAfter.Sub(vpool.QuoteAssetReserve).Abs() - - return quoteAmount, nil -} + quoteReservesAfter := invariant.Quo(baseReservesAfter) + quoteOutAbs = quoteReservesAfter.Sub(vpool.QuoteAssetReserve).Abs() -// IncreaseBaseAssetReserve increases the quote reserve by amount -func (vpool *Vpool) IncreaseBaseAssetReserve(amount sdk.Dec) { - vpool.BaseAssetReserve = vpool.BaseAssetReserve.Add(amount) + return quoteOutAbs, nil } -// DecreaseBaseAssetReserve descreases the quote asset reserve by amount -func (vpool *Vpool) DecreaseBaseAssetReserve(amount sdk.Dec) { - vpool.BaseAssetReserve = vpool.BaseAssetReserve.Sub(amount) -} - -func (vpool *Vpool) IncreaseQuoteAssetReserve(amount sdk.Dec) { +// AddToQuoteAssetReserve adds 'amount' to the quote asset reserves +// The 'amount' is not assumed to be positive. +func (vpool *Vpool) AddToQuoteAssetReserve(amount sdk.Dec) { vpool.QuoteAssetReserve = vpool.QuoteAssetReserve.Add(amount) } -// DecreaseQuoteAssetReserve decreases the base reserve by amount -func (vpool *Vpool) DecreaseQuoteAssetReserve(amount sdk.Dec) { - vpool.QuoteAssetReserve = vpool.QuoteAssetReserve.Sub(amount) +// AddToBaseAssetReserve adds 'amount' to the base asset reserves +// The 'amount' is not assumed to be positive. +func (vpool *Vpool) AddToBaseAssetReserve(amount sdk.Dec) { + vpool.BaseAssetReserve = vpool.BaseAssetReserve.Add(amount) } // ValidateReserves checks that reserves are positive. @@ -245,3 +240,14 @@ func (vpool Vpool) ToSnapshot(ctx sdk.Context) ReserveSnapshot { } return snapshot } + +func (dir Direction) ToMultiplier() int64 { + var dirMult int64 + switch dir { + case Direction_ADD_TO_POOL, Direction_DIRECTION_UNSPECIFIED: + dirMult = 1 + case Direction_REMOVE_FROM_POOL: + dirMult = -1 + } + return dirMult +} diff --git a/x/vpool/types/pool_test.go b/x/vpool/types/pool_test.go index 041033862..63db77f49 100644 --- a/x/vpool/types/pool_test.go +++ b/x/vpool/types/pool_test.go @@ -66,8 +66,7 @@ func TestGetBaseAmountByQuoteAmount(t *testing.T) { name string baseAssetReserve sdk.Dec quoteAssetReserve sdk.Dec - quoteAmount sdk.Dec - direction Direction + quoteIn sdk.Dec expectedBaseAmount sdk.Dec expectedErr error }{ @@ -75,34 +74,46 @@ func TestGetBaseAmountByQuoteAmount(t *testing.T) { name: "quote amount zero", baseAssetReserve: sdk.NewDec(1000), quoteAssetReserve: sdk.NewDec(1000), - quoteAmount: sdk.ZeroDec(), - direction: Direction_ADD_TO_POOL, + quoteIn: sdk.ZeroDec(), expectedBaseAmount: sdk.ZeroDec(), }, { - name: "simple add quote to pool", - baseAssetReserve: sdk.NewDec(1000), - quoteAssetReserve: sdk.NewDec(1000), - quoteAmount: sdk.NewDec(500), - direction: Direction_ADD_TO_POOL, + name: "simple add quote to pool", + baseAssetReserve: sdk.NewDec(1000), + quoteAssetReserve: sdk.NewDec(1000), // swapInvariant = 1000 * 1000 + quoteIn: sdk.NewDec(500), // quoteReserves = 1000 + 500 + // swapInvariant / quoteReserves - baseReserves = 333.33 expectedBaseAmount: sdk.MustNewDecFromStr("333.333333333333333333"), }, { - name: "simple remove quote from pool", - baseAssetReserve: sdk.NewDec(1000), - quoteAssetReserve: sdk.NewDec(1000), - quoteAmount: sdk.NewDec(500), - direction: Direction_REMOVE_FROM_POOL, + name: "simple remove quote from pool", + baseAssetReserve: sdk.NewDec(1000), + quoteAssetReserve: sdk.NewDec(1000), // swapInvariant = 1000 * 1000 + quoteIn: sdk.NewDec(-500), // quoteReserves = 1000 - 500 + // swapInvariant / quoteReserves - baseReserves = 1000 expectedBaseAmount: sdk.NewDec(1000), }, { name: "too much quote removed results in error", baseAssetReserve: sdk.NewDec(1000), + quoteAssetReserve: sdk.NewDec(1000), // swapInvariant = 1000 * 1000 + quoteIn: sdk.NewDec(-1000), // quoteReserves = 1000 - 1000 + expectedErr: ErrQuoteReserveAtZero, + }, + { + name: "attempt to remove more than the quote reserves", + baseAssetReserve: sdk.NewDec(1000), quoteAssetReserve: sdk.NewDec(1000), - quoteAmount: sdk.NewDec(1000), - direction: Direction_REMOVE_FROM_POOL, + quoteIn: sdk.NewDec(-9999), expectedErr: ErrQuoteReserveAtZero, }, + { + name: "add large amount to the quote reserves", + baseAssetReserve: sdk.NewDec(1000), + quoteAssetReserve: sdk.NewDec(1000), // swapInvariant = 1000 * 1000 + quoteIn: sdk.NewDec(999_555_999), // quoteReserves = 1000 + 999_555_999 + expectedBaseAmount: sdk.MustNewDecFromStr("999.998999556802663137"), + }, } for _, tc := range tests { @@ -121,7 +132,7 @@ func TestGetBaseAmountByQuoteAmount(t *testing.T) { }, } - amount, err := pool.GetBaseAmountByQuoteAmount(tc.direction, tc.quoteAmount) + amount, err := pool.GetBaseAmountByQuoteAmount(tc.quoteIn) if tc.expectedErr != nil { require.ErrorIs(t, err, tc.expectedErr, "expected error: %w, got: %w", tc.expectedErr, err) @@ -142,8 +153,7 @@ func TestGetQuoteAmountByBaseAmount(t *testing.T) { name string baseAssetReserve sdk.Dec quoteAssetReserve sdk.Dec - baseAmount sdk.Dec - direction Direction + baseIn sdk.Dec expectedQuoteAmount sdk.Dec expectedErr error }{ @@ -151,32 +161,28 @@ func TestGetQuoteAmountByBaseAmount(t *testing.T) { name: "base amount zero", baseAssetReserve: sdk.NewDec(1000), quoteAssetReserve: sdk.NewDec(1000), - baseAmount: sdk.ZeroDec(), - direction: Direction_ADD_TO_POOL, + baseIn: sdk.ZeroDec(), expectedQuoteAmount: sdk.ZeroDec(), }, { name: "simple add base to pool", baseAssetReserve: sdk.NewDec(1000), quoteAssetReserve: sdk.NewDec(1000), - baseAmount: sdk.NewDec(500), - direction: Direction_ADD_TO_POOL, + baseIn: sdk.NewDec(500), expectedQuoteAmount: sdk.MustNewDecFromStr("333.333333333333333333"), }, { name: "simple remove base from pool", baseAssetReserve: sdk.NewDec(1000), quoteAssetReserve: sdk.NewDec(1000), - baseAmount: sdk.NewDec(500), - direction: Direction_REMOVE_FROM_POOL, + baseIn: sdk.NewDec(-500), expectedQuoteAmount: sdk.NewDec(1000), }, { name: "too much base removed results in error", baseAssetReserve: sdk.NewDec(1000), quoteAssetReserve: sdk.NewDec(1000), - baseAmount: sdk.NewDec(1000), - direction: Direction_REMOVE_FROM_POOL, + baseIn: sdk.NewDec(-1000), expectedErr: ErrBaseReserveAtZero, }, } @@ -197,7 +203,7 @@ func TestGetQuoteAmountByBaseAmount(t *testing.T) { }, } - amount, err := pool.GetQuoteAmountByBaseAmount(tc.direction, tc.baseAmount) + amount, err := pool.GetQuoteAmountByBaseAmount(tc.baseIn) if tc.expectedErr != nil { require.ErrorIs(t, err, tc.expectedErr, "expected error: %w, got: %w", tc.expectedErr, err) @@ -228,19 +234,19 @@ func TestIncreaseDecreaseReserves(t *testing.T) { } t.Log("decrease quote asset reserve") - pool.DecreaseQuoteAssetReserve(sdk.NewDec(100)) + pool.AddToQuoteAssetReserve(sdk.NewDec(-100)) require.Equal(t, sdk.NewDec(999_900), pool.QuoteAssetReserve) t.Log("increase quote asset reserve") - pool.IncreaseQuoteAssetReserve(sdk.NewDec(100)) + pool.AddToQuoteAssetReserve(sdk.NewDec(100)) require.Equal(t, sdk.NewDec(1*common.Precision), pool.QuoteAssetReserve) t.Log("decrease base asset reserve") - pool.DecreaseBaseAssetReserve(sdk.NewDec(100)) + pool.AddToBaseAssetReserve(sdk.NewDec(-100)) require.Equal(t, sdk.NewDec(999_900), pool.BaseAssetReserve) t.Log("increase base asset reserve") - pool.IncreaseBaseAssetReserve(sdk.NewDec(100)) + pool.AddToBaseAssetReserve(sdk.NewDec(100)) require.Equal(t, sdk.NewDec(1*common.Precision), pool.BaseAssetReserve) } From 31cd475db33a0d5d616332c32c6827bbcae2ebe2 Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Thu, 8 Dec 2022 15:58:51 -0300 Subject: [PATCH 7/8] fix(dex): fix single asset join (#1114) * feat: fix single asset join * chore: changelog --- CHANGELOG.md | 2 +- x/dex/keeper/keeper.go | 2 +- x/dex/keeper/keeper_test.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 794bb0af5..29d7e9eda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -* ... +* [#1114](https://github.com/NibiruChain/nibiru/pull/1114) - fix(dex): fix single asset join ## [v0.16.0](https://github.com/NibiruChain/nibiru/releases/tag/v0.16.0) - Unreleased diff --git a/x/dex/keeper/keeper.go b/x/dex/keeper/keeper.go index 2dea0b272..4e9cfa7eb 100644 --- a/x/dex/keeper/keeper.go +++ b/x/dex/keeper/keeper.go @@ -445,7 +445,7 @@ func (k Keeper) JoinPool( ) (pool types.Pool, numSharesOut sdk.Coin, remCoins sdk.Coins, err error) { pool, _ = k.FetchPool(ctx, poolId) - if len(tokensIn) != len(pool.PoolAssets) { + if len(tokensIn) != len(pool.PoolAssets) && !shouldSwap { return pool, numSharesOut, remCoins, errors.New("too few assets to join this pool") } diff --git a/x/dex/keeper/keeper_test.go b/x/dex/keeper/keeper_test.go index ad59654fa..3558bac71 100644 --- a/x/dex/keeper/keeper_test.go +++ b/x/dex/keeper/keeper_test.go @@ -666,6 +666,37 @@ func TestJoinPoolAllAssets(t *testing.T) { ), /*shares=*/ 150), }, + { + name: "join with some assets, pool empty in one side, none remaining", + joinerInitialFunds: sdk.NewCoins( + sdk.NewInt64Coin("bar", 100), + sdk.NewInt64Coin("foo", 100), + ), + initialPool: mock.DexPool( + /*poolId=*/ 1, + /*assets=*/ sdk.NewCoins( + sdk.NewInt64Coin("bar", 100), + sdk.NewInt64Coin("foo", 1), + ), + /*shares=*/ 100), + tokensIn: sdk.NewCoins( + sdk.NewInt64Coin("foo", 100), + ), + expectedNumSharesOut: sdk.NewInt64Coin(shareDenom, 900), + expectedRemCoins: sdk.NewCoins(sdk.NewInt64Coin("foo", 1)), + expectedJoinerFinalFunds: sdk.NewCoins( + sdk.NewInt64Coin(shareDenom, 50), + sdk.NewInt64Coin("bar", 0), + sdk.NewInt64Coin("foo", 0), + ), + expectedFinalPool: mock.DexPool( + /*poolId=*/ 1, + /*assets=*/ sdk.NewCoins( + sdk.NewInt64Coin("bar", 100), + sdk.NewInt64Coin("foo", 100), + ), + /*shares=*/ 1000), + }, { name: "join with some assets, but swap done", joinerInitialFunds: sdk.NewCoins( From db6348009b5daa0ce4c3a53c1155928be713f46b Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:45:47 -0300 Subject: [PATCH 8/8] fix: fix error on over fluctuation limit for simulations (#1113) * fix: fix error on over fluctuation limit for simulations --- CHANGELOG.md | 2 ++ x/perp/simulation/operations.go | 34 +++++++++++++++++++++++++++++- x/perp/types/expected_keepers.go | 1 + x/testutil/mock/perp_interfaces.go | 15 +++++++++++++ x/vpool/keeper/keeper.go | 25 +++++++++++++++++----- 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29d7e9eda..23397314e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Bug Fixes +* [#1113](https://github.com/NibiruChain/nibiru/pull/1113) - fix: fix quick simulation issue * [#1114](https://github.com/NibiruChain/nibiru/pull/1114) - fix(dex): fix single asset join ## [v0.16.0](https://github.com/NibiruChain/nibiru/releases/tag/v0.16.0) - Unreleased diff --git a/x/perp/simulation/operations.go b/x/perp/simulation/operations.go index fa3fe6411..07faffc0d 100644 --- a/x/perp/simulation/operations.go +++ b/x/perp/simulation/operations.go @@ -59,18 +59,34 @@ func SimulateMsgOpenPosition(ak types.AccountKeeper, bk types.BankKeeper, k keep leverage := simtypes.RandomDecAmount(r, pool.Config.MaxLeverage.Sub(sdk.OneDec())).Add(sdk.OneDec()) // between [1, MaxLeverage] openNotional := leverage.MulInt(quoteAmt) + + var side types.Side + var direction pooltypes.Direction + if r.Float32() < .5 { + side = types.Side_BUY + direction = pooltypes.Direction_ADD_TO_POOL + } else { + side = types.Side_SELL + direction = pooltypes.Direction_REMOVE_FROM_POOL + } + feesAmt := openNotional.Mul(sdk.MustNewDecFromStr("0.002")).Ceil().TruncateInt() spentCoins := sdk.NewCoins(sdk.NewCoin(common.DenomNUSD, quoteAmt.Add(feesAmt))) msg := &types.MsgOpenPosition{ Sender: simAccount.Address.String(), TokenPair: common.Pair_BTC_NUSD.String(), - Side: types.Side_BUY, + Side: side, QuoteAssetAmount: quoteAmt, Leverage: leverage, BaseAssetAmountLimit: sdk.ZeroInt(), } + isOverFluctation := checkIsOverFluctation(ctx, k, pool, openNotional, direction) + if isOverFluctation { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "over fluctuation limit"), nil, nil + } + opMsg, futureOps, err := simulation.GenAndDeliverTxWithRandFees( simulation.OperationInput{ R: r, @@ -96,6 +112,22 @@ func SimulateMsgOpenPosition(ak types.AccountKeeper, bk types.BankKeeper, k keep } } +// Ensure wether the position we open won't trigger the fluctuation limit. +func checkIsOverFluctation( + ctx sdk.Context, k keeper.Keeper, pool pooltypes.Vpool, openNotional sdk.Dec, direction pooltypes.Direction) bool { + quoteDelta := openNotional + baseDelta, _ := pool.GetBaseAmountByQuoteAmount(quoteDelta.Abs().MulInt64(direction.ToMultiplier())) + snapshot, _ := k.VpoolKeeper.GetLastSnapshot(ctx, pool) + currentPrice := snapshot.QuoteAssetReserve.Quo(snapshot.BaseAssetReserve) + newPrice := pool.QuoteAssetReserve.Add(quoteDelta).Quo(pool.BaseAssetReserve.Sub(baseDelta)) + + fluctuationLimitRatio := pool.Config.FluctuationLimitRatio + snapshotUpperLimit := currentPrice.Mul(sdk.OneDec().Add(fluctuationLimitRatio)) + snapshotLowerLimit := currentPrice.Mul(sdk.OneDec().Sub(fluctuationLimitRatio)) + isOverFluctation := newPrice.GT(snapshotUpperLimit) || newPrice.LT(snapshotLowerLimit) + return isOverFluctation +} + /* getMaxQuoteForPool computes the maximum quote the user can swap considering the max fluctuation ratio and trade limit ratio. diff --git a/x/perp/types/expected_keepers.go b/x/perp/types/expected_keepers.go index 744d8eadc..2f3b1990d 100644 --- a/x/perp/types/expected_keepers.go +++ b/x/perp/types/expected_keepers.go @@ -110,6 +110,7 @@ type VpoolKeeper interface { GetMaxLeverage(ctx sdk.Context, pair common.AssetPair) sdk.Dec ExistsPool(ctx sdk.Context, pair common.AssetPair) bool GetSettlementPrice(ctx sdk.Context, pair common.AssetPair) (sdk.Dec, error) + GetLastSnapshot(ctx sdk.Context, pool vpooltypes.Vpool) (vpooltypes.ReserveSnapshot, error) } type EpochKeeper interface { diff --git a/x/testutil/mock/perp_interfaces.go b/x/testutil/mock/perp_interfaces.go index 26da43d21..12d8970f3 100644 --- a/x/testutil/mock/perp_interfaces.go +++ b/x/testutil/mock/perp_interfaces.go @@ -351,6 +351,21 @@ func (mr *MockVpoolKeeperMockRecorder) GetBaseAssetTWAP(arg0, arg1, arg2, arg3, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBaseAssetTWAP", reflect.TypeOf((*MockVpoolKeeper)(nil).GetBaseAssetTWAP), arg0, arg1, arg2, arg3, arg4) } +// GetLastSnapshot mocks base method. +func (m *MockVpoolKeeper) GetLastSnapshot(arg0 types2.Context, arg1 types1.Vpool) (types1.ReserveSnapshot, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLastSnapshot", arg0, arg1) + ret0, _ := ret[0].(types1.ReserveSnapshot) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLastSnapshot indicates an expected call of GetLastSnapshot. +func (mr *MockVpoolKeeperMockRecorder) GetLastSnapshot(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLastSnapshot", reflect.TypeOf((*MockVpoolKeeper)(nil).GetLastSnapshot), arg0, arg1) +} + // GetMaintenanceMarginRatio mocks base method. func (m *MockVpoolKeeper) GetMaintenanceMarginRatio(arg0 types2.Context, arg1 common.AssetPair) types2.Dec { m.ctrl.T.Helper() diff --git a/x/vpool/keeper/keeper.go b/x/vpool/keeper/keeper.go index 2d1e38c98..e30bf3d99 100644 --- a/x/vpool/keeper/keeper.go +++ b/x/vpool/keeper/keeper.go @@ -249,12 +249,10 @@ func (k Keeper) checkFluctuationLimitRatio(ctx sdk.Context, pool types.Vpool) er return nil } - it := k.ReserveSnapshots.Iterate(ctx, collections.PairRange[common.AssetPair, time.Time]{}.Prefix(pool.Pair).Descending()) - defer it.Close() - if !it.Valid() { - return fmt.Errorf("error getting last snapshot number for pair %s", pool.Pair) + latestSnapshot, err := k.GetLastSnapshot(ctx, pool) + if err != nil { + return err } - latestSnapshot := it.Value() if pool.IsOverFluctuationLimitInRelationWithSnapshot(latestSnapshot) { return types.ErrOverFluctuationLimit } @@ -262,6 +260,23 @@ func (k Keeper) checkFluctuationLimitRatio(ctx sdk.Context, pool types.Vpool) er return nil } +/* +GetLastSnapshot retrieve the last snapshot for a particular vpool + +args: + - ctx: the cosmos-sdk context + - pool: the vpool to check +*/ +func (k Keeper) GetLastSnapshot(ctx sdk.Context, pool types.Vpool) (types.ReserveSnapshot, error) { + it := k.ReserveSnapshots.Iterate(ctx, collections.PairRange[common.AssetPair, time.Time]{}.Prefix(pool.Pair).Descending()) + defer it.Close() + if !it.Valid() { + return types.ReserveSnapshot{}, fmt.Errorf("error getting last snapshot number for pair %s", pool.Pair) + } + latestSnapshot := it.Value() + return latestSnapshot, nil +} + /* IsOverSpreadLimit compares the current spot price of the vpool (given by pair) to the underlying's index price (given by an oracle). It panics if you provide it with a pair that doesn't exist in the state.