Skip to content

Allow owners to change their subnet symbol #1770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Jul 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
430859b
export SYMBOLS + DEFAULT_SYMBOL constants
l0r1s Jun 19, 2025
ecc88be
added utils for tests
l0r1s Jun 19, 2025
ecd42d4
added set_symbol extrinsic
l0r1s Jun 19, 2025
ef811a8
update the registration logic when setting symbol
l0r1s Jun 19, 2025
ae5df93
added tests
l0r1s Jun 19, 2025
e25e77b
disallow using root symbol
l0r1s Jun 19, 2025
d16a06f
cargo clippy
l0r1s Jun 19, 2025
6a42285
cargo fmt
l0r1s Jun 19, 2025
abc9e47
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jun 20, 2025
4476a52
cargo clippy
l0r1s Jun 20, 2025
52d46fd
cargo fix
l0r1s Jun 20, 2025
a76294b
cargo fmt
l0r1s Jun 20, 2025
a1ad985
fix test
l0r1s Jun 20, 2025
8f96894
fix failing tests due to root symbol exclusion
l0r1s Jun 20, 2025
b774e4a
make symbols static
l0r1s Jun 20, 2025
fe60a3a
remove the use of get_symbol_for_subnet in metagraph/dynamic_info, us…
l0r1s Jun 20, 2025
15ba642
fix clippy + fmt
l0r1s Jun 20, 2025
b693505
fix/added new tests
l0r1s Jun 20, 2025
301a5a5
make it faster + rename to update_symbol
l0r1s Jun 20, 2025
84ec48e
fix HashSet to BTreeSet
l0r1s Jun 20, 2025
83308b4
added benchmark + weight
l0r1s Jun 20, 2025
6d039d5
cargo fmt
l0r1s Jun 20, 2025
95e6476
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jun 23, 2025
0659f43
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jun 24, 2025
7ca49af
added token symbol to root/apex at genesis
l0r1s Jun 26, 2025
6c5435c
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jun 26, 2025
e25922e
extract logic to symbols
l0r1s Jun 26, 2025
5cb888e
added symbols migration to fix shift
l0r1s Jun 26, 2025
9cc1bf0
fix missing import
l0r1s Jun 26, 2025
62e7ed0
cargo clippy
l0r1s Jun 26, 2025
aa445f4
cargo fmt
l0r1s Jun 26, 2025
12acdc5
bump spec version
l0r1s Jun 26, 2025
f991f89
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jun 27, 2025
b98cc61
bump spec version
l0r1s Jun 27, 2025
a891950
cargo fmt
l0r1s Jun 27, 2025
d70b25d
update ext weights/reads/writes
l0r1s Jun 30, 2025
07d288c
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jun 30, 2025
cf243d8
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jun 30, 2025
cfd8a94
cargo fmt
l0r1s Jun 30, 2025
fafc24f
fix call index
l0r1s Jun 30, 2025
58c2c73
Merge branch 'devnet-ready' into feat/dynamic-symbol
l0r1s Jul 1, 2025
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
16 changes: 16 additions & 0 deletions pallets/subtensor/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1575,4 +1575,20 @@ mod pallet_benchmarks {
assert!(!SubnetLeaseShares::<T>::contains_prefix(lease_id));
assert!(!AccumulatedLeaseDividends::<T>::contains_key(lease_id));
}

