Skip to content

Commit cfe38a5

Browse files
committed
More tests for dividend variables
1 parent ee4941d commit cfe38a5

File tree

2 files changed

+182
-11
lines changed

2 files changed

+182
-11
lines changed

pallets/subtensor/src/staking/stake_utils.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,14 @@ impl<T: Config> Pallet<T> {
11081108
// Otherwise, calculate the fee based on the alpha estimate
11091109
// Here we are using TotalHotkeyAlphaLastEpoch, which is exactly the value that
11101110
// was used to calculate AlphaDividendsPerSubnet
1111-
let mut fee = alpha_estimate
1111+
let tao_estimate = U96F32::saturating_from_num(
1112+
Self::sim_swap_alpha_for_tao(
1113+
origin_netuid,
1114+
alpha_estimate.saturating_to_num::<u64>(),
1115+
)
1116+
.unwrap_or(0),
1117+
);
1118+
let mut fee = tao_estimate
11121119
.saturating_mul(
11131120
U96F32::saturating_from_num(AlphaDividendsPerSubnet::<T>::get(
11141121
origin_netuid,
@@ -1118,14 +1125,13 @@ impl<T: Config> Pallet<T> {
11181125
TotalHotkeyAlphaLastEpoch::<T>::get(&origin_hotkey, origin_netuid),
11191126
)),
11201127
)
1121-
.saturating_mul(Self::get_alpha_price(origin_netuid)) // fee needs to be in TAO
11221128
.saturating_to_num::<u64>();
11231129

11241130
// 0.005% per epoch matches to 44% annual in compound interest. Do not allow the fee
11251131
// to be lower than that. (1.00005^(365*20) ~= 1.44)
11261132
let apr_20_percent = U96F32::saturating_from_num(0.00005);
11271133
fee = fee.max(
1128-
alpha_estimate
1134+
tao_estimate
11291135
.saturating_mul(apr_20_percent)
11301136
.saturating_to_num::<u64>(),
11311137
);

pallets/subtensor/src/tests/staking.rs

+173-8
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,170 @@ fn test_remove_stake_total_issuance_no_change() {
771771
});
772772
}
773773

774+
// cargo test --package pallet-subtensor --lib -- tests::staking::test_remove_prev_epoch_stake --exact --show-output --nocapture
775+
#[test]
776+
fn test_remove_prev_epoch_stake() {
777+
new_test_ext(1).execute_with(|| {
778+
let def_fee = DefaultStakingFee::<Test>::get();
779+
780+
// Test case: (amount_to_stake, AlphaDividendsPerSubnet, TotalHotkeyAlphaLastEpoch, expected_fee)
781+
[
782+
// No previous epoch stake and low hotkey stake
783+
(
784+
DefaultMinStake::<Test>::get() * 10,
785+
0_u64,
786+
1000_u64,
787+
def_fee * 2,
788+
),
789+
// Same, but larger amount to stake - we get 0.005% for unstake
790+
(
791+
1_000_000_000,
792+
0_u64,
793+
1000_u64,
794+
(1_000_000_000_f64 * 0.00005) as u64 + def_fee,
795+
),
796+
(
797+
100_000_000_000,
798+
0_u64,
799+
1000_u64,
800+
(100_000_000_000_f64 * 0.00005) as u64 + def_fee,
801+
),
802+
// Lower previous epoch stake than current stake
803+
// Staking/unstaking 100 TAO, divs / total = 0.1 => fee is 1 TAO
804+
(
805+
100_000_000_000,
806+
1_000_000_000_u64,
807+
10_000_000_000_u64,
808+
(100_000_000_000_f64 * 0.1) as u64 + def_fee,
809+
),
810+
// Staking/unstaking 100 TAO, divs / total = 0.001 => fee is 0.01 TAO
811+
(
812+
100_000_000_000,
813+
10_000_000_u64,
814+
10_000_000_000_u64,
815+
(100_000_000_000_f64 * 0.001) as u64 + def_fee,
816+
),
817+
// Higher previous epoch stake than current stake
818+
(
819+
1_000_000_000,
820+
100_000_000_000_u64,
821+
100_000_000_000_000_u64,
822+
(1_000_000_000_f64 * 0.001) as u64 + def_fee,
823+
),
824+
]
825+
.iter()
826+
.for_each(
827+
|(amount_to_stake, alpha_divs, hotkey_alpha, expected_fee)| {
828+
let subnet_owner_coldkey = U256::from(1);
829+
let subnet_owner_hotkey = U256::from(2);
830+
let hotkey_account_id = U256::from(581337);
831+
let coldkey_account_id = U256::from(81337);
832+
let amount = *amount_to_stake;
833+
let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey);
834+
register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123);
835+
836+
// Give it some $$$ in his coldkey balance
837+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount);
838+
AlphaDividendsPerSubnet::<Test>::insert(netuid, hotkey_account_id, *alpha_divs);
839+
TotalHotkeyAlphaLastEpoch::<Test>::insert(hotkey_account_id, netuid, *hotkey_alpha);
840+
let balance_before = SubtensorModule::get_coldkey_balance(&coldkey_account_id);
841+
842+
// Stake to hotkey account, and check if the result is ok
843+
assert_ok!(SubtensorModule::add_stake(
844+
RuntimeOrigin::signed(coldkey_account_id),
845+
hotkey_account_id,
846+
netuid,
847+
amount
848+
));
849+
850+
// Remove all stake
851+
let stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
852+
&hotkey_account_id,
853+
&coldkey_account_id,
854+
netuid,
855+
);
856+
857+
assert_ok!(SubtensorModule::remove_stake(
858+
RuntimeOrigin::signed(coldkey_account_id),
859+
hotkey_account_id,
860+
netuid,
861+
stake
862+
));
863+
864+
// Measure actual fee
865+
let balance_after = SubtensorModule::get_coldkey_balance(&coldkey_account_id);
866+
let actual_fee = balance_before - balance_after;
867+
868+
assert_abs_diff_eq!(actual_fee, *expected_fee, epsilon = *expected_fee / 100,);
869+
},
870+
);
871+
});
872+
}
873+
874+
// cargo test --package pallet-subtensor --lib -- tests::staking::test_staking_sets_div_variables --exact --show-output --nocapture
875+
#[test]
876+
fn test_staking_sets_div_variables() {
877+
new_test_ext(1).execute_with(|| {
878+
let subnet_owner_coldkey = U256::from(1);
879+
let subnet_owner_hotkey = U256::from(2);
880+
let hotkey_account_id = U256::from(581337);
881+
let coldkey_account_id = U256::from(81337);
882+
let amount = 100_000_000_000;
883+
let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey);
884+
let tempo = 10;
885+
Tempo::<Test>::insert(netuid, tempo);
886+
register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123);
887+
888+
// Give it some $$$ in his coldkey balance
889+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount);
890+
891+
// Verify that divident variables are clear in the beginning
892+
assert_eq!(
893+
AlphaDividendsPerSubnet::<Test>::get(netuid, hotkey_account_id),
894+
0
895+
);
896+
assert_eq!(
897+
TotalHotkeyAlphaLastEpoch::<Test>::get(hotkey_account_id, netuid),
898+
0
899+
);
900+
901+
// Stake to hotkey account, and check if the result is ok
902+
assert_ok!(SubtensorModule::add_stake(
903+
RuntimeOrigin::signed(coldkey_account_id),
904+
hotkey_account_id,
905+
netuid,
906+
amount
907+
));
908+
909+
// Verify that divident variables are still clear in the beginning
910+
assert_eq!(
911+
AlphaDividendsPerSubnet::<Test>::get(netuid, hotkey_account_id),
912+
0
913+
);
914+
assert_eq!(
915+
TotalHotkeyAlphaLastEpoch::<Test>::get(hotkey_account_id, netuid),
916+
0
917+
);
918+
919+
// Wait for 1 epoch
920+
step_block(tempo + 1);
921+
922+
// Verify that divident variables have been set
923+
let stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
924+
&hotkey_account_id,
925+
&coldkey_account_id,
926+
netuid,
927+
);
928+
929+
assert!(AlphaDividendsPerSubnet::<Test>::get(netuid, hotkey_account_id) > 0);
930+
assert_abs_diff_eq!(
931+
TotalHotkeyAlphaLastEpoch::<Test>::get(hotkey_account_id, netuid),
932+
stake,
933+
epsilon = stake / 100_000
934+
);
935+
});
936+
}
937+
774938
/***********************************************************
775939
staking::get_coldkey_balance() tests
776940
************************************************************/
@@ -2300,7 +2464,7 @@ fn test_remove_stake_fee_realistic_values() {
23002464
SubnetTAO::<Test>::insert(netuid, tao_reserve.to_num::<u64>());
23012465
SubnetAlphaIn::<Test>::insert(netuid, alpha_in.to_num::<u64>());
23022466
AlphaDividendsPerSubnet::<Test>::insert(netuid, hotkey, alpha_divs);
2303-
let current_price = SubtensorModule::get_alpha_price(netuid).to_num::<f64>();
2467+
TotalHotkeyAlphaLastEpoch::<Test>::insert(hotkey, netuid, alpha_to_unstake);
23042468

23052469
// Add stake first time to init TotalHotkeyAlpha
23062470
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
@@ -2310,17 +2474,18 @@ fn test_remove_stake_fee_realistic_values() {
23102474
alpha_to_unstake,
23112475
);
23122476

2313-
// Estimate fees
2314-
let mut expected_fee: f64 = current_price * alpha_divs as f64;
2315-
if expected_fee < alpha_to_unstake as f64 * 0.00005 {
2316-
expected_fee = alpha_to_unstake as f64 * 0.00005;
2317-
}
2318-
23192477
// Remove stake to measure fee
23202478
let balance_before = SubtensorModule::get_coldkey_balance(&coldkey);
23212479
let expected_tao_no_fee =
23222480
SubtensorModule::sim_swap_alpha_for_tao(netuid, alpha_to_unstake).unwrap();
23232481

2482+
// Estimate fees
2483+
let mut expected_fee =
2484+
expected_tao_no_fee as f64 * alpha_divs as f64 / alpha_to_unstake as f64;
2485+
if expected_fee < expected_tao_no_fee as f64 * 0.00005 {
2486+
expected_fee = expected_tao_no_fee as f64 * 0.00005;
2487+
}
2488+
23242489
assert_ok!(SubtensorModule::remove_stake(
23252490
RuntimeOrigin::signed(coldkey),
23262491
hotkey,
@@ -3942,7 +4107,7 @@ fn test_remove_99_9991_per_cent_stake_removes_all() {
39424107
assert_abs_diff_eq!(
39434108
SubtensorModule::get_coldkey_balance(&coldkey_account_id),
39444109
amount - fee,
3945-
epsilon = 10000,
4110+
epsilon = 100000,
39464111
);
39474112
assert_eq!(
39484113
SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id),

0 commit comments

Comments
 (0)