diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db2d2b78cf..367f0137610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - [11066](https://github.com/vegaprotocol/vega/issues/11066) - Ensure vesting statistics match vesting accounts numbers. - [11279](https://github.com/vegaprotocol/vega/issues/11279) - Handle properly the case of multiple transfers for the same game id. - [11293](https://github.com/vegaprotocol/vega/issues/11293) - Panic in data node with position estimate endpoint. +- [11401](https://github.com/vegaprotocol/vega/issues/11401) - Ignore dispatch strategies with zero `ref-counts` when calculating payouts. - [11379](https://github.com/vegaprotocol/vega/issues/11379) - Source chain id is now populated in `GQL Erc20WithdrawalApproval` endpoint. - [11279](https://github.com/vegaprotocol/vega/issues/11279) - Handle properly the case of multiple transfers for the same game id. - [11297](https://github.com/vegaprotocol/vega/issues/11297) - Handle properly asset decimals < market decimals when uncrossing the order book upon leaving auction. diff --git a/core/banking/engine.go b/core/banking/engine.go index d302347d3a4..df400a0d39d 100644 --- a/core/banking/engine.go +++ b/core/banking/engine.go @@ -622,6 +622,10 @@ func (e *Engine) GetDispatchStrategy(hash string) *proto.DispatchStrategy { return nil } + if ds.refCount == 0 { + return nil + } + return ds.ds } diff --git a/core/banking/recurring_transfers_test.go b/core/banking/recurring_transfers_test.go index a0f342ea283..7dcbf3d24a6 100644 --- a/core/banking/recurring_transfers_test.go +++ b/core/banking/recurring_transfers_test.go @@ -17,6 +17,7 @@ package banking_test import ( "context" + "encoding/hex" "fmt" "testing" @@ -26,6 +27,7 @@ import ( "code.vegaprotocol.io/vega/core/types" "code.vegaprotocol.io/vega/libs/crypto" "code.vegaprotocol.io/vega/libs/num" + "code.vegaprotocol.io/vega/libs/proto" "code.vegaprotocol.io/vega/protos/vega" "github.com/golang/mock/gomock" @@ -738,3 +740,72 @@ func TestMarketAssetMismatchRejectsTransfer(t *testing.T) { eng.marketActivityTracker.EXPECT().MarketTrackedForAsset(gomock.Any(), gomock.Any()).Times(1).Return(false) require.Error(t, eng.TransferFunds(context.Background(), recurring)) } + +func TestDispatchStrategyRemoval(t *testing.T) { + e := getTestEngine(t) + + dispatchStrat := &vega.DispatchStrategy{ + AssetForMetric: "zohar", + Metric: vega.DispatchMetric_DISPATCH_METRIC_AVERAGE_POSITION, + Markets: []string{"mmm"}, + EntityScope: vega.EntityScope_ENTITY_SCOPE_INDIVIDUALS, + IndividualScope: vega.IndividualScope_INDIVIDUAL_SCOPE_IN_TEAM, + WindowLength: 1, + LockPeriod: 1, + DistributionStrategy: vega.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK, + } + + p, err := proto.Marshal(dispatchStrat) + require.NoError(t, err) + dsHash := hex.EncodeToString(crypto.Hash(p)) + + var endEpoch uint64 = 100 + party := "03ae90688632c649c4beab6040ff5bd04dbde8efbf737d8673bbda792a110301" + ctx := context.Background() + transfer := &types.TransferFunds{ + Kind: types.TransferCommandKindRecurring, + Recurring: &types.RecurringTransfer{ + TransferBase: &types.TransferBase{ + ID: "TRANSFERID", + From: party, + FromAccountType: types.AccountTypeGeneral, + To: "0000000000000000000000000000000000000000000000000000000000000000", + ToAccountType: types.AccountTypeGlobalReward, + Asset: assetNameETH, + Amount: num.NewUint(100), + Reference: "someref", + }, + StartEpoch: 8, + EndEpoch: &endEpoch, + Factor: num.MustDecimalFromString("0.9"), + DispatchStrategy: dispatchStrat, + }, + } + + e.assets.EXPECT().Get(gomock.Any()).AnyTimes().Return(assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil) + e.broker.EXPECT().Send(gomock.Any()).AnyTimes() + e.marketActivityTracker.EXPECT().MarketTrackedForAsset(gomock.Any(), gomock.Any()).Times(1).Return(true) + assert.NoError(t, e.TransferFunds(ctx, transfer)) + + // it exists + assert.NotNil(t, e.GetDispatchStrategy(dsHash)) + + // now cancel + require.NoError(t, e.CancelTransferFunds(ctx, + &types.CancelTransferFunds{ + Party: party, + TransferID: "TRANSFERID", + }, + ), + ) + + // it does not exist (secretly it does but has ref-count 0) + assert.Nil(t, e.GetDispatchStrategy(dsHash)) + + // roll into the next epoch end + e.OnEpoch(context.Background(), types.Epoch{Seq: 8, Action: vega.EpochAction_EPOCH_ACTION_END}) + e.OnEpoch(context.Background(), types.Epoch{Seq: 9, Action: vega.EpochAction_EPOCH_ACTION_START}) + + // still not there + assert.Nil(t, e.GetDispatchStrategy(dsHash)) +}