Skip to content

Commit 2bb5e20

Browse files
authored
Fix/charge-for-swap-before-schedule (#1141)
* charge for swap before sched * add swap cost to the events * pass swap cost into swap_coldkey call * fmt * oops, add arg * commit Cargo.lock * bump spec * fix tests
1 parent ecd680b commit 2bb5e20

File tree

6 files changed

+78
-14
lines changed

6 files changed

+78
-14
lines changed

pallets/subtensor/src/benchmarks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ reveal_weights {
515515
Identities::<T>::insert(&old_coldkey, identity);
516516

517517
// Benchmark setup complete, now execute the extrinsic
518-
}: swap_coldkey(RawOrigin::Root, old_coldkey.clone(), new_coldkey.clone())
518+
}: swap_coldkey(RawOrigin::Root, old_coldkey.clone(), new_coldkey.clone(), swap_cost)
519519

520520
batch_reveal_weights {
521521
let tempo: u16 = 0;

pallets/subtensor/src/macros/dispatches.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,12 +962,13 @@ mod dispatches {
962962
origin: OriginFor<T>,
963963
old_coldkey: T::AccountId,
964964
new_coldkey: T::AccountId,
965+
swap_cost: u64,
965966
) -> DispatchResultWithPostInfo {
966967
// Ensure it's called with root privileges (scheduler has root privileges)
967968
ensure_root(origin)?;
968969
log::info!("swap_coldkey: {:?} -> {:?}", old_coldkey, new_coldkey);
969970

970-
Self::do_swap_coldkey(&old_coldkey, &new_coldkey)
971+
Self::do_swap_coldkey(&old_coldkey, &new_coldkey, swap_cost)
971972
}
972973

973974
/// Sets the childkey take for a given hotkey.
@@ -1327,13 +1328,21 @@ mod dispatches {
13271328
Error::<T>::SwapAlreadyScheduled
13281329
);
13291330

1331+
// Calculate the swap cost and ensure sufficient balance
1332+
let swap_cost = Self::get_key_swap_cost();
1333+
ensure!(
1334+
Self::can_remove_balance_from_coldkey_account(&who, swap_cost),
1335+
Error::<T>::NotEnoughBalanceToPaySwapColdKey
1336+
);
1337+
13301338
let current_block: BlockNumberFor<T> = <frame_system::Pallet<T>>::block_number();
13311339
let duration: BlockNumberFor<T> = ColdkeySwapScheduleDuration::<T>::get();
13321340
let when: BlockNumberFor<T> = current_block.saturating_add(duration);
13331341

13341342
let call = Call::<T>::swap_coldkey {
13351343
old_coldkey: who.clone(),
13361344
new_coldkey: new_coldkey.clone(),
1345+
swap_cost,
13371346
};
13381347

13391348
let bound_call = T::Preimages::bound(LocalCallOf::<T>::from(call.clone()))
@@ -1354,6 +1363,7 @@ mod dispatches {
13541363
old_coldkey: who.clone(),
13551364
new_coldkey: new_coldkey.clone(),
13561365
execution_block: when,
1366+
swap_cost,
13571367
});
13581368

13591369
Ok(().into())

