@@ -105,6 +105,117 @@ async fn success() {
105
105
assert_eq ! ( stake_pool. next_withdrawal_fee, None ) ;
106
106
}
107
107
108
+ #[ tokio:: test]
109
+ async fn success_fee_cannot_increase_more_than_once ( ) {
110
+ let ( mut context, stake_pool_accounts, new_withdrawal_fee) = setup ( None ) . await ;
111
+
112
+ let stake_pool = get_account (
113
+ & mut context. banks_client ,
114
+ & stake_pool_accounts. stake_pool . pubkey ( ) ,
115
+ )
116
+ . await ;
117
+ let stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool. data . as_slice ( ) ) . unwrap ( ) ;
118
+ let old_withdrawal_fee = stake_pool. withdrawal_fee ;
119
+
120
+ let transaction = Transaction :: new_signed_with_payer (
121
+ & [ instruction:: set_fee (
122
+ & id ( ) ,
123
+ & stake_pool_accounts. stake_pool . pubkey ( ) ,
124
+ & stake_pool_accounts. manager . pubkey ( ) ,
125
+ FeeType :: Withdrawal ( new_withdrawal_fee) ,
126
+ ) ] ,
127
+ Some ( & context. payer . pubkey ( ) ) ,
128
+ & [ & context. payer , & stake_pool_accounts. manager ] ,
129
+ context. last_blockhash ,
130
+ ) ;
131
+ context
132
+ . banks_client
133
+ . process_transaction ( transaction)
134
+ . await
135
+ . unwrap ( ) ;
136
+
137
+ let stake_pool = get_account (
138
+ & mut context. banks_client ,
139
+ & stake_pool_accounts. stake_pool . pubkey ( ) ,
140
+ )
141
+ . await ;
142
+ let stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool. data . as_slice ( ) ) . unwrap ( ) ;
143
+
144
+ assert_eq ! ( stake_pool. withdrawal_fee, old_withdrawal_fee) ;
145
+ assert_eq ! ( stake_pool. next_withdrawal_fee, Some ( new_withdrawal_fee) ) ;
146
+
147
+ let first_normal_slot = context. genesis_config ( ) . epoch_schedule . first_normal_slot ;
148
+ let slots_per_epoch = context. genesis_config ( ) . epoch_schedule . slots_per_epoch ;
149
+
150
+ context
151
+ . warp_to_slot ( first_normal_slot + slots_per_epoch)
152
+ . unwrap ( ) ;
153
+ stake_pool_accounts
154
+ . update_all (
155
+ & mut context. banks_client ,
156
+ & context. payer ,
157
+ & context. last_blockhash ,
158
+ & [ ] ,
159
+ false ,
160
+ )
161
+ . await ;
162
+
163
+ let stake_pool = get_account (
164
+ & mut context. banks_client ,
165
+ & stake_pool_accounts. stake_pool . pubkey ( ) ,
166
+ )
167
+ . await ;
168
+ let stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool. data . as_slice ( ) ) . unwrap ( ) ;
169
+ assert_eq ! ( stake_pool. withdrawal_fee, new_withdrawal_fee) ;
170
+ assert_eq ! ( stake_pool. next_withdrawal_fee, None ) ;
171
+
172
+ // try setting to the old fee in the same epoch
173
+ let transaction = Transaction :: new_signed_with_payer (
174
+ & [ instruction:: set_fee (
175
+ & id ( ) ,
176
+ & stake_pool_accounts. stake_pool . pubkey ( ) ,
177
+ & stake_pool_accounts. manager . pubkey ( ) ,
178
+ FeeType :: Withdrawal ( old_withdrawal_fee) ,
179
+ ) ] ,
180
+ Some ( & context. payer . pubkey ( ) ) ,
181
+ & [ & context. payer , & stake_pool_accounts. manager ] ,
182
+ context. last_blockhash ,
183
+ ) ;
184
+ context
185
+ . banks_client
186
+ . process_transaction ( transaction)
187
+ . await
188
+ . unwrap ( ) ;
189
+
190
+ let stake_pool = get_account (
191
+ & mut context. banks_client ,
192
+ & stake_pool_accounts. stake_pool . pubkey ( ) ,
193
+ )
194
+ . await ;
195
+ let stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool. data . as_slice ( ) ) . unwrap ( ) ;
196
+ assert_eq ! ( stake_pool. withdrawal_fee, new_withdrawal_fee) ;
197
+ assert_eq ! ( stake_pool. next_withdrawal_fee, Some ( old_withdrawal_fee) ) ;
198
+
199
+ let error = stake_pool_accounts
200
+ . update_stake_pool_balance (
201
+ & mut context. banks_client ,
202
+ & context. payer ,
203
+ & context. last_blockhash ,
204
+ )
205
+ . await ;
206
+ assert ! ( error. is_none( ) ) ;
207
+
208
+ // Check that nothing has changed after updating the stake pool
209
+ let stake_pool = get_account (
210
+ & mut context. banks_client ,
211
+ & stake_pool_accounts. stake_pool . pubkey ( ) ,
212
+ )
213
+ . await ;
214
+ let stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool. data . as_slice ( ) ) . unwrap ( ) ;
215
+ assert_eq ! ( stake_pool. withdrawal_fee, new_withdrawal_fee) ;
216
+ assert_eq ! ( stake_pool. next_withdrawal_fee, Some ( old_withdrawal_fee) ) ;
217
+ }
218
+
108
219
#[ tokio:: test]
109
220
async fn success_increase_fee_from_0 ( ) {
110
221
let ( mut context, stake_pool_accounts, _) = setup ( Some ( Fee {
0 commit comments