diff --git a/CHANGELOG.md b/CHANGELOG.md index 6207174201..860702146a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,7 +81,7 @@ - [11177](https://github.com/vegaprotocol/vega/issues/11177) - Adjust the formulas for reduced position to the spec update and fix handling of closed out position. - [11193](https://github.com/vegaprotocol/vega/issues/11193) - Fix loading of liquidation strategy from proto with missing data. - [11200](https://github.com/vegaprotocol/vega/issues/11200) - Make sure a party can afford the trades before they are submitted to the book. - +- [11205](https://github.com/vegaprotocol/vega/issues/11205) - Evaluate transfer interval correctly. ## 0.75.0 ### 🚨 Breaking changes diff --git a/core/banking/gov_transfers.go b/core/banking/gov_transfers.go index f6ccfd3a5a..a647aed7a9 100644 --- a/core/banking/gov_transfers.go +++ b/core/banking/gov_transfers.go @@ -93,8 +93,8 @@ func (e *Engine) distributeRecurringGovernanceTransfers(ctx context.Context) { } if gTransfer.Config.RecurringTransferConfig.DispatchStrategy != nil && gTransfer.Config.RecurringTransferConfig.DispatchStrategy.TransferInterval != nil && - (e.currentEpoch-gTransfer.Config.RecurringTransferConfig.StartEpoch+1) < uint64(*gTransfer.Config.RecurringTransferConfig.DispatchStrategy.TransferInterval) && - (e.currentEpoch-gTransfer.Config.RecurringTransferConfig.StartEpoch+1)%uint64(*gTransfer.Config.RecurringTransferConfig.DispatchStrategy.TransferInterval) != 0 { + ((e.currentEpoch-gTransfer.Config.RecurringTransferConfig.StartEpoch+1) < uint64(*gTransfer.Config.RecurringTransferConfig.DispatchStrategy.TransferInterval) || + (e.currentEpoch-gTransfer.Config.RecurringTransferConfig.StartEpoch+1)%uint64(*gTransfer.Config.RecurringTransferConfig.DispatchStrategy.TransferInterval) != 0) { continue } diff --git a/core/banking/recurring_transfers.go b/core/banking/recurring_transfers.go index 975e740f6e..a0b80ac19d 100644 --- a/core/banking/recurring_transfers.go +++ b/core/banking/recurring_transfers.go @@ -229,8 +229,8 @@ func (e *Engine) distributeRecurringTransfers(ctx context.Context, newEpoch uint } if v.DispatchStrategy != nil && v.DispatchStrategy.TransferInterval != nil && - (newEpoch-v.StartEpoch+1) < uint64(*v.DispatchStrategy.TransferInterval) && - (newEpoch-v.StartEpoch+1)%uint64(*v.DispatchStrategy.TransferInterval) != 0 { + ((newEpoch-v.StartEpoch+1) < uint64(*v.DispatchStrategy.TransferInterval) || + (newEpoch-v.StartEpoch+1)%uint64(*v.DispatchStrategy.TransferInterval) != 0) { continue } diff --git a/core/integration/features/verified/rewards-over-window.feature b/core/integration/features/verified/rewards-over-window.feature index 1c80de7477..b8dd1dded2 100644 --- a/core/integration/features/verified/rewards-over-window.feature +++ b/core/integration/features/verified/rewards-over-window.feature @@ -96,6 +96,40 @@ Feature: Maker fees paid reward metric calculated correctly for time window And "referee3" should have vesting account balance of "2000" for asset "USD-1-10" + Scenario: Party funds pool with recurring transfer scoping individuals with transfer interval 5 + + Given the parties submit the following recurring transfers: + | id | from | from_account_type | to | to_account_type | entity_scope | teams | ntop | asset | amount | start_epoch | end_epoch | factor | metric | metric_asset | markets | window_length | transfer_interval | + | 1 | a3c024b4e23230c89884a54a813b1ecb4cb0f827a38641c66eeca466da6b2ddf | ACCOUNT_TYPE_GENERAL | 0000000000000000000000000000000000000000000000000000000000000000 | ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES | INDIVIDUALS | | 1 | USD-1-10 | 10000 | 1 | | 1 | DISPATCH_METRIC_MAKER_FEES_PAID | USD-1-10 | ETH/USD-1-10 | 5 | 5 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | + | referrer1 | ETH/USD-1-10 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | + | referee1 | ETH/USD-1-10 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC | + | referrer1 | ETH/USD-1-10 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | + | referee2 | ETH/USD-1-10 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC | + | referrer1 | ETH/USD-1-10 | sell | 5 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | + | referee3 | ETH/USD-1-10 | buy | 5 | 1000 | 1 | TYPE_LIMIT | TIF_GTC | + + When the network moves ahead "5" epochs + Then "referee1" should have vesting account balance of "4000" for asset "USD-1-10" + And "referee2" should have vesting account balance of "4000" for asset "USD-1-10" + And "referee3" should have vesting account balance of "2000" for asset "USD-1-10" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | + | referrer1 | ETH/USD-1-10 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | + | referee1 | ETH/USD-1-10 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC | + | referrer1 | ETH/USD-1-10 | sell | 10 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | + | referee2 | ETH/USD-1-10 | buy | 10 | 1000 | 1 | TYPE_LIMIT | TIF_GTC | + | referrer1 | ETH/USD-1-10 | sell | 5 | 1000 | 0 | TYPE_LIMIT | TIF_GTC | + | referee3 | ETH/USD-1-10 | buy | 5 | 1000 | 1 | TYPE_LIMIT | TIF_GTC | + + When the network moves ahead "5" epochs + Then "referee1" should have vesting account balance of "8000" for asset "USD-1-10" + And "referee2" should have vesting account balance of "8000" for asset "USD-1-10" + And "referee3" should have vesting account balance of "4000" for asset "USD-1-10" + + Scenario: Party funds pool with recurring transfer scoping teams Given the parties submit the following recurring transfers: @@ -111,7 +145,7 @@ Feature: Maker fees paid reward metric calculated correctly for time window | referee3 | ETH/USD-1-10 | buy | 5 | 1000 | 1 | TYPE_LIMIT | TIF_GTC | When the network moves ahead "1" epochs - # NB: the change here is because before we were returning the score for fees paid for 0 so when choosing the top n members we'd be looking at the top 2 scores out of the 3 + # NB: the change here is because before we were returning the score for fees paid for 0 so when choosing the top n members we'd be looking at the top 2 scores out of the 3 # so team2 would get a score of 0.6, now they get 0.3, and team1 gets 0.4 so team1 gets 0.4/0.7 and team2 gets 0.3/0.7 Then "referee1" should have vesting account balance of "5714" for asset "USD-1-10" And "referee2" should have vesting account balance of "2142" for asset "USD-1-10" diff --git a/core/integration/steps/table_wrapper.go b/core/integration/steps/table_wrapper.go index 319885bdac..57a591c226 100644 --- a/core/integration/steps/table_wrapper.go +++ b/core/integration/steps/table_wrapper.go @@ -299,6 +299,12 @@ func (r RowWrapper) U32(name string) uint32 { return uint32(value) } +func (r RowWrapper) I32(name string) int32 { + value, err := strconv.ParseInt(r.values[name], 10, 32) + panicW(name, err) + return int32(value) +} + func (r RowWrapper) MustU64Slice(name, sep string) []uint64 { value, err := U64Slice(r.mustColumn(name), sep) panicW(name, err) diff --git a/core/integration/steps/transfers.go b/core/integration/steps/transfers.go index 20293a45fd..909bf9051e 100644 --- a/core/integration/steps/transfers.go +++ b/core/integration/steps/transfers.go @@ -154,7 +154,7 @@ func PartiesSubmitRecurringTransfers( func parseRecurringTransferTable(table *godog.Table) []RowWrapper { return StrictParseTable(table, []string{ "id", "from", "from_account_type", "to", "to_account_type", "asset", "amount", "start_epoch", "end_epoch", "factor", - }, []string{"metric", "metric_asset", "markets", "lock_period", "window_length", "entity_scope", "individual_scope", "teams", "ntop", "staking_requirement", "notional_requirement", "distribution_strategy", "ranks", "cap_reward_fee_multiple", "error"}) + }, []string{"metric", "metric_asset", "markets", "lock_period", "window_length", "entity_scope", "individual_scope", "teams", "ntop", "staking_requirement", "notional_requirement", "distribution_strategy", "ranks", "cap_reward_fee_multiple", "transfer_interval", "error"}) } func rowToRecurringTransfer(r RowWrapper) *types.RecurringTransfer { @@ -192,6 +192,12 @@ func rowToRecurringTransfer(r RowWrapper) *types.RecurringTransfer { windowLength = r.U64("window_length") } + var transferInterval *int32 + if r.HasColumn("transfer_interval") { + interval := r.I32("transfer_interval") + transferInterval = &interval + } + distributionStrategy := proto.DistributionStrategy_DISTRIBUTION_STRATEGY_PRO_RATA var ranks []*proto.Rank if r.HasColumn("distribution_strategy") { @@ -274,7 +280,8 @@ func rowToRecurringTransfer(r RowWrapper) *types.RecurringTransfer { NTopPerformers: ntop, StakingRequirement: stakingRequirement, NotionalTimeWeightedAveragePositionRequirement: notionalRequirement, - RankTable: ranks, + RankTable: ranks, + TransferInterval: transferInterval, } if capRewardFeeMultiple != "" { dispatchStrategy.CapRewardFeeMultiple = &capRewardFeeMultiple