Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add eligible keys filter to reward transfers #11628

Merged
merged 2 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@
- [11577](https://github.com/vegaprotocol/vega/issues/11577) - Add API for party discounts and rewards.
- [10716](https://github.com/vegaprotocol/vega/issues/10716) - Set Tendermint defaults during init.
- [11612](https://github.com/vegaprotocol/vega/issues/11612) - Reward scaling support.
-[11624](https://github.com/vegaprotocol/vega/issues/11624) - prevent creation of rewards with no payout, but with high computational cost.
- [11624](https://github.com/vegaprotocol/vega/issues/11624) - prevent creation of rewards with no payout, but with high computational cost.
- [11512](https://github.com/vegaprotocol/vega/issues/11512) - Add loss socialisation amounts to funding payment API.
- [11627](https://github.com/vegaprotocol/vega/issues/11627) - Add eligible keys filter to reward transfers.

### 🐛 Fixes

Expand Down
2 changes: 1 addition & 1 deletion core/banking/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ type Topology interface {
type MarketActivityTracker interface {
CalculateMetricForIndividuals(ctx context.Context, ds *vega.DispatchStrategy) []*types.PartyContributionScore
CalculateMetricForTeams(ctx context.Context, ds *vega.DispatchStrategy) ([]*types.PartyContributionScore, map[string][]*types.PartyContributionScore)
GetMarketsWithEligibleProposer(asset string, markets []string, payoutAsset string, funder string) []*types.MarketContributionScore
GetMarketsWithEligibleProposer(asset string, markets []string, payoutAsset string, funder string, eligibleKeys []string) []*types.MarketContributionScore
MarkPaidProposer(asset, market, payoutAsset string, marketsInScope []string, funder string)
MarketTrackedForAsset(market, asset string) bool
TeamStatsForMarkets(allMarketsForAssets, onlyTheseMarkets []string) map[string]map[string]*num.Uint
Expand Down
2 changes: 1 addition & 1 deletion core/banking/gov_transfers.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func (e *Engine) processGovernanceTransfer(
ds := gTransfer.Config.RecurringTransferConfig.DispatchStrategy
// if the metric is market value we make the transfer to the market account (as opposed to the metric's hash account)
if ds.Metric == vegapb.DispatchMetric_DISPATCH_METRIC_MARKET_VALUE {
marketProposersScore := e.marketActivityTracker.GetMarketsWithEligibleProposer(ds.AssetForMetric, ds.Markets, gTransfer.Config.Asset, gTransfer.Config.Source)
marketProposersScore := e.marketActivityTracker.GetMarketsWithEligibleProposer(ds.AssetForMetric, ds.Markets, gTransfer.Config.Asset, gTransfer.Config.Source, ds.EligibleKeys)
for _, fms := range marketProposersScore {
amt, _ := num.UintFromDecimal(transferAmount.ToDecimal().Mul(fms.Score))
if amt.IsZero() {
Expand Down
8 changes: 4 additions & 4 deletions core/banking/mocks/mocks.go

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

2 changes: 1 addition & 1 deletion core/banking/recurring_transfers.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func (e *Engine) distributeRecurringTransfers(ctx context.Context, newEpoch uint
// different to how all other metric based rewards behave. The reason is that we need the context of the funder
// and this context is lost when the transfer has already gone through
if v.DispatchStrategy.Metric == vegapb.DispatchMetric_DISPATCH_METRIC_MARKET_VALUE {
marketProposersScore := e.marketActivityTracker.GetMarketsWithEligibleProposer(v.DispatchStrategy.AssetForMetric, v.DispatchStrategy.Markets, v.Asset, v.From)
marketProposersScore := e.marketActivityTracker.GetMarketsWithEligibleProposer(v.DispatchStrategy.AssetForMetric, v.DispatchStrategy.Markets, v.Asset, v.From, v.DispatchStrategy.EligibleKeys)
for _, fms := range marketProposersScore {
amt, _ := num.UintFromDecimal(amount.ToDecimal().Mul(fms.Score))
if amt.IsZero() {
Expand Down
25 changes: 23 additions & 2 deletions core/execution/common/market_activity_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,12 @@ func (mat *MarketActivityTracker) RemoveAMMParty(asset, marketID, ammParty strin

// GetMarketsWithEligibleProposer gets all the markets within the given asset (or just all the markets in scope passed as a parameter) that
// are eligible for proposer bonus.
func (mat *MarketActivityTracker) GetMarketsWithEligibleProposer(asset string, markets []string, payoutAsset string, funder string) []*types.MarketContributionScore {
func (mat *MarketActivityTracker) GetMarketsWithEligibleProposer(asset string, markets []string, payoutAsset string, funder string, eligibleKeys []string) []*types.MarketContributionScore {
eligibleKeySet := make(map[string]struct{}, len(eligibleKeys))
for _, ek := range eligibleKeys {
eligibleKeySet[ek] = struct{}{}
}

var mkts []string
if len(markets) > 0 {
mkts = markets
Expand Down Expand Up @@ -382,7 +387,10 @@ func (mat *MarketActivityTracker) GetMarketsWithEligibleProposer(asset string, m
for _, a := range assets {
for _, v := range mkts {
if t, ok := mat.getMarketTracker(a, v); ok && (len(asset) == 0 || t.asset == asset) && mat.IsMarketEligibleForBonus(a, v, payoutAsset, markets, funder) {
eligibleMarkets = append(eligibleMarkets, v)
proposer := mat.GetProposer(v)
if _, ok := eligibleKeySet[proposer]; len(eligibleKeySet) == 0 || ok {
eligibleMarkets = append(eligibleMarkets, v)
}
}
}
}
Expand Down Expand Up @@ -881,6 +889,19 @@ func (mat *MarketActivityTracker) getPartiesInScope(ds *vega.DispatchStrategy) [
} else if ds.IndividualScope == vega.IndividualScope_INDIVIDUAL_SCOPE_AMM {
parties = sortedK(mat.GetAllAMMParties(ds.AssetForMetric, ds.Markets))
}
if len(ds.EligibleKeys) > 0 {
eligibleParties := make([]string, 0, len(parties))
ep := make(map[string]struct{}, len(ds.EligibleKeys))
for _, ek := range ds.EligibleKeys {
ep[ek] = struct{}{}
}
for _, pp := range parties {
if _, ok := ep[pp]; ok {
eligibleParties = append(eligibleParties, pp)
}
}
parties = eligibleParties
}
return parties
}

Expand Down
36 changes: 21 additions & 15 deletions core/execution/common/market_activity_tracker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1185,12 +1185,14 @@ func TestMarketProposerBonusScenarios(t *testing.T) {
tracker.MarketProposed("asset2", "market6", "me2")

// no trading done so far so expect no one to be eligible for bonus
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset2", []string{}, "VEGA", "zohar")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar", []string{})))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset2", []string{}, "VEGA", "zohar", []string{})))

// market1 goes above the threshold only it should be eligible
tracker.AddValueTraded("asset1", "market1", num.NewUint(5001))
require.Equal(t, 1, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar")))
require.Equal(t, 1, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{})))
require.Equal(t, 1, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{"me"})))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{"not me"})))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market2", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market3", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))
Expand All @@ -1200,7 +1202,11 @@ func TestMarketProposerBonusScenarios(t *testing.T) {
// now market 2 and 3 become eligible
tracker.AddValueTraded("asset1", "market2", num.NewUint(5001))
tracker.AddValueTraded("asset1", "market3", num.NewUint(5001))
require.Equal(t, 2, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar")))
require.Equal(t, 2, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{})))
require.Equal(t, 2, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{"me", "me2"})))
require.Equal(t, 1, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{"me", "not me"})))
require.Equal(t, 1, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{"me2", "not me"})))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{"not me"})))

// show that only markets 2 and 3 are now eligible with this combo
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))
Expand All @@ -1212,14 +1218,14 @@ func TestMarketProposerBonusScenarios(t *testing.T) {

// now market4 goes above the threshold but no one gets paid by this combo
tracker.AddValueTraded("asset1", "market4", num.NewUint(5001))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market2", "market3"}, "VEGA", "zohar", []string{})))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market2", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market3", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market4", "VEGA", []string{"market1", "market2", "market3"}, "zohar"))

