Skip to content

Commit 278f546

Browse files
committed
feat: fix and add more tests
1 parent 10e3bef commit 278f546

File tree

3 files changed

+167
-23
lines changed

3 files changed

+167
-23
lines changed

core/vesting/engine.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ type PartyRewards struct {
6868
}
6969

7070
type multiplierAndQuantBalance struct {
71-
multiplier num.Decimal
72-
quantumBalance num.Decimal
71+
Multiplier num.Decimal
72+
QuantumBalance num.Decimal
7373
}
7474

7575
type Engine struct {
@@ -202,32 +202,32 @@ func (e *Engine) getSummedBonusMultiplier(keys []string) multiplierAndQuantBalan
202202
continue
203203
}
204204

205-
summed.quantumBalance = summed.quantumBalance.Add(quantumBalanceForKey)
205+
summed.QuantumBalance = summed.QuantumBalance.Add(quantumBalanceForKey)
206206
}
207207

208-
summed.multiplier = e.rewardBonusMultiplier(summed.quantumBalance)
208+
summed.Multiplier = e.rewardBonusMultiplier(summed.QuantumBalance)
209209

210210
return summed
211211
}
212212

213213
// GetRewardBonusMultiplier returns the reward bonus multiplier and quantum balance sum for a party and it's derived keys.
214214
func (e *Engine) GetRewardBonusMultiplier(party string) (num.Decimal, num.Decimal) {
215-
partyID, derivedKeys := e.parties.RelatedKeys(party)
216-
217215
owner := party
216+
217+
partyID, derivedKeys := e.parties.RelatedKeys(party)
218218
if partyID != nil {
219219
owner = partyID.String()
220220
}
221221

222222
if cached, ok := e.summedRewardBonusMultiplierCache[owner]; ok {
223-
return cached.quantumBalance, cached.multiplier
223+
return cached.QuantumBalance, cached.Multiplier
224224
}
225225

226226
summed := e.getSummedBonusMultiplier(append(derivedKeys, owner))
227227

228228
e.summedRewardBonusMultiplierCache[owner] = summed
229229

230-
return summed.quantumBalance, summed.multiplier
230+
return summed.QuantumBalance, summed.Multiplier
231231
}
232232

