Skip to content
Merged
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
14 changes: 14 additions & 0 deletions pallets/subtensor/src/staking/stake_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,13 @@ impl<T: Config> Pallet<T> {
netuid,
alpha,
);
if netuid == NetUid::ROOT {
Self::remove_stake_adjust_root_claimed_for_hotkey_and_coldkey(
origin_hotkey,
origin_coldkey,
alpha,
);
}

// Increase alpha on destination keys
let actual_alpha_moved = Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
Expand All @@ -870,6 +877,13 @@ impl<T: Config> Pallet<T> {
netuid,
actual_alpha_decrease,
);
if netuid == NetUid::ROOT {
Self::add_stake_adjust_root_claimed_for_hotkey_and_coldkey(
destination_hotkey,
destination_coldkey,
actual_alpha_decrease.into(),
);
}

// Calculate TAO equivalent based on current price (it is accurate because
// there's no slippage in this move)
Expand Down
232 changes: 232 additions & 0 deletions pallets/subtensor/src/tests/claim_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1825,3 +1825,235 @@ fn test_claim_root_default_mode_keep() {
assert_eq!(RootClaimType::<Test>::get(coldkey), RootClaimTypeEnum::Swap);
});
}

#[test]
fn test_claim_root_with_moved_stake() {
new_test_ext(1).execute_with(|| {
let owner_coldkey = U256::from(1001);
let hotkey = U256::from(1002);
let alice_coldkey = U256::from(1003);
let bob_coldkey = U256::from(1004);
let eve_coldkey = U256::from(1005);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);

SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0
SubtokenEnabled::<Test>::insert(NetUid::ROOT, true);
NetworksAdded::<Test>::insert(NetUid::ROOT, true);

let root_stake = 8_000_000u64;
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&alice_coldkey,
NetUid::ROOT,
root_stake.into(),
);
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&bob_coldkey,
NetUid::ROOT,
root_stake.into(),
);

let initial_total_hotkey_alpha = 10_000_000u64;
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&owner_coldkey,
netuid,
initial_total_hotkey_alpha.into(),
);

// Claim root alpha

assert_ok!(SubtensorModule::set_root_claim_type(
RuntimeOrigin::signed(alice_coldkey),
RootClaimTypeEnum::Keep
),);
assert_ok!(SubtensorModule::set_root_claim_type(
RuntimeOrigin::signed(bob_coldkey),
RootClaimTypeEnum::Keep
),);

assert_ok!(SubtensorModule::set_root_claim_type(
RuntimeOrigin::signed(eve_coldkey),
RootClaimTypeEnum::Keep
),);

// Distribute pending root alpha

let pending_root_alpha = 10_000_000u64;
SubtensorModule::distribute_emission(
netuid,
AlphaCurrency::ZERO,
AlphaCurrency::ZERO,
pending_root_alpha.into(),
AlphaCurrency::ZERO,
);

assert_ok!(SubtensorModule::claim_root(
RuntimeOrigin::signed(alice_coldkey),
BTreeSet::from([netuid])
));
assert_ok!(SubtensorModule::claim_root(
RuntimeOrigin::signed(bob_coldkey),
BTreeSet::from([netuid])
));

// Check stakes
let validator_take_percent = 0.18f64;

let alice_stake: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&alice_coldkey,
netuid,
)
.into();

let bob_stake: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&bob_coldkey,
netuid,
)
.into();

let estimated_stake = (pending_root_alpha as f64) * (1f64 - validator_take_percent) / 2f64;

assert_eq!(alice_stake, bob_stake);

assert_abs_diff_eq!(alice_stake, estimated_stake as u64, epsilon = 100u64,);

// Distribute pending root alpha

let pending_root_alpha = 10_000_000u64;
SubtensorModule::distribute_emission(
netuid,
AlphaCurrency::ZERO,
AlphaCurrency::ZERO,
pending_root_alpha.into(),
AlphaCurrency::ZERO,
);

// Transfer stake to other coldkey
let stake_decrement = root_stake / 2u64;

assert_ok!(SubtensorModule::transfer_stake(
RuntimeOrigin::signed(bob_coldkey,),
eve_coldkey,
hotkey,
NetUid::ROOT,
NetUid::ROOT,
stake_decrement.into(),
));

let eve_stake: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&eve_coldkey,
netuid,
)
.into();

assert_ok!(SubtensorModule::claim_root(
RuntimeOrigin::signed(alice_coldkey),
BTreeSet::from([netuid])
));
assert_ok!(SubtensorModule::claim_root(
RuntimeOrigin::signed(bob_coldkey),
BTreeSet::from([netuid])
));

assert_ok!(SubtensorModule::claim_root(
RuntimeOrigin::signed(eve_coldkey),
BTreeSet::from([netuid])
));

// Check new stakes

let alice_stake2: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&alice_coldkey,
netuid,
)
.into();

let bob_stake2: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&bob_coldkey,
netuid,
)
.into();

let eve_stake2: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&eve_coldkey,
netuid,
)
.into();

// Eve should not have gotten any root claim
let eve_stake_diff = eve_stake2 - eve_stake;
assert_abs_diff_eq!(eve_stake_diff, 0, epsilon = 100u64,);

let estimated_stake = (pending_root_alpha as f64) * (1f64 - validator_take_percent) / 2f64;

let alice_stake_diff = alice_stake2 - alice_stake;
let bob_stake_diff = bob_stake2 - bob_stake;

assert_abs_diff_eq!(alice_stake_diff, bob_stake_diff, epsilon = 100u64,);
assert_abs_diff_eq!(bob_stake_diff, estimated_stake as u64, epsilon = 100u64,);

// Transfer stake back
let stake_increment = stake_decrement;

assert_ok!(SubtensorModule::transfer_stake(
RuntimeOrigin::signed(eve_coldkey,),
bob_coldkey,
hotkey,
NetUid::ROOT,
NetUid::ROOT,
stake_increment.into(),
));

// Distribute pending root alpha

let pending_root_alpha = 10_000_000u64;
SubtensorModule::distribute_emission(
netuid,
AlphaCurrency::ZERO,
AlphaCurrency::ZERO,
pending_root_alpha.into(),
AlphaCurrency::ZERO,
);

assert_ok!(SubtensorModule::claim_root(
RuntimeOrigin::signed(alice_coldkey),
BTreeSet::from([netuid])
));
assert_ok!(SubtensorModule::claim_root(
RuntimeOrigin::signed(bob_coldkey),
BTreeSet::from([netuid])
));

// Check new stakes

let alice_stake3: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&alice_coldkey,
netuid,
)
.into();

let bob_stake3: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&hotkey,
&bob_coldkey,
netuid,
)
.into();

let estimated_stake = (pending_root_alpha as f64) * (1f64 - validator_take_percent) / 2f64;

let alice_stake_diff2 = alice_stake3 - alice_stake2;
let bob_stake_diff2 = bob_stake3 - bob_stake2;

assert_abs_diff_eq!(alice_stake_diff2, bob_stake_diff2, epsilon = 100u64,);
assert_abs_diff_eq!(bob_stake_diff2, estimated_stake as u64, epsilon = 100u64,);
});
}
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,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: 365,
spec_version: 366,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading