Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
18ad00a
owner set validator cut
open-junius Sep 12, 2025
3048554
commit Cargo.lock
open-junius Sep 12, 2025
5372967
commit Cargo.lock
open-junius Sep 12, 2025
6de0f23
commit Cargo.lock
open-junius Sep 12, 2025
634079e
fix unit test
open-junius Sep 12, 2025
15fd19c
precision improvement
open-junius Sep 14, 2025
ab1d2ec
rebase pr
open-junius Oct 2, 2025
6730799
commit Cargo.lock
open-junius Oct 2, 2025
31e62ba
commit Cargo.lock
open-junius Oct 2, 2025
35785da
clean up code
open-junius Oct 2, 2025
d5fdb55
Merge branch 'devnet-ready' into validator_cut
open-junius Oct 3, 2025
a04b2cc
fix unit test
open-junius Oct 3, 2025
ee6957a
add separate test file
open-junius Oct 7, 2025
e792af1
update emisson accroding to rate
open-junius Oct 7, 2025
8e07a52
add test file to mod
open-junius Oct 7, 2025
d5f44c5
more test cases
open-junius Oct 7, 2025
b2dd663
cargo clippy
open-junius Oct 7, 2025
1cb952e
cargo fix
open-junius Oct 7, 2025
a1bc8b5
cargo fix
open-junius Oct 7, 2025
279cdf3
cargo fix
open-junius Oct 7, 2025
7e48760
Merge branch 'devnet-ready' into validator_cut
open-junius Oct 7, 2025
e358179
bump version
open-junius Oct 7, 2025
6e55a8b
Merge branch 'devnet-ready' into validator_cut
open-junius Oct 8, 2025
cc9304d
auto-update benchmark weights
github-actions[bot] Oct 8, 2025
85b082a
minx max limit
open-junius Oct 8, 2025
43fce2e
add min/max value for validator cut
open-junius Oct 9, 2025
3d6180f
commit Cargo.lock
open-junius Oct 9, 2025
e6b2612
commit Cargo.lock
open-junius Oct 9, 2025
fd40e3d
commit Cargo.lock
open-junius Oct 9, 2025
5a9c7f9
cargo clippy
open-junius Oct 9, 2025
c3077aa
commit Cargo.lock
open-junius Oct 9, 2025
dbaf5c2
commit Cargo.lock
open-junius Oct 9, 2025
c2df16d
fix conflict
open-junius Oct 9, 2025
51e97e2
fix unit tests
open-junius Oct 9, 2025
c551ca2
update boundary
open-junius Oct 9, 2025
e974265
fix unit tests
open-junius Oct 9, 2025
466cf5d
remove invalid edge case
open-junius Oct 10, 2025
92a88ff
fix conflict
open-junius Oct 10, 2025
3c4a86e
Merge branch 'devnet-ready' into validator_cut
open-junius Oct 16, 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
26 changes: 26 additions & 0 deletions pallets/admin-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1898,6 +1898,32 @@ pub mod pallet {
);
Ok(())
}

/// Sets the validator cut for a subnet.
/// Only callable by subnet owner or root.
#[pallet::call_index(78)]
#[pallet::weight(Weight::from_parts(15_000_000, 0)
.saturating_add(<T as frame_system::Config>::DbWeight::get().reads(1_u64))
.saturating_add(<T as frame_system::Config>::DbWeight::get().writes(1_u64)))]
pub fn sudo_set_validator_cut(
origin: OriginFor<T>,
netuid: NetUid,
cut: u16,
) -> DispatchResult {
let maybe_owner = pallet_subtensor::Pallet::<T>::ensure_sn_owner_or_root_with_limits(
origin,
netuid,
&[TransactionType::OwnerHyperparamUpdate],
)?;
pallet_subtensor::Pallet::<T>::set_validator_cut(netuid, cut);
log::debug!("ValidatorCutSet( netuid: {netuid:?}, cut: {cut:?} ) ");
pallet_subtensor::Pallet::<T>::record_owner_rl(
maybe_owner,
netuid,
&[TransactionType::OwnerHyperparamUpdate],
);
Ok(())
}
}
}

Expand Down
118 changes: 118 additions & 0 deletions pallets/admin-utils/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2269,3 +2269,121 @@ fn test_sudo_set_subsubnet_count() {
));
});
}

#[test]
fn test_get_validator_cut() {
new_test_ext().execute_with(|| {
let netuid = NetUid::from(1);
let expected_cut: u16 = 5000; // 50% cut

// Set up a network
add_network(netuid, 10);

// Set a validator cut value
SubtensorModule::set_validator_cut(netuid, expected_cut);

// Test that we can retrieve the value
let retrieved_cut = SubtensorModule::get_validator_cut(netuid);
assert_eq!(retrieved_cut, expected_cut);
});
}

