diff --git a/x/dex/keeper/core.go b/x/dex/keeper/core.go index eb53bbd4b..4503476af 100644 --- a/x/dex/keeper/core.go +++ b/x/dex/keeper/core.go @@ -512,11 +512,14 @@ func (k Keeper) CancelLimitOrderCore( makerAmountToReturn := tranche.RemoveTokenIn(trancheUser) _, takerAmountOut := tranche.Withdraw(trancheUser) - trancheUser.SharesWithdrawn = trancheUser.SharesOwned - // Remove the canceled shares from the limitOrder tranche.TotalMakerDenom = tranche.TotalMakerDenom.Sub(trancheUser.SharesOwned) - tranche.TotalTakerDenom = tranche.TotalTakerDenom.Sub(takerAmountOut) + sharesWithdrawnTakerDenom := math_utils.NewPrecDecFromInt(trancheUser.SharesWithdrawn). + Quo(tranche.PriceTakerToMaker). + TruncateInt() + totalAmountOut := sharesWithdrawnTakerDenom.Add(takerAmountOut) + tranche.TotalTakerDenom = tranche.TotalTakerDenom.Sub(totalAmountOut) + trancheUser.SharesWithdrawn = trancheUser.SharesOwned if makerAmountToReturn.IsPositive() || takerAmountOut.IsPositive() { makerCoinOut := sdk.NewCoin(tradePairID.MakerDenom, makerAmountToReturn) diff --git a/x/dex/keeper/integration_cancellimitorder_test.go b/x/dex/keeper/integration_cancellimitorder_test.go index 9c12b8d0f..f72a444d6 100644 --- a/x/dex/keeper/integration_cancellimitorder_test.go +++ b/x/dex/keeper/integration_cancellimitorder_test.go @@ -384,3 +384,67 @@ func (s *DexTestSuite) TestCancelJITNextBlock() { s.aliceCancelsLimitSellFails(trancheKey, types.ErrActiveLimitOrderNotFound) s.assertAliceBalances(0, 0) } + +func (s *DexTestSuite) TestWithdrawThenCancel() { + s.fundAliceBalances(50, 0) + s.fundBobBalances(50, 0) + s.fundCarolBalances(0, 40) + + // // GIVEN alice and bob each limit sells 50 TokenA + trancheKey := s.aliceLimitSells("TokenA", 0, 50) + s.bobLimitSells("TokenA", 0, 50) + + s.carolLimitSells("TokenB", -1, 10, types.LimitOrderType_FILL_OR_KILL) + + // WHEN alice withdraws and cancels her limit order + s.aliceWithdrawsLimitSell(trancheKey) + s.aliceCancelsLimitSell(trancheKey) + s.assertAliceBalances(45, 5) + + s.bobWithdrawsLimitSell(trancheKey) + s.assertBobBalances(0, 5) + s.bobCancelsLimitSell(trancheKey) + s.assertBobBalances(45, 5) +} + +func (s *DexTestSuite) TestWithdrawThenCancel2() { + s.fundAliceBalances(50, 0) + s.fundBobBalances(50, 0) + s.fundCarolBalances(0, 40) + + // // GIVEN alice and bob each limit sells 50 TokenA + trancheKey := s.aliceLimitSells("TokenA", 0, 50) + s.bobLimitSells("TokenA", 0, 50) + + s.carolLimitSells("TokenB", -1, 10, types.LimitOrderType_FILL_OR_KILL) + + // WHEN alice withdraws and cancels her limit order + s.aliceWithdrawsLimitSell(trancheKey) + s.aliceCancelsLimitSell(trancheKey) + s.assertAliceBalances(45, 5) + + s.bobCancelsLimitSell(trancheKey) + s.assertBobBalances(45, 5) +} + +func (s *DexTestSuite) TestWithdrawThenCancelLowTick() { + s.fundAliceBalances(50, 0) + s.fundBobBalances(50, 0) + s.fundCarolBalances(0, 40) + + // // GIVEN alice and bob each limit sells 50 TokenA + trancheKey := s.aliceLimitSells("TokenA", 20000, 50) + s.bobLimitSells("TokenA", 20000, 50) + + s.carolLimitSells("TokenB", -20001, 10, types.LimitOrderType_FILL_OR_KILL) + + // WHEN alice withdraws and cancels her limit order + s.aliceWithdrawsLimitSell(trancheKey) + s.aliceCancelsLimitSell(trancheKey) + s.assertAliceBalancesInt(sdkmath.NewInt(13058413), sdkmath.NewInt(4999999)) + + s.bobWithdrawsLimitSell(trancheKey) + s.assertBobBalancesInt(sdkmath.ZeroInt(), sdkmath.NewInt(4999999)) + s.bobCancelsLimitSell(trancheKey) + s.assertBobBalancesInt(sdkmath.NewInt(13058413), sdkmath.NewInt(4999999)) +}