pallets/subtensor/src/macros/events.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ mod events {
155155
old_coldkey: T::AccountId,
156156
/// the account ID of new coldkey
157157
new_coldkey: T::AccountId,
158+
/// the swap cost
159+
swap_cost: u64,
158160
},
159161
/// All balance of a hotkey has been unstaked and transferred to a new coldkey
160162
AllBalanceUnstakedAndTransferredToNewColdkey {
@@ -175,6 +177,8 @@ mod events {
175177
new_coldkey: T::AccountId,
176178
/// The arbitration block for the coldkey swap
177179
execution_block: BlockNumberFor<T>,
180+
/// The swap cost
181+
swap_cost: u64,
178182
},
179183
/// The arbitration period has been extended
180184
ArbitrationPeriodExtended {

pallets/subtensor/src/swap/swap_coldkey.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ impl<T: Config> Pallet<T> {
3333
pub fn do_swap_coldkey(
3434
old_coldkey: &T::AccountId,
3535
new_coldkey: &T::AccountId,
36+
swap_cost: u64,
3637
) -> DispatchResultWithPostInfo {
3738
// 2. Initialize the weight for this operation
3839
let mut weight: Weight = T::DbWeight::get().reads(2);
@@ -55,8 +56,7 @@ impl<T: Config> Pallet<T> {
5556
Identities::<T>::insert(new_coldkey, identity);
5657
}
5758

58-
// 6. Calculate the swap cost and ensure sufficient balance
59-
let swap_cost = Self::get_key_swap_cost();
59+
// 6. Ensure sufficient balance for the swap cost
6060
ensure!(
6161
Self::can_remove_balance_from_coldkey_account(old_coldkey, swap_cost),
6262
Error::<T>::NotEnoughBalanceToPaySwapColdKey
@@ -83,6 +83,7 @@ impl<T: Config> Pallet<T> {
8383
Self::deposit_event(Event::ColdkeySwapped {
8484
old_coldkey: old_coldkey.clone(),
8585
new_coldkey: new_coldkey.clone(),
86+
swap_cost,
8687
});
8788

8889
// 12. Return the result with the updated weight

pallets/subtensor/src/tests/swap_coldkey.rs

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,8 @@ fn test_do_swap_coldkey_success() {
709709
assert_ok!(SubtensorModule::do_swap_coldkey(
710710
// <<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
711711
&old_coldkey,
712-
&new_coldkey
712+
&new_coldkey,
713+
swap_cost
713714
));
714715

715716
// Log state after swap
@@ -782,6 +783,7 @@ fn test_do_swap_coldkey_success() {
782783
Event::ColdkeySwapped {
783784
old_coldkey,
784785
new_coldkey,
786+
swap_cost,
785787
}
786788
.into(),
787789
);
@@ -1195,7 +1197,11 @@ fn test_do_swap_coldkey_with_subnet_ownership() {
11951197
OwnedHotkeys::<Test>::insert(old_coldkey, vec![hotkey]);
11961198

11971199
// Perform the swap
1198-
assert_ok!(SubtensorModule::do_swap_coldkey(&old_coldkey, &new_coldkey));
1200+
assert_ok!(SubtensorModule::do_swap_coldkey(
1201+
&old_coldkey,
1202+
&new_coldkey,
1203+
swap_cost
1204+
));
11991205

12001206
// Verify subnet ownership transfer
12011207
assert_eq!(SubnetOwner::<Test>::get(netuid), new_coldkey);
@@ -1652,8 +1658,10 @@ fn test_schedule_swap_coldkey_success() {
16521658
let old_coldkey: U256 = U256::from(1);
16531659
let new_coldkey: U256 = U256::from(2);
16541660

1661+
let swap_cost = SubtensorModule::get_key_swap_cost();
1662+
16551663
// Add balance to the old coldkey account
1656-
SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 1000);
1664+
SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, swap_cost + 1_000);
16571665

16581666
// Schedule the coldkey swap
16591667
assert_ok!(SubtensorModule::schedule_swap_coldkey(
@@ -1673,6 +1681,7 @@ fn test_schedule_swap_coldkey_success() {
16731681
old_coldkey,
16741682
new_coldkey,
16751683
execution_block: expected_execution_block,
1684+
swap_cost,
16761685
}
16771686
.into(),
16781687
);
@@ -1689,7 +1698,9 @@ fn test_schedule_swap_coldkey_duplicate() {
16891698
let old_coldkey = U256::from(1);
16901699
let new_coldkey = U256::from(2);
16911700

1692-
SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 2000);
1701+
let swap_cost = SubtensorModule::get_key_swap_cost();
1702+
1703+
SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, swap_cost + 2_000);
16931704

16941705
assert_ok!(SubtensorModule::schedule_swap_coldkey(
16951706
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
@@ -1734,6 +1745,8 @@ fn test_schedule_swap_coldkey_execution() {
17341745
"Initial ownership check failed"
17351746
);
17361747

1748+
let swap_cost = SubtensorModule::get_key_swap_cost();
1749+
17371750
// Schedule the swap
17381751
assert_ok!(SubtensorModule::schedule_swap_coldkey(
17391752
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
@@ -1749,6 +1762,7 @@ fn test_schedule_swap_coldkey_execution() {
17491762
old_coldkey,
17501763
new_coldkey,
17511764
execution_block,
1765+
swap_cost,
17521766
}
17531767
.into(),
17541768
);
@@ -1790,6 +1804,7 @@ fn test_schedule_swap_coldkey_execution() {
17901804
Event::ColdkeySwapped {
17911805
old_coldkey,
17921806
new_coldkey,
1807+
swap_cost,
17931808
}
17941809
.into(),
17951810
);
@@ -1807,7 +1822,8 @@ fn test_direct_swap_coldkey_call_fails() {
18071822
SubtensorModule::swap_coldkey(
18081823
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
18091824
old_coldkey,
1810-
new_coldkey
1825+
new_coldkey,
1826+
0
18111827
),
18121828
BadOrigin
18131829
);
@@ -1822,7 +1838,9 @@ fn test_schedule_swap_coldkey_with_pending_swap() {
18221838
let new_coldkey1 = U256::from(2);
18231839
let new_coldkey2 = U256::from(3);
18241840

1825-
SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 2000);
1841+
let swap_cost = SubtensorModule::get_key_swap_cost();
1842+
1843+
SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, swap_cost + 1_000);
18261844

18271845
assert_ok!(SubtensorModule::schedule_swap_coldkey(
18281846
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
@@ -1876,7 +1894,11 @@ fn test_coldkey_swap_delegate_identity_updated() {
18761894
assert!(Identities::<Test>::get(old_coldkey).is_some());
18771895
assert!(Identities::<Test>::get(new_coldkey).is_none());
18781896

1879-
assert_ok!(SubtensorModule::do_swap_coldkey(&old_coldkey, &new_coldkey));
1897+
assert_ok!(SubtensorModule::do_swap_coldkey(
1898+
&old_coldkey,
1899+
&new_coldkey,
1900+
burn_cost
1901+
));
18801902

18811903
assert!(Identities::<Test>::get(old_coldkey).is_none());
18821904
assert!(Identities::<Test>::get(new_coldkey).is_some());
@@ -1912,7 +1934,11 @@ fn test_coldkey_swap_no_identity_no_changes() {
19121934
assert!(Identities::<Test>::get(old_coldkey).is_none());
19131935

19141936
// Perform the coldkey swap
1915-
assert_ok!(SubtensorModule::do_swap_coldkey(&old_coldkey, &new_coldkey));
1937+
assert_ok!(SubtensorModule::do_swap_coldkey(
1938+
&old_coldkey,
1939+
&new_coldkey,
1940+
burn_cost
1941+
));
19161942

19171943
// Ensure no identities have been changed
19181944
assert!(Identities::<Test>::get(old_coldkey).is_none());
@@ -1956,10 +1982,33 @@ fn test_coldkey_swap_no_identity_no_changes_newcoldkey_exists() {
19561982
assert!(Identities::<Test>::get(old_coldkey).is_none());
19571983

19581984
// Perform the coldkey swap
1959-
assert_ok!(SubtensorModule::do_swap_coldkey(&old_coldkey, &new_coldkey));
1985+
assert_ok!(SubtensorModule::do_swap_coldkey(
1986+
&old_coldkey,
1987+
&new_coldkey,
1988+
burn_cost
1989+
));
19601990

19611991
// Ensure no identities have been changed
19621992
assert!(Identities::<Test>::get(old_coldkey).is_none());
19631993
assert!(Identities::<Test>::get(new_coldkey).is_some());
19641994
});
19651995
}
1996+
1997+
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test swap_coldkey -- test_cant_schedule_swap_without_enough_to_burn --exact --nocapture
1998+
#[test]
1999+
fn test_cant_schedule_swap_without_enough_to_burn() {
2000+
new_test_ext(1).execute_with(|| {
2001+
let old_coldkey = U256::from(3);
2002+
let new_coldkey = U256::from(4);
2003+
let hotkey = U256::from(5);
2004+
2005+
let burn_cost = SubtensorModule::get_key_swap_cost();
2006+
assert_noop!(
2007+
SubtensorModule::schedule_swap_coldkey(
2008+
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
2009+
new_coldkey
2010+
),
2011+
Error::<Test>::NotEnoughBalanceToPaySwapColdKey
2012+
);
2013+
});
2014+
}

runtime/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
220220
// `spec_version`, and `authoring_version` are the same between Wasm and native.
221221
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
222222
// the compatible custom types.
223-
spec_version: 222,
223+
spec_version: 223,
224224
impl_version: 1,
225225
apis: RUNTIME_API_VERSIONS,
226226
transaction_version: 1,

0 commit comments

Comments
 (0)