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