Skip to content

Commit

Permalink
fix: prevent IteratePoolOrders to run forever
Browse files Browse the repository at this point in the history
  • Loading branch information
kingcre committed Aug 31, 2023
1 parent 868f1c1 commit da79275
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 5 deletions.
18 changes: 13 additions & 5 deletions x/amm/keeper/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ func (k Keeper) IteratePoolOrders(ctx sdk.Context, pool types.Pool, isBuy bool,
qty = types.Amount0DeltaRoundingDec(currentSqrtPrice, orderSqrtPrice, orderLiquidity, false)
openQty = sdk.MinDec(reserveBalance, qty)
}
if openQty.IsPositive() && (openQty.GTE(pool.MinOrderQuantity) || orderTick == tick) {
if openQty.IsPositive() && (orderTick == tick || (openQty.GTE(pool.MinOrderQuantity))) {
if cb(orderPrice, qty, openQty) {
return true
}
reserveBalance = reserveBalance.Sub(exchangetypes.DepositAmount(isBuy, orderPrice, qty))
currentPrice = orderPrice
} else { // No more possible order price
break
}
if orderTick == tick {
break
Expand Down Expand Up @@ -129,30 +131,36 @@ func NextOrderTick(
intermediate := liquidityDec.Power(2).Add(
minOrderQty.Mul(liquidityDec).MulTruncate(currentSqrtPrice).MulInt64(4))
orderSqrtPrice := utils.DecApproxSqrt(intermediate).Sub(liquidityDec).QuoTruncate(minOrderQty.MulInt64(2))
if !orderSqrtPrice.IsPositive() || orderSqrtPrice.GTE(currentSqrtPrice) {
if !orderSqrtPrice.IsPositive() {
return 0, false
}
// 2. Check min order quote
orderSqrtPrice2 := currentSqrtPrice.Mul(liquidityDec).Sub(minOrderQuote).QuoTruncate(liquidityDec)
if !orderSqrtPrice2.IsPositive() || orderSqrtPrice2.GTE(currentSqrtPrice) {
if !orderSqrtPrice2.IsPositive() {
return 0, false
}
orderPrice := sdk.MinDec(orderSqrtPrice, orderSqrtPrice2).Power(2)
if orderPrice.GTE(currentPrice) {
return 0, false
}
tick = types.AdjustPriceToTickSpacing(orderPrice, tickSpacing, false)
return tick, true
}
// 1. Check min order qty
orderSqrtPrice := currentSqrtPrice.Mul(liquidityDec).
QuoRoundUp(liquidityDec.Sub(minOrderQty.Mul(currentSqrtPrice)))
if !orderSqrtPrice.IsPositive() || orderSqrtPrice.LTE(currentSqrtPrice) {
if !orderSqrtPrice.IsPositive() {
return 0, false
}
// 2. Check min order quote
orderSqrtPrice2 := minOrderQuote.Mul(currentSqrtPrice).QuoRoundUp(liquidityDec).Add(currentSqrtPrice)
if !orderSqrtPrice2.IsPositive() || orderSqrtPrice2.LTE(currentSqrtPrice) {
if !orderSqrtPrice2.IsPositive() {
return 0, false
}
orderPrice := sdk.MaxDec(orderSqrtPrice, orderSqrtPrice2).Power(2)
if orderPrice.LTE(currentPrice) {
return 0, false
}
tick = types.AdjustPriceToTickSpacing(orderPrice, tickSpacing, true)
return tick, true
}
24 changes: 24 additions & 0 deletions x/amm/keeper/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,27 @@ func (s *KeeperTestSuite) TestSwapEdgecase1() {

s.SwapExactAmountIn(ordererAddr, []uint64{market.Id}, utils.ParseDecCoin("35987097uusd"), utils.ParseDecCoin("0ucre"), false)
}

func (s *KeeperTestSuite) TestPoolOrdersEdgecase() {
// Check if there's no infinite loop in IteratePoolOrders.
market, pool := s.CreateMarketAndPool("ucre", "uusd", utils.ParseDec("0.000000089916180444"))
marketState := s.App.ExchangeKeeper.MustGetMarketState(s.Ctx, market.Id)
marketState.LastPrice = utils.ParseDecP("0.000000089795000000")
s.App.ExchangeKeeper.SetMarketState(s.Ctx, market.Id, marketState)

lpAddr := s.FundedAccount(1, enoughCoins)
s.AddLiquidity(
lpAddr, pool.Id, types.MinPrice, types.MaxPrice,
utils.ParseCoins("13010176813853779ucre,1169825406uusd"))

obs := s.App.ExchangeKeeper.ConstructMemOrderBookSide(s.Ctx, market, exchangetypes.MemOrderBookSideOptions{
IsBuy: false,
MaxNumPriceLevels: 1,
}, nil)
s.Require().Len(obs.Levels(), 1)
obs = s.App.ExchangeKeeper.ConstructMemOrderBookSide(s.Ctx, market, exchangetypes.MemOrderBookSideOptions{
IsBuy: true,
MaxNumPriceLevels: 1,
}, nil)
s.Require().Len(obs.Levels(), 1)
}

0 comments on commit da79275

Please sign in to comment.