Skip to content

Commit

Permalink
feat: eligible reward + support for lottery rank distribution strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
ze97286 committed Aug 7, 2024
1 parent d725830 commit 1d9abe3
Show file tree
Hide file tree
Showing 27 changed files with 1,838 additions and 1,312 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
- [11523](https://github.com/vegaprotocol/vega/issues/11523) - Change method of caching to improve `AMM` snapshot performance.
- [11426](https://github.com/vegaprotocol/vega/issues/11426) - `EstimateAMMBounds` now reports issues with commitment.
- [11459](https://github.com/vegaprotocol/vega/issues/11459) - Deprecate time weight position reward metric and replace it with time weighted notional.
- [11528](https://github.com/vegaprotocol/vega/issues/11528) - Added support for eligible entities reward.
- [11372](https://github.com/vegaprotocol/vega/issues/11372) - Support combined filters for the `AMM` API.

- [11535](https://github.com/vegaprotocol/vega/issues/11535) - Added support for lottery rank distribution strategy.
### 🐛 Fixes

- [11521](https://github.com/vegaprotocol/vega/issues/11521) - Restore `AMM` position factor when loading from a snapshot.
Expand Down
6 changes: 5 additions & 1 deletion commands/proposal_submission.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ var validTransfers = map[protoTypes.AccountType]map[protoTypes.AccountType]struc
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES: {},
},
protoTypes.AccountType_ACCOUNT_TYPE_INSURANCE: {
protoTypes.AccountType_ACCOUNT_TYPE_GENERAL: {},
Expand All @@ -69,6 +70,7 @@ var validTransfers = map[protoTypes.AccountType]map[protoTypes.AccountType]struc
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES: {},
},
protoTypes.AccountType_ACCOUNT_TYPE_GLOBAL_INSURANCE: {
protoTypes.AccountType_ACCOUNT_TYPE_GENERAL: {},
Expand All @@ -84,6 +86,7 @@ var validTransfers = map[protoTypes.AccountType]map[protoTypes.AccountType]struc
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN: {},
protoTypes.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES: {},
},
}

Expand Down Expand Up @@ -744,7 +747,8 @@ func checkNewTransferConfiguration(changes *vegapb.NewTransferConfiguration) Err
changes.DestinationType == vega.AccountType_ACCOUNT_TYPE_REWARD_RELATIVE_RETURN ||
changes.DestinationType == vega.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY ||
changes.DestinationType == vega.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING ||
changes.DestinationType == vega.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN {
changes.DestinationType == vega.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN ||
changes.DestinationType == vega.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES {
errs.AddForProperty("new_transfer.changes.destination_type", ErrIsNotValid)
}
if oneoff.DeliverOn < 0 {
Expand Down
22 changes: 22 additions & 0 deletions commands/proposal_submission_new_transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -77,6 +78,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -87,6 +89,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -97,6 +100,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_AVERAGE_NOTIONAL: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -107,6 +111,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_RELATIVE_RETURN: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -117,6 +122,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -127,6 +133,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RELATIVE_RETURN,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -137,6 +144,7 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RELATIVE_RETURN,
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
Expand All @@ -147,6 +155,18 @@ func testInvalidDestForMetric(t *testing.T) {
types.DispatchMetric_DISPATCH_METRIC_RELATIVE_RETURN,
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES,
},
types.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES: {
types.DispatchMetric_DISPATCH_METRIC_LP_FEES_RECEIVED,
types.DispatchMetric_DISPATCH_METRIC_MAKER_FEES_PAID,
types.DispatchMetric_DISPATCH_METRIC_MAKER_FEES_RECEIVED,
types.DispatchMetric_DISPATCH_METRIC_MARKET_VALUE,
types.DispatchMetric_DISPATCH_METRIC_AVERAGE_NOTIONAL,
types.DispatchMetric_DISPATCH_METRIC_RELATIVE_RETURN,
types.DispatchMetric_DISPATCH_METRIC_RETURN_VOLATILITY,
types.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
types.DispatchMetric_DISPATCH_METRIC_REALISED_RETURN,
},
}

Expand Down Expand Up @@ -264,6 +284,7 @@ func testRecurringWithDispatchInvalidTypes(t *testing.T) {
delete(invalidTypes, types.AccountType_ACCOUNT_TYPE_REWARD_RELATIVE_RETURN)
delete(invalidTypes, types.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN)
delete(invalidTypes, types.AccountType_ACCOUNT_TYPE_REWARD_AVERAGE_NOTIONAL)
delete(invalidTypes, types.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES)
delete(invalidTypes, types.AccountType_ACCOUNT_TYPE_INSURANCE)
delete(invalidTypes, types.AccountType_ACCOUNT_TYPE_GENERAL)

Expand Down Expand Up @@ -676,6 +697,7 @@ func testNewTransferChangeSubmissionInvalidDestinationTypeFails(t *testing.T) {
delete(allAccountTypes, int32(types.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY))
delete(allAccountTypes, int32(types.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING))
delete(allAccountTypes, int32(types.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN))
delete(allAccountTypes, int32(types.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES))
delete(allAccountTypes, int32(types.AccountType_ACCOUNT_TYPE_UNSPECIFIED))

for at := range allAccountTypes {
Expand Down
18 changes: 14 additions & 4 deletions commands/transfer_funds.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ func checkTransfer(cmd *commandspb.Transfer) (e Errors) {
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_RELATIVE_RETURN ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING {
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES {
errs.AddForProperty("transfer.account.to", errors.New("transfers to metric-based reward accounts must be recurring transfers that specify a distribution metric"))
}
case *commandspb.Transfer_Recurring:
Expand Down Expand Up @@ -155,6 +156,7 @@ func checkTransfer(cmd *commandspb.Transfer) (e Errors) {
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_RELATIVE_RETURN ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES ||
cmd.ToAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING {
if k.Recurring.DispatchStrategy == nil {
errs.AddForProperty("transfer.kind.dispatch_strategy", ErrIsRequired)
Expand Down Expand Up @@ -187,11 +189,12 @@ func validateDispatchStrategy(toAccountType vega.AccountType, dispatchStrategy *
toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_RELATIVE_RETURN &&
toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_REALISED_RETURN &&
toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY &&
toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES &&
toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING {
errs.AddForProperty(destinationPrefixErr, ErrIsNotValid)
}
// check asset for metric is passed unless it's a market proposer reward
if len(dispatchStrategy.AssetForMetric) <= 0 && toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS && toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING {
if len(dispatchStrategy.AssetForMetric) <= 0 && toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES && toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS && toAccountType != vega.AccountType_ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING {
errs.AddForProperty(prefix+".asset_for_metric", ErrIsRequired)
}
if len(dispatchStrategy.AssetForMetric) > 0 && !IsVegaID(dispatchStrategy.AssetForMetric) {
Expand All @@ -216,6 +219,9 @@ func validateDispatchStrategy(toAccountType vega.AccountType, dispatchStrategy *
if toAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_AVERAGE_NOTIONAL && dispatchStrategy.Metric != vega.DispatchMetric_DISPATCH_METRIC_AVERAGE_NOTIONAL {
errs.AddForProperty(prefix+".dispatch_metric", mismatchingAccountTypeError(toAccountType, dispatchStrategy.Metric))
}
if toAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_ELIGIBLE_ENTITIES && dispatchStrategy.Metric != vega.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES {
errs.AddForProperty(prefix+".dispatch_metric", mismatchingAccountTypeError(toAccountType, dispatchStrategy.Metric))
}
if toAccountType == vega.AccountType_ACCOUNT_TYPE_REWARD_RELATIVE_RETURN && dispatchStrategy.Metric != vega.DispatchMetric_DISPATCH_METRIC_RELATIVE_RETURN {
errs.AddForProperty(prefix+".dispatch_metric", mismatchingAccountTypeError(toAccountType, dispatchStrategy.Metric))
}
Expand All @@ -238,6 +244,10 @@ func validateDispatchStrategy(toAccountType vega.AccountType, dispatchStrategy *
errs.AddForProperty(prefix+".n_top_performers", ErrIsRequired)
}

if dispatchStrategy.Metric == vega.DispatchMetric_DISPATCH_METRIC_ELIGIBLE_ENTITIES && len(dispatchStrategy.NotionalTimeWeightedAveragePositionRequirement) > 0 && len(dispatchStrategy.AssetForMetric) == 0 {
errs.AddForProperty(prefix+".asset_for_metric", fmt.Errorf("asset for metric must be provided if NotionalTimeWeightedAveragePositionRequirement is specified"))
}

if dispatchStrategy.EntityScope != vega.EntityScope_ENTITY_SCOPE_TEAMS && len(dispatchStrategy.NTopPerformers) != 0 {
errs.AddForProperty(prefix+".n_top_performers", errors.New("must not be set when entity scope is not "+vega.EntityScope_ENTITY_SCOPE_TEAMS.String()))
}
Expand Down Expand Up @@ -296,10 +306,10 @@ func validateDispatchStrategy(toAccountType vega.AccountType, dispatchStrategy *
if dispatchStrategy.WindowLength > 100 {
errs.AddForProperty(prefix+".window_length", ErrMustBeAtMost100)
}
if len(dispatchStrategy.RankTable) == 0 && dispatchStrategy.DistributionStrategy == vega.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK {
if len(dispatchStrategy.RankTable) == 0 && (dispatchStrategy.DistributionStrategy == vega.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK || dispatchStrategy.DistributionStrategy == vega.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK_LOTTERY) {
errs.AddForProperty(prefix+".rank_table", ErrMustBePositive)
}
if len(dispatchStrategy.RankTable) > 0 && dispatchStrategy.DistributionStrategy != vega.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK {
if len(dispatchStrategy.RankTable) > 0 && dispatchStrategy.DistributionStrategy != vega.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK && dispatchStrategy.DistributionStrategy != vega.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK_LOTTERY {
errs.AddForProperty(prefix+".rank_table", errors.New("should not be set for distribution strategy "+dispatchStrategy.DistributionStrategy.String()))
}
if len(dispatchStrategy.RankTable) > 500 {
Expand Down
1 change: 1 addition & 0 deletions core/banking/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ type MarketActivityTracker interface {
MarketTrackedForAsset(market, asset string) bool
TeamStatsForMarkets(allMarketsForAssets, onlyTheseMarkets []string) map[string]map[string]*num.Uint
PublishGameMetric(ctx context.Context, dispatchStrategy []*vega.DispatchStrategy, now time.Time)
GameFinished(gameID string)
}

type EthereumEventSource interface {
Expand Down
1 change: 1 addition & 0 deletions core/banking/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func getTestEngine(t *testing.T) *testEngine {
primaryBridgeView := mocks.NewMockERC20BridgeView(ctrl)
secondaryBridgeView := mocks.NewMockERC20BridgeView(ctrl)
marketActivityTracker := mocks.NewMockMarketActivityTracker(ctrl)
marketActivityTracker.EXPECT().GameFinished(gomock.Any()).AnyTimes()
ethSource := mocks.NewMockEthereumEventSource(ctrl)

notary.EXPECT().OfferSignatures(gomock.Any(), gomock.Any()).AnyTimes()
Expand Down
12 changes: 12 additions & 0 deletions core/banking/mocks/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion core/banking/recurring_transfers.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ func (e *Engine) cleanupStaleDispatchStrategies() {
for hash, dsc := range e.hashToStrategy {
if dsc.refCount == 0 {
delete(e.hashToStrategy, hash)
e.marketActivityTracker.GameFinished(hash)
}
}
}
Expand Down Expand Up @@ -215,7 +216,7 @@ func (e *Engine) dispatchRequired(ctx context.Context, ds *vegapb.DispatchStrate
break
}
}
required = hasNonZeroMetric || (hasEligibleParties && ds.DistributionStrategy == vegapb.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK)
required = hasNonZeroMetric || (hasEligibleParties && (ds.DistributionStrategy == vegapb.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK || ds.DistributionStrategy == vegapb.DistributionStrategy_DISTRIBUTION_STRATEGY_RANK_LOTTERY))
return required
} else {
tcs, pcs := e.marketActivityTracker.CalculateMetricForTeams(ctx, ds)
Expand Down
Loading

0 comments on commit 1d9abe3

Please sign in to comment.