Skip to content

Commit 3347e56

Browse files
authored
Merge pull request #1048 from neutron-org/chore/better_tranche_share_calc
Add decSharesWithdrawn field for more accurate share calculation
2 parents 7537be1 + a85f2d8 commit 3347e56

18 files changed

+325
-64
lines changed

proto/neutron/dex/limit_order_tranche_user.proto

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ message LimitOrderTrancheUser {
1818
(gogoproto.nullable) = false,
1919
(gogoproto.jsontag) = "shares_owned"
2020
];
21+
22+
// DEPRECATED: shares_withdrawn will be removed in a future release, `dec_shares_withdrawn` should be used
2123
string shares_withdrawn = 6 [
24+
deprecated = true,
2225
(gogoproto.moretags) = "yaml:\"shares_withdrawn\"",
2326
(gogoproto.customtype) = "cosmossdk.io/math.Int",
2427
(gogoproto.nullable) = false,
@@ -32,4 +35,10 @@ message LimitOrderTrancheUser {
3235
(gogoproto.jsontag) = "shares_cancelled"
3336
];
3437
LimitOrderType order_type = 8;
38+
string dec_shares_withdrawn = 9 [
39+
(gogoproto.moretags) = "yaml:\"dec_shares_withdrawn\"",
40+
(gogoproto.customtype) = "github.com/neutron-org/neutron/v10/utils/math.PrecDec",
41+
(gogoproto.nullable) = false,
42+
(gogoproto.jsontag) = "dec_shares_withdrawn"
43+
];
3544
}

tests/dex/state_withdraw_limit_order_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,10 @@ func (s *DexStateTestSuite) assertWithdrawFilledAmount(params withdrawLimitOrder
187187
s.False(found)
188188
} else {
189189
s.True(found)
190-
remainingShares := ut.SharesOwned.Sub(ut.SharesWithdrawn)
191-
s.True(expectedBalanceA.Equal(remainingShares), "Expected Balance A %v != Actual %v", expectedBalanceA, remainingShares)
190+
sharesOwnedDec := math_utils.NewPrecDecFromInt(ut.SharesOwned)
191+
remainingShares := sharesOwnedDec.Sub(ut.DecSharesWithdrawn)
192+
expectedBalanceADec := math_utils.NewPrecDecFromInt(expectedBalanceA)
193+
s.True(expectedBalanceADec.Equal(remainingShares), "Expected Balance A %v != Actual %v", expectedBalanceA, remainingShares)
192194
}
193195
}
194196
}

