@@ -13,72 +13,193 @@ use common_primitives::{
13
13
use frame_support:: { assert_noop, assert_ok, traits:: Get } ;
14
14
15
15
// 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 ) {
17
17
let provider_name = String :: from ( "Cst-" ) + target. to_string ( ) . as_str ( ) ;
18
18
register_provider ( * target, provider_name) ;
19
19
if amount. gt ( & 0u64 ) {
20
20
assert_ok ! ( Capacity :: stake(
21
21
RuntimeOrigin :: signed( staker. clone( ) ) ,
22
22
* target,
23
23
* amount,
24
- ProviderBoost
24
+ staking_type . clone ( )
25
25
) ) ;
26
+ let target = Capacity :: get_target_for ( staker, target) . unwrap ( ) ;
27
+ assert_eq ! ( target. amount, * amount) ;
28
+ assert_eq ! ( target. staking_type, staking_type) ;
26
29
}
27
30
}
28
31
29
32
type TestCapacityDetails = CapacityDetails < BalanceOf < Test > , u32 > ;
30
33
type TestTargetDetails = StakingTargetDetails < Test > ;
31
34
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
+ }
32
63
#[ test]
33
64
fn do_retarget_happy_path ( ) {
34
65
new_test_ext ( ) . execute_with ( || {
35
- let staker = 200u64 ;
66
+ let staker = 10_000 ;
36
67
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 ;
39
70
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 ( ) ) ;
42
74
43
75
// 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 ) ) ;
45
77
46
78
// 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 ) ;
56
80
57
81
// 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 ) ;
66
83
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 ( ) ) ;
74
85
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 ) ;
82
203
} )
83
204
}
84
205
@@ -89,8 +210,8 @@ fn do_retarget_deletes_staking_target_details_if_zero_balance() {
89
210
let from_msa: MessageSourceId = 1 ;
90
211
let to_msa: MessageSourceId = 2 ;
91
212
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 ) ;
94
215
95
216
// stake additional to provider from another Msa, doesn't matter which type.
96
217
// total staked to from_msa is now 22u64.
@@ -101,7 +222,7 @@ fn do_retarget_deletes_staking_target_details_if_zero_balance() {
101
222
MaximumCapacity
102
223
) ) ;
103
224
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 ) ) ;
105
226
106
227
let expected_from_details: TestCapacityDetails = CapacityDetails {
107
228
remaining_capacity : 1 ,
@@ -145,8 +266,8 @@ fn change_staking_starget_emits_event_on_success() {
145
266
let from_amount = 20u64 ;
146
267
let to_amount = from_amount / 2 ;
147
268
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 ) ;
150
271
151
272
assert_ok ! ( Capacity :: change_staking_target(
152
273
RuntimeOrigin :: signed( staker) ,
@@ -172,8 +293,8 @@ fn change_staking_target_errors_if_too_many_changes_before_thaw() {
172
293
173
294
let max_chunks: u32 = <Test as Config >:: MaxUnlockingChunks :: get ( ) ;
174
295
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 ) ;
177
298
178
299
let retarget_amount = 10u64 ;
179
300
for _i in 0 ..( max_chunks) {
@@ -204,13 +325,12 @@ fn change_staking_target_garbage_collects_thawed_chunks() {
204
325
let staking_account = 200u64 ;
205
326
let from_target: MessageSourceId = 3 ;
206
327
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 ) ;
209
330
210
331
CurrentEraInfo :: < Test > :: set ( RewardEraInfo { era_index : 20 , started_at : 100 } ) ;
211
332
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 {
214
334
assert_ok ! ( Capacity :: change_staking_target(
215
335
RuntimeOrigin :: signed( staking_account) ,
216
336
from_target,
@@ -240,7 +360,6 @@ fn change_staking_target_test_parametric_validity() {
240
360
active : 20 ,
241
361
total : 20 ,
242
362
unlocking : Default :: default ( ) ,
243
- staking_type : ProviderBoost ,
244
363
last_rewards_claimed_at : None ,
245
364
stake_change_unlocking : Default :: default ( ) ,
246
365
} ,
@@ -250,9 +369,9 @@ fn change_staking_target_test_parametric_validity() {
250
369
let to_target_not_provider: MessageSourceId = 2 ;
251
370
let from_target: MessageSourceId = 3 ;
252
371
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 ) ;
256
375
257
376
assert_ok ! ( Capacity :: stake(
258
377
RuntimeOrigin :: signed( from_account) ,
@@ -317,6 +436,13 @@ fn change_staking_target_test_parametric_validity() {
317
436
retarget_amount: 999 ,
318
437
expected_err: Error :: <Test >:: InsufficientStakingBalance ,
319
438
} ,
439
+ TestCase {
440
+ from_account,
441
+ from_target,
442
+ to_target: from_target,
443
+ retarget_amount: 999 ,
444
+ expected_err: Error :: <Test >:: CannotRetargetToSameProvider ,
445
+ } ,
320
446
] ;
321
447
322
448
for tc in test_cases {
@@ -332,3 +458,9 @@ fn change_staking_target_test_parametric_validity() {
332
458
}
333
459
} ) ;
334
460
}
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
+ }
0 commit comments