Skip to content

Commit be47139

Browse files
authored
Merge pull request #2302 from latent-to/fix/ensure-recycle-at-most-amount
fix: ensure burn/recycle at most amount
2 parents 07c22cb + 47fdfb8 commit be47139

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

pallets/subtensor/src/macros/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,5 +266,7 @@ mod errors {
266266
InvalidRootClaimThreshold,
267267
/// Exceeded subnet limit number or zero.
268268
InvalidSubnetNumber,
269+
/// Unintended precision loss when unstaking alpha
270+
PrecisionLoss,
269271
}
270272
}

pallets/subtensor/src/staking/recycle_alpha.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ impl<T: Config> Pallet<T> {
5555
&hotkey, &coldkey, netuid, amount,
5656
);
5757

58+
ensure!(actual_alpha_decrease <= amount, Error::<T>::PrecisionLoss);
59+
5860
// Recycle means we should decrease the alpha issuance tracker.
59-
Self::recycle_subnet_alpha(netuid, amount);
61+
Self::recycle_subnet_alpha(netuid, actual_alpha_decrease);
6062

6163
Self::deposit_event(Event::AlphaRecycled(
6264
coldkey,
@@ -120,7 +122,9 @@ impl<T: Config> Pallet<T> {
120122
&hotkey, &coldkey, netuid, amount,
121123
);
122124

123-
Self::burn_subnet_alpha(netuid, amount);
125+
ensure!(actual_alpha_decrease <= amount, Error::<T>::PrecisionLoss);
126+
127+
Self::burn_subnet_alpha(netuid, actual_alpha_decrease);
124128

125129
// Deposit event
126130
Self::deposit_event(Event::AlphaBurned(

pallets/subtensor/src/tests/recycle_alpha.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use approx::assert_abs_diff_eq;
22
use frame_support::{assert_noop, assert_ok, traits::Currency};
33
use sp_core::U256;
4+
use substrate_fixed::types::U64F64;
45
use subtensor_runtime_common::{AlphaCurrency, Currency as CurrencyT};
56

67
use super::mock;
@@ -543,3 +544,77 @@ fn test_burn_errors() {
543544
);
544545
});
545546
}
547+
548+
#[test]
549+
fn test_recycle_precision_loss() {
550+
new_test_ext(1).execute_with(|| {
551+
let coldkey = U256::from(1);
552+
let hotkey = U256::from(2);
553+
554+
let netuid = add_dynamic_network(&hotkey, &coldkey);
555+
556+
Balances::make_free_balance_be(&coldkey, 1_000_000_000);
557+
// sanity check
558+
assert!(SubtensorModule::if_subnet_exist(netuid));
559+
560+
// add stake to coldkey-hotkey pair so we can recycle it
561+
let stake = 200_000;
562+
increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake.into(), netuid);
563+
564+
// amount to recycle
565+
let recycle_amount = AlphaCurrency::from(stake / 2);
566+
567+
// Modify the alpha pool denominator so it's low-precision
568+
let denominator = U64F64::from_num(0.00000001);
569+
TotalHotkeyShares::<Test>::insert(hotkey, netuid, denominator);
570+
Alpha::<Test>::insert((&hotkey, &coldkey, netuid), denominator);
571+
572+
// recycle, expect error due to precision loss
573+
assert_noop!(
574+
SubtensorModule::recycle_alpha(
575+
RuntimeOrigin::signed(coldkey),
576+
hotkey,
577+
recycle_amount,
578+
netuid
579+
),
580+
Error::<Test>::PrecisionLoss
581+
);
582+
});
583+
}
584+
585+
#[test]
586+
fn test_burn_precision_loss() {
587+
new_test_ext(1).execute_with(|| {
588+
let coldkey = U256::from(1);
589+
let hotkey = U256::from(2);
590+
591+
let netuid = add_dynamic_network(&hotkey, &coldkey);
592+
593+
Balances::make_free_balance_be(&coldkey, 1_000_000_000);
594+
// sanity check
595+
assert!(SubtensorModule::if_subnet_exist(netuid));
596+
597+
// add stake to coldkey-hotkey pair so we can recycle it
598+
let stake = 200_000;
599+
increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake.into(), netuid);
600+
601+
// amount to recycle
602+
let burn_amount = AlphaCurrency::from(stake / 2);
603+
604+
// Modify the alpha pool denominator so it's low-precision
605+
let denominator = U64F64::from_num(0.00000001);
606+
TotalHotkeyShares::<Test>::insert(hotkey, netuid, denominator);
607+
Alpha::<Test>::insert((&hotkey, &coldkey, netuid), denominator);
608+
609+
// burn, expect error due to precision loss
610+
assert_noop!(
611+
SubtensorModule::burn_alpha(
612+
RuntimeOrigin::signed(coldkey),
613+
hotkey,
614+
burn_amount,
615+
netuid
616+
),
617+
Error::<Test>::PrecisionLoss
618+
);
619+
});
620+
}

0 commit comments

Comments
 (0)