#[benchmark]
fn update_symbol() {
let coldkey: T::AccountId = whitelisted_caller();
let netuid = NetUid::from(1);
let tempo: u16 = 1;
Subtensor::<T>::init_new_network(netuid, tempo);
SubnetOwner::<T>::insert(netuid, coldkey.clone());

let new_symbol = Subtensor::<T>::get_symbol_for_subnet(NetUid::from(42));

#[extrinsic_call]
_(RawOrigin::Signed(coldkey), netuid, new_symbol.clone());

assert_eq!(TokenSymbol::<T>::get(netuid), new_symbol);
}
}
41 changes: 39 additions & 2 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ mod dispatches {
/// User register a new subnetwork
#[pallet::call_index(59)]
#[pallet::weight((Weight::from_parts(260_500_000, 0)
.saturating_add(T::DbWeight::get().reads(33))
.saturating_add(T::DbWeight::get().reads(36))
.saturating_add(T::DbWeight::get().writes(51)), DispatchClass::Operational, Pays::No))]
pub fn register_network(origin: OriginFor<T>, hotkey: T::AccountId) -> DispatchResult {
Self::do_register_network(origin, &hotkey, 1, None)
Expand Down Expand Up @@ -1539,7 +1539,7 @@ mod dispatches {
/// User register a new subnetwork
#[pallet::call_index(79)]
#[pallet::weight((Weight::from_parts(239_700_000, 0)
.saturating_add(T::DbWeight::get().reads(32))
.saturating_add(T::DbWeight::get().reads(35))
.saturating_add(T::DbWeight::get().writes(50)), DispatchClass::Operational, Pays::No))]
pub fn register_network_with_identity(
origin: OriginFor<T>,
Expand Down Expand Up @@ -2138,5 +2138,42 @@ mod dispatches {
) -> DispatchResultWithPostInfo {
Self::do_terminate_lease(origin, lease_id, hotkey)
}

/// Updates the symbol for a subnet.
///
/// # Arguments
/// * `origin` - The origin of the call, which must be the subnet owner or root.
/// * `netuid` - The unique identifier of the subnet on which the symbol is being set.
/// * `symbol` - The symbol to set for the subnet.
///
/// # Errors
/// Returns an error if:
/// * The transaction is not signed by the subnet owner.
/// * The symbol does not exist.
/// * The symbol is already in use by another subnet.
///
/// # Events
/// Emits a `SymbolUpdated` event on success.
#[pallet::call_index(112)]
#[pallet::weight((
Weight::from_parts(28_840_000, 0).saturating_add(T::DbWeight::get().reads_writes(4, 1)),
DispatchClass::Operational,
Pays::Yes
))]
pub fn update_symbol(
origin: OriginFor<T>,
netuid: NetUid,
symbol: Vec<u8>,
) -> DispatchResult {
Self::ensure_subnet_owner_or_root(origin, netuid)?;

Self::ensure_symbol_exists(&symbol)?;
Self::ensure_symbol_available(&symbol)?;

TokenSymbol::<T>::insert(netuid, symbol.clone());

Self::deposit_event(Event::SymbolUpdated { netuid, symbol });
Ok(())
}
}
}
4 changes: 4 additions & 0 deletions pallets/subtensor/src/macros/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,5 +238,9 @@ mod errors {
BeneficiaryDoesNotOwnHotkey,
/// Expected beneficiary origin.
ExpectedBeneficiaryOrigin,
/// Symbol does not exist.
SymbolDoesNotExist,
/// Symbol already in use.
SymbolAlreadyInUse,
}
}
8 changes: 8 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,5 +373,13 @@ mod events {
/// The subnet ID
netuid: NetUid,
},

/// The symbol for a subnet has been updated.
SymbolUpdated {
/// The subnet ID
netuid: NetUid,
/// The symbol that has been updated.
symbol: Vec<u8>,
},
}
}
7 changes: 7 additions & 0 deletions pallets/subtensor/src/macros/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ mod genesis {
// Set target registrations for validators as 1 per block.
TargetRegistrationsPerInterval::<T>::insert(NetUid::ROOT, 1);

// Set token symbol for root
TokenSymbol::<T>::insert(
NetUid::ROOT,
Pallet::<T>::get_symbol_for_subnet(NetUid::ROOT),
);

let netuid = NetUid::from(1);
let hotkey = DefaultAccount::<T>::get();
SubnetMechanism::<T>::insert(netuid, 1); // Make dynamic.
Expand Down Expand Up @@ -96,6 +102,7 @@ mod genesis {
Uids::<T>::insert(netuid, hotkey.clone(), 0); // Make uid - hotkey association.
BlockAtRegistration::<T>::insert(netuid, 0, block_number); // Fill block at registration.
IsNetworkMember::<T>::insert(hotkey.clone(), netuid, true); // Fill network is member.
TokenSymbol::<T>::insert(netuid, Pallet::<T>::get_symbol_for_subnet(netuid));
}
}
}
52 changes: 52 additions & 0 deletions pallets/subtensor/src/migrations/migrate_subnet_symbols.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use super::*;
use alloc::string::String;
use frame_support::IterableStorageMap;
use frame_support::{traits::Get, weights::Weight};

