Skip to content

Commit e5cd7f3

Browse files
authored
Merge pull request #1947 from opentensor/fix/root-reserves
Fix updating root and stable subnets counters on stakes and unstakes
2 parents d50b8a3 + 5f1634b commit e5cd7f3

File tree

2 files changed

+204
-81
lines changed

2 files changed

+204
-81
lines changed

pallets/subtensor/src/staking/stake_utils.rs

Lines changed: 84 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -572,53 +572,54 @@ impl<T: Config> Pallet<T> {
572572
) -> Result<SwapResult, DispatchError> {
573573
// Step 1: Get the mechanism type for the subnet (0 for Stable, 1 for Dynamic)
574574
let mechanism_id: u16 = SubnetMechanism::<T>::get(netuid);
575-
if mechanism_id == 1 {
576-
let swap_result = T::SwapInterface::swap(
575+
let swap_result = if mechanism_id == 1 {
576+
T::SwapInterface::swap(
577577
netuid.into(),
578578
OrderType::Buy,
579579
tao.into(),
580580
price_limit.into(),
581581
drop_fees,
582582
false,
583-
)?;
584-
let alpha_decrease =
585-
AlphaCurrency::from(swap_result.alpha_reserve_delta.unsigned_abs());
586-
587-
// Decrease Alpha reserves.
588-
Self::decrease_provided_alpha_reserve(netuid.into(), alpha_decrease);
589-
590-
// Increase Alpha outstanding.
591-
SubnetAlphaOut::<T>::mutate(netuid, |total| {
592-
*total = total.saturating_add(swap_result.amount_paid_out.into());
593-
});
594-
595-
// Increase only the protocol TAO reserve. We only use the sum of
596-
// (SubnetTAO + SubnetTaoProvided) in tao_reserve(), so it is irrelevant
597-
// which one to increase.
598-
SubnetTAO::<T>::mutate(netuid, |total| {
599-
*total = total.saturating_add((swap_result.tao_reserve_delta as u64).into());
600-
});
601-
602-
// Increase Total Tao reserves.
603-
TotalStake::<T>::mutate(|total| *total = total.saturating_add(tao));
604-
605-
// Increase total subnet TAO volume.
606-
SubnetVolume::<T>::mutate(netuid, |total| {
607-
*total = total.saturating_add(tao.to_u64() as u128);
608-
});
609-
610-
// Return the alpha received.
611-
Ok(swap_result)
583+
)?
612584
} else {
585+
let abs_delta: u64 = tao.into();
586+
613587
// Step 3.b.1: Stable mechanism, just return the value 1:1
614-
Ok(SwapResult {
588+
SwapResult {
615589
amount_paid_in: tao.into(),
616590
amount_paid_out: tao.into(),
617591
fee_paid: 0,
618-
tao_reserve_delta: 0,
619-
alpha_reserve_delta: 0,
620-
})
621-
}
592+
tao_reserve_delta: abs_delta as i64,
593+
alpha_reserve_delta: (abs_delta as i64).neg(),
594+
}
595+
};
596+
597+
let alpha_decrease = AlphaCurrency::from(swap_result.alpha_reserve_delta.unsigned_abs());
598+
599+
// Decrease Alpha reserves.
600+
Self::decrease_provided_alpha_reserve(netuid.into(), alpha_decrease);
601+
602+
// Increase Alpha outstanding.
603+
SubnetAlphaOut::<T>::mutate(netuid, |total| {
604+
*total = total.saturating_add(swap_result.amount_paid_out.into());
605+
});
606+
607+
// Increase only the protocol TAO reserve. We only use the sum of
608+
// (SubnetTAO + SubnetTaoProvided) in tao_reserve(), so it is irrelevant
609+
// which one to increase.
610+
SubnetTAO::<T>::mutate(netuid, |total| {
611+
*total = total.saturating_add((swap_result.tao_reserve_delta as u64).into());
612+
});
613+
614+
// Increase Total Tao reserves.
615+
TotalStake::<T>::mutate(|total| *total = total.saturating_add(tao));
616+
617+
// Increase total subnet TAO volume.
618+
SubnetVolume::<T>::mutate(netuid, |total| {
619+
*total = total.saturating_add(tao.to_u64() as u128);
620+
});
621+
622+
Ok(swap_result)
622623
}
623624

