Skip to content

Commit

Permalink
Merge pull request #11678 from vegaprotocol/HVMR-coverage
Browse files Browse the repository at this point in the history
Hvmr coverage
  • Loading branch information
EVODelavega authored Sep 12, 2024
2 parents 2a7b888 + fde7f78 commit 2f119c3
Show file tree
Hide file tree
Showing 11 changed files with 666 additions and 10 deletions.
2 changes: 1 addition & 1 deletion commands/proposal_submission.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ func checkVolumeRebateProgramChanges(changes *vegapb.VolumeRebateProgramChanges,

func checkVolumeRebateBenefitTier(index int, tier *vegapb.VolumeRebateBenefitTier) Errors {
errs := NewErrors()
propertyPath := fmt.Sprintf("update_volume_discount_program.changes.benefit_tiers.%d", index)
propertyPath := fmt.Sprintf("update_volume_rebate_program.changes.benefit_tiers.%d", index)
if len(tier.MinimumPartyMakerVolumeFraction) == 0 {
errs.AddForProperty(propertyPath+".minimum_party_maker_volume_fraction", ErrIsRequired)
} else {
Expand Down
173 changes: 173 additions & 0 deletions commands/proposal_submission_update_rebate_program_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Copyright (C) 2023 Gobalsky Labs Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package commands_test

import (
"testing"
"time"

"code.vegaprotocol.io/vega/commands"
types "code.vegaprotocol.io/vega/protos/vega"
commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"

"github.com/stretchr/testify/assert"
)

func TestVolumeRebateSubmission(t *testing.T) {
t.Run("empty submission", testUpdateRebateProgram)
t.Run("0095-HVMR-001: invalid end timestamp", testInvalidEndTime)
t.Run("0095-HVMR-003: tier validation", testInvalidTiers)
t.Run("0095-HVMR-004: invalid window length", testInvalidWindowLength)
}

func testUpdateRebateProgram(t *testing.T) {
err := checkProposalSubmission(&commandspb.ProposalSubmission{
Terms: &types.ProposalTerms{
Change: &types.ProposalTerms_UpdateVolumeRebateProgram{},
},
})

assert.Contains(t, err.Get("proposal_submission.terms.change.update_volume_rebate_program"), commands.ErrIsRequired)
// missing changes, same problem
err = checkProposalSubmission(&commandspb.ProposalSubmission{
Terms: &types.ProposalTerms{
Change: &types.ProposalTerms_UpdateVolumeRebateProgram{
UpdateVolumeRebateProgram: &types.UpdateVolumeRebateProgram{},
},
},
})

assert.Contains(t, err.Get("proposal_submission.terms.change.update_volume_rebate_program.changes"), commands.ErrIsRequired)
}

// testInvalidEndTime covers 0095-HVMR-001.
func testInvalidEndTime(t *testing.T) {
end := time.Now()
enact := end.Add(time.Second)
prop := &commandspb.ProposalSubmission{
Terms: &types.ProposalTerms{
EnactmentTimestamp: enact.Unix(),
Change: &types.ProposalTerms_UpdateVolumeRebateProgram{
UpdateVolumeRebateProgram: &types.UpdateVolumeRebateProgram{
Changes: &types.VolumeRebateProgramChanges{
EndOfProgramTimestamp: end.Unix(),
},
},
},
},
}
err := checkProposalSubmission(prop)
assert.Contains(t, err.Get("proposal_submission.terms.change.update_volume_rebate_program.changes.end_of_program_timestamp"), commands.ErrMustBeGreaterThanEnactmentTimestamp)
}

// testInvalidWindowLength covers 0095-HVMR-004.
func testInvalidWindowLength(t *testing.T) {
enact := time.Now()
end := enact.Add(time.Second)
prop := &commandspb.ProposalSubmission{
Terms: &types.ProposalTerms{
EnactmentTimestamp: enact.Unix(),
Change: &types.ProposalTerms_UpdateVolumeRebateProgram{
UpdateVolumeRebateProgram: &types.UpdateVolumeRebateProgram{
Changes: &types.VolumeRebateProgramChanges{
EndOfProgramTimestamp: end.Unix(),
WindowLength: 0, // zero is invalid
},
},
},
},
}
err := checkProposalSubmission(prop)
assert.Contains(t, err.Get("proposal_submission.terms.change.update_volume_rebate_program.changes.window_length"), commands.ErrIsRequired)
// now too high of a value
prop = &commandspb.ProposalSubmission{
Terms: &types.ProposalTerms{
EnactmentTimestamp: enact.Unix(),
Change: &types.ProposalTerms_UpdateVolumeRebateProgram{
UpdateVolumeRebateProgram: &types.UpdateVolumeRebateProgram{
Changes: &types.VolumeRebateProgramChanges{
EndOfProgramTimestamp: end.Unix(),
WindowLength: 10000,
},
},
},
},
}
err = checkProposalSubmission(prop)
assert.Contains(t, err.Get("proposal_submission.terms.change.update_volume_rebate_program.changes.window_length"), commands.ErrMustBeAtMost200)
}

// testInvalidTiers covers 0095-HVMR-003.
func testInvalidTiers(t *testing.T) {
errMap := map[string]error{
"proposal_submission.terms.change.update_volume_rebate_program.changes.benefit_tiers.0.minimum_party_maker_volume_fraction": commands.ErrIsRequired,
"proposal_submission.terms.change.update_volume_rebate_program.changes.benefit_tiers.1.minimum_party_maker_volume_fraction": commands.ErrIsNotValidNumber,
"proposal_submission.terms.change.update_volume_rebate_program.changes.benefit_tiers.2.minimum_party_maker_volume_fraction": commands.ErrMustBePositive,
"proposal_submission.terms.change.update_volume_rebate_program.changes.benefit_tiers.3.minimum_party_maker_volume_fraction": commands.ErrMustBePositive,
"proposal_submission.terms.change.update_volume_rebate_program.changes.benefit_tiers.4.additional_maker_rebate": commands.ErrIsRequired,
"proposal_submission.terms.change.update_volume_rebate_program.changes.benefit_tiers.5.additional_maker_rebate": commands.ErrIsNotValidNumber,
"proposal_submission.terms.change.update_volume_rebate_program.changes.benefit_tiers.6.additional_maker_rebate": commands.ErrMustBePositiveOrZero,
}
enact := time.Now()
end := enact.Add(time.Second)
prop := &commandspb.ProposalSubmission{
Terms: &types.ProposalTerms{
EnactmentTimestamp: enact.Unix(),
Change: &types.ProposalTerms_UpdateVolumeRebateProgram{
UpdateVolumeRebateProgram: &types.UpdateVolumeRebateProgram{
Changes: &types.VolumeRebateProgramChanges{
EndOfProgramTimestamp: end.Unix(),
WindowLength: 10,
BenefitTiers: []*types.VolumeRebateBenefitTier{
{
MinimumPartyMakerVolumeFraction: "",
AdditionalMakerRebate: "0.1",
},
{
MinimumPartyMakerVolumeFraction: "invalid",
AdditionalMakerRebate: "0.1",
},
{
MinimumPartyMakerVolumeFraction: "-1",
AdditionalMakerRebate: "0.1",
},
{
MinimumPartyMakerVolumeFraction: "0",
AdditionalMakerRebate: "0.1",
},
{
MinimumPartyMakerVolumeFraction: "0.1",
AdditionalMakerRebate: "",
},
{
MinimumPartyMakerVolumeFraction: "0.1",
AdditionalMakerRebate: "invalid",
},
{
MinimumPartyMakerVolumeFraction: "0.1",
AdditionalMakerRebate: "-0.1",
},
},
},
},
},
},
}
err := checkProposalSubmission(prop)
for g, c := range errMap {
assert.Contains(t, err.Get(g), c, err.Error())
}
}
2 changes: 2 additions & 0 deletions core/governance/engine_update_referral_program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func testSubmittingProposalForReferralProgramUpdateSucceeds(t *testing.T) {
require.NotNil(t, toSubmit)
}

// testSubmittingProposalForReferralProgramUpdateWithTooManyTiersFails covers 0095-HVMR-002.
func testSubmittingProposalForReferralProgramUpdateWithTooManyTiersFails(t *testing.T) {
now := time.Now()
ctx := vgtest.VegaContext(vgrand.RandomStr(5), vgtest.RandomPositiveI64())
Expand Down Expand Up @@ -324,6 +325,7 @@ func testSubmittingProposalForReferralProgramUpdateWithTooHighDiscountFactorFail
require.Nil(t, toSubmit)
}

// testSubmittingProposalForReferralProgramUpdateEndsBeforeEnactsFails covers 0095-HVMR-001.
func testSubmittingProposalForReferralProgramUpdateEndsBeforeEnactsFails(t *testing.T) {
now := time.Now()
ctx := vgtest.VegaContext(vgrand.RandomStr(5), vgtest.RandomPositiveI64())
Expand Down
118 changes: 118 additions & 0 deletions core/integration/features/verified/finite-rewards.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
Feature: Team Rewards

Setup a maker fees received team game with a fee cap.

We want to make it so that one team is allocated rewards and the other team is allocated rewards.

- Team A should have also paid rewards and not have their rewards capped.
- Team B should not have paid rewards and have their rewards capped.

Question is what happens to the left over rewards.


Background:

And the average block duration is "1"
And the following network parameters are set:
| name | value |
| referralProgram.minStakedVegaTokens | 0 |
| market.fee.factors.makerFee | 0.01 |
| network.markPriceUpdateMaximumFrequency | 0s |
| validators.epoch.length | 60s |

# Initialise the markets
And the following assets are registered:
| id | decimal places | quantum |
| USD-0-1 | 0 | 1 |
And the markets:
| id | quote name | asset | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | decimal places | position decimal places |
| ETH/USD-0-1 | ETH | USD-0-1 | default-log-normal-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 1e-3 | 0 | default-futures | 0 | 0 |

# Initialise the parties
Given the parties deposit on asset's general account the following amount:
| party | asset | amount |
| aux1 | USD-0-1 | 1000000000000 |
| aux2 | USD-0-1 | 1000000000000 |
| party1 | USD-0-1 | 1000000000000 |
| party2 | USD-0-1 | 1000000000000 |
| a3c024b4e23230c89884a54a813b1ecb4cb0f827a38641c66eeca466da6b2ddf | USD-0-1 | 1000000000000 |

# Exit opening auctions
When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux1 | ETH/USD-0-1 | buy | 1 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
| aux2 | ETH/USD-0-1 | sell | 1 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
And the opening auction period ends for market "ETH/USD-0-1"
And the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "ETH/USD-0-1"

Given the parties create the following referral codes:
| party | code | is_team | team |
| party1 | referral-code-1 | true | team1 |
Given the parties create the following referral codes:
| party | code | is_team | team |
| party2 | referral-code-1 | true | team2 |

Scenario: Check a one-off pay out can be done with start epoch = end epoch

Given the current epoch is "0"
When the parties submit the following recurring transfers:
| id | from | from_account_type | to | to_account_type | entity_scope | asset | amount | start_epoch | end_epoch | factor | metric | metric_asset | markets | lock_period | window_length | ntop | cap_reward_fee_multiple |
| 1 | a3c024b4e23230c89884a54a813b1ecb4cb0f827a38641c66eeca466da6b2ddf | ACCOUNT_TYPE_GENERAL | 0000000000000000000000000000000000000000000000000000000000000000 | ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES | TEAMS | USD-0-1 | 100 | 1 | 2 | 1 | DISPATCH_METRIC_MAKER_FEES_RECEIVED | USD-0-1 | ETH/USD-0-1 | 10 | 1 | 1 | 1 |
Then the network moves ahead "1" epochs

## pary1
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux1 | ETH/USD-0-1 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
| party1 | ETH/USD-0-1 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC |
| party1 | ETH/USD-0-1 | buy | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
| aux1 | ETH/USD-0-1 | sell | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC |
And the following trades should be executed:
| buyer | size | price | seller | aggressor side | buyer maker fee | seller maker fee |
| party1 | 10 | 1000 | aux1 | buy | 100 | 0 |
| party1 | 10 | 1000 | aux1 | sell | 0 | 100 |

# party2
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux1 | ETH/USD-0-1 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
| party2 | ETH/USD-0-1 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC |
And the following trades should be executed:
| buyer | size | price | seller | aggressor side | buyer maker fee |
| party2 | 10 | 1000 | aux1 | buy | 100 |

When the network moves ahead "1" epochs
And parties should have the following vesting account balances:
| party | asset | balance |
| party1 | USD-0-1 | 100 |
| party2 | USD-0-1 | 0 |


## pary1
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux1 | ETH/USD-0-1 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
| party1 | ETH/USD-0-1 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC |
| party1 | ETH/USD-0-1 | buy | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
| aux1 | ETH/USD-0-1 | sell | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC |
And the following trades should be executed:
| buyer | size | price | seller | aggressor side | buyer maker fee | seller maker fee |
| party1 | 10 | 1000 | aux1 | buy | 100 | 0 |
| party1 | 10 | 1000 | aux1 | sell | 0 | 100 |

# party2
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux1 | ETH/USD-0-1 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC |
| party2 | ETH/USD-0-1 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC |
And the following trades should be executed:
| buyer | size | price | seller | aggressor side | buyer maker fee |
| party2 | 10 | 1000 | aux1 | buy | 100 |

When the network moves ahead "1" epochs
And parties should have the following vesting account balances:
| party | asset | balance |
| party1 | USD-0-1 | 200 |
| party2 | USD-0-1 | 0 |

Then debug transfers
Loading

0 comments on commit 2f119c3

Please sign in to comment.