// now "all" is funded by zohar
require.Equal(t, 4, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar")))
require.Equal(t, 4, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar", []string{})))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "VEGA", []string{}, "zohar"))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market2", "VEGA", []string{}, "zohar"))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market3", "VEGA", []string{}, "zohar"))
Expand All @@ -1231,14 +1237,14 @@ func TestMarketProposerBonusScenarios(t *testing.T) {
tracker.MarkPaidProposer("asset1", "market4", "VEGA", []string{}, "zohar")

// everyone were paid so next time no one is eligible
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar", []string{})))

// a new market is proposed and gets over the limit
tracker.MarketProposed("asset1", "market7", "mememe")
tracker.AddValueTraded("asset1", "market7", num.NewUint(5001))

// only the new market should be eligible for the "all" combo funded by zohar
require.Equal(t, 1, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar")))
require.Equal(t, 1, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar", []string{})))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "VEGA", []string{}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market2", "VEGA", []string{}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market3", "VEGA", []string{}, "zohar"))
Expand All @@ -1247,10 +1253,10 @@ func TestMarketProposerBonusScenarios(t *testing.T) {
tracker.MarkPaidProposer("asset1", "market7", "VEGA", []string{}, "zohar")

// check that they are no longer eligible for this combo of all
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "zohar", []string{})))

// check new combo
require.Equal(t, 3, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "VEGA", "zohar")))
require.Equal(t, 3, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "VEGA", "zohar", []string{})))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "VEGA", []string{"market1", "market3", "market7"}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market2", "VEGA", []string{"market1", "market3", "market7"}, "zohar"))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market3", "VEGA", []string{"market1", "market3", "market7"}, "zohar"))
Expand All @@ -1262,10 +1268,10 @@ func TestMarketProposerBonusScenarios(t *testing.T) {
tracker.MarkPaidProposer("asset1", "market7", "VEGA", []string{"market1", "market3", "market7"}, "zohar")

// now that they're marked as paid check they're no longer eligible
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "VEGA", "zohar")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "VEGA", "zohar", []string{})))