233233
// GetSingleAndSummedRewardBonusMultipliers returns a single and summed reward bonus multipliers and quantum balances for a party.
@@ -238,13 +238,15 @@ func (e *Engine) GetSingleAndSummedRewardBonusMultipliers(party string) (
238238
single multiplierAndQuantBalance,
239239
summed multiplierAndQuantBalance,
240240
) {
241+
owner := party
242+
241243
partyID, derivedKeys := e.parties.RelatedKeys(party)
244+
if partyID != nil {
245+
owner = partyID.String()
246+
}
242247

243248
single = e.getSummedBonusMultiplier([]string{party})
244249

245-
// calculate with derived keys. First add the owner's quantum balance.
246-
owner := partyID.String()
247-
248250
if cached, ok := e.summedRewardBonusMultiplierCache[owner]; ok {
249251
return single, cached
250252
}
@@ -495,14 +497,14 @@ func (e *Engine) broadcastVestingStatsUpdate(ctx context.Context, seq uint64) {
495497
for _, party := range parties {
496498
single, summed := e.GetSingleAndSummedRewardBonusMultipliers(party)
497499
// To avoid excessively large decimals.
498-
single.quantumBalance.Round(2)
499-
summed.quantumBalance.Round(2)
500+
single.QuantumBalance.Round(2)
501+
summed.QuantumBalance.Round(2)
500502
evt.Stats = append(evt.Stats, &eventspb.PartyVestingStats{
501503
PartyId: party,
502-
RewardBonusMultiplier: single.multiplier.String(),
503-
QuantumBalance: single.quantumBalance.String(),
504-
SummedRewardBonusMultiplier: summed.multiplier.String(),
505-
SummedQuantumBalance: summed.quantumBalance.String(),
504+
RewardBonusMultiplier: single.Multiplier.String(),
505+
QuantumBalance: single.QuantumBalance.String(),
506+
SummedRewardBonusMultiplier: summed.Multiplier.String(),
507+
SummedQuantumBalance: summed.QuantumBalance.String(),
506508
})
507509
}
508510

core/vesting/engine_test.go

Lines changed: 136 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,21 +1069,21 @@ func TestDistributeWithRelatedKeys(t *testing.T) {
10691069
Stats: []*eventspb.PartyVestingStats{
10701070
{
10711071
PartyId: derivedKeys[0],
1072-
RewardBonusMultiplier: "2",
1072+
RewardBonusMultiplier: "1",
10731073
QuantumBalance: "145",
10741074
SummedRewardBonusMultiplier: "3",
10751075
SummedQuantumBalance: "825",
10761076
},
10771077
{
10781078
PartyId: derivedKeys[1],
1079-
RewardBonusMultiplier: "2",
1079+
RewardBonusMultiplier: "1",
10801080
QuantumBalance: "145",
10811081
SummedRewardBonusMultiplier: "3",
10821082
SummedQuantumBalance: "825",
10831083
},
10841084
{
10851085
PartyId: derivedKeys[2],
1086-
RewardBonusMultiplier: "2",
1086+
RewardBonusMultiplier: "1",
10871087
QuantumBalance: "145",
10881088
SummedRewardBonusMultiplier: "3",
10891089
SummedQuantumBalance: "825",
@@ -1166,12 +1166,33 @@ func TestDistributeWithRelatedKeys(t *testing.T) {
11661166
assert.Equal(t, eventspb.VestingStatsUpdated{
11671167
AtEpoch: epochSeq,
11681168
Stats: []*eventspb.PartyVestingStats{
1169+
{
1170+
PartyId: derivedKeys[0],
1171+
RewardBonusMultiplier: "1",
1172+
QuantumBalance: "150",
1173+
SummedRewardBonusMultiplier: "3",
1174+
SummedQuantumBalance: "850",
1175+
},
1176+
{
1177+
PartyId: derivedKeys[1],
1178+
RewardBonusMultiplier: "1",
1179+
QuantumBalance: "150",
1180+
SummedRewardBonusMultiplier: "3",
1181+
SummedQuantumBalance: "850",
1182+
},
1183+
{
1184+
PartyId: derivedKeys[2],
1185+
RewardBonusMultiplier: "1",
1186+
QuantumBalance: "150",
1187+
SummedRewardBonusMultiplier: "3",
1188+
SummedQuantumBalance: "850",
1189+
},
11691190
{
11701191
PartyId: party,
11711192
RewardBonusMultiplier: "2",
11721193
QuantumBalance: "400",
1173-
SummedRewardBonusMultiplier: "2",
1174-
SummedQuantumBalance: "400",
1194+
SummedRewardBonusMultiplier: "3",
1195+
SummedQuantumBalance: "850",
11751196
},
11761197
},
11771198
}, e.Proto())
@@ -1219,6 +1240,116 @@ func TestDistributeWithRelatedKeys(t *testing.T) {
12191240
})
12201241
}
12211242

1243+
func TestGetRewardBonusMultiplier(t *testing.T) {
1244+
v := getTestEngine(t)
1245+
1246+
ctx := context.Background()
1247+
1248+
// distribute 90% as the base rate,
1249+
// so first we distribute some, then we get under the minimum value, and all the rest
1250+
// is distributed
1251+
require.NoError(t, v.OnRewardVestingBaseRateUpdate(ctx, num.MustDecimalFromString("0.9")))
1252+
// this is multiplied by the quantum, so it will make it 100% of the quantum
1253+
require.NoError(t, v.OnRewardVestingMinimumTransferUpdate(ctx, num.MustDecimalFromString("1")))
1254+
1255+
require.NoError(t, v.OnBenefitTiersUpdate(ctx, &vegapb.VestingBenefitTiers{
1256+
Tiers: []*vegapb.VestingBenefitTier{
1257+
{
1258+
MinimumQuantumBalance: "200",
1259+
RewardMultiplier: "1",
1260+
},
1261+
{
1262+
MinimumQuantumBalance: "500",
1263+
RewardMultiplier: "2",
1264+
},
1265+
{
1266+
MinimumQuantumBalance: "1200",
1267+
RewardMultiplier: "3",
1268+
},
1269+
},
1270+
}))
1271+
1272+
party := "party1"
1273+
partyID := types.PartyID(party)
1274+
vegaAsset := "VEGA"
1275+
derivedKeys := []string{"derived1", "derived2", "derived3", "derived4"}
1276+
1277+
v.parties.EXPECT().RelatedKeys(party).Return(&partyID, derivedKeys).AnyTimes()
1278+
1279+
v.col.InitVestedBalance(party, vegaAsset, num.NewUint(500))
1280+
1281+
for _, key := range derivedKeys {
1282+
v.col.InitVestedBalance(key, vegaAsset, num.NewUint(250))
1283+
v.parties.EXPECT().RelatedKeys(key).Return(&partyID, derivedKeys).AnyTimes()
1284+
}
1285+
1286+
for _, key := range append(derivedKeys, party) {
1287+
balance, multiplier := v.GetRewardBonusMultiplier(key)
1288+
require.Equal(t, num.DecimalFromInt64(1500), balance)
1289+
require.Equal(t, num.DecimalFromInt64(3), multiplier)
1290+
}
1291+
1292+
// check that we only called the GetVestingQuantumBalance once for each key
1293+
// later calls should be cached
1294+
require.Equal(t, 5, v.col.GetVestingQuantumBalanceCallCount())
1295+
1296+
v.col.ResetVestingQuantumBalanceCallCount()
1297+
1298+
single, summed := v.GetSingleAndSummedRewardBonusMultipliers(party)
1299+
require.Equal(t, num.DecimalFromInt64(500), single.QuantumBalance)
1300+
require.Equal(t, num.DecimalFromInt64(2), single.Multiplier)
1301+
require.Equal(t, num.DecimalFromInt64(1500), summed.QuantumBalance)
1302+
require.Equal(t, num.DecimalFromInt64(3), summed.Multiplier)
1303+
1304+
for _, key := range derivedKeys {
1305+
single, summed := v.GetSingleAndSummedRewardBonusMultipliers(key)
1306+
require.Equal(t, num.DecimalFromInt64(250), single.QuantumBalance)
1307+
require.Equal(t, num.DecimalFromInt64(1), single.Multiplier)
1308+
require.Equal(t, num.DecimalFromInt64(1500), summed.QuantumBalance)
1309+
require.Equal(t, num.DecimalFromInt64(3), summed.Multiplier)
1310+
}
1311+
1312+
// here we check that we just called 5 more times to re-calculate single values
1313+
// summed should be cached
1314+
require.Equal(t, 5, v.col.GetVestingQuantumBalanceCallCount())
1315+
1316+
v.broker.EXPECT().Send(gomock.Any()).AnyTimes()
1317+
1318+
// now we simulate the end of the epoch
1319+
// it will reset cache for reward bonus multipliers
1320+
v.OnEpochEvent(ctx, types.Epoch{
1321+
Action: vegapb.EpochAction_EPOCH_ACTION_END,
1322+
Seq: 1,
1323+
})
1324+
1325+
v.col.ResetVestingQuantumBalanceCallCount()
1326+
1327+
for _, key := range append(derivedKeys, party) {
1328+
balance, multiplier := v.GetRewardBonusMultiplier(key)
1329+
require.Equal(t, num.DecimalFromInt64(1500), balance)
1330+
require.Equal(t, num.DecimalFromInt64(3), multiplier)
1331+
}
1332+
1333+
// now it's called 5 times again because the cache gets reset at the end of the epoch
1334+
require.Equal(t, 5, v.col.GetVestingQuantumBalanceCallCount())
1335+
1336+
v.OnEpochEvent(ctx, types.Epoch{
1337+
Action: vegapb.EpochAction_EPOCH_ACTION_END,
1338+
Seq: 1,
1339+
})
1340+
1341+
v.col.ResetVestingQuantumBalanceCallCount()
1342+
1343+
for _, key := range append(derivedKeys, party) {
1344+
balance, multiplier := v.GetRewardBonusMultiplier(key)
1345+
require.Equal(t, num.DecimalFromInt64(1500), balance)
1346+
require.Equal(t, num.DecimalFromInt64(3), multiplier)
1347+
}
1348+
1349+
// now it's called 5 times again because the cache gets reset at the end of the epoch
1350+
require.Equal(t, 5, v.col.GetVestingQuantumBalanceCallCount())
1351+
}
1352+
12221353
// LedgerMovements is the result of a mock, so it doesn't really make sense to
12231354
// verify data consistency.
12241355
func expectLedgerMovements(t *testing.T, v *testEngine) {

core/vesting/helper_for_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ func newEngine(t *testing.T) *testSnapshotEngine {
108108
}
109109

110110
type collateralMock struct {
111-
vestedAccountAmount map[string]map[string]*num.Uint
111+
vestedAccountAmount map[string]map[string]*num.Uint
112+
vestingQuantumBalanceCallCount int
112113
}
113114

114115
func (c *collateralMock) InitVestedBalance(party, asset string, balance *num.Uint) {
@@ -156,9 +157,19 @@ func (c *collateralMock) GetAllVestingQuantumBalance(party string) num.Decimal {
156157
balance = balance.Add(num.DecimalFromUint(n))
157158
}
158159

160+
c.vestingQuantumBalanceCallCount += 1
161+
159162
return balance
160163
}
161164

165+
func (c *collateralMock) ResetVestingQuantumBalanceCallCount() {
166+
c.vestingQuantumBalanceCallCount = 0
167+
}
168+
169+
func (c *collateralMock) GetVestingQuantumBalanceCallCount() int {
170+
return c.vestingQuantumBalanceCallCount
171+
}
172+
162173
func newCollateralMock(t *testing.T) *collateralMock {
163174
t.Helper()
164175

0 commit comments

Comments
 (0)