#[test]
fn test_set_validator_cut() {
new_test_ext().execute_with(|| {
let netuid = NetUid::from(2);
let initial_cut: u16 = pallet_subtensor::DefaultValidatorCut::<Test>::get();
let new_cut: u16 = 7500; // 75% cut

// Set up a network
add_network(netuid, 10);

// Verify initial value
assert_eq!(SubtensorModule::get_validator_cut(netuid), initial_cut);

// Set new validator cut
SubtensorModule::set_validator_cut(netuid, new_cut);

// Verify the value was set correctly
assert_eq!(SubtensorModule::get_validator_cut(netuid), new_cut);
});
}

#[test]
fn test_sudo_set_validator_cut() {
new_test_ext().execute_with(|| {
let netuid = NetUid::from(3);
let to_be_set: u16 = 4200; // 42% cut

// Set up a network
add_network(netuid, 10);

let sn_owner = U256::from(1324);
// Set the Subnet Owner
SubnetOwner::<Test>::insert(netuid, sn_owner);

let init_value = SubtensorModule::get_validator_cut(netuid);

// Test that non-authorized origin fails (using a regular signed origin)
assert_eq!(
AdminUtils::sudo_set_validator_cut(
<<Test as Config>::RuntimeOrigin>::signed(U256::from(1)),
netuid,
to_be_set
),
Err(DispatchError::BadOrigin)
);
// Value should remain unchangeds
assert_eq!(SubtensorModule::get_validator_cut(netuid), init_value);

assert_ok!(AdminUtils::sudo_set_validator_cut(
<<Test as Config>::RuntimeOrigin>::signed(sn_owner),
netuid,
to_be_set
));

// Verify the value was set correctly
assert_eq!(SubtensorModule::get_validator_cut(netuid), to_be_set);
});
}

#[test]
fn test_sudo_set_validator_cut_root() {
new_test_ext().execute_with(|| {
let netuid = NetUid::from(4);
let to_be_set: u16 = 10000; // 100% cut

// Set up a network
add_network(netuid, 10);

// Test that root can set the validator cut successfully
assert_ok!(AdminUtils::sudo_set_validator_cut(
<<Test as Config>::RuntimeOrigin>::root(),
netuid,
to_be_set
));

// Verify the value was set correctly
assert_eq!(SubtensorModule::get_validator_cut(netuid), to_be_set);
});
}

#[test]
fn test_validator_cut_bounds() {
new_test_ext().execute_with(|| {
let netuid = NetUid::from(5);
let min_cut: u16 = 0; // 0% cut
let max_cut: u16 = u16::MAX; // 100% cut

// Set up a network
add_network(netuid, 10);

// Test minimum value
SubtensorModule::set_validator_cut(netuid, min_cut);
assert_eq!(SubtensorModule::get_validator_cut(netuid), min_cut);

// Test maximum value
SubtensorModule::set_validator_cut(netuid, max_cut);
assert_eq!(SubtensorModule::get_validator_cut(netuid), max_cut);
});
}
4 changes: 3 additions & 1 deletion pallets/subtensor/src/coinbase/run_coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,10 +663,12 @@ impl<T: Config> Pallet<T> {
});
log::debug!("incentive_sum: {incentive_sum:?}");

let validator_cut = Self::get_validator_cut(netuid);
let pending_validator_alpha = if !incentive_sum.is_zero() {
pending_alpha
.saturating_add(pending_swapped)
.saturating_div(2.into())
.saturating_div(AlphaCurrency::from(u16::MAX as u64))
.saturating_mul(AlphaCurrency::from(validator_cut as u64))
.saturating_sub(pending_swapped)
} else {
// If the incentive is 0, then Validators get 100% of the alpha.
Expand Down
11 changes: 11 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,17 @@ pub mod pallet {
pub type ImmuneOwnerUidsLimit<T> =
StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmuneOwnerUidsLimit<T>>;

#[pallet::type_value]
/// Default validator cut 50%
pub fn DefaultValidatorCut<T: Config>() -> u16 {
u16::MAX / 2
}

#[pallet::storage]
/// --- MAP ( netuid ) --> Validator cut
pub type ValidatorCut<T> =
StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultValidatorCut<T>>;

/// =======================================
/// ==== Subnetwork Consensus Storage ====
/// =======================================
Expand Down
20 changes: 20 additions & 0 deletions pallets/subtensor/src/staking/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,24 @@ impl<T: Config> Pallet<T> {
*total = total.saturating_sub(amount);
});
}

/// Gets the validator cut for a given subnet.
///
/// # Arguments
/// * `netuid` - The network UID.
///
/// # Returns
/// The validator cut value for the subnet.
pub fn get_validator_cut(netuid: NetUid) -> u16 {
ValidatorCut::<T>::get(netuid)
}

/// Sets the validator cut for a given subnet.
///
/// # Arguments
/// * `netuid` - The network UID.
/// * `cut` - The validator cut value to set.
pub fn set_validator_cut(netuid: NetUid, cut: u16) {
ValidatorCut::<T>::insert(netuid, cut);
}
}
Loading