Skip to content

Commit

Permalink
Merge pull request #208 from crescent-network/fix/pool-order-price-limit
Browse files Browse the repository at this point in the history
fix: limit pool order price range by MaxOrderPriceRatio
  • Loading branch information
kingcre authored Sep 12, 2023
2 parents adc85f7 + eeea283 commit 065090a
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 27 deletions.
14 changes: 14 additions & 0 deletions app/testutil/amm.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ func (s *TestSuite) AddLiquidity(ownerAddr sdk.AccAddress, poolId uint64, lowerP
return
}

func (s *TestSuite) AddLiquidityByLiquidity(ownerAddr sdk.AccAddress, poolId uint64, lowerPrice, upperPrice sdk.Dec, desiredLiquidity sdk.Int) (position ammtypes.Position, liquidity sdk.Int, amt sdk.Coins) {
s.T().Helper()
pool := s.App.AMMKeeper.MustGetPool(s.Ctx, poolId)
poolState := s.App.AMMKeeper.MustGetPoolState(s.Ctx, poolId)
amt0, amt1 := ammtypes.AmountsForLiquidity(
utils.DecApproxSqrt(poolState.CurrentPrice),
utils.DecApproxSqrt(lowerPrice),
utils.DecApproxSqrt(upperPrice),
desiredLiquidity)
return s.AddLiquidity(
ownerAddr, pool.Id, lowerPrice, upperPrice,
sdk.NewCoins(sdk.NewCoin(pool.Denom0, amt0), sdk.NewCoin(pool.Denom1, amt1)))
}

func (s *TestSuite) RemoveLiquidity(ownerAddr sdk.AccAddress, positionId uint64, liquidity sdk.Int) (position ammtypes.Position, amt sdk.Coins) {
s.T().Helper()
var err error
Expand Down
30 changes: 6 additions & 24 deletions x/amm/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -906,14 +906,9 @@ func (s *KeeperTestSuite) TestQueryOrderBookEdgecase() {
market, pool := s.CreateMarketAndPool("ucre", "uusd", utils.ParseDec("0.000000000002410188"))

lpAddr := s.FundedAccount(1, enoughCoins)
amt0, amt1 := types.AmountsForLiquidity(
utils.DecApproxSqrt(utils.ParseDec("0.000000000002410188")),
utils.DecApproxSqrt(types.MinPrice),
utils.DecApproxSqrt(types.MaxPrice),
sdk.NewInt(160843141868))
s.AddLiquidity(
s.AddLiquidityByLiquidity(
lpAddr, pool.Id, types.MinPrice, types.MaxPrice,
sdk.NewCoins(sdk.NewCoin(pool.Denom0, amt0), sdk.NewCoin(pool.Denom1, amt1)))
sdk.NewInt(160843141868))

querier := exchangekeeper.Querier{Keeper: s.App.ExchangeKeeper}
resp, err := querier.OrderBook(sdk.WrapSDKContext(s.Ctx), &exchangetypes.QueryOrderBookRequest{
Expand Down Expand Up @@ -948,27 +943,14 @@ func (s *KeeperTestSuite) TestQueryOrderBookEdgecase2() {
market, pool := s.CreateMarketAndPool("ucre", "uusd", utils.ParseDec("1"))

lpAddr := s.FundedAccount(1, enoughCoins)
amt0, amt1 := types.AmountsForLiquidity(
utils.DecApproxSqrt(utils.ParseDec("1")),
utils.DecApproxSqrt(types.MinPrice),
utils.DecApproxSqrt(types.MaxPrice),
sdk.NewInt(10))
s.AddLiquidity(
lpAddr, pool.Id, types.MinPrice, types.MaxPrice,
sdk.NewCoins(sdk.NewCoin(pool.Denom0, amt0), sdk.NewCoin(pool.Denom1, amt1)))
s.AddLiquidityByLiquidity(
lpAddr, pool.Id, types.MinPrice, types.MaxPrice, sdk.NewInt(10))

querier := exchangekeeper.Querier{Keeper: s.App.ExchangeKeeper}
resp, err := querier.OrderBook(sdk.WrapSDKContext(s.Ctx), &exchangetypes.QueryOrderBookRequest{
MarketId: market.Id,
})
s.Require().NoError(err)
expected := []exchangetypes.OrderBookPriceLevel{
{P: utils.ParseDec("1000000000000000000000000000000000000.000000000000000000"), Q: utils.ParseDec("9.014670721835706842")},
}
s.Require().GreaterOrEqual(len(resp.OrderBooks[0].Sells), len(expected))
for i, level := range expected {
s.AssertEqual(level.P, resp.OrderBooks[0].Sells[i].P)
s.AssertEqual(level.Q, resp.OrderBooks[0].Sells[i].Q)
}
s.Require().Empty(resp.OrderBooks[0].Buys)
// Due to too low liquidity, order book is not displayed.
s.Require().Empty(resp.OrderBooks)
}
21 changes: 21 additions & 0 deletions x/amm/keeper/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,24 @@ func (s *KeeperTestSuite) TestPoolOrdersEdgecase() {
}, nil)
s.Require().Len(obs.Levels(), 1)
}

func (s *KeeperTestSuite) TestPoolOrderMaxOrderPriceRatio() {
market := s.CreateMarket("ucre", "uusd")

mmAddr := s.FundedAccount(1, enoughCoins)
s.MakeLastPrice(market.Id, mmAddr, utils.ParseDec("5"))

// last price != pool price
pool := s.CreatePool(market.Id, utils.ParseDec("100"))

s.AddLiquidityByLiquidity(
mmAddr, pool.Id, utils.ParseDec("50"), utils.ParseDec("200"),
sdk.NewInt(1000000))

ordererAddr := s.FundedAccount(2, enoughCoins)
s.PlaceLimitOrder(
market.Id, ordererAddr, false, utils.ParseDec("5.05"), sdk.NewDec(100_000000), 0)

s.AssertEqual(utils.ParseDec("90"), s.keeper.MustGetPoolState(s.Ctx, pool.Id).CurrentPrice)
s.AssertEqual(utils.ParseDec("90"), *s.App.ExchangeKeeper.MustGetMarketState(s.Ctx, market.Id).LastPrice)
}
7 changes: 7 additions & 0 deletions x/amm/keeper/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,19 @@ func (k OrderSource) ConstructMemOrderBookSide(
if !found {
return nil // no pool found
}
maxPriceRatio := k.exchangeKeeper.GetMaxOrderPriceRatio(ctx)
poolState := k.MustGetPoolState(ctx, pool.Id)
minPrice, maxPrice := exchangetypes.OrderPriceLimit(poolState.CurrentPrice, maxPriceRatio)

reserveAddr := pool.MustGetReserveAddress()
accQty := utils.ZeroDec
accQuote := utils.ZeroDec
numPriceLevels := 0
k.IteratePoolOrders(ctx, pool, opts.IsBuy, func(price, qty, openQty sdk.Dec) (stop bool) {
if (opts.IsBuy && price.LT(minPrice)) ||
(!opts.IsBuy && price.GT(maxPrice)) {
return true
}
if opts.ReachedLimit(price, accQty, accQuote, numPriceLevels) {
return true
}
Expand Down
1 change: 1 addition & 0 deletions x/amm/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type BankKeeper interface {
}

type ExchangeKeeper interface {
GetMaxOrderPriceRatio(ctx sdk.Context) sdk.Dec
GetMarket(ctx sdk.Context, marketId uint64) (market exchangetypes.Market, found bool)
LookupMarket(ctx sdk.Context, marketId uint64) (found bool)
IterateAllMarkets(ctx sdk.Context, cb func(market exchangetypes.Market) (stop bool))
Expand Down
6 changes: 3 additions & 3 deletions x/exchange/types/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ func (marketState MarketState) Validate() error {
return nil
}

func OrderPriceLimit(lastPrice, maxOrderPriceRatio sdk.Dec) (minPrice, maxPrice sdk.Dec) {
minPrice = lastPrice.Mul(utils.OneDec.Sub(maxOrderPriceRatio))
maxPrice = lastPrice.Mul(utils.OneDec.Add(maxOrderPriceRatio))
func OrderPriceLimit(basePrice, maxOrderPriceRatio sdk.Dec) (minPrice, maxPrice sdk.Dec) {
minPrice = basePrice.Mul(utils.OneDec.Sub(maxOrderPriceRatio))
maxPrice = basePrice.Mul(utils.OneDec.Add(maxOrderPriceRatio))
return
}

0 comments on commit 065090a

Please sign in to comment.