diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index e838f81a30..a62084de5c 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -120,6 +120,8 @@ pub mod pallet { CommitmentSetRateLimitExceeded, /// Space Limit Exceeded for the current interval SpaceLimitExceeded, + /// Indicates that unreserve returned a leftover, which is unexpected. + UnexpectedUnreserveLeftover, } #[pallet::type_value] @@ -266,7 +268,9 @@ pub mod pallet { if old_deposit > id.deposit { let err_amount = T::Currency::unreserve(&who, old_deposit.saturating_sub(id.deposit)); - debug_assert!(err_amount.is_zero()); + if !err_amount.is_zero() { + return Err(Error::::UnexpectedUnreserveLeftover.into()); + } } >::insert(netuid, &who, id); diff --git a/pallets/commitments/src/tests.rs b/pallets/commitments/src/tests.rs index e6bf38c445..f03e99080e 100644 --- a/pallets/commitments/src/tests.rs +++ b/pallets/commitments/src/tests.rs @@ -4,14 +4,17 @@ use sp_std::prelude::*; #[cfg(test)] use crate::{ CommitmentInfo, CommitmentOf, Config, Data, Error, Event, MaxSpace, Pallet, RateLimit, - RevealedCommitments, TimelockedIndex, + Registration, RevealedCommitments, TimelockedIndex, mock::{ - DRAND_QUICKNET_SIG_HEX, RuntimeEvent, RuntimeOrigin, Test, insert_drand_pulse, + Balances, DRAND_QUICKNET_SIG_HEX, RuntimeEvent, RuntimeOrigin, Test, insert_drand_pulse, new_test_ext, produce_ciphertext, }, }; use frame_support::pallet_prelude::Hooks; -use frame_support::{BoundedVec, assert_noop, assert_ok, traits::Get}; +use frame_support::{ + BoundedVec, assert_noop, assert_ok, + traits::{Currency, Get, ReservableCurrency}, +}; use frame_system::Pallet as System; #[allow(clippy::indexing_slicing)] @@ -1220,3 +1223,42 @@ fn on_initialize_reveals_matured_timelocks() { } }); } + +#[test] +fn set_commitment_unreserve_leftover_fails() { + new_test_ext().execute_with(|| { + use frame_system::RawOrigin; + + let netuid = 999; + let who = 99; + + Balances::make_free_balance_be(&who, 10_000); + + let fake_deposit = 100; + let dummy_info = CommitmentInfo { + fields: BoundedVec::try_from(vec![]).expect("empty fields is fine"), + }; + let registration = Registration { + deposit: fake_deposit, + info: dummy_info, + block: 0u64.into(), + }; + + CommitmentOf::::insert(netuid, who, registration); + + assert_ok!(Balances::reserve(&who, fake_deposit)); + assert_eq!(Balances::reserved_balance(who), 100); + + Balances::unreserve(&who, 10_000); + assert_eq!(Balances::reserved_balance(who), 0); + + let commit_small = Box::new(CommitmentInfo { + fields: BoundedVec::try_from(vec![]).expect("no fields is fine"), + }); + + assert_noop!( + Pallet::::set_commitment(RawOrigin::Signed(who).into(), netuid, commit_small), + Error::::UnexpectedUnreserveLeftover + ); + }); +} diff --git a/pallets/subtensor/src/macros/events.rs b/pallets/subtensor/src/macros/events.rs index 04a2093abf..e756145f3a 100644 --- a/pallets/subtensor/src/macros/events.rs +++ b/pallets/subtensor/src/macros/events.rs @@ -14,9 +14,9 @@ mod events { /// a network is removed. NetworkRemoved(u16), /// stake has been transferred from the a coldkey account onto the hotkey staking account. - StakeAdded(T::AccountId, T::AccountId, u64, u64, u16), + StakeAdded(T::AccountId, T::AccountId, u64, u64, u16, u64), /// stake has been removed from the hotkey staking account onto the coldkey account. - StakeRemoved(T::AccountId, T::AccountId, u64, u64, u16), + StakeRemoved(T::AccountId, T::AccountId, u64, u64, u16, u64), /// stake has been moved from origin (hotkey, subnet ID) to destination (hotkey, subnet ID) of this amount (in TAO). StakeMoved(T::AccountId, T::AccountId, u16, T::AccountId, u16, u64), /// a caller successfully sets their weights on a subnetwork. diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 53e8dbaa55..7757851649 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -794,14 +794,16 @@ impl Pallet { tao_unstaked, actual_alpha_decrease, netuid, + actual_fee, )); log::debug!( - "StakeRemoved( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?} )", + "StakeRemoved( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?}, fee: {:?} )", coldkey.clone(), hotkey.clone(), tao_unstaked, actual_alpha_decrease, - netuid + netuid, + actual_fee ); // Step 6: Return the amount of TAO unstaked. @@ -857,14 +859,16 @@ impl Pallet { tao_staked, actual_alpha, netuid, + actual_fee, )); log::debug!( - "StakeAdded( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?} )", + "StakeAdded( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?}, fee: {:?} )", coldkey.clone(), hotkey.clone(), tao_staked, actual_alpha, - netuid + netuid, + actual_fee ); // Step 7: Return the amount of alpha staked diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index 310c1d5fde..e4721c03f5 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -239,7 +239,7 @@ impl Pallet { netuid_to_register, mechid ); - Self::deposit_event(Event::NetworkAdded(netuid_to_register, 0)); + Self::deposit_event(Event::NetworkAdded(netuid_to_register, mechid)); // --- 17. Return success. Ok(()) @@ -272,7 +272,6 @@ impl Pallet { Self::set_target_registrations_per_interval(netuid, 1); Self::set_adjustment_alpha(netuid, 17_893_341_751_498_265_066); // 18_446_744_073_709_551_615 * 0.97 = 17_893_341_751_498_265_066 Self::set_immunity_period(netuid, 5000); - Self::set_min_burn(netuid, 1); Self::set_min_difficulty(netuid, u64::MAX); Self::set_max_difficulty(netuid, u64::MAX); diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index cf0f14ea7c..9729d55d1a 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -152,7 +152,7 @@ parameter_types! { pub const InitialTxDelegateTakeRateLimit: u64 = 1; // 1 block take rate limit for testing pub const InitialTxChildKeyTakeRateLimit: u64 = 1; // 1 block take rate limit for testing pub const InitialBurn: u64 = 0; - pub const InitialMinBurn: u64 = 0; + pub const InitialMinBurn: u64 = 500_000; pub const InitialMaxBurn: u64 = 1_000_000_000; pub const InitialValidatorPruneLen: u64 = 0; pub const InitialScalingLawPower: u16 = 50; diff --git a/pallets/subtensor/src/tests/registration.rs b/pallets/subtensor/src/tests/registration.rs index 50d409561d..1ae16d95c0 100644 --- a/pallets/subtensor/src/tests/registration.rs +++ b/pallets/subtensor/src/tests/registration.rs @@ -1,5 +1,6 @@ #![allow(clippy::unwrap_used)] +use approx::assert_abs_diff_eq; use frame_support::traits::Currency; use super::mock::*; @@ -535,11 +536,11 @@ fn test_burn_adjustment() { new_test_ext(1).execute_with(|| { let netuid: u16 = 1; let tempo: u16 = 13; - let burn_cost: u64 = 1000; + let init_burn_cost: u64 = InitialMinBurn::get() + 10_000; let adjustment_interval = 1; let target_registrations_per_interval = 1; add_network(netuid, tempo, 0); - SubtensorModule::set_burn(netuid, burn_cost); + SubtensorModule::set_burn(netuid, init_burn_cost); SubtensorModule::set_adjustment_interval(netuid, adjustment_interval); SubtensorModule::set_adjustment_alpha(netuid, 58000); // Set to old value. SubtensorModule::set_target_registrations_per_interval( @@ -550,7 +551,7 @@ fn test_burn_adjustment() { // Register key 1. let hotkey_account_id_1 = U256::from(1); let coldkey_account_id_1 = U256::from(1); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id_1, 10000); + SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id_1, init_burn_cost); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(hotkey_account_id_1), netuid, @@ -560,7 +561,7 @@ fn test_burn_adjustment() { // Register key 2. let hotkey_account_id_2 = U256::from(2); let coldkey_account_id_2 = U256::from(2); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id_2, 10000); + SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id_2, init_burn_cost); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(hotkey_account_id_2), netuid, @@ -571,8 +572,13 @@ fn test_burn_adjustment() { // Step the block and trigger the adjustment. step_block(1); - // Check the adjusted burn. - assert_eq!(SubtensorModule::get_burn_as_u64(netuid), 1500); + // Check the adjusted burn is above the initial min burn. + assert!(SubtensorModule::get_burn_as_u64(netuid) > init_burn_cost); + assert_abs_diff_eq!( + SubtensorModule::get_burn_as_u64(netuid), + init_burn_cost.saturating_mul(3).saturating_div(2), // 1.5x + epsilon = 1000 + ); }); } diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index 1daf19159f..4ceeaab897 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -222,3 +222,40 @@ fn test_do_start_call_ok_with_same_block_number_after_coinbase() { } }); } + +#[test] +fn test_register_network_min_burn_at_default() { + new_test_ext(1).execute_with(|| { + let sn_owner_coldkey = U256::from(0); + let sn_owner_hotkey = U256::from(1); + let cost = SubtensorModule::get_network_lock_cost(); + + // Give coldkey enough for lock + SubtensorModule::add_balance_to_coldkey_account(&sn_owner_coldkey, cost + 10_000_000_000); + + // Register network + assert_ok!(SubtensorModule::register_network( + <::RuntimeOrigin>::signed(sn_owner_coldkey), + sn_owner_hotkey + )); + // Get last events + let events = System::events(); + let min_burn_event = events + .iter() + .filter(|event| { + matches!( + event.event, + RuntimeEvent::SubtensorModule(Event::::NetworkAdded(..)) + ) + }) + .last(); + + let netuid = match min_burn_event.map(|event| event.event.clone()) { + Some(RuntimeEvent::SubtensorModule(Event::::NetworkAdded(netuid, _))) => netuid, + _ => panic!("Expected NetworkAdded event"), + }; + + // Check min burn is set to default + assert_eq!(MinBurn::::get(netuid), InitialMinBurn::get()); + }); +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index ee920ef930..1aec928978 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -207,7 +207,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: 255, + spec_version: 256, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,