@@ -71,6 +71,10 @@ fn dissolve_refunds_full_lock_cost_when_no_emission() {
7171 let hot = U256 :: from ( 4 ) ;
7272 let net = add_dynamic_network ( & hot, & cold) ;
7373
74+ // Mark this subnet as *legacy* so owner refund path is enabled.
75+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( net) ;
76+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at. saturating_add ( 1 ) ) ;
77+
7478 let lock: TaoCurrency = TaoCurrency :: from ( 1_000_000 ) ;
7579 SubtensorModule :: set_subnet_locked_balance ( net, lock) ;
7680 SubnetTAO :: < Test > :: insert ( net, TaoCurrency :: from ( 0 ) ) ;
@@ -126,6 +130,10 @@ fn dissolve_two_stakers_pro_rata_distribution() {
126130 let oh = U256 :: from ( 51 ) ;
127131 let net = add_dynamic_network ( & oh, & oc) ;
128132
133+ // Mark this subnet as *legacy* so owner refund path is enabled.
134+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( net) ;
135+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at. saturating_add ( 1 ) ) ;
136+
129137 let ( s1_hot, s1_cold, a1) = ( U256 :: from ( 201 ) , U256 :: from ( 301 ) , 300u128 ) ;
130138 let ( s2_hot, s2_cold, a2) = ( U256 :: from ( 202 ) , U256 :: from ( 302 ) , 700u128 ) ;
131139
@@ -134,7 +142,7 @@ fn dissolve_two_stakers_pro_rata_distribution() {
134142
135143 let pot: u64 = 10_000 ;
136144 SubnetTAO :: < Test > :: insert ( net, TaoCurrency :: from ( pot) ) ;
137- SubtensorModule :: set_subnet_locked_balance ( net, 5_000 . into ( ) ) ; // owner refund path present but emission = 0
145+ SubtensorModule :: set_subnet_locked_balance ( net, 5_000 . into ( ) ) ; // owner refund path present; emission = 0
138146
139147 // Cold-key balances before
140148 let s1_before = SubtensorModule :: get_coldkey_balance ( & s1_cold) ;
@@ -199,6 +207,10 @@ fn dissolve_owner_cut_refund_logic() {
199207 let oh = U256 :: from ( 71 ) ;
200208 let net = add_dynamic_network ( & oh, & oc) ;
201209
210+ // Mark this subnet as *legacy* so owner refund path is enabled.
211+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( net) ;
212+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at. saturating_add ( 1 ) ) ;
213+
202214 // One staker and a TAO pot (not relevant to refund amount).
203215 let sh = U256 :: from ( 77 ) ;
204216 let sc = U256 :: from ( 88 ) ;
@@ -683,6 +695,10 @@ fn destroy_alpha_out_multiple_stakers_pro_rata() {
683695 let owner_hot = U256 :: from ( 20 ) ;
684696 let netuid = add_dynamic_network ( & owner_hot, & owner_cold) ;
685697
698+ // Mark this subnet as *legacy* so owner refund path is enabled.
699+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( netuid) ;
700+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at. saturating_add ( 1 ) ) ;
701+
686702 // 2. Two stakers on that subnet
687703 let ( c1, h1) = ( U256 :: from ( 111 ) , U256 :: from ( 211 ) ) ;
688704 let ( c2, h2) = ( U256 :: from ( 222 ) , U256 :: from ( 333 ) ) ;
@@ -779,6 +795,10 @@ fn destroy_alpha_out_many_stakers_complex_distribution() {
779795 SubtensorModule :: set_max_registrations_per_block ( netuid, 1_000u16 ) ;
780796 SubtensorModule :: set_target_registrations_per_interval ( netuid, 1_000u16 ) ;
781797
798+ // Mark this subnet as *legacy* so owner refund path is enabled.
799+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( netuid) ;
800+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at. saturating_add ( 1 ) ) ;
801+
782802 // Runtime-exact min amount = min_stake + fee
783803 let min_amount = {
784804 let min_stake = DefaultMinStake :: < Test > :: get ( ) ;
@@ -914,6 +934,141 @@ fn destroy_alpha_out_many_stakers_complex_distribution() {
914934 } ) ;
915935}
916936
937+ #[ test]
938+ fn destroy_alpha_out_refund_gating_by_registration_block ( ) {
939+ // ──────────────────────────────────────────────────────────────────────
940+ // Case A: LEGACY subnet → refund applied
941+ // ──────────────────────────────────────────────────────────────────────
942+ new_test_ext ( 0 ) . execute_with ( || {
943+ // Owner + subnet
944+ let owner_cold = U256 :: from ( 10_000 ) ;
945+ let owner_hot = U256 :: from ( 20_000 ) ;
946+ let netuid = add_dynamic_network ( & owner_hot, & owner_cold) ;
947+
948+ // Mark as *legacy*: registered_at < start_block
949+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( netuid) ;
950+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at. saturating_add ( 1 ) ) ;
951+
952+ // Lock and (nonzero) emissions
953+ let lock_u64: u64 = 50_000 ;
954+ SubtensorModule :: set_subnet_locked_balance ( netuid, TaoCurrency :: from ( lock_u64) ) ;
955+ Emission :: < Test > :: insert (
956+ netuid,
957+ vec ! [ AlphaCurrency :: from( 1_500u64 ) , AlphaCurrency :: from( 3_000u64 ) ] , // total 4_500 α
958+ ) ;
959+ // Owner cut ≈ 50%
960+ SubnetOwnerCut :: < Test > :: put ( 32_768u16 ) ;
961+
962+ // Compute expected refund using the same math as the pallet
963+ let frac: U96F32 = SubtensorModule :: get_float_subnet_owner_cut ( ) ;
964+ let total_emitted_alpha: u64 = 1_500 + 3_000 ; // 4_500 α
965+ let owner_alpha_u64: u64 = U96F32 :: from_num ( total_emitted_alpha)
966+ . saturating_mul ( frac)
967+ . floor ( )
968+ . saturating_to_num :: < u64 > ( ) ;
969+
970+ // Prefer sim_swap; fall back to current price if unavailable.
971+ let owner_emission_tao_u64: u64 = <Test as pallet:: Config >:: SwapInterface :: sim_swap (
972+ netuid. into ( ) ,
973+ OrderType :: Sell ,
974+ owner_alpha_u64,
975+ )
976+ . map ( |res| res. amount_paid_out )
977+ . unwrap_or_else ( |_| {
978+ let price: U96F32 =
979+ <Test as pallet:: Config >:: SwapInterface :: current_alpha_price ( netuid. into ( ) ) ;
980+ U96F32 :: from_num ( owner_alpha_u64)
981+ . saturating_mul ( price)
982+ . floor ( )
983+ . saturating_to_num :: < u64 > ( )
984+ } ) ;
985+
986+ let expected_refund: u64 = lock_u64. saturating_sub ( owner_emission_tao_u64) ;
987+
988+ // Balances before
989+ let owner_before = SubtensorModule :: get_coldkey_balance ( & owner_cold) ;
990+
991+ // Run the path under test
992+ assert_ok ! ( SubtensorModule :: destroy_alpha_in_out_stakes( netuid) ) ;
993+
994+ // Owner received their refund…
995+ let owner_after = SubtensorModule :: get_coldkey_balance ( & owner_cold) ;
996+ assert_eq ! ( owner_after, owner_before + expected_refund) ;
997+
998+ // …and the lock is always cleared to zero by destroy_alpha_in_out_stakes.
999+ assert_eq ! (
1000+ SubtensorModule :: get_subnet_locked_balance( netuid) ,
1001+ TaoCurrency :: from( 0u64 )
1002+ ) ;
1003+ } ) ;
1004+
1005+ // ──────────────────────────────────────────────────────────────────────
1006+ // Case B: NON‑LEGACY subnet → NO refund;
1007+ // ──────────────────────────────────────────────────────────────────────
1008+ new_test_ext ( 0 ) . execute_with ( || {
1009+ // Owner + subnet
1010+ let owner_cold = U256 :: from ( 1_111 ) ;
1011+ let owner_hot = U256 :: from ( 2_222 ) ;
1012+ let netuid = add_dynamic_network ( & owner_hot, & owner_cold) ;
1013+
1014+ // Explicitly set start_block <= registered_at to make it non‑legacy.
1015+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( netuid) ;
1016+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at) ;
1017+
1018+ // Lock and emissions present (should be ignored for refund)
1019+ let lock_u64: u64 = 42_000 ;
1020+ SubtensorModule :: set_subnet_locked_balance ( netuid, TaoCurrency :: from ( lock_u64) ) ;
1021+ Emission :: < Test > :: insert ( netuid, vec ! [ AlphaCurrency :: from( 5_000u64 ) ] ) ;
1022+ SubnetOwnerCut :: < Test > :: put ( 32_768u16 ) ; // ~50%
1023+
1024+ // Balances before
1025+ let owner_before = SubtensorModule :: get_coldkey_balance ( & owner_cold) ;
1026+
1027+ // Run the path under test
1028+ assert_ok ! ( SubtensorModule :: destroy_alpha_in_out_stakes( netuid) ) ;
1029+
1030+ // No refund for non‑legacy
1031+ let owner_after = SubtensorModule :: get_coldkey_balance ( & owner_cold) ;
1032+ assert_eq ! ( owner_after, owner_before) ;
1033+
1034+ // Lock is still cleared to zero by the routine
1035+ assert_eq ! (
1036+ SubtensorModule :: get_subnet_locked_balance( netuid) ,
1037+ TaoCurrency :: from( 0u64 )
1038+ ) ;
1039+ } ) ;
1040+
1041+ // ──────────────────────────────────────────────────────────────────────
1042+ // Case C: LEGACY subnet but lock = 0 → no refund;
1043+ // ──────────────────────────────────────────────────────────────────────
1044+ new_test_ext ( 0 ) . execute_with ( || {
1045+ // Owner + subnet
1046+ let owner_cold = U256 :: from ( 9_999 ) ;
1047+ let owner_hot = U256 :: from ( 8_888 ) ;
1048+ let netuid = add_dynamic_network ( & owner_hot, & owner_cold) ;
1049+
1050+ // Mark as *legacy*
1051+ let reg_at = NetworkRegisteredAt :: < Test > :: get ( netuid) ;
1052+ NetworkRegistrationStartBlock :: < Test > :: put ( reg_at. saturating_add ( 1 ) ) ;
1053+
1054+ // lock = 0; emissions present (must not matter)
1055+ SubtensorModule :: set_subnet_locked_balance ( netuid, TaoCurrency :: from ( 0u64 ) ) ;
1056+ Emission :: < Test > :: insert ( netuid, vec ! [ AlphaCurrency :: from( 10_000u64 ) ] ) ;
1057+ SubnetOwnerCut :: < Test > :: put ( 32_768u16 ) ; // ~50%
1058+
1059+ let owner_before = SubtensorModule :: get_coldkey_balance ( & owner_cold) ;
1060+ assert_ok ! ( SubtensorModule :: destroy_alpha_in_out_stakes( netuid) ) ;
1061+ let owner_after = SubtensorModule :: get_coldkey_balance ( & owner_cold) ;
1062+
1063+ // No refund possible when lock = 0
1064+ assert_eq ! ( owner_after, owner_before) ;
1065+ assert_eq ! (
1066+ SubtensorModule :: get_subnet_locked_balance( netuid) ,
1067+ TaoCurrency :: from( 0u64 )
1068+ ) ;
1069+ } ) ;
1070+ }
1071+
9171072#[ test]
9181073fn prune_none_with_no_networks ( ) {
9191074 new_test_ext ( 0 ) . execute_with ( || {
0 commit comments