x/dex/genesis_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/neutron-org/neutron/v10/testutil/common/nullify"
1111
keepertest "github.com/neutron-org/neutron/v10/testutil/dex/keeper"
12+
math_utils "github.com/neutron-org/neutron/v10/utils/math"
1213
"github.com/neutron-org/neutron/v10/x/dex"
1314
"github.com/neutron-org/neutron/v10/x/dex/types"
1415
)
@@ -26,7 +27,7 @@ func TestGenesis(t *testing.T) {
2627
TrancheKey: "0",
2728
Address: "fakeAddr",
2829
SharesOwned: math.NewInt(10),
29-
SharesWithdrawn: math.NewInt(0),
30+
DecSharesWithdrawn: math_utils.ZeroPrecDec(),
3031
},
3132
{
3233
TradePairId: &types.TradePairID{
@@ -37,7 +38,7 @@ func TestGenesis(t *testing.T) {
3738
TrancheKey: "0",
3839
Address: "fakeAddr",
3940
SharesOwned: math.NewInt(10),
40-
SharesWithdrawn: math.NewInt(0),
41+
DecSharesWithdrawn: math_utils.ZeroPrecDec(),
4142
},
4243
},
4344
TickLiquidityList: []*types.TickLiquidity{

x/dex/keeper/cancel_limit_order.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ func (k Keeper) ExecuteCancelLimitOrder(
9191
tranche.TotalMakerDenom = tranche.TotalMakerDenom.Sub(trancheUser.SharesOwned)
9292

9393
// Calculate total number of shares removed previously withdrawn by the user (denominated in takerDenom)
94-
sharesWithdrawnTakerDenom := math_utils.NewPrecDecFromInt(trancheUser.SharesWithdrawn).
95-
Quo(tranche.PriceTakerToMaker)
94+
sharesWithdrawnTakerDenom := trancheUser.DecSharesWithdrawn.
95+
Mul(tranche.MakerPrice)
9696

9797
// Calculate the total amount removed including prior withdrawals (denominated in takerDenom)
9898
totalAmountOutTakerDenom := sharesWithdrawnTakerDenom.Add(takerAmountOut)
@@ -101,7 +101,7 @@ func (k Keeper) ExecuteCancelLimitOrder(
101101
tranche.SetTotalTakerDenom(tranche.DecTotalTakerDenom.Sub(totalAmountOutTakerDenom))
102102

103103
// Set TrancheUser to 100% shares withdrawn
104-
trancheUser.SharesWithdrawn = trancheUser.SharesOwned
104+
trancheUser.SetSharesWithdrawn(math_utils.NewPrecDecFromInt(trancheUser.SharesOwned))
105105

106106
if !makerAmountToReturn.IsPositive() && !takerAmountOut.IsPositive() {
107107
return types.PrecDecCoin{}, types.PrecDecCoin{}, sdkerrors.Wrapf(types.ErrCancelEmptyLimitOrder, "%s", tranche.Key.TrancheKey)

x/dex/keeper/grpc_query_limit_order_tranche_user.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package keeper
33
import (
44
"context"
55

6-
"cosmossdk.io/math"
76
"cosmossdk.io/store/prefix"
87
sdk "github.com/cosmos/cosmos-sdk/types"
98
"github.com/cosmos/cosmos-sdk/types/query"
109
"google.golang.org/grpc/codes"
1110
"google.golang.org/grpc/status"
1211

12+
math_utils "github.com/neutron-org/neutron/v10/utils/math"
1313
"github.com/neutron-org/neutron/v10/x/dex/types"
1414
)
1515

@@ -47,7 +47,7 @@ func (k Keeper) LimitOrderTrancheUserAll(
4747
}, nil
4848
}
4949

50-
func (k Keeper) CalcWithdrawableShares(ctx sdk.Context, trancheUser types.LimitOrderTrancheUser) (amount math.Int, err error) {
50+
func (k Keeper) CalcWithdrawableShares(ctx sdk.Context, trancheUser types.LimitOrderTrancheUser) (amount math_utils.PrecDec, err error) {
5151
tradePairID, tickIndex := trancheUser.TradePairId, trancheUser.TickIndexTakerToMaker
5252

5353
tranche, _, found := k.FindLimitOrderTranche(
@@ -60,7 +60,7 @@ func (k Keeper) CalcWithdrawableShares(ctx sdk.Context, trancheUser types.LimitO
6060
)
6161

6262
if !found {
63-
return math.ZeroInt(), status.Error(codes.NotFound, "Tranche not found")
63+
return math_utils.ZeroPrecDec(), status.Error(codes.NotFound, "Tranche not found")
6464
}
6565
withdrawableShares, _ := tranche.CalcWithdrawAmount(&trancheUser)
6666

@@ -89,7 +89,8 @@ func (k Keeper) LimitOrderTrancheUser(c context.Context,
8989
if err != nil {
9090
return nil, err
9191
}
92-
resp.WithdrawableShares = &withdrawAmt
92+
withdrawAmtInt := withdrawAmt.TruncateInt()
93+
resp.WithdrawableShares = &withdrawAmtInt
9394
}
9495

9596
return resp, nil

x/dex/keeper/integration_cancellimitorder_test.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,9 @@ func (s *DexTestSuite) TestWithdrawThenCancelLowTick() {
532532
s.assertAliceBalancesInt(sdkmath.NewInt(13058413), sdkmath.NewInt(4999999))
533533

534534
s.bobWithdrawsLimitSell(trancheKey)
535-
s.assertBobBalancesInt(sdkmath.ZeroInt(), sdkmath.NewInt(4999999))
535+
s.assertBobBalances(0, 5)
536536
s.bobCancelsLimitSell(trancheKey)
537-
s.assertBobBalancesInt(sdkmath.NewInt(13058413), sdkmath.NewInt(4999999))
537+
s.assertBobBalancesInt(sdkmath.NewInt(13058413), sdkmath.NewInt(5_000_000))
538538
}
539539

540540
func (s *DexTestSuite) TestWrongSharesProtectionCancel() {
@@ -553,3 +553,51 @@ func (s *DexTestSuite) TestWrongSharesProtectionCancel() {
553553

554554
s.assertAliceBalances(1, 0)
555555
}
556+
557+
func (s *DexTestSuite) TestCanceLimitOrderClearsPosition() {
558+
s.fundAccountBalancesInt(s.alice, sdkmath.NewInt(10_000), sdkmath.ZeroInt())
559+
s.fundAccountBalancesInt(s.bob, sdkmath.NewInt(500_000), sdkmath.ZeroInt())
560+
s.fundAccountBalancesInt(s.carol, sdkmath.ZeroInt(), sdkmath.NewInt(22_015))
561+
562+
// GIVEN alice and bob place GTC limit sells at tick -100000
563+
trancheKey := s.limitSellsIntSuccess(s.alice, "TokenA", -100000, sdkmath.NewInt(10_000))
564+
s.limitSellsIntSuccess(s.bob, "TokenA", -100000, sdkmath.NewInt(500_000))
565+
566+
// AND carol swaps 22,015 TokenB for TokeA
567+
s.limitSellsIntSuccess(s.carol, "TokenB", -100001, sdkmath.NewInt(22_015), types.LimitOrderType_FILL_OR_KILL)
568+
569+
// WHEN Alice withdraws then cancels
570+
s.aliceWithdrawsLimitSell(trancheKey)
571+
s.aliceCancelsLimitSell(trancheKey)
572+
573+
// THEN totalTakerDenom == ReservesTakerDenom
574+
tranche, _, found := s.App.DexKeeper.FindLimitOrderTranche(
575+
s.Ctx,
576+
&types.LimitOrderTrancheKey{
577+
TradePairId: types.MustNewTradePairID("TokenB", "TokenA"),
578+
TickIndexTakerToMaker: 100000,
579+
TrancheKey: trancheKey,
580+
},
581+
)
582+
s.True(found)
583+
584+
s.Equal(tranche.DecTotalTakerDenom, tranche.DecReservesTakerDenom)
585+
586+
// WHEN bob cancels his limit order, the tranche only contains dust
587+
s.bobCancelsLimitSell(trancheKey)
588+
589+
// Final tranche state
590+
tranche, _, found = s.App.DexKeeper.FindLimitOrderTranche(
591+
s.Ctx,
592+
&types.LimitOrderTrancheKey{
593+
TradePairId: types.MustNewTradePairID("TokenB", "TokenA"),
594+
TickIndexTakerToMaker: 100000,
595+
TrancheKey: trancheKey,
596+
},
597+
)
598+
s.True(found)
599+
600+
// NOTE: we are using the Int fields just to ensure only dust is left
601+
s.Assert().Equal(tranche.ReservesTakerDenom, sdkmath.ZeroInt())
602+
s.Assert().Equal(tranche.TotalTakerDenom, sdkmath.ZeroInt())
603+
}

x/dex/keeper/limit_order_tranche_user.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
storetypes "cosmossdk.io/store/types"
88
sdk "github.com/cosmos/cosmos-sdk/types"
99

10+
math_utils "github.com/neutron-org/neutron/v10/utils/math"
1011
"github.com/neutron-org/neutron/v10/x/dex/types"
1112
)
1213

@@ -33,6 +34,7 @@ func (k Keeper) GetOrInitLimitOrderTrancheUser(
3334
Address: receiver,
3435
SharesOwned: math.ZeroInt(),
3536
SharesWithdrawn: math.ZeroInt(),
37+
DecSharesWithdrawn: math_utils.ZeroPrecDec(),
3638
TickIndexTakerToMaker: tickIndex,
3739
TradePairId: tradePairID,
3840
OrderType: orderType,

x/dex/keeper/limit_order_tranche_user_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/neutron-org/neutron/v10/testutil/common/nullify"
1313
keepertest "github.com/neutron-org/neutron/v10/testutil/dex/keeper"
14+
math_utils "github.com/neutron-org/neutron/v10/utils/math"
1415
"github.com/neutron-org/neutron/v10/x/dex/keeper"
1516
"github.com/neutron-org/neutron/v10/x/dex/types"
1617
)
@@ -24,7 +25,7 @@ func createNLimitOrderTrancheUser(keeper *keeper.Keeper, ctx sdk.Context, n int)
2425
TradePairId: &types.TradePairID{MakerDenom: "TokenA", TakerDenom: "TokenB"},
2526
TickIndexTakerToMaker: int64(i),
2627
SharesOwned: math.NewInt(100),
27-
SharesWithdrawn: math.ZeroInt(),
28+
DecSharesWithdrawn: math_utils.ZeroPrecDec(),
2829
}
2930
items[i] = val
3031
keeper.SetLimitOrderTrancheUser(ctx, items[i])
@@ -42,7 +43,7 @@ func createNLimitOrderTrancheUserWithAddress(keeper *keeper.Keeper, ctx sdk.Cont
4243
TradePairId: &types.TradePairID{MakerDenom: "TokenA", TakerDenom: "TokenB"},
4344
TickIndexTakerToMaker: 0,
4445
SharesOwned: math.ZeroInt(),
45-
SharesWithdrawn: math.ZeroInt(),
46+
DecSharesWithdrawn: math_utils.ZeroPrecDec(),
4647
}
4748
items[i] = val
4849
keeper.SetLimitOrderTrancheUser(ctx, items[i])
@@ -91,7 +92,8 @@ func (s *DexTestSuite) TestGetAllLimitOrders() {
9192
TrancheKey: trancheKeyA,
9293
Address: s.alice.String(),
9394
SharesOwned: math.NewInt(10_000_000),
94-
SharesWithdrawn: math.NewInt(0),
95+
SharesWithdrawn: math.ZeroInt(),
96+
DecSharesWithdrawn: math_utils.ZeroPrecDec(),
9597
SharesCancelled: math.ZeroInt(),
9698
},
9799
LOList[0],
@@ -102,7 +104,8 @@ func (s *DexTestSuite) TestGetAllLimitOrders() {
102104
TrancheKey: trancheKeyB,
103105
Address: s.alice.String(),
104106
SharesOwned: math.NewInt(10_000_000),
105-
SharesWithdrawn: math.NewInt(0),
107+
SharesWithdrawn: math.ZeroInt(),
108+
DecSharesWithdrawn: math_utils.ZeroPrecDec(),
106109
SharesCancelled: math.ZeroInt(),
107110
},
108111
LOList[1],

x/dex/keeper/migrations.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
v4 "github.com/neutron-org/neutron/v10/x/dex/migrations/v4"
88
v5 "github.com/neutron-org/neutron/v10/x/dex/migrations/v5"
99
v6 "github.com/neutron-org/neutron/v10/x/dex/migrations/v6"
10+
v7 "github.com/neutron-org/neutron/v10/x/dex/migrations/v7"
1011
)
1112

1213
// Migrator is a struct for handling in-place store migrations.
@@ -38,3 +39,8 @@ func (m Migrator) Migrate4to5(ctx sdk.Context) error {
3839
func (m Migrator) Migrate5to6(ctx sdk.Context) error {
3940
return v6.MigrateStore(ctx, m.keeper.cdc, m.keeper.storeKey)
4041
}
42+
43+
// Migrate6to7 migrates from version 6 to 7.
44+
func (m Migrator) Migrate6to7(ctx sdk.Context) error {
45+
return v7.MigrateStore(ctx, m.keeper.cdc, m.keeper.storeKey)
46+
}

x/dex/keeper/withdraw_filled_limit_order.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55

66
sdkerrors "cosmossdk.io/errors"
7-
"cosmossdk.io/math"
87
sdk "github.com/cosmos/cosmos-sdk/types"
98

109
math_utils "github.com/neutron-org/neutron/v10/utils/math"
@@ -82,7 +81,7 @@ func (k Keeper) ExecuteWithdrawFilledLimitOrder(
8281
remainingTokenIn := math_utils.ZeroPrecDec()
8382
// It's possible that a TrancheUser exists but tranche does not if LO was filled entirely through a swap
8483
if found {
85-
var amountOutTokenIn math.Int
84+
var amountOutTokenIn math_utils.PrecDec
8685
amountOutTokenIn, amountOutTokenOut, err = tranche.Withdraw(trancheUser)
8786
if err != nil {
8887
return types.PrecDecCoin{}, types.PrecDecCoin{}, err
@@ -97,12 +96,13 @@ func (k Keeper) ExecuteWithdrawFilledLimitOrder(
9796
k.UpdateInactiveTranche(ctx, tranche)
9897

9998
// Since the order has already been filled we treat this as a complete withdrawal
100-
trancheUser.SharesWithdrawn = trancheUser.SharesOwned
99+
trancheUser.SetSharesWithdrawn(math_utils.NewPrecDecFromInt(trancheUser.SharesOwned))
101100

102101
} else {
103102
// This was an active tranche (still has MakerReserves) and we have only removed TakerReserves; we will save it as an active tranche
104103
k.UpdateTranche(ctx, tranche)
105-
trancheUser.SharesWithdrawn = trancheUser.SharesWithdrawn.Add(amountOutTokenIn)
104+
totalSharesWithdrawn := trancheUser.DecSharesWithdrawn.Add(amountOutTokenIn)
105+
trancheUser.SetSharesWithdrawn(totalSharesWithdrawn)
106106
}
107107

108108
}

0 commit comments

Comments
 (0)