// check new asset for the same combo
require.Equal(t, 3, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "USDC", "zohar")))
require.Equal(t, 3, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "USDC", "zohar", []string{})))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "USDC", []string{"market1", "market3", "market7"}, "zohar"))
require.False(t, tracker.IsMarketEligibleForBonus("asset1", "market2", "USDC", []string{"market1", "market3", "market7"}, "zohar"))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market3", "USDC", []string{"market1", "market3", "market7"}, "zohar"))
Expand All @@ -1277,10 +1283,10 @@ func TestMarketProposerBonusScenarios(t *testing.T) {
tracker.MarkPaidProposer("asset1", "market7", "USDC", []string{"market1", "market3", "market7"}, "zohar")

// now that they're marked as paid check they're no longer eligible
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "USDC", "zohar")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{"market1", "market3", "market7"}, "USDC", "zohar", []string{})))

// check new funder for the all combo
require.Equal(t, 5, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "jeremy")))
require.Equal(t, 5, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "jeremy", []string{})))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market1", "VEGA", []string{}, "jeremy"))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market2", "VEGA", []string{}, "jeremy"))
require.True(t, tracker.IsMarketEligibleForBonus("asset1", "market3", "VEGA", []string{}, "jeremy"))
Expand All @@ -1292,7 +1298,7 @@ func TestMarketProposerBonusScenarios(t *testing.T) {
tracker.MarkPaidProposer("asset1", "market3", "VEGA", []string{}, "jeremy")
tracker.MarkPaidProposer("asset1", "market4", "VEGA", []string{}, "jeremy")
tracker.MarkPaidProposer("asset1", "market7", "VEGA", []string{}, "jeremy")
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "jeremy")))
require.Equal(t, 0, len(tracker.GetMarketsWithEligibleProposer("asset1", []string{}, "VEGA", "jeremy", []string{})))
}

func TestNotionalMetric(t *testing.T) {
Expand Down
Loading
Loading