Skip to content

Commit 215d15a

Browse files
committed
* Check from/to aren't the same when retargeting
* Performance: move non-db checks to top when retargeting * Lots more tests * Fix a bug where we weren't setting the staking type on a retarget * Remove staking type from StakingAccountDetails * Fix broken tests from last commit
1 parent 207f5bd commit 215d15a

File tree

3 files changed

+188
-58
lines changed

3 files changed

+188
-58
lines changed

e2e/capacity/change_staking_target.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import { firstValueFrom } from "rxjs";
1414
import { MessageSourceId} from "@frequency-chain/api-augment/interfaces";
1515

16-
describe.only("change_staking_target tests", () => {
16+
describe("change_staking_target tests", () => {
1717
const tokenMinStake: bigint = 1n * CENTS;
1818
const capacityMin: bigint = tokenMinStake / 50n;
1919

pallets/capacity/src/tests/change_staking_target_tests.rs

Lines changed: 186 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,72 +13,193 @@ use common_primitives::{
1313
use frame_support::{assert_noop, assert_ok, traits::Get};
1414

1515
// staker is unused unless amount > 0
16-
fn setup_provider(staker: &u64, target: &MessageSourceId, amount: &u64) {
16+
fn setup_provider(staker: &u64, target: &MessageSourceId, amount: &u64, staking_type: StakingType) {
1717
let provider_name = String::from("Cst-") + target.to_string().as_str();
1818
register_provider(*target, provider_name);
1919
if amount.gt(&0u64) {
2020
assert_ok!(Capacity::stake(
2121
RuntimeOrigin::signed(staker.clone()),
2222
*target,
2323
*amount,
24-
ProviderBoost
24+
staking_type.clone()
2525
));
26+
let target = Capacity::get_target_for(staker, target).unwrap();
27+
assert_eq!(target.amount, *amount);
28+
assert_eq!(target.staking_type, staking_type);
2629
}
2730
}
2831

2932
type TestCapacityDetails = CapacityDetails<BalanceOf<Test>, u32>;
3033
type TestTargetDetails = StakingTargetDetails<Test>;
3134

35+
fn assert_capacity_details(
36+
msa_id: MessageSourceId,
37+
remaining_capacity: u64,
38+
total_tokens_staked: u64,
39+
total_capacity_issued: u64,
40+
) {
41+
let expected_from_details: TestCapacityDetails = CapacityDetails {
42+
remaining_capacity,
43+
total_tokens_staked,
44+
total_capacity_issued,
45+
last_replenished_epoch: 0,
46+
};
47+
let from_capacity_details: TestCapacityDetails = Capacity::get_capacity_for(msa_id).unwrap();
48+
assert_eq!(from_capacity_details, expected_from_details);
49+
}
50+
51+
fn assert_target_details(
52+
staker: u64,
53+
msa_id: MessageSourceId,
54+
amount: u64,
55+
capacity: u64,
56+
staking_type: StakingType,
57+
) {
58+
let expected_from_target_details: TestTargetDetails =
59+
StakingTargetDetails { amount, capacity, staking_type };
60+
let from_target_details = Capacity::get_target_for(staker, msa_id).unwrap();
61+
assert_eq!(from_target_details, expected_from_target_details);
62+
}
3263
#[test]
3364
fn do_retarget_happy_path() {
3465
new_test_ext().execute_with(|| {
35-
let staker = 200u64;
66+
let staker = 10_000;
3667
let from_msa: MessageSourceId = 1;
37-
let from_amount = 20u64;
38-
let to_amount = from_amount / 2;
68+
let from_amount = 600u64;
69+
let to_amount = 300u64;
3970
let to_msa: MessageSourceId = 2;
40-
setup_provider(&staker, &from_msa, &from_amount);
41-
setup_provider(&staker, &to_msa, &to_amount);
71+
let staking_type = ProviderBoost;
72+
setup_provider(&staker, &from_msa, &from_amount, staking_type.clone());
73+
setup_provider(&staker, &to_msa, &to_amount, staking_type.clone());
4274

4375
// retarget half the stake to to_msa
44-
assert_ok!(Capacity::do_retarget(&staker, &from_msa, &to_msa, &to_amount));
76+
assert_ok!(Capacity::do_retarget(&staker, &from_msa, &to_msa, &to_amount, &staking_type));
4577

4678
// expect from stake amounts to be halved
47-
let expected_from_details: TestCapacityDetails = CapacityDetails {
48-
remaining_capacity: 1,
49-
total_tokens_staked: 10,
50-
total_capacity_issued: 1,
51-
last_replenished_epoch: 0,
52-
};
53-
let from_capacity_details: TestCapacityDetails =
54-
Capacity::get_capacity_for(from_msa).unwrap();
55-
assert_eq!(from_capacity_details, expected_from_details);
79+
assert_capacity_details(from_msa, 1, 300, 1);
5680

5781
// expect to stake amounts to be increased by the retarget amount
58-
let expected_to_details: TestCapacityDetails = CapacityDetails {
59-
remaining_capacity: 2,
60-
total_tokens_staked: 20,
61-
total_capacity_issued: 2,
62-
last_replenished_epoch: 0,
63-
};
64-
let to_capacity_details = Capacity::get_capacity_for(to_msa).unwrap();
65-
assert_eq!(to_capacity_details, expected_to_details);
82+
assert_capacity_details(to_msa, 3, 600, 3);
6683

67-
let expected_from_target_details: TestTargetDetails = StakingTargetDetails {
68-
amount: 10,
69-
capacity: 1,
70-
staking_type: StakingType::MaximumCapacity,
71-
};
72-
let from_target_details = Capacity::get_target_for(staker, from_msa).unwrap();
73-
assert_eq!(from_target_details, expected_from_target_details);
84+
assert_target_details(staker, from_msa, 300, 1, staking_type.clone());
7485

75-
let expected_to_target_details: TestTargetDetails = StakingTargetDetails {
76-
amount: 20,
77-
capacity: 2,
78-
staking_type: StakingType::MaximumCapacity,
79-
};
80-
let to_target_details = Capacity::get_target_for(staker, to_msa).unwrap();
81-
assert_eq!(to_target_details, expected_to_target_details);
86+
assert_target_details(staker, to_msa, 600, 3, staking_type.clone());
87+
})
88+
}
89+
90+
#[test]
91+
fn do_retarget_flip_flop() {
92+
new_test_ext().execute_with(|| {
93+
let staker = 10_000;
94+
let from_msa: MessageSourceId = 1;
95+
let from_amount = 600u64;
96+
let to_amount = 300u64;
97+
let to_msa: MessageSourceId = 2;
98+
setup_provider(&staker, &from_msa, &from_amount, ProviderBoost);
99+
setup_provider(&staker, &to_msa, &to_amount, ProviderBoost);
100+
101+
for i in 0..4 {
102+
if i % 2 == 0 {
103+
assert_ok!(Capacity::do_retarget(
104+
&staker,
105+
&from_msa,
106+
&to_msa,
107+
&to_amount,
108+
&ProviderBoost
109+
));
110+
} else {
111+
assert_ok!(Capacity::do_retarget(
112+
&staker,
113+
&to_msa,
114+
&from_msa,
115+
&to_amount,
116+
&ProviderBoost
117+
));
118+
}
119+
}
120+
assert_capacity_details(from_msa, 3, 600, 3);
121+
assert_capacity_details(to_msa, 1, 300, 1);
122+
})
123+
}
124+
125+
#[test]
126+
// check that no capacity is minted or burned just by retargeting.
127+
fn check_retarget_rounding_errors() {
128+
new_test_ext().execute_with(|| {
129+
let staker = 10_000;
130+
let from_msa: MessageSourceId = 1;
131+
let from_amount = 666u64;
132+
let to_amount = 301u64;
133+
let to_msa: MessageSourceId = 2;
134+
135+
setup_provider(&staker, &from_msa, &from_amount, ProviderBoost);
136+
setup_provider(&staker, &to_msa, &to_amount, ProviderBoost);
137+
assert_capacity_details(from_msa, 3, 666, 3);
138+
assert_capacity_details(to_msa, 1, 301, 1);
139+
// 666+301= 967, 3+1=4
140+
141+
assert_ok!(Capacity::do_retarget(&staker, &from_msa, &to_msa, &301u64, &ProviderBoost));
142+
assert_capacity_details(to_msa, 3, 602, 3);
143+
assert_capacity_details(from_msa, 1, 365, 1);
144+
// 602+365 = 967, 3+1 = 4
145+
146+
assert_ok!(Capacity::do_retarget(&staker, &to_msa, &from_msa, &151u64, &ProviderBoost));
147+
assert_capacity_details(to_msa, 2, 451, 2);
148+
assert_capacity_details(from_msa, 2, 516, 2);
149+
// 451+516 = 967, 2+2 = 4
150+
})
151+
}
152+
153+
fn assert_total_capacity(msas: Vec<MessageSourceId>, total: u64) {
154+
let sum = msas
155+
.into_iter()
156+
.map(|a| {
157+
let capacity_details: TestCapacityDetails = Capacity::get_capacity_for(a).unwrap();
158+
capacity_details.total_capacity_issued
159+
})
160+
.fold(0, |a, b| a + b);
161+
assert_eq!(total, sum);
162+
}
163+
#[test]
164+
fn check_retarget_multiple_stakers() {
165+
new_test_ext().execute_with(|| {
166+
let staker_10k = 10_000;
167+
let staker_600 = 600u64;
168+
let staker_500 = 500u64;
169+
let staker_400 = 400u64;
170+
171+
let from_msa: MessageSourceId = 1;
172+
let to_msa: MessageSourceId = 2;
173+
let amt1 = 192u64;
174+
let amt2 = 313u64;
175+
176+
setup_provider(&staker_10k, &from_msa, &647u64, ProviderBoost);
177+
setup_provider(&staker_500, &to_msa, &293u64, ProviderBoost);
178+
assert_ok!(Capacity::stake(
179+
RuntimeOrigin::signed(staker_600.clone()),
180+
from_msa,
181+
479u64,
182+
MaximumCapacity
183+
));
184+
assert_ok!(Capacity::stake(
185+
RuntimeOrigin::signed(staker_400.clone()),
186+
to_msa,
187+
211u64,
188+
MaximumCapacity
189+
));
190+
191+
// 647 * .1 * .05 = 3 (rounded down)
192+
// 293 * .1 * .05 = 1 (rounded down)
193+
// 479 * .1 = 48 (rounded up)
194+
// 211 * .1 = 21 (rounded down)
195+
// total capacity should be 73
196+
assert_total_capacity(vec![from_msa, to_msa], 73);
197+
198+
assert_ok!(Capacity::do_retarget(&staker_10k, &from_msa, &to_msa, &amt2, &ProviderBoost));
199+
assert_ok!(Capacity::do_retarget(&staker_600, &from_msa, &to_msa, &amt1, &MaximumCapacity));
200+
assert_ok!(Capacity::do_retarget(&staker_500, &to_msa, &from_msa, &amt1, &ProviderBoost));
201+
assert_ok!(Capacity::do_retarget(&staker_400, &to_msa, &from_msa, &amt1, &MaximumCapacity));
202+
assert_total_capacity(vec![from_msa, to_msa], 73);
82203
})
83204
}
84205

@@ -89,8 +210,8 @@ fn do_retarget_deletes_staking_target_details_if_zero_balance() {
89210
let from_msa: MessageSourceId = 1;
90211
let to_msa: MessageSourceId = 2;
91212
let amount = 10u64;
92-
setup_provider(&staker, &from_msa, &amount);
93-
setup_provider(&staker, &to_msa, &amount);
213+
setup_provider(&staker, &from_msa, &amount, MaximumCapacity);
214+
setup_provider(&staker, &to_msa, &amount, MaximumCapacity);
94215

95216
// stake additional to provider from another Msa, doesn't matter which type.
96217
// total staked to from_msa is now 22u64.
@@ -101,7 +222,7 @@ fn do_retarget_deletes_staking_target_details_if_zero_balance() {
101222
MaximumCapacity
102223
));
103224

104-
assert_ok!(Capacity::do_retarget(&staker, &from_msa, &to_msa, &amount));
225+
assert_ok!(Capacity::do_retarget(&staker, &from_msa, &to_msa, &amount, &MaximumCapacity));
105226

106227
let expected_from_details: TestCapacityDetails = CapacityDetails {
107228
remaining_capacity: 1,
@@ -145,8 +266,8 @@ fn change_staking_starget_emits_event_on_success() {
145266
let from_amount = 20u64;
146267
let to_amount = from_amount / 2;
147268
let to_msa: MessageSourceId = 2;
148-
setup_provider(&staker, &from_msa, &from_amount);
149-
setup_provider(&staker, &to_msa, &to_amount);
269+
setup_provider(&staker, &from_msa, &from_amount, ProviderBoost);
270+
setup_provider(&staker, &to_msa, &to_amount, ProviderBoost);
150271

151272
assert_ok!(Capacity::change_staking_target(
152273
RuntimeOrigin::signed(staker),
@@ -172,8 +293,8 @@ fn change_staking_target_errors_if_too_many_changes_before_thaw() {
172293

173294
let max_chunks: u32 = <Test as Config>::MaxUnlockingChunks::get();
174295
let staking_amount = ((max_chunks + 2u32) * 10u32) as u64;
175-
setup_provider(&staker, &from_msa, &staking_amount);
176-
setup_provider(&staker, &to_msa, &10u64);
296+
setup_provider(&staker, &from_msa, &staking_amount, ProviderBoost);
297+
setup_provider(&staker, &to_msa, &10u64, ProviderBoost);
177298

178299
let retarget_amount = 10u64;
179300
for _i in 0..(max_chunks) {
@@ -204,13 +325,12 @@ fn change_staking_target_garbage_collects_thawed_chunks() {
204325
let staking_account = 200u64;
205326
let from_target: MessageSourceId = 3;
206327
let to_target: MessageSourceId = 4;
207-
setup_provider(&staking_account, &from_target, &staked_amount);
208-
setup_provider(&staking_account, &to_target, &staked_amount);
328+
setup_provider(&staking_account, &from_target, &staked_amount, ProviderBoost);
329+
setup_provider(&staking_account, &to_target, &staked_amount, ProviderBoost);
209330

210331
CurrentEraInfo::<Test>::set(RewardEraInfo { era_index: 20, started_at: 100 });
211332
let max_chunks = <Test as Config>::MaxUnlockingChunks::get();
212-
for i in 0..max_chunks {
213-
println!("{:?}", i);
333+
for _i in 0..max_chunks {
214334
assert_ok!(Capacity::change_staking_target(
215335
RuntimeOrigin::signed(staking_account),
216336
from_target,
@@ -240,7 +360,6 @@ fn change_staking_target_test_parametric_validity() {
240360
active: 20,
241361
total: 20,
242362
unlocking: Default::default(),
243-
staking_type: ProviderBoost,
244363
last_rewards_claimed_at: None,
245364
stake_change_unlocking: Default::default(),
246365
},
@@ -250,9 +369,9 @@ fn change_staking_target_test_parametric_validity() {
250369
let to_target_not_provider: MessageSourceId = 2;
251370
let from_target: MessageSourceId = 3;
252371
let to_target: MessageSourceId = 4;
253-
setup_provider(&from_account, &from_target_not_staked, &0u64);
254-
setup_provider(&from_account, &from_target, &staked_amount);
255-
setup_provider(&from_account, &to_target, &staked_amount);
372+
setup_provider(&from_account, &from_target_not_staked, &0u64, ProviderBoost);
373+
setup_provider(&from_account, &from_target, &staked_amount, ProviderBoost);
374+
setup_provider(&from_account, &to_target, &staked_amount, ProviderBoost);
256375

257376
assert_ok!(Capacity::stake(
258377
RuntimeOrigin::signed(from_account),
@@ -317,6 +436,13 @@ fn change_staking_target_test_parametric_validity() {
317436
retarget_amount: 999,
318437
expected_err: Error::<Test>::InsufficientStakingBalance,
319438
},
439+
TestCase {
440+
from_account,
441+
from_target,
442+
to_target: from_target,
443+
retarget_amount: 999,
444+
expected_err: Error::<Test>::CannotRetargetToSameProvider,
445+
},
320446
];
321447

322448
for tc in test_cases {
@@ -332,3 +458,9 @@ fn change_staking_target_test_parametric_validity() {
332458
}
333459
});
334460
}
461+
462+
#[test]
463+
fn change_staking_target_cannot_switch_staking_type() {
464+
// if you want to switch staking type you must unstake completely and restake regardless of
465+
// whether it is with an existing or new provider.
466+
}

pallets/capacity/src/tests/rewards_provider_tests.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::{
55
};
66
use frame_support::assert_err;
77

8-
use common_primitives::capacity::StakingType::MaximumCapacity;
98
use sp_core::H256;
109

1110
#[test]
@@ -21,7 +20,6 @@ fn test_staking_reward_total_happy_path() {
2120
active: 1,
2221
total: 1,
2322
unlocking: Default::default(),
24-
staking_type: MaximumCapacity,
2523
last_rewards_claimed_at: None,
2624
stake_change_unlocking: Default::default(),
2725
},
@@ -52,7 +50,7 @@ fn test_reward_pool_size_happy_path() {
5250
TestCase { total_staked: 4, expected_reward_pool: 0 },
5351
TestCase { total_staked: 10, expected_reward_pool: 1 },
5452
TestCase { total_staked: 3333333, expected_reward_pool: 333333 },
55-
TestCase { total_staked: 66666666, expected_reward_pool: 666666 },
53+
TestCase { total_staked: 66666666, expected_reward_pool: 6666666 },
5654
];
5755
let era = 20u32;
5856
CurrentEraInfo::<Test>::set(RewardEraInfo { era_index: era, started_at: 200u32 });

0 commit comments

Comments
 (0)