Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions pallets/subtensor/src/swap/swap_coldkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ impl<T: Config> Pallet<T> {
// Transfer any remaining balance from old_coldkey to new_coldkey
Self::transfer_all_tao_and_kill(old_coldkey, new_coldkey)?;

Self::set_last_tx_block(new_coldkey, Self::get_current_block_as_u64());

Self::deposit_event(Event::ColdkeySwapped {
old_coldkey: old_coldkey.clone(),
new_coldkey: new_coldkey.clone(),
Expand Down
31 changes: 5 additions & 26 deletions pallets/subtensor/src/swap/swap_hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ impl<T: Config> Pallet<T> {
/// # Errors
///
/// * `NonAssociatedColdKey` - If the coldkey does not own the old hotkey.
/// * `HotKeySetTxRateLimitExceeded` - If the transaction rate limit is exceeded.
/// * `NewHotKeyIsSameWithOld` - If the new hotkey is the same as the old hotkey.
/// * `HotKeyAlreadyRegisteredInSubNet` - If the new hotkey is already registered in the subnet.
/// * `NewHotKeyNotCleanForRootSwap` - If the swap touches root and the new hotkey
Expand Down Expand Up @@ -52,17 +51,6 @@ impl<T: Config> Pallet<T> {
// 4. Ensure the new hotkey is different from the old one
ensure!(old_hotkey != new_hotkey, Error::<T>::NewHotKeyIsSameWithOld);

// 5. Get the current block number
let block: u64 = Self::get_current_block_as_u64();

// 6. Ensure the transaction rate limit is not exceeded
ensure!(
!Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block),
Error::<T>::HotKeySetTxRateLimitExceeded
);

weight.saturating_accrue(T::DbWeight::get().reads(2));

match netuid {
// 7. Ensure the hotkey is not registered on the network before, if netuid is provided
Some(netuid) => {
Expand Down Expand Up @@ -96,12 +84,7 @@ impl<T: Config> Pallet<T> {
);
}

// 8. Swap LastTxBlock
let last_tx_block: u64 = Self::get_last_tx_block(old_hotkey);
Self::set_last_tx_block(new_hotkey, last_tx_block);
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));

// 9. Swap LastTxBlockDelegateTake
// 8. Swap LastTxBlockDelegateTake
let last_tx_block_delegate_take: u64 = Self::get_last_tx_block_delegate_take(old_hotkey);
Self::set_last_tx_block_delegate_take(new_hotkey, last_tx_block_delegate_take);
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
Expand Down Expand Up @@ -144,11 +127,7 @@ impl<T: Config> Pallet<T> {
keep_stake,
)?;

// 20. Update the last transaction block for the coldkey
Self::set_last_tx_block(&coldkey, block);
weight.saturating_accrue(T::DbWeight::get().writes(1));

// 21. Emit an event for the hotkey swap
// 20. Emit an event for the hotkey swap
Self::deposit_event(Event::HotkeySwapped {
coldkey,
old_hotkey: old_hotkey.clone(),
Expand Down Expand Up @@ -359,10 +338,10 @@ impl<T: Config> Pallet<T> {
keep_stake,
)?;

// 10. Update the last transaction block for the coldkey
Self::set_last_tx_block(coldkey, block);
// 10. Record the per-subnet swap block for the HotkeySwapOnSubnetInterval gate.
// The generic LastTxBlock setter is dropped together with its removed check.
LastHotkeySwapOnNetuid::<T>::insert(netuid, coldkey, block);
weight.saturating_accrue(T::DbWeight::get().writes(2));
weight.saturating_accrue(T::DbWeight::get().writes(1));

// 11. Emit an event for the hotkey swap
Self::deposit_event(Event::HotkeySwappedOnSubnet {
Expand Down
43 changes: 9 additions & 34 deletions pallets/subtensor/src/tests/swap_hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,9 +719,9 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() {
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_tx_rate_limit_exceeded --exact --nocapture
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_no_tx_rate_limit --exact --nocapture
#[test]
fn test_swap_hotkey_tx_rate_limit_exceeded() {
fn test_swap_hotkey_no_tx_rate_limit() {
new_test_ext(1).execute_with(|| {
let netuid = NetUid::from(1);
let tempo: u16 = 13;
Expand All @@ -731,16 +731,9 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() {
let coldkey = U256::from(3);
let swap_cost = SubtensorModule::get_key_swap_cost() * 2.into();

let tx_rate_limit = 1;

// Get the current transaction rate limit
let current_tx_rate_limit = SubtensorModule::get_tx_rate_limit();
log::info!("current_tx_rate_limit: {current_tx_rate_limit:?}");

// Set the transaction rate limit
SubtensorModule::set_tx_rate_limit(tx_rate_limit);
// assert the rate limit is set to 1000 blocks
assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit);
// Set a strict tx rate limit to prove it no longer gates hotkey swaps.
SubtensorModule::set_tx_rate_limit(1);
assert_eq!(SubtensorModule::get_tx_rate_limit(), 1);

// Setup initial state
add_network(netuid, tempo, 0);
Expand All @@ -756,20 +749,8 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() {
false,
));

// Attempt to perform another swap immediately, which should fail due to rate limit
assert_err!(
SubtensorModule::do_swap_hotkey(
<<Test as Config>::RuntimeOrigin>::signed(coldkey),
&new_hotkey_1,
&new_hotkey_2,
None,
false,
),
Error::<Test>::HotKeySetTxRateLimitExceeded
);

// move in time past the rate limit
step_block(1001);
// A second swap in the same block now succeeds (rate limit removed); the fee is
// charged again, so the coldkey must have funded two swaps.
assert_ok!(SubtensorModule::do_swap_hotkey(
<<Test as Config>::RuntimeOrigin>::signed(coldkey),
&new_hotkey_1,
Expand Down Expand Up @@ -1567,12 +1548,9 @@ fn test_swap_hotkey_swap_rate_limits() {
let netuid = add_dynamic_network(&old_hotkey, &coldkey);
add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into());

let last_tx_block = 123;
let delegate_take_block = 4567;
let child_key_take_block = 8910;

// Set the last tx block for the old hotkey
SubtensorModule::set_last_tx_block(&old_hotkey, last_tx_block);
// Set the last delegate take block for the old hotkey
SubtensorModule::set_last_tx_block_delegate_take(&old_hotkey, delegate_take_block);
// Set last childkey take block for the old hotkey
Expand All @@ -1587,11 +1565,8 @@ fn test_swap_hotkey_swap_rate_limits() {
false,
));

// Check for new hotkey
assert_eq!(
SubtensorModule::get_last_tx_block(&new_hotkey),
last_tx_block
);
// Check for new hotkey (LastTxBlock is no longer transferred: the generic tx rate
// limit was removed, so it is dead state). The take rate limits are still active.
assert_eq!(
SubtensorModule::get_last_tx_block_delegate_take(&new_hotkey),
delegate_take_block
Expand Down
73 changes: 2 additions & 71 deletions pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,69 +774,6 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() {
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_tx_rate_limit_exceeded --exact --nocapture
#[test]
fn test_swap_hotkey_tx_rate_limit_exceeded() {
new_test_ext(1).execute_with(|| {
let netuid = NetUid::from(1);
let tempo: u16 = 13;
let old_hotkey = U256::from(1);
let new_hotkey_1 = U256::from(2);
let new_hotkey_2 = U256::from(4);
let coldkey = U256::from(3);
let swap_cost = TaoBalance::from(1_000_000_000u64) * 2.into();

let tx_rate_limit = 1;

// Get the current transaction rate limit
let current_tx_rate_limit = SubtensorModule::get_tx_rate_limit();
log::info!("current_tx_rate_limit: {current_tx_rate_limit:?}");

// Set the transaction rate limit
SubtensorModule::set_tx_rate_limit(tx_rate_limit);
// assert the rate limit is set to 1000 blocks
assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit);

// Setup initial state
add_network(netuid, tempo, 0);
register_ok_neuron(netuid, old_hotkey, coldkey, 0);
add_balance_to_coldkey_account(&coldkey, swap_cost);

// Perform the first swap
System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get());
assert_ok!(SubtensorModule::do_swap_hotkey(
RuntimeOrigin::signed(coldkey),
&old_hotkey,
&new_hotkey_1,
Some(netuid),
false
),);

// Attempt to perform another swap immediately, which should fail due to rate limit
assert_err!(
SubtensorModule::do_swap_hotkey(
RuntimeOrigin::signed(coldkey),
&old_hotkey,
&new_hotkey_1,
Some(netuid),
false
),
Error::<Test>::HotKeySetTxRateLimitExceeded
);

// move in time past the rate limit
step_block(1001);
System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get());
assert_ok!(SubtensorModule::do_swap_hotkey(
<<Test as Config>::RuntimeOrigin>::signed(coldkey),
&new_hotkey_1,
&new_hotkey_2,
None,
false
));
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_do_swap_hotkey_err_not_owner --exact --nocapture
#[test]
fn test_do_swap_hotkey_err_not_owner() {
Expand Down Expand Up @@ -1574,15 +1511,12 @@ fn test_swap_hotkey_swap_rate_limits() {
let new_hotkey = U256::from(2);
let coldkey = U256::from(3);

let last_tx_block = 123;
let delegate_take_block = 4567;
let child_key_take_block = 8910;

let netuid = add_dynamic_network(&old_hotkey, &coldkey);
add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into());

// Set the last tx block for the old hotkey
SubtensorModule::set_last_tx_block(&old_hotkey, last_tx_block);
// Set the last delegate take block for the old hotkey
SubtensorModule::set_last_tx_block_delegate_take(&old_hotkey, delegate_take_block);
// Set last childkey take block for the old hotkey
Expand All @@ -1598,11 +1532,8 @@ fn test_swap_hotkey_swap_rate_limits() {
false
),);

// Check for new hotkey
assert_eq!(
SubtensorModule::get_last_tx_block(&new_hotkey),
last_tx_block
);
// Check for new hotkey (LastTxBlock is no longer transferred: the generic tx rate
// limit was removed.
assert_eq!(
SubtensorModule::get_last_tx_block_delegate_take(&new_hotkey),
delegate_take_block
Expand Down
Loading