624625
/// Swaps a subnet's Alpha token for TAO.
@@ -633,62 +634,64 @@ impl<T: Config> Pallet<T> {
633634
// Step 1: Get the mechanism type for the subnet (0 for Stable, 1 for Dynamic)
634635
let mechanism_id: u16 = SubnetMechanism::<T>::get(netuid);
635636
// Step 2: Swap alpha and attain tao
636-
if mechanism_id == 1 {
637-
let swap_result = T::SwapInterface::swap(
637+
let swap_result = if mechanism_id == 1 {
638+
T::SwapInterface::swap(
638639
netuid.into(),
639640
OrderType::Sell,
640641
alpha.into(),
641642
price_limit.into(),
642643
drop_fees,
643644
false,
644-
)?;
645-
646-
// Increase only the protocol Alpha reserve. We only use the sum of
647-
// (SubnetAlphaIn + SubnetAlphaInProvided) in alpha_reserve(), so it is irrelevant
648-
// which one to increase.
649-
SubnetAlphaIn::<T>::mutate(netuid, |total| {
650-
*total = total.saturating_add((swap_result.alpha_reserve_delta as u64).into());
651-
});
652-
653-
// Decrease Alpha outstanding.
654-
// TODO: Deprecate, not accurate in v3 anymore
655-
SubnetAlphaOut::<T>::mutate(netuid, |total| {
656-
*total = total.saturating_sub((swap_result.alpha_reserve_delta as u64).into());
657-
});
658-
659-
// Decrease tao reserves.
660-
Self::decrease_provided_tao_reserve(
661-
netuid.into(),
662-
swap_result
663-
.tao_reserve_delta
664-
.abs()
665-
.try_into()
666-
.unwrap_or(0)
667-
.into(),
668-
);
669-
670-
// Reduce total TAO reserves.
671-
TotalStake::<T>::mutate(|total| {
672-
*total = total.saturating_sub(swap_result.amount_paid_out.into())
673-
});
674-
675-
// Increase total subnet TAO volume.
676-
SubnetVolume::<T>::mutate(netuid, |total| {
677-
*total = total.saturating_add(swap_result.amount_paid_out.into())
678-
});
679-
680-
// Return the tao received.
681-
Ok(swap_result)
645+
)?
682646
} else {
647+
let abs_delta: u64 = alpha.into();
648+
683649
// Step 3.b.1: Stable mechanism, just return the value 1:1
684-
Ok(SwapResult {
650+
SwapResult {
685651
amount_paid_in: alpha.into(),
686652
amount_paid_out: alpha.into(),
687653
fee_paid: 0,
688-
tao_reserve_delta: 0,
689-
alpha_reserve_delta: 0,
690-
})
691-
}
654+
tao_reserve_delta: (abs_delta as i64).neg(),
655+
alpha_reserve_delta: abs_delta as i64,
656+
}
657+
};
658+
659+
// Increase only the protocol Alpha reserve. We only use the sum of
660+
// (SubnetAlphaIn + SubnetAlphaInProvided) in alpha_reserve(), so it is irrelevant
661+
// which one to increase.
662+
SubnetAlphaIn::<T>::mutate(netuid, |total| {
663+
*total = total.saturating_add((swap_result.alpha_reserve_delta as u64).into());
664+
});
665+
666+
// Decrease Alpha outstanding.
667+
// TODO: Deprecate, not accurate in v3 anymore
668+
SubnetAlphaOut::<T>::mutate(netuid, |total| {
669+
*total = total.saturating_sub((swap_result.alpha_reserve_delta as u64).into());
670+
});
671+
672+
// Decrease tao reserves.
673+
Self::decrease_provided_tao_reserve(
674+
netuid.into(),
675+
swap_result
676+
.tao_reserve_delta
677+
.abs()
678+
.try_into()
679+
.unwrap_or(0)
680+
.into(),
681+
);
682+
683+
// Reduce total TAO reserves.
684+
TotalStake::<T>::mutate(|total| {
685+
*total = total.saturating_sub(swap_result.amount_paid_out.into())
686+
});
687+
688+
// Increase total subnet TAO volume.
689+
SubnetVolume::<T>::mutate(netuid, |total| {
690+
*total = total.saturating_add(swap_result.amount_paid_out.into())
691+
});
692+
693+
// Return the tao received.
694+
Ok(swap_result)
692695
}
693696

694697
/// Unstakes alpha from a subnet for a given hotkey and coldkey pair.

