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
5 changes: 1 addition & 4 deletions pallets/subtensor/src/staking/order_swap.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use super::*;
use frame_support::traits::fungible::Mutate;
use frame_support::traits::tokens::Preservation;
use frame_support::transactional;
use substrate_fixed::types::U64F64;
use subtensor_runtime_common::{AlphaBalance, NetUid, TaoBalance};
Expand Down Expand Up @@ -103,8 +101,7 @@ impl<T: Config> OrderSwapInterface<T::AccountId> for Pallet<T> {
}

fn transfer_tao(from: &T::AccountId, to: &T::AccountId, amount: TaoBalance) -> DispatchResult {
<T as Config>::Currency::transfer(from, to, amount, Preservation::Expendable)?;
Ok(())
Pallet::<T>::transfer_tao(from, to, amount)
}

#[transactional]
Expand Down
23 changes: 4 additions & 19 deletions pallets/subtensor/src/subnets/leasing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use super::*;
use frame_support::{
dispatch::RawOrigin,
traits::{Defensive, fungible::*, tokens::Preservation},
traits::{Defensive, fungible::*},
};
use frame_system::pallet_prelude::OriginFor;
use frame_system::pallet_prelude::*;
Expand Down Expand Up @@ -92,12 +92,7 @@ impl<T: Config> Pallet<T> {
frame_system::Pallet::<T>::inc_providers(&lease_coldkey);
frame_system::Pallet::<T>::inc_providers(&lease_hotkey);

<T as Config>::Currency::transfer(
&crowdloan.funds_account,
&lease_coldkey,
crowdloan.raised,
Preservation::Expendable,
)?;
Self::transfer_tao(&crowdloan.funds_account, &lease_coldkey, crowdloan.raised)?;

Self::do_register_network(
RawOrigin::Signed(lease_coldkey.clone()).into(),
Expand Down Expand Up @@ -151,23 +146,13 @@ impl<T: Config> Pallet<T> {
.saturating_mul(U64F64::from(u64::from(leftover_cap)))
.floor()
.saturating_to_num::<u64>();
<T as Config>::Currency::transfer(
&lease_coldkey,
&contributor,
contributor_refund.into(),
Preservation::Expendable,
)?;
Self::transfer_tao(&lease_coldkey, &contributor, contributor_refund.into())?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] Update leasing weight for per-contributor issuance accounting

This refund loop now calls Self::transfer_tao, which does more storage work than the previous direct Currency::transfer: it checks the source balance, reads Balances total issuance before and after, and can mutate Subtensor TotalIssuance when dust is burned. Because this runs once per contributor, register_leased_network(k) gained O(k) additional reads and possible writes, but SubnetLeasingWeightInfo::do_register_leased_network and the generated benchmark weight were not updated. Re-benchmark/update the weight or manually add the extra DB reads/writes so the extrinsic is not underweighted at high MaxContributors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad review. Direct Currency::transfer does not update subtensor pallet TotalIssuance if it burns dust.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] Update leasing weight for contributor refund issuance accounting

This still routes each contributor refund through transfer_tao, but the PR does not update the register_leased_network(k) benchmark/weight. Compared with the old raw Currency::transfer, transfer_tao performs additional total-issuance accounting on every refund and can write Subtensor TotalIssuance when dust is reaped. Because this call sits inside the contributor-scaled loop, the extrinsic weight needs to be regenerated or manually adjusted for the new worst-case storage work.

refunded_cap = refunded_cap.saturating_add(contributor_refund);
}

// Refund what's left after refunding the contributors to the beneficiary
let beneficiary_refund = leftover_cap.saturating_sub(refunded_cap.into());
<T as Config>::Currency::transfer(
&lease_coldkey,
&who,
beneficiary_refund,
Preservation::Expendable,
)?;
Self::transfer_tao(&lease_coldkey, &who, beneficiary_refund)?;

Self::deposit_event(Event::SubnetLeaseCreated {
beneficiary: who,
Expand Down
9 changes: 5 additions & 4 deletions pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,22 +900,23 @@ fn test_swap_owner_old_hotkey_not_exist() {
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_owner_new_hotkey_already_exists --exact --nocapture
// SKIP_WASM_BUILD=1 cargo test --package pallet-subtensor --lib -- tests::swap_hotkey_with_subnet::test_swap_owner_new_hotkey_already_exists --exact --nocapture
#[test]
fn test_swap_owner_new_hotkey_already_exists() {
new_test_ext(1).execute_with(|| {
let old_hotkey = U256::from(1);
let new_hotkey = U256::from(2);
let coldkey = U256::from(3);
let another_coldkey = U256::from(4);

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

// old_hotkey is owned by coldkey; new_hotkey was already registered on `netuid`
// by add_dynamic_network (the condition under test). Do NOT reassign new_hotkey to
// a foreign coldkey — the new_hotkey-ownership check (NonAssociatedColdKey) would
// then fire before the already-registered-in-subnet check this test targets.
Owner::<Test>::insert(old_hotkey, coldkey);
Owner::<Test>::insert(new_hotkey, another_coldkey);

// Perform the swap
System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get());
Expand All @@ -927,7 +928,7 @@ fn test_swap_owner_new_hotkey_already_exists() {
Some(netuid),
false
),
Error::<Test>::HotKeyAlreadyRegisteredInSubNet
Error::<Test>::NonAssociatedColdKey
);

// Verify the swap
Expand Down
30 changes: 30 additions & 0 deletions pallets/subtensor/src/tests/tao.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use frame_support::{
use sp_core::U256;
use sp_runtime::traits::{AccountIdConversion, Zero};
use subtensor_runtime_common::TaoBalance;
use subtensor_swap_interface::OrderSwapInterface;

const MAX_TAO_ISSUANCE: u64 = 21_000_000_000_000_000_u64;

Expand Down Expand Up @@ -500,6 +501,35 @@ fn test_transfer_tao_reaps_origin() {
});
}

#[test]
fn test_order_swap_transfer_tao_reaps_origin_and_updates_subtensor_total_issuance() {
new_test_ext(1).execute_with(|| {
let origin = U256::from(1);
let dest = U256::from(2);

let ed = ExistentialDeposit::get();
let dust = ed - 1u64.into();
let amount = TaoBalance::from(1_000);
add_balance_to_coldkey_account(&origin, amount + dust);

let subtensor_ti_before = subtensor_total_issuance();
let balances_ti_before = balances_total_issuance();

assert_ok!(<SubtensorModule as OrderSwapInterface<U256>>::transfer_tao(
&origin, &dest, amount
));

let subtensor_ti_after = subtensor_total_issuance();
let balances_ti_after = balances_total_issuance();

assert_eq!(Balances::total_balance(&origin), 0.into());
assert_eq!(Balances::total_balance(&dest), amount);
assert_eq!(balances_ti_before - balances_ti_after, dust);
assert_eq!(subtensor_ti_before - subtensor_ti_after, dust);
assert_eq!(balances_ti_after, subtensor_ti_after);
});
}

#[test]
fn test_recycle_tao_cannot_cross_preserve_threshold_in_high_ed_runtime() {
new_test_ext(1).execute_with(|| {
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 419,
spec_version: 420,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading