code.vegaprotocol.io/vega@v0.79.0/core/banking/fee_discount_test.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package banking_test 17 18 import ( 19 "context" 20 "testing" 21 22 "code.vegaprotocol.io/vega/core/assets" 23 "code.vegaprotocol.io/vega/core/assets/builtin" 24 "code.vegaprotocol.io/vega/core/types" 25 "code.vegaprotocol.io/vega/libs/num" 26 proto "code.vegaprotocol.io/vega/protos/vega" 27 28 "github.com/golang/mock/gomock" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 func TestBankingTransactionFeeDiscount(t *testing.T) { 33 party := "party-1" 34 asset := assets.NewAsset(builtin.New("vega", &types.AssetDetails{ 35 Name: "vega", 36 Symbol: "vega", 37 Quantum: num.DecimalFromFloat(10), 38 })) 39 assetID := asset.Type().ID 40 41 t.Run("decay amount", func(t *testing.T) { 42 eng := getTestEngine(t) 43 44 ctx := context.Background() 45 eng.broker.EXPECT().SendBatch(gomock.Any()).AnyTimes() 46 eng.broker.EXPECT().Send(gomock.Any()).AnyTimes() 47 eng.assets.EXPECT().Get(gomock.Any()).Return(asset, nil).AnyTimes() 48 49 eng.OnTransferFeeDiscountDecayFractionUpdate(context.Background(), num.DecimalFromFloat(0.5)) 50 eng.OnTransferFeeDiscountMinimumTrackedAmountUpdate(context.Background(), num.DecimalFromFloat(1)) 51 52 asset2 := "asset-2" 53 party2 := "party-2" 54 55 assert.Equal(t, "0", eng.AvailableFeeDiscount(assetID, party).String()) 56 assert.Equal(t, "0", eng.AvailableFeeDiscount(asset2, party2).String()) 57 eng.RegisterTradingFees(ctx, assetID, map[string]*num.Uint{party: num.NewUint(25)}) 58 eng.RegisterTradingFees(ctx, assetID, map[string]*num.Uint{party: num.NewUint(25)}) 59 eng.RegisterTradingFees(ctx, asset2, map[string]*num.Uint{party2: num.NewUint(20)}) 60 eng.OnEpoch(ctx, types.Epoch{Action: proto.EpochAction_EPOCH_ACTION_END}) 61 assert.Equal(t, "50", eng.AvailableFeeDiscount(assetID, party).String()) 62 assert.Equal(t, "20", eng.AvailableFeeDiscount(asset2, party2).String()) 63 eng.RegisterTradingFees(ctx, assetID, nil) 64 eng.OnEpoch(ctx, types.Epoch{Action: proto.EpochAction_EPOCH_ACTION_END}) 65 // decay by half 66 assert.Equal(t, "25", eng.AvailableFeeDiscount(assetID, party).String()) 67 assert.Equal(t, "10", eng.AvailableFeeDiscount(asset2, party2).String()) 68 eng.RegisterTradingFees(ctx, assetID, nil) 69 eng.OnEpoch(ctx, types.Epoch{Action: proto.EpochAction_EPOCH_ACTION_END}) 70 // decay by half 71 assert.Equal(t, "12", eng.AvailableFeeDiscount(assetID, party).String()) 72 assert.Equal(t, "0", eng.AvailableFeeDiscount(asset2, party2).String()) 73 eng.RegisterTradingFees(ctx, assetID, nil) 74 eng.OnEpoch(ctx, types.Epoch{Action: proto.EpochAction_EPOCH_ACTION_END}) 75 76 // decay by half but it's 0 because decayed amount (6) is less then 77 // asset quantum x TransferFeeDiscountMinimumTrackedAmount (10 x 1) 78 assert.Equal(t, "0", eng.AvailableFeeDiscount(assetID, party).String()) 79 }) 80 81 t.Run("apply fee discount", func(t *testing.T) { 82 eng := getTestEngine(t) 83 84 ctx := context.Background() 85 eng.broker.EXPECT().SendBatch(gomock.Any()).AnyTimes() 86 eng.broker.EXPECT().Send(gomock.Any()).AnyTimes() 87 eng.assets.EXPECT().Get(gomock.Any()).Return(asset, nil).AnyTimes() 88 89 eng.OnTransferFeeDiscountDecayFractionUpdate(context.Background(), num.DecimalFromFloat(0.5)) 90 91 assert.Equal(t, "0", eng.AvailableFeeDiscount(assetID, party).String()) 92 93 // expect the whole fee to be paid 94 discountedFee, discount := eng.ApplyFeeDiscount(ctx, assetID, party, num.NewUint(5)) 95 assert.Equal(t, "5", discountedFee.String()) 96 assert.Equal(t, "0", discount.String()) 97 eng.RegisterTradingFees(ctx, assetID, map[string]*num.Uint{party: num.NewUint(10)}) 98 // move to another epoch 99 eng.OnEpoch(ctx, types.Epoch{Action: proto.EpochAction_EPOCH_ACTION_END}) 100 101 assert.Equal(t, "10", eng.AvailableFeeDiscount(assetID, party).String()) 102 103 // expect discount of 10 to be applied 104 discountedFee, discount = eng.ApplyFeeDiscount(ctx, assetID, party, num.NewUint(15)) 105 assert.Equal(t, "5", discountedFee.String()) 106 assert.Equal(t, "10", discount.String()) 107 eng.RegisterTradingFees(ctx, assetID, map[string]*num.Uint{party: num.NewUint(20)}) 108 // move to another epoch 109 eng.OnEpoch(ctx, types.Epoch{Action: proto.EpochAction_EPOCH_ACTION_END}) 110 111 assert.Equal(t, "20", eng.AvailableFeeDiscount(assetID, party).String()) 112 113 // expect discount of 3 to be applied 114 discountedFee, discount = eng.ApplyFeeDiscount(ctx, assetID, party, num.NewUint(3)) 115 assert.Equal(t, "0", discountedFee.String()) 116 assert.Equal(t, "3", discount.String()) 117 118 assert.Equal(t, "17", eng.AvailableFeeDiscount(assetID, party).String()) 119 120 eng.RegisterTradingFees(ctx, assetID, map[string]*num.Uint{party: num.NewUint(5)}) 121 // move to another epoch 122 eng.OnEpoch(ctx, types.Epoch{Action: proto.EpochAction_EPOCH_ACTION_END}) 123 124 // it's 13 because 9 was decayed and extra 5 added = 17-8+5 125 assert.Equal(t, "13", eng.AvailableFeeDiscount(assetID, party).String()) 126 127 // expect discount of 4 to be applied 128 discountedFee, discount = eng.ApplyFeeDiscount(ctx, assetID, party, num.NewUint(4)) 129 assert.Equal(t, "0", discountedFee.String()) 130 assert.Equal(t, "4", discount.String()) 131 }) 132 }