pallets/subtensor/src/tests/staking.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5425,3 +5425,123 @@ fn test_stake_rate_limits() {
54255425
)));
54265426
});
54275427
}
5428+
5429+
// cargo test --package pallet-subtensor --lib -- tests::staking::test_add_root_updates_counters --exact --show-output
5430+
#[test]
5431+
fn test_add_root_updates_counters() {
5432+
new_test_ext(0).execute_with(|| {
5433+
let hotkey_account_id = U256::from(561337);
5434+
let coldkey_account_id = U256::from(61337);
5435+
add_network(NetUid::ROOT, 10, 0);
5436+
assert_ok!(SubtensorModule::root_register(
5437+
RuntimeOrigin::signed(coldkey_account_id).clone(),
5438+
hotkey_account_id,
5439+
));
5440+
let stake_amount = 1_000_000_000;
5441+
5442+
// Give it some $$$ in his coldkey balance
5443+
let initial_balance = stake_amount + ExistentialDeposit::get();
5444+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, initial_balance);
5445+
5446+
// Setup SubnetAlphaIn (because we are going to stake)
5447+
SubnetAlphaIn::<Test>::insert(NetUid::ROOT, AlphaCurrency::from(stake_amount));
5448+
5449+
// Stake to hotkey account, and check if the result is ok
5450+
assert_ok!(SubtensorModule::add_stake(
5451+
RuntimeOrigin::signed(coldkey_account_id),
5452+
hotkey_account_id,
5453+
NetUid::ROOT,
5454+
stake_amount.into()
5455+
));
5456+
5457+
// Check if stake has increased
5458+
let new_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id);
5459+
assert_eq!(new_stake, stake_amount.into());
5460+
5461+
// Check if total stake has increased accordingly.
5462+
assert_eq!(SubtensorModule::get_total_stake(), stake_amount.into());
5463+
5464+
// SubnetTAO updated
5465+
assert_eq!(SubnetTAO::<Test>::get(NetUid::ROOT), stake_amount.into());
5466+
5467+
// SubnetAlphaIn updated
5468+
assert_eq!(SubnetAlphaIn::<Test>::get(NetUid::ROOT), 0.into());
5469+
5470+
// SubnetAlphaOut updated
5471+
assert_eq!(
5472+
SubnetAlphaOut::<Test>::get(NetUid::ROOT),
5473+
stake_amount.into()
5474+
);
5475+
5476+
// SubnetVolume updated
5477+
assert_eq!(
5478+
SubnetVolume::<Test>::get(NetUid::ROOT),
5479+
stake_amount as u128
5480+
);
5481+
});
5482+
}
5483+
5484+
// cargo test --package pallet-subtensor --lib -- tests::staking::test_remove_root_updates_counters --exact --show-output
5485+
#[test]
5486+
fn test_remove_root_updates_counters() {
5487+
new_test_ext(0).execute_with(|| {
5488+
let hotkey_account_id = U256::from(561337);
5489+
let coldkey_account_id = U256::from(61337);
5490+
add_network(NetUid::ROOT, 10, 0);
5491+
assert_ok!(SubtensorModule::root_register(
5492+
RuntimeOrigin::signed(coldkey_account_id).clone(),
5493+
hotkey_account_id,
5494+
));
5495+
let stake_amount = 1_000_000_000;
5496+
5497+
// Give it some $$$ in his coldkey balance
5498+
let initial_balance = stake_amount + ExistentialDeposit::get();
5499+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, initial_balance);
5500+
5501+
// Setup existing stake
5502+
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
5503+
&hotkey_account_id,
5504+
&coldkey_account_id,
5505+
NetUid::ROOT,
5506+
stake_amount.into(),
5507+
);
5508+
5509+
// Setup TotalStake, SubnetAlphaOut and SubnetTAO (because we are going to unstake)
5510+
TotalStake::<Test>::set(TaoCurrency::from(stake_amount));
5511+
SubnetTAO::<Test>::insert(NetUid::ROOT, TaoCurrency::from(stake_amount));
5512+
SubnetAlphaOut::<Test>::insert(NetUid::ROOT, AlphaCurrency::from(stake_amount));
5513+
5514+
// Stake to hotkey account, and check if the result is ok
5515+
assert_ok!(SubtensorModule::remove_stake(
5516+
RuntimeOrigin::signed(coldkey_account_id),
5517+
hotkey_account_id,
5518+
NetUid::ROOT,
5519+
stake_amount.into()
5520+
));
5521+
5522+
// Check if stake has been decreased
5523+
let new_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id);
5524+
assert_eq!(new_stake, 0.into());
5525+
5526+
// Check if total stake has decreased accordingly.
5527+
assert_eq!(SubtensorModule::get_total_stake(), 0.into());
5528+
5529+
// SubnetTAO updated
5530+
assert_eq!(SubnetTAO::<Test>::get(NetUid::ROOT), 0.into());
5531+
5532+
// SubnetAlphaIn updated
5533+
assert_eq!(
5534+
SubnetAlphaIn::<Test>::get(NetUid::ROOT),
5535+
stake_amount.into()
5536+
);
5537+
5538+
// SubnetAlphaOut updated
5539+
assert_eq!(SubnetAlphaOut::<Test>::get(NetUid::ROOT), 0.into());
5540+
5541+
// SubnetVolume updated
5542+
assert_eq!(
5543+
SubnetVolume::<Test>::get(NetUid::ROOT),
5544+
stake_amount as u128
5545+
);
5546+
});
5547+
}

0 commit comments

Comments
 (0)