@@ -217,4 +217,101 @@ impl<T: Config> Pallet<T> {
217
217
// 10. Return success.
218
218
Ok ( ( ) )
219
219
}
220
+
221
+ /// Swaps a specified amount of stake for the same `(coldkey, hotkey)` pair from one subnet
222
+ /// (`origin_netuid`) to another (`destination_netuid`).
223
+ ///
224
+ /// # Arguments
225
+ /// * `origin` - The origin of the transaction, which must be signed by the coldkey that owns the hotkey.
226
+ /// * `hotkey` - The hotkey whose stake is being swapped.
227
+ /// * `origin_netuid` - The subnet ID from which stake is removed.
228
+ /// * `destination_netuid` - The subnet ID to which stake is added.
229
+ /// * `alpha_amount` - The amount of stake to swap.
230
+ ///
231
+ /// # Returns
232
+ /// * `DispatchResult` - Indicates success or failure.
233
+ ///
234
+ /// # Errors
235
+ /// This function returns an error if:
236
+ /// * The origin is not signed by the correct coldkey (i.e., not associated with `hotkey`).
237
+ /// * Either the `origin_netuid` or the `destination_netuid` does not exist.
238
+ /// * The specified `hotkey` does not exist.
239
+ /// * The `(coldkey, hotkey, origin_netuid)` does not have enough stake (`alpha_amount`).
240
+ /// * The unstaked amount is below `DefaultMinStake`.
241
+ ///
242
+ /// # Events
243
+ /// Emits a `StakeSwapped` event upon successful completion.
244
+ pub fn do_swap_stake (
245
+ origin : T :: RuntimeOrigin ,
246
+ hotkey : T :: AccountId ,
247
+ origin_netuid : u16 ,
248
+ destination_netuid : u16 ,
249
+ alpha_amount : u64 ,
250
+ ) -> dispatch:: DispatchResult {
251
+ // 1. Ensure the extrinsic is signed by the coldkey.
252
+ let coldkey = ensure_signed ( origin) ?;
253
+
254
+ // 2. Check that both subnets exist.
255
+ ensure ! (
256
+ Self :: if_subnet_exist( origin_netuid) ,
257
+ Error :: <T >:: SubnetNotExists
258
+ ) ;
259
+ ensure ! (
260
+ Self :: if_subnet_exist( destination_netuid) ,
261
+ Error :: <T >:: SubnetNotExists
262
+ ) ;
263
+
264
+ // 3. Check that the hotkey exists.
265
+ ensure ! (
266
+ Self :: hotkey_account_exists( & hotkey) ,
267
+ Error :: <T >:: HotKeyAccountNotExists
268
+ ) ;
269
+
270
+ // 4. Ensure this coldkey actually owns the hotkey.
271
+ ensure ! (
272
+ Self :: coldkey_owns_hotkey( & coldkey, & hotkey) ,
273
+ Error :: <T >:: NonAssociatedColdKey
274
+ ) ;
275
+
276
+ // 5. Ensure there is enough stake in the origin subnet.
277
+ let origin_alpha =
278
+ Self :: get_stake_for_hotkey_and_coldkey_on_subnet ( & hotkey, & coldkey, origin_netuid) ;
279
+ ensure ! (
280
+ alpha_amount <= origin_alpha,
281
+ Error :: <T >:: NotEnoughStakeToWithdraw
282
+ ) ;
283
+
284
+ // 6. Unstake from the origin subnet, returning TAO (or a 1:1 equivalent).
285
+ let tao_unstaked =
286
+ Self :: unstake_from_subnet ( & hotkey, & coldkey, origin_netuid, alpha_amount) ;
287
+
288
+ // 7. Check that the unstaked amount is above the minimum stake threshold.
289
+ ensure ! (
290
+ tao_unstaked >= DefaultMinStake :: <T >:: get( ) ,
291
+ Error :: <T >:: AmountTooLow
292
+ ) ;
293
+
294
+ // 8. Stake the unstaked amount into the destination subnet, using the same coldkey/hotkey.
295
+ Self :: stake_into_subnet ( & hotkey, & coldkey, destination_netuid, tao_unstaked) ;
296
+
297
+ // 9. Emit an event for logging.
298
+ log:: info!(
299
+ "StakeSwapped(coldkey: {:?}, hotkey: {:?}, origin_netuid: {:?}, destination_netuid: {:?}, amount: {:?})" ,
300
+ coldkey,
301
+ hotkey,
302
+ origin_netuid,
303
+ destination_netuid,
304
+ tao_unstaked
305
+ ) ;
306
+ Self :: deposit_event ( Event :: StakeSwapped (
307
+ coldkey,
308
+ hotkey,
309
+ origin_netuid,
310
+ destination_netuid,
311
+ tao_unstaked,
312
+ ) ) ;
313
+
314
+ // 10. Return success.
315
+ Ok ( ( ) )
316
+ }
220
317
}
0 commit comments