/// Migrates the subnet symbols to their correct values because some shift is present
/// after subnet 81.
pub fn migrate_subnet_symbols<T: Config>() -> Weight {
let migration_name = b"migrate_subnet_symbols".to_vec();

// Initialize the weight with one read operation.
let mut weight = T::DbWeight::get().reads(1);

// Check if the migration has already run
if HasMigrationRun::<T>::get(&migration_name) {
log::info!(
"Migration '{:?}' has already run. Skipping.",
String::from_utf8_lossy(&migration_name)
);
return weight;
}
log::info!(
"Running migration '{}'",
String::from_utf8_lossy(&migration_name)
);

// Get all netuids
let netuids: Vec<NetUid> = <NetworksAdded<T> as IterableStorageMap<NetUid, bool>>::iter()
.map(|(netuid, _)| netuid)
.collect();

for netuid in netuids.iter() {
// Get the symbol for the subnet
let symbol = Pallet::<T>::get_symbol_for_subnet(*netuid);

// Set the symbol for the subnet
TokenSymbol::<T>::insert(*netuid, symbol);
weight = weight.saturating_add(T::DbWeight::get().writes(1));
}

// Mark the migration as completed
HasMigrationRun::<T>::insert(&migration_name, true);
weight = weight.saturating_add(T::DbWeight::get().writes(1));

log::info!(
"Migration '{:?}' completed.",
String::from_utf8_lossy(&migration_name)
);

// Return the migration weight.
weight
}
1 change: 1 addition & 0 deletions pallets/subtensor/src/migrations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub mod migrate_set_min_difficulty;
pub mod migrate_set_subtoken_enabled;
pub mod migrate_stake_threshold;
pub mod migrate_subnet_identities_to_v3;
pub mod migrate_subnet_symbols;
pub mod migrate_subnet_volume;
pub mod migrate_to_v1_separate_emission;
pub mod migrate_to_v2_fixed_total_stake;
Expand Down
2 changes: 1 addition & 1 deletion pallets/subtensor/src/rpc_info/dynamic_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<T: Config> Pallet<T> {
.into_iter()
.map(Compact)
.collect(),
token_symbol: Self::get_symbol_for_subnet(netuid)
token_symbol: TokenSymbol::<T>::get(netuid)
.into_iter()
.map(Compact)
.collect(),
Expand Down
4 changes: 2 additions & 2 deletions pallets/subtensor/src/rpc_info/metagraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ impl<T: Config> Pallet<T> {
.into_iter()
.map(Compact)
.collect(), // Name
symbol: Self::get_symbol_for_subnet(netuid)
symbol: TokenSymbol::<T>::get(netuid)
.into_iter()
.map(Compact)
.collect(), // Symbol.
Expand Down Expand Up @@ -835,7 +835,7 @@ impl<T: Config> Pallet<T> {
Some(SelectiveMetagraphIndex::Symbol) => SelectiveMetagraph {
netuid: netuid.into(),
symbol: Some(
Self::get_symbol_for_subnet(netuid)
TokenSymbol::<T>::get(netuid)
.into_iter()
.map(Compact)
.collect(),
Expand Down
23 changes: 11 additions & 12 deletions pallets/subtensor/src/subnets/subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,23 +148,23 @@ impl<T: Config> Pallet<T> {
Error::<T>::NotEnoughBalanceToStake
);

// --- 5. Determine the netuid to register.
// --- 6. Determine the netuid to register.
let netuid_to_register = Self::get_next_netuid();

// --- 6. Perform the lock operation.
// --- 7. Perform the lock operation.
let actual_tao_lock_amount: u64 =
Self::remove_balance_from_coldkey_account(&coldkey, lock_amount)?;
log::debug!("actual_tao_lock_amount: {:?}", actual_tao_lock_amount);

// --- 7. Set the lock amount for use to determine pricing.
// --- 8. Set the lock amount for use to determine pricing.
Self::set_network_last_lock(actual_tao_lock_amount);

// --- 8. Set initial and custom parameters for the network.
// --- 9. Set initial and custom parameters for the network.
let default_tempo = DefaultTempo::<T>::get();
Self::init_new_network(netuid_to_register, default_tempo);
log::debug!("init_new_network: {:?}", netuid_to_register);

// --- 9 . Add the caller to the neuron set.
// --- 10. Add the caller to the neuron set.
Self::create_account_if_non_existent(&coldkey, hotkey);
Self::append_neuron(netuid_to_register, hotkey, current_block);
log::debug!(
Expand All @@ -173,24 +173,23 @@ impl<T: Config> Pallet<T> {
hotkey
);

// --- 10. Set the mechanism.
// --- 11. Set the mechanism.
SubnetMechanism::<T>::insert(netuid_to_register, mechid);
log::debug!(
"SubnetMechanism for netuid {:?} set to: {:?}",
netuid_to_register,
mechid
);

// --- 11. Set the creation terms.
// --- 12. Set the creation terms.
NetworkLastRegistered::<T>::set(current_block);
NetworkRegisteredAt::<T>::insert(netuid_to_register, current_block);

// --- 14. Init the pool by putting the lock as the initial alpha.
TokenSymbol::<T>::insert(
netuid_to_register,
Self::get_symbol_for_subnet(netuid_to_register),
); // Set subnet token symbol.
// --- 13. Set the symbol.
let symbol = Self::get_next_available_symbol(netuid_to_register);
TokenSymbol::<T>::insert(netuid_to_register, symbol);

// --- 14. Init the pool by putting the lock as the initial alpha.
// Put initial TAO from lock into subnet TAO and produce numerically equal amount of Alpha
// The initial TAO is the locked amount, with a minimum of 1 RAO and a cap of 100 TAO.
let pool_initial_tao = Self::get_network_min_lock();
Expand Down
Loading
Loading