From a3d902428111fb12b9310e515b0e3e7b75d3dc95 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Thu, 6 Mar 2025 14:17:50 -0500 Subject: [PATCH 1/3] Initial slow down for price ema --- pallets/subtensor/src/staking/stake_utils.rs | 8 ++- pallets/subtensor/src/tests/coinbase.rs | 64 +++++++++++++++++--- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 0a3659b6ac..afecdb6d51 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -57,7 +57,13 @@ impl Pallet { } } pub fn update_moving_price(netuid: u16) { - let alpha: I96F32 = SubnetMovingAlpha::::get(); + let blocks_since_registration = I96F32::saturating_from_num( + Self::get_current_block_as_u64().saturating_sub(NetworkRegisteredAt::::get(netuid)), + ); + let alpha: I96F32 = + SubnetMovingAlpha::::get().saturating_mul(blocks_since_registration.safe_div( + blocks_since_registration.saturating_add(I96F32::saturating_from_num(7200)), + )); let minus_alpha: I96F32 = I96F32::saturating_from_num(1.0).saturating_sub(alpha); let current_price: I96F32 = alpha .saturating_mul(Self::get_alpha_price(netuid).min(I96F32::saturating_from_num(1.0))); diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 94cb786e48..686e94e199 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -195,6 +195,9 @@ fn test_coinbase_moving_prices() { SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1) ); + // Skip some blocks so that EMA price is now slowed down + System::set_block_number(7_200_000); + SubtensorModule::update_moving_price(netuid); assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), @@ -207,10 +210,7 @@ fn test_coinbase_moving_prices() { // Run moving 1 times. SubtensorModule::update_moving_price(netuid); // Assert price is == 100% of the real price. - assert_eq!( - SubtensorModule::get_moving_alpha_price(netuid), - I96F32::from_num(1.0) - ); + assert!(I96F32::from_num(1.0) - SubtensorModule::get_moving_alpha_price(netuid) < 0.001); // Set price to zero. SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); SubnetMovingAlpha::::set(I96F32::from_num(0.1)); @@ -222,13 +222,63 @@ fn test_coinbase_moving_prices() { SubtensorModule::update_moving_price(netuid); SubtensorModule::update_moving_price(netuid); // Assert price is > 50% of the real price. - assert_eq!( - SubtensorModule::get_moving_alpha_price(netuid), - I96F32::from_num(0.468559) + assert!( + (I96F32::from_num(0.468559) - SubtensorModule::get_moving_alpha_price(netuid)).abs() + < 0.001 ); }); } +// Test moving price updates slow down at the beginning. +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_update_moving_price_initial --exact --show-output --nocapture +#[test] +fn test_update_moving_price_initial() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + add_network(netuid, 1, 0); + // Set current price to 1.0 + SubnetTAO::::insert(netuid, 1_000_000); + SubnetAlphaIn::::insert(netuid, 1_000_000); + SubnetMechanism::::insert(netuid, 1); + SubnetMovingAlpha::::set(I96F32::from_num(0.5)); + SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); + + // Registered recently + System::set_block_number(510); + NetworkRegisteredAt::::insert(netuid, 500); + + SubtensorModule::update_moving_price(netuid); + + let new_price = SubnetMovingPrice::::get(netuid); + assert!(new_price.to_num::() < 0.001); + }); +} + +// Test moving price updates slow down at the beginning. +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_update_moving_price_after_time --exact --show-output --nocapture +#[test] +fn test_update_moving_price_after_time() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + add_network(netuid, 1, 0); + // Set current price to 1.0 + SubnetTAO::::insert(netuid, 1_000_000); + SubnetAlphaIn::::insert(netuid, 1_000_000); + SubnetMechanism::::insert(netuid, 1); + SubnetMovingAlpha::::set(I96F32::from_num(0.5)); + SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); + + // Registered long time ago + System::set_block_number(7_200_500); + NetworkRegisteredAt::::insert(netuid, 500); + + SubtensorModule::update_moving_price(netuid); + + let new_price = SubnetMovingPrice::::get(netuid); + assert!((new_price.to_num::() - 0.5).abs() < 0.001); + }); +} + // Test basic alpha issuance in coinbase mechanism. // This test verifies that: // - Alpha issuance is initialized to 0 for new subnets From c1d825603387f81a8d3f9a564c262d6c9f114bbb Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Thu, 6 Mar 2025 14:48:25 -0500 Subject: [PATCH 2/3] bump --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 11ca6d6d03..78e26d5dcb 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -228,7 +228,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: 245, + spec_version: 246, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 67f5aec139f04d987f980080583afd17fdb54216 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Thu, 6 Mar 2025 15:46:17 -0500 Subject: [PATCH 3/3] Extend slow-down to 2 weeks --- pallets/subtensor/src/staking/stake_utils.rs | 3 ++- pallets/subtensor/src/tests/coinbase.rs | 28 +++++++++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index afecdb6d51..b69160a9a4 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -60,9 +60,10 @@ impl Pallet { let blocks_since_registration = I96F32::saturating_from_num( Self::get_current_block_as_u64().saturating_sub(NetworkRegisteredAt::::get(netuid)), ); + // 7200 * 14 = 100_800 is the halving time let alpha: I96F32 = SubnetMovingAlpha::::get().saturating_mul(blocks_since_registration.safe_div( - blocks_since_registration.saturating_add(I96F32::saturating_from_num(7200)), + blocks_since_registration.saturating_add(I96F32::saturating_from_num(100_800)), )); let minus_alpha: I96F32 = I96F32::saturating_from_num(1.0).saturating_sub(alpha); let current_price: I96F32 = alpha diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 686e94e199..61c99c3817 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -190,12 +190,14 @@ fn test_coinbase_moving_prices() { SubnetAlphaIn::::insert(netuid, 1_000_000); SubnetMechanism::::insert(netuid, 1); SubnetMovingPrice::::insert(netuid, I96F32::from_num(1)); + NetworkRegisteredAt::::insert(netuid, 1); + // Updating the moving price keeps it the same. assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1) ); - // Skip some blocks so that EMA price is now slowed down + // Skip some blocks so that EMA price is not slowed down System::set_block_number(7_200_000); SubtensorModule::update_moving_price(netuid); @@ -209,21 +211,23 @@ fn test_coinbase_moving_prices() { SubnetMovingAlpha::::set(I96F32::from_num(1.0)); // Run moving 1 times. SubtensorModule::update_moving_price(netuid); - // Assert price is == 100% of the real price. - assert!(I96F32::from_num(1.0) - SubtensorModule::get_moving_alpha_price(netuid) < 0.001); + // Assert price is ~ 100% of the real price. + assert!(I96F32::from_num(1.0) - SubtensorModule::get_moving_alpha_price(netuid) < 0.05); // Set price to zero. SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); SubnetMovingAlpha::::set(I96F32::from_num(0.1)); - // Run moving 6 times. - SubtensorModule::update_moving_price(netuid); - SubtensorModule::update_moving_price(netuid); - SubtensorModule::update_moving_price(netuid); - SubtensorModule::update_moving_price(netuid); - SubtensorModule::update_moving_price(netuid); - SubtensorModule::update_moving_price(netuid); + + // EMA price 14 days after registration + System::set_block_number(7_200 * 14); + + // Run moving 14 times. + for _ in 0..14 { + SubtensorModule::update_moving_price(netuid); + } + // Assert price is > 50% of the real price. assert!( - (I96F32::from_num(0.468559) - SubtensorModule::get_moving_alpha_price(netuid)).abs() + (I96F32::from_num(0.512325) - SubtensorModule::get_moving_alpha_price(netuid)).abs() < 0.001 ); }); @@ -269,7 +273,7 @@ fn test_update_moving_price_after_time() { SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); // Registered long time ago - System::set_block_number(7_200_500); + System::set_block_number(72_000_500); NetworkRegisteredAt::::insert(netuid, 500); SubtensorModule::update_moving_price(netuid);