From cf3d68645df072ae7ea3b6f6547863b48fcdb03c Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 31 Mar 2026 18:56:22 +0800 Subject: [PATCH 01/12] add origin in extension --- chain-extensions/src/lib.rs | 32 +++++++++++++++++++++----------- chain-extensions/src/tests.rs | 10 +++++++--- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/chain-extensions/src/lib.rs b/chain-extensions/src/lib.rs index 14ea23d9c8..552f9c3ab9 100644 --- a/chain-extensions/src/lib.rs +++ b/chain-extensions/src/lib.rs @@ -63,7 +63,7 @@ where { fn dispatch(env: &mut Env) -> Result where - Env: SubtensorExtensionEnv, + Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let func_id: FunctionId = env.func_id().try_into().map_err(|_| { @@ -101,12 +101,13 @@ where .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let call_result = pallet_subtensor::Pallet::::add_stake( - RawOrigin::Signed(env.caller()).into(), - hotkey, - netuid, - amount_staked, - ); + let origin = match env.origin() { + pallet_contracts::Origin::Signed(caller) => RawOrigin::Signed(caller).into(), + pallet_contracts::Origin::Root => RawOrigin::Root.into(), + }; + + let call_result = + pallet_subtensor::Pallet::::add_stake(origin, hotkey, netuid, amount_staked); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), @@ -527,12 +528,17 @@ where } } -trait SubtensorExtensionEnv { +trait SubtensorExtensionEnv +where + T: pallet_contracts::Config, +{ fn func_id(&self) -> u16; fn charge_weight(&mut self, weight: Weight) -> Result<(), DispatchError>; - fn read_as(&mut self) -> Result; + fn read_as(&mut self) -> Result; fn write_output(&mut self, data: &[u8]) -> Result<(), DispatchError>; - fn caller(&mut self) -> AccountId; + fn caller(&mut self) -> T::AccountId; + #[allow(dead_code)] + fn origin(&mut self) -> pallet_contracts::Origin; } struct ContractsEnvAdapter<'a, 'b, T, E> @@ -558,7 +564,7 @@ where } } -impl<'a, 'b, T, E> SubtensorExtensionEnv for ContractsEnvAdapter<'a, 'b, T, E> +impl<'a, 'b, T, E> SubtensorExtensionEnv for ContractsEnvAdapter<'a, 'b, T, E> where T: pallet_subtensor::Config + pallet_contracts::Config, T::AccountId: Clone, @@ -583,4 +589,8 @@ where fn caller(&mut self) -> T::AccountId { self.env.ext().address().clone() } + + fn origin(&mut self) -> pallet_contracts::Origin { + self.env.ext().caller() + } } diff --git a/chain-extensions/src/tests.rs b/chain-extensions/src/tests.rs index b8956e8659..228d68c889 100644 --- a/chain-extensions/src/tests.rs +++ b/chain-extensions/src/tests.rs @@ -752,7 +752,7 @@ impl MockEnv { } } -impl SubtensorExtensionEnv for MockEnv { +impl SubtensorExtensionEnv for MockEnv { fn func_id(&self) -> u16 { self.func_id } @@ -769,8 +769,8 @@ impl SubtensorExtensionEnv for MockEnv { Ok(()) } - fn read_as(&mut self) -> Result { - T::decode(&mut &self.input[..]).map_err(|_| DispatchError::Other("mock env decode failure")) + fn read_as(&mut self) -> Result { + U::decode(&mut &self.input[..]).map_err(|_| DispatchError::Other("mock env decode failure")) } fn write_output(&mut self, data: &[u8]) -> Result<(), DispatchError> { @@ -782,6 +782,10 @@ impl SubtensorExtensionEnv for MockEnv { fn caller(&mut self) -> AccountId { self.caller } + + fn origin(&mut self) -> pallet_contracts::Origin { + pallet_contracts::Origin::Signed(self.caller.clone()) + } } fn assert_success(ret: RetVal) { From 9ca2d41338fda5afbf2e8881689ac60abdf7239a Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 31 Mar 2026 19:00:39 +0800 Subject: [PATCH 02/12] cargo clippy --- chain-extensions/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain-extensions/src/tests.rs b/chain-extensions/src/tests.rs index 228d68c889..9cf31a5a89 100644 --- a/chain-extensions/src/tests.rs +++ b/chain-extensions/src/tests.rs @@ -784,7 +784,7 @@ impl SubtensorExtensionEnv for MockEnv { } fn origin(&mut self) -> pallet_contracts::Origin { - pallet_contracts::Origin::Signed(self.caller.clone()) + pallet_contracts::Origin::Signed(self.caller) } } From a34f34bb7b1a22af112d0f76fbe136e3591a47da Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 31 Mar 2026 19:38:05 +0800 Subject: [PATCH 03/12] add origin convert func --- chain-extensions/src/lib.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/chain-extensions/src/lib.rs b/chain-extensions/src/lib.rs index 552f9c3ab9..981de66144 100644 --- a/chain-extensions/src/lib.rs +++ b/chain-extensions/src/lib.rs @@ -101,13 +101,14 @@ where .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = match env.origin() { - pallet_contracts::Origin::Signed(caller) => RawOrigin::Signed(caller).into(), - pallet_contracts::Origin::Root => RawOrigin::Root.into(), - }; + let origin = convert_origin(env.origin()); - let call_result = - pallet_subtensor::Pallet::::add_stake(origin, hotkey, netuid, amount_staked); + let call_result = pallet_subtensor::Pallet::::add_stake( + origin.into(), + hotkey, + netuid, + amount_staked, + ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), @@ -528,6 +529,17 @@ where } } +// Convert from the contract origin to the raw origin +fn convert_origin(origin: pallet_contracts::Origin) -> RawOrigin +where + T: pallet_contracts::Config, +{ + match origin { + pallet_contracts::Origin::Signed(caller) => RawOrigin::Signed(caller), + pallet_contracts::Origin::Root => RawOrigin::Root, + } +} + trait SubtensorExtensionEnv where T: pallet_contracts::Config, From 0eccffb95bc25239466182982e4373d81f3472d6 Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 31 Mar 2026 20:44:25 +0800 Subject: [PATCH 04/12] add all functions --- chain-extensions/src/lib.rs | 440 +++++++++++++++++++++++++++++++++- chain-extensions/src/types.rs | 14 ++ 2 files changed, 451 insertions(+), 3 deletions(-) diff --git a/chain-extensions/src/lib.rs b/chain-extensions/src/lib.rs index 981de66144..824d30eb8d 100644 --- a/chain-extensions/src/lib.rs +++ b/chain-extensions/src/lib.rs @@ -101,10 +101,8 @@ where .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - let call_result = pallet_subtensor::Pallet::::add_stake( - origin.into(), + RawOrigin::Signed(env.caller()).into(), hotkey, netuid, amount_staked, @@ -505,6 +503,442 @@ where } } } + FunctionId::CallerAddStakeV1 => { + let weight = Weight::from_parts(394_300_000, 0) + .saturating_add(T::DbWeight::get().reads(18)) + .saturating_add(T::DbWeight::get().writes(9)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, amount_staked): (T::AccountId, NetUid, TaoBalance) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::add_stake( + origin.into(), + hotkey, + netuid, + amount_staked, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerRemoveStakeV1 => { + let weight = Weight::from_parts(196_800_000, 0) + .saturating_add(T::DbWeight::get().reads(19)) + .saturating_add(T::DbWeight::get().writes(10)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, amount_unstaked): (T::AccountId, NetUid, AlphaBalance) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::remove_stake( + origin.into(), + hotkey, + netuid, + amount_unstaked, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerUnstakeAllV1 => { + let weight = Weight::from_parts(28_830_000, 0) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(0)); + + env.charge_weight(weight)?; + + let hotkey: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::unstake_all(origin.into(), hotkey); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerUnstakeAllAlphaV1 => { + let weight = Weight::from_parts(358_500_000, 0) + .saturating_add(T::DbWeight::get().reads(36_u64)) + .saturating_add(T::DbWeight::get().writes(21_u64)); + + env.charge_weight(weight)?; + + let hotkey: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = + pallet_subtensor::Pallet::::unstake_all_alpha(origin.into(), hotkey); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerMoveStakeV1 => { + let weight = Weight::from_parts(164_300_000, 0) + .saturating_add(T::DbWeight::get().reads(15_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)); + + env.charge_weight(weight)?; + + let ( + origin_hotkey, + destination_hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + ): (T::AccountId, T::AccountId, NetUid, NetUid, AlphaBalance) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::move_stake( + origin.into(), + origin_hotkey, + destination_hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerTransferStakeV1 => { + let weight = Weight::from_parts(160_300_000, 0) + .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)); + + env.charge_weight(weight)?; + + let (destination_coldkey, hotkey, origin_netuid, destination_netuid, alpha_amount): ( + T::AccountId, + T::AccountId, + NetUid, + NetUid, + AlphaBalance, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::transfer_stake( + origin.into(), + destination_coldkey, + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerSwapStakeV1 => { + let weight = Weight::from_parts(351_300_000, 0) + .saturating_add(T::DbWeight::get().reads(35_u64)) + .saturating_add(T::DbWeight::get().writes(22_u64)); + + env.charge_weight(weight)?; + + let (hotkey, origin_netuid, destination_netuid, alpha_amount): ( + T::AccountId, + NetUid, + NetUid, + AlphaBalance, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::swap_stake( + origin.into(), + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerAddStakeLimitV1 => { + let weight = Weight::from_parts(402_900_000, 0) + .saturating_add(T::DbWeight::get().reads(24_u64)) + .saturating_add(T::DbWeight::get().writes(15)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, amount_staked, limit_price, allow_partial): ( + T::AccountId, + NetUid, + TaoBalance, + TaoBalance, + bool, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::add_stake_limit( + origin.into(), + hotkey, + netuid, + amount_staked, + limit_price, + allow_partial, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerRemoveStakeLimitV1 => { + let weight = Weight::from_parts(377_400_000, 0) + .saturating_add(T::DbWeight::get().reads(28_u64)) + .saturating_add(T::DbWeight::get().writes(14)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, amount_unstaked, limit_price, allow_partial): ( + T::AccountId, + NetUid, + AlphaBalance, + TaoBalance, + bool, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::remove_stake_limit( + origin.into(), + hotkey, + netuid, + amount_unstaked, + limit_price, + allow_partial, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerSwapStakeLimitV1 => { + let weight = Weight::from_parts(411_500_000, 0) + .saturating_add(T::DbWeight::get().reads(35_u64)) + .saturating_add(T::DbWeight::get().writes(22_u64)); + + env.charge_weight(weight)?; + + let ( + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + limit_price, + allow_partial, + ): (T::AccountId, NetUid, NetUid, AlphaBalance, TaoBalance, bool) = + env.read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::swap_stake_limit( + origin.into(), + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + limit_price, + allow_partial, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerRemoveStakeFullLimitV1 => { + let weight = Weight::from_parts(395_300_000, 0) + .saturating_add(T::DbWeight::get().reads(28_u64)) + .saturating_add(T::DbWeight::get().writes(14_u64)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, limit_price): (T::AccountId, NetUid, Option) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::remove_stake_full_limit( + origin.into(), + hotkey, + netuid, + limit_price, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerSetColdkeyAutoStakeHotkeyV1 => { + let weight = Weight::from_parts(29_930_000, 0) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)); + + env.charge_weight(weight)?; + + let (netuid, hotkey): (NetUid, T::AccountId) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let origin = convert_origin(env.origin()); + + let call_result = pallet_subtensor::Pallet::::set_coldkey_auto_stake_hotkey( + origin.into(), + netuid, + hotkey, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerAddProxyV1 => { + let weight = ::WeightInfo::add_proxy( + ::MaxProxies::get(), + ); + + env.charge_weight(weight)?; + + let delegate: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let delegate_lookup = + <::Lookup as StaticLookup>::Source::from(delegate); + + let origin = convert_origin(env.origin()); + + let call_result = pallet_proxy::Pallet::::add_proxy( + origin.into(), + delegate_lookup, + ProxyType::Staking, + 0u32.into(), + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } + FunctionId::CallerRemoveProxyV1 => { + let weight = ::WeightInfo::remove_proxy( + ::MaxProxies::get(), + ); + + env.charge_weight(weight)?; + + let delegate: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let delegate_lookup = + <::Lookup as StaticLookup>::Source::from(delegate); + + let origin = convert_origin(env.origin()); + + let call_result = pallet_proxy::Pallet::::remove_proxy( + origin.into(), + delegate_lookup, + ProxyType::Staking, + 0u32.into(), + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } FunctionId::GetAlphaPriceV1 => { let netuid: NetUid = env .read_as() diff --git a/chain-extensions/src/types.rs b/chain-extensions/src/types.rs index ee6298ad5b..8473d4c80a 100644 --- a/chain-extensions/src/types.rs +++ b/chain-extensions/src/types.rs @@ -21,6 +21,20 @@ pub enum FunctionId { AddProxyV1 = 13, RemoveProxyV1 = 14, GetAlphaPriceV1 = 15, + CallerAddStakeV1 = 16, + CallerRemoveStakeV1 = 17, + CallerUnstakeAllV1 = 18, + CallerUnstakeAllAlphaV1 = 19, + CallerMoveStakeV1 = 20, + CallerTransferStakeV1 = 21, + CallerSwapStakeV1 = 22, + CallerAddStakeLimitV1 = 23, + CallerRemoveStakeLimitV1 = 24, + CallerSwapStakeLimitV1 = 25, + CallerRemoveStakeFullLimitV1 = 26, + CallerSetColdkeyAutoStakeHotkeyV1 = 27, + CallerAddProxyV1 = 28, + CallerRemoveProxyV1 = 29, } #[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Debug)] From c0a2c2b064c1ac33194e90f87c2dc94c851dbbc3 Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 1 Apr 2026 16:32:36 +0800 Subject: [PATCH 05/12] add tests --- chain-extensions/src/tests.rs | 811 ++++++++++++++++++++++ chain-extensions/src/types.rs | 34 + contract-tests/bittensor/lib.rs | 305 ++++++++ contract-tests/package-lock.json | 37 +- contract-tests/test/wasm.contract.test.ts | 347 +++++++++ contract-tests/yarn.lock | 251 ++++++- 6 files changed, 1745 insertions(+), 40 deletions(-) diff --git a/chain-extensions/src/tests.rs b/chain-extensions/src/tests.rs index 9cf31a5a89..a3a7c45939 100644 --- a/chain-extensions/src/tests.rs +++ b/chain-extensions/src/tests.rs @@ -1009,3 +1009,814 @@ fn get_alpha_price_returns_encoded_price() { ); }); } + +/// `Caller*` dispatch uses `env.origin()` via `convert_origin`; with [`MockEnv`] both match +/// `Signed(caller)`, so outcomes align with non-`Caller` arms while charging Caller weights where +/// they differ. +mod caller_dispatch_tests { + use super::*; + + #[test] + fn caller_add_stake_success_updates_stake_and_returns_success_code() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(10101); + let hotkey = U256::from(10202); + let min_stake = DefaultMinStake::::get(); + let amount_raw = min_stake.to_u64().saturating_mul(10); + let amount: TaoBalance = amount_raw.into(); + + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + mock::setup_reserves( + netuid, + (amount_raw * 1_000_000).into(), + AlphaBalance::from(amount_raw * 10_000_000), + ); + mock::register_ok_neuron(netuid, hotkey, coldkey, 0); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + amount_raw.into(), + ); + + let expected_weight = Weight::from_parts(394_300_000, 0) + .saturating_add(::DbWeight::get().reads(18)) + .saturating_add(::DbWeight::get().writes(9)); + + let mut env = MockEnv::new( + FunctionId::CallerAddStakeV1, + coldkey, + (hotkey, netuid, amount).encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + assert_eq!(env.charged_weight(), Some(expected_weight)); + + let total_stake = + pallet_subtensor::Pallet::::get_total_stake_for_hotkey(&hotkey); + assert!(total_stake > TaoBalance::ZERO); + }); + } + + #[test] + fn caller_remove_stake_with_no_stake_returns_amount_too_low() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(30301); + let hotkey = U256::from(30302); + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + mock::register_ok_neuron(netuid, hotkey, coldkey, 0); + + let min_stake = DefaultMinStake::::get(); + let amount: AlphaBalance = AlphaBalance::from(min_stake.to_u64()); + + let expected_weight = Weight::from_parts(196_800_000, 0) + .saturating_add(::DbWeight::get().reads(19)) + .saturating_add(::DbWeight::get().writes(10)); + + let mut env = MockEnv::new( + FunctionId::CallerRemoveStakeV1, + coldkey, + (hotkey, netuid, amount).encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + match ret { + RetVal::Converging(code) => { + assert_eq!(code, Output::AmountTooLow as u32, "mismatched error output") + } + _ => panic!("unexpected return value"), + } + assert_eq!(env.charged_weight(), Some(expected_weight)); + }); + } + + #[test] + fn caller_unstake_all_success_unstakes_balance() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(40001); + let owner_coldkey = U256::from(40002); + let coldkey = U256::from(50001); + let hotkey = U256::from(50002); + let min_stake = DefaultMinStake::::get(); + let stake_amount_raw = min_stake.to_u64().saturating_mul(200); + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + + mock::setup_reserves( + netuid, + stake_amount_raw.saturating_mul(10).into(), + AlphaBalance::from(stake_amount_raw.saturating_mul(20)), + ); + + mock::register_ok_neuron(netuid, hotkey, coldkey, 0); + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + (stake_amount_raw + 1_000_000_000).into(), + ); + + assert_ok!(pallet_subtensor::Pallet::::add_stake( + RawOrigin::Signed(coldkey).into(), + hotkey, + netuid, + stake_amount_raw.into(), + )); + + mock::remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid); + + let expected_weight = Weight::from_parts(28_830_000, 0) + .saturating_add(::DbWeight::get().reads(6)) + .saturating_add(::DbWeight::get().writes(0)); + + let pre_balance = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + + let mut env = MockEnv::new(FunctionId::CallerUnstakeAllV1, coldkey, hotkey.encode()) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let remaining_alpha = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + assert!(remaining_alpha <= AlphaBalance::from(1_000)); + + let post_balance = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + assert!(post_balance > pre_balance); + }); + } + + #[test] + fn caller_unstake_all_alpha_success_moves_stake_to_root() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(41001); + let owner_coldkey = U256::from(41002); + let coldkey = U256::from(51001); + let hotkey = U256::from(51002); + let min_stake = DefaultMinStake::::get(); + let stake_amount_raw = min_stake.to_u64().saturating_mul(220); + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + + mock::setup_reserves( + netuid, + stake_amount_raw.saturating_mul(20).into(), + AlphaBalance::from(stake_amount_raw.saturating_mul(30)), + ); + + mock::register_ok_neuron(netuid, hotkey, coldkey, 0); + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + (stake_amount_raw + 1_000_000_000).into(), + ); + + assert_ok!(pallet_subtensor::Pallet::::add_stake( + RawOrigin::Signed(coldkey).into(), + hotkey, + netuid, + stake_amount_raw.into(), + )); + + mock::remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid); + + let expected_weight = Weight::from_parts(358_500_000, 0) + .saturating_add(::DbWeight::get().reads(36)) + .saturating_add(::DbWeight::get().writes(21)); + + let mut env = + MockEnv::new(FunctionId::CallerUnstakeAllAlphaV1, coldkey, hotkey.encode()) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let subnet_alpha = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + assert!(subnet_alpha <= AlphaBalance::from(1_000)); + + let root_alpha = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + NetUid::ROOT, + ); + assert!(root_alpha > AlphaBalance::ZERO); + }); + } + + #[test] + fn caller_move_stake_success_moves_alpha_between_hotkeys() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(42001); + let owner_coldkey = U256::from(42002); + let coldkey = U256::from(52001); + let origin_hotkey = U256::from(52002); + let destination_hotkey = U256::from(52003); + + let min_stake = DefaultMinStake::::get(); + let stake_amount_raw = min_stake.to_u64().saturating_mul(240); + + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + mock::setup_reserves( + netuid, + stake_amount_raw.saturating_mul(15).into(), + AlphaBalance::from(stake_amount_raw.saturating_mul(25)), + ); + + mock::register_ok_neuron(netuid, origin_hotkey, coldkey, 0); + mock::register_ok_neuron(netuid, destination_hotkey, coldkey, 1); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + (stake_amount_raw + 1_000_000_000).into(), + ); + + assert_ok!(pallet_subtensor::Pallet::::add_stake( + RawOrigin::Signed(coldkey).into(), + origin_hotkey, + netuid, + stake_amount_raw.into(), + )); + + mock::remove_stake_rate_limit_for_tests(&origin_hotkey, &coldkey, netuid); + + let alpha_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &origin_hotkey, + &coldkey, + netuid, + ); + let alpha_to_move: AlphaBalance = (alpha_before.to_u64() / 2).into(); + + let expected_weight = Weight::from_parts(164_300_000, 0) + .saturating_add(::DbWeight::get().reads(15)) + .saturating_add(::DbWeight::get().writes(7)); + + let mut env = MockEnv::new( + FunctionId::CallerMoveStakeV1, + coldkey, + ( + origin_hotkey, + destination_hotkey, + netuid, + netuid, + alpha_to_move, + ) + .encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let origin_alpha_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &origin_hotkey, + &coldkey, + netuid, + ); + let destination_alpha_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &destination_hotkey, + &coldkey, + netuid, + ); + + assert_eq!(origin_alpha_after, alpha_before - alpha_to_move); + assert_eq!(destination_alpha_after, alpha_to_move); + }); + } + + #[test] + fn caller_transfer_stake_success_moves_between_coldkeys() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(43001); + let owner_coldkey = U256::from(43002); + let origin_coldkey = U256::from(53001); + let destination_coldkey = U256::from(53002); + let hotkey = U256::from(53003); + + let min_stake = DefaultMinStake::::get(); + let stake_amount_raw = min_stake.to_u64().saturating_mul(250); + + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + mock::setup_reserves( + netuid, + stake_amount_raw.saturating_mul(15).into(), + AlphaBalance::from(stake_amount_raw.saturating_mul(25)), + ); + + mock::register_ok_neuron(netuid, hotkey, origin_coldkey, 0); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &origin_coldkey, + (stake_amount_raw + 1_000_000_000).into(), + ); + + assert_ok!(pallet_subtensor::Pallet::::add_stake( + RawOrigin::Signed(origin_coldkey).into(), + hotkey, + netuid, + stake_amount_raw.into(), + )); + + mock::remove_stake_rate_limit_for_tests(&hotkey, &origin_coldkey, netuid); + + let alpha_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &origin_coldkey, + netuid, + ); + let alpha_to_transfer: AlphaBalance = (alpha_before.to_u64() / 3).into(); + + let expected_weight = Weight::from_parts(160_300_000, 0) + .saturating_add(::DbWeight::get().reads(13)) + .saturating_add(::DbWeight::get().writes(6)); + + let mut env = MockEnv::new( + FunctionId::CallerTransferStakeV1, + origin_coldkey, + ( + destination_coldkey, + hotkey, + netuid, + netuid, + alpha_to_transfer, + ) + .encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let origin_alpha_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &origin_coldkey, + netuid, + ); + let destination_alpha_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &destination_coldkey, + netuid, + ); + + assert_eq!(origin_alpha_after, alpha_before - alpha_to_transfer); + assert_eq!(destination_alpha_after, alpha_to_transfer); + }); + } + + #[test] + fn caller_swap_stake_success_moves_between_subnets() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey_a = U256::from(44001); + let owner_coldkey_a = U256::from(44002); + let owner_hotkey_b = U256::from(44003); + let owner_coldkey_b = U256::from(44004); + let coldkey = U256::from(54001); + let hotkey = U256::from(54002); + + let min_stake = DefaultMinStake::::get(); + let stake_amount_raw = min_stake.to_u64().saturating_mul(260); + + let netuid_a = mock::add_dynamic_network(&owner_hotkey_a, &owner_coldkey_a); + let netuid_b = mock::add_dynamic_network(&owner_hotkey_b, &owner_coldkey_b); + + mock::setup_reserves( + netuid_a, + stake_amount_raw.saturating_mul(18).into(), + AlphaBalance::from(stake_amount_raw.saturating_mul(30)), + ); + mock::setup_reserves( + netuid_b, + stake_amount_raw.saturating_mul(20).into(), + AlphaBalance::from(stake_amount_raw.saturating_mul(28)), + ); + + mock::register_ok_neuron(netuid_a, hotkey, coldkey, 0); + mock::register_ok_neuron(netuid_b, hotkey, coldkey, 1); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + (stake_amount_raw + 1_000_000_000).into(), + ); + + assert_ok!(pallet_subtensor::Pallet::::add_stake( + RawOrigin::Signed(coldkey).into(), + hotkey, + netuid_a, + stake_amount_raw.into(), + )); + + mock::remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid_a); + + let alpha_origin_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_a, + ); + let alpha_destination_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_b, + ); + let alpha_to_swap: AlphaBalance = (alpha_origin_before.to_u64() / 3).into(); + + let expected_weight = Weight::from_parts(351_300_000, 0) + .saturating_add(::DbWeight::get().reads(35)) + .saturating_add(::DbWeight::get().writes(22)); + + let mut env = MockEnv::new( + FunctionId::CallerSwapStakeV1, + coldkey, + (hotkey, netuid_a, netuid_b, alpha_to_swap).encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let alpha_origin_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_a, + ); + let alpha_destination_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_b, + ); + + assert!(alpha_origin_after < alpha_origin_before); + assert!(alpha_destination_after > alpha_destination_before); + }); + } + + #[test] + fn caller_add_stake_limit_success_executes_within_price_guard() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(45001); + let owner_coldkey = U256::from(45002); + let coldkey = U256::from(55001); + let hotkey = U256::from(55002); + let amount_raw: u64 = 900_000_000_000; + let limit_price: TaoBalance = 24_000_000_000u64.into(); + + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + + mock::setup_reserves( + netuid, + TaoBalance::from(150_000_000_000_u64), + AlphaBalance::from(100_000_000_000_u64), + ); + + mock::register_ok_neuron(netuid, hotkey, coldkey, 0); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + (amount_raw + 1_000_000_000).into(), + ); + + let stake_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + let balance_before = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + + let expected_weight = Weight::from_parts(402_900_000, 0) + .saturating_add(::DbWeight::get().reads(24)) + .saturating_add(::DbWeight::get().writes(15)); + + let mut env = MockEnv::new( + FunctionId::CallerAddStakeLimitV1, + coldkey, + ( + hotkey, + netuid, + TaoBalance::from(amount_raw), + limit_price, + true, + ) + .encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let stake_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + let balance_after = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + + assert!(stake_after > stake_before); + assert!(stake_after > AlphaBalance::ZERO); + assert!(balance_after < balance_before); + }); + } + + #[test] + fn caller_remove_stake_limit_success_respects_price_limit() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(46001); + let owner_coldkey = U256::from(46002); + let coldkey = U256::from(56001); + let hotkey = U256::from(56002); + let stake_amount_raw: u64 = 320_000_000_000; + + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + mock::setup_reserves( + netuid, + TaoBalance::from(120_000_000_000_u64), + AlphaBalance::from(100_000_000_000_u64), + ); + + mock::register_ok_neuron(netuid, hotkey, coldkey, 0); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + TaoBalance::from(stake_amount_raw + 1_000_000_000), + ); + + assert_ok!(pallet_subtensor::Pallet::::add_stake( + RawOrigin::Signed(coldkey).into(), + hotkey, + netuid, + stake_amount_raw.into(), + )); + + mock::remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid); + + let alpha_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + + let current_price = + ::SwapInterface::current_alpha_price( + netuid.into(), + ); + let limit_price_value = (current_price.to_num::() * 990_000_000f64).round() as u64; + let limit_price: TaoBalance = limit_price_value.into(); + + let alpha_to_unstake: AlphaBalance = (alpha_before.to_u64() / 2).into(); + + let expected_weight = Weight::from_parts(377_400_000, 0) + .saturating_add(::DbWeight::get().reads(28)) + .saturating_add(::DbWeight::get().writes(14)); + + let balance_before = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + + let mut env = MockEnv::new( + FunctionId::CallerRemoveStakeLimitV1, + coldkey, + (hotkey, netuid, alpha_to_unstake, limit_price, true).encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + assert_eq!(env.charged_weight(), Some(expected_weight)); + + let alpha_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + let balance_after = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + + assert!(alpha_after < alpha_before); + assert!(balance_after > balance_before); + }); + } + + #[test] + fn caller_swap_stake_limit_matches_standard_slippage_path() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey_a = U256::from(47001); + let owner_coldkey_a = U256::from(47002); + let owner_hotkey_b = U256::from(47003); + let owner_coldkey_b = U256::from(47004); + let coldkey = U256::from(57001); + let hotkey = U256::from(57002); + + let stake_alpha = AlphaBalance::from(150_000_000_000u64); + + let netuid_a = mock::add_dynamic_network(&owner_hotkey_a, &owner_coldkey_a); + let netuid_b = mock::add_dynamic_network(&owner_hotkey_b, &owner_coldkey_b); + + mock::setup_reserves( + netuid_a, + TaoBalance::from(150_000_000_000_u64), + AlphaBalance::from(110_000_000_000_u64), + ); + mock::setup_reserves( + netuid_b, + TaoBalance::from(120_000_000_000_u64), + AlphaBalance::from(90_000_000_000_u64), + ); + + mock::register_ok_neuron(netuid_a, hotkey, coldkey, 0); + mock::register_ok_neuron(netuid_b, hotkey, coldkey, 1); + + pallet_subtensor::Pallet::::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + netuid_a, + stake_alpha, + ); + + mock::remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid_a); + + let alpha_origin_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_a, + ); + let alpha_destination_before = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_b, + ); + + let alpha_to_swap: AlphaBalance = (alpha_origin_before.to_u64() / 8).into(); + let limit_price: TaoBalance = 100u64.into(); + + let expected_weight = Weight::from_parts(411_500_000, 0) + .saturating_add(::DbWeight::get().reads(35)) + .saturating_add(::DbWeight::get().writes(22)); + + let mut env = MockEnv::new( + FunctionId::CallerSwapStakeLimitV1, + coldkey, + (hotkey, netuid_a, netuid_b, alpha_to_swap, limit_price, true).encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let alpha_origin_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_a, + ); + let alpha_destination_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid_b, + ); + + assert!(alpha_origin_after <= alpha_origin_before); + assert!(alpha_destination_after >= alpha_destination_before); + }); + } + + #[test] + fn caller_remove_stake_full_limit_success_with_limit_price() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(48001); + let owner_coldkey = U256::from(48002); + let coldkey = U256::from(58001); + let hotkey = U256::from(58002); + let stake_amount_raw: u64 = 340_000_000_000; + + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + mock::setup_reserves( + netuid, + TaoBalance::from(130_000_000_000_u64), + AlphaBalance::from(110_000_000_000_u64), + ); + + mock::register_ok_neuron(netuid, hotkey, coldkey, 0); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &coldkey, + TaoBalance::from(stake_amount_raw + 1_000_000_000), + ); + + assert_ok!(pallet_subtensor::Pallet::::add_stake( + RawOrigin::Signed(coldkey).into(), + hotkey, + netuid, + stake_amount_raw.into(), + )); + + mock::remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid); + + let expected_weight = Weight::from_parts(395_300_000, 0) + .saturating_add(::DbWeight::get().reads(28)) + .saturating_add(::DbWeight::get().writes(14)); + + let balance_before = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + + let mut env = MockEnv::new( + FunctionId::CallerRemoveStakeFullLimitV1, + coldkey, + (hotkey, netuid, Option::::None).encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + assert_eq!(env.charged_weight(), Some(expected_weight)); + + let alpha_after = + pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, &coldkey, netuid, + ); + let balance_after = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + + assert!(alpha_after.is_zero()); + assert!(balance_after > balance_before); + }); + } + + #[test] + fn caller_set_coldkey_auto_stake_hotkey_success_sets_destination() { + mock::new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(49001); + let owner_coldkey = U256::from(49002); + let coldkey = U256::from(59001); + let hotkey = U256::from(59002); + + let netuid = mock::add_dynamic_network(&owner_hotkey, &owner_coldkey); + + pallet_subtensor::Owner::::insert(hotkey, coldkey); + pallet_subtensor::OwnedHotkeys::::insert(coldkey, vec![hotkey]); + pallet_subtensor::Uids::::insert(netuid, hotkey, 0u16); + + assert_eq!( + pallet_subtensor::AutoStakeDestination::::get(coldkey, netuid), + None + ); + + let expected_weight = Weight::from_parts(29_930_000, 0) + .saturating_add(::DbWeight::get().reads(4)) + .saturating_add(::DbWeight::get().writes(2)); + + let mut env = MockEnv::new( + FunctionId::CallerSetColdkeyAutoStakeHotkeyV1, + coldkey, + (netuid, hotkey).encode(), + ) + .with_expected_weight(expected_weight); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + assert_eq!(env.charged_weight(), Some(expected_weight)); + + assert_eq!( + pallet_subtensor::AutoStakeDestination::::get(coldkey, netuid), + Some(hotkey) + ); + }); + } + + #[test] + fn caller_add_proxy_success_creates_proxy_relationship() { + mock::new_test_ext(1).execute_with(|| { + let delegator = U256::from(60001); + let delegate = U256::from(60002); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &delegator, + 1_000_000_000.into(), + ); + + let mut env = MockEnv::new(FunctionId::CallerAddProxyV1, delegator, delegate.encode()); + + let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); + assert_success(ret); + + let proxies = pallet_subtensor_proxy::Proxies::::get(delegator).0; + assert_eq!(proxies.len(), 1); + }); + } + + #[test] + fn caller_remove_proxy_success_removes_proxy_relationship() { + mock::new_test_ext(1).execute_with(|| { + let delegator = U256::from(70001); + let delegate = U256::from(70002); + + pallet_subtensor::Pallet::::add_balance_to_coldkey_account( + &delegator, + 1_000_000_000.into(), + ); + + let mut add_env = + MockEnv::new(FunctionId::CallerAddProxyV1, delegator, delegate.encode()); + assert_success(SubtensorChainExtension::::dispatch(&mut add_env).unwrap()); + + let mut remove_env = + MockEnv::new(FunctionId::CallerRemoveProxyV1, delegator, delegate.encode()); + let ret = SubtensorChainExtension::::dispatch(&mut remove_env).unwrap(); + assert_success(ret); + + let proxies_after = pallet_subtensor_proxy::Proxies::::get(delegator).0; + assert_eq!(proxies_after.len(), 0); + }); + } +} diff --git a/chain-extensions/src/types.rs b/chain-extensions/src/types.rs index 8473d4c80a..fd543bf74d 100644 --- a/chain-extensions/src/types.rs +++ b/chain-extensions/src/types.rs @@ -111,3 +111,37 @@ impl From for Output { } } } + +#[cfg(test)] +mod function_id_tests { + use super::FunctionId; + use num_enum::TryFromPrimitive; + + #[test] + fn caller_variants_have_stable_discriminants() { + assert_eq!(FunctionId::GetAlphaPriceV1 as u16, 15); + assert_eq!(FunctionId::CallerAddStakeV1 as u16, 16); + assert_eq!(FunctionId::CallerRemoveStakeV1 as u16, 17); + assert_eq!(FunctionId::CallerUnstakeAllV1 as u16, 18); + assert_eq!(FunctionId::CallerUnstakeAllAlphaV1 as u16, 19); + assert_eq!(FunctionId::CallerMoveStakeV1 as u16, 20); + assert_eq!(FunctionId::CallerTransferStakeV1 as u16, 21); + assert_eq!(FunctionId::CallerSwapStakeV1 as u16, 22); + assert_eq!(FunctionId::CallerAddStakeLimitV1 as u16, 23); + assert_eq!(FunctionId::CallerRemoveStakeLimitV1 as u16, 24); + assert_eq!(FunctionId::CallerSwapStakeLimitV1 as u16, 25); + assert_eq!(FunctionId::CallerRemoveStakeFullLimitV1 as u16, 26); + assert_eq!(FunctionId::CallerSetColdkeyAutoStakeHotkeyV1 as u16, 27); + assert_eq!(FunctionId::CallerAddProxyV1 as u16, 28); + assert_eq!(FunctionId::CallerRemoveProxyV1 as u16, 29); + } + + #[test] + fn caller_ids_roundtrip_try_from_primitive() { + for id in 16u16..=29u16 { + let v = FunctionId::try_from_primitive(id) + .unwrap_or_else(|_| panic!("try_from_primitive failed for {id}")); + assert_eq!(v as u16, id); + } + } +} diff --git a/contract-tests/bittensor/lib.rs b/contract-tests/bittensor/lib.rs index 8867d017d8..c5e988bb9f 100755 --- a/contract-tests/bittensor/lib.rs +++ b/contract-tests/bittensor/lib.rs @@ -22,6 +22,20 @@ pub enum FunctionId { AddProxyV1 = 13, RemoveProxyV1 = 14, GetAlphaPriceV1 = 15, + CallerAddStakeV1 = 16, + CallerRemoveStakeV1 = 17, + CallerUnstakeAllV1 = 18, + CallerUnstakeAllAlphaV1 = 19, + CallerMoveStakeV1 = 20, + CallerTransferStakeV1 = 21, + CallerSwapStakeV1 = 22, + CallerAddStakeLimitV1 = 23, + CallerRemoveStakeLimitV1 = 24, + CallerSwapStakeLimitV1 = 25, + CallerRemoveStakeFullLimitV1 = 26, + CallerSetColdkeyAutoStakeHotkeyV1 = 27, + CallerAddProxyV1 = 28, + CallerRemoveProxyV1 = 29, } #[ink::chain_extension(extension = 0x1000)] @@ -130,6 +144,99 @@ pub trait RuntimeReadWrite { #[ink(function = 15)] fn get_alpha_price(netuid: u16) -> u64; + + #[ink(function = 16)] + fn caller_add_stake( + hotkey: ::AccountId, + netuid: u16, + amount: u64, + ); + + #[ink(function = 17)] + fn caller_remove_stake( + hotkey: ::AccountId, + netuid: u16, + amount: u64, + ); + + #[ink(function = 18)] + fn caller_unstake_all(hotkey: ::AccountId); + + #[ink(function = 19)] + fn caller_unstake_all_alpha(hotkey: ::AccountId); + + #[ink(function = 20)] + fn caller_move_stake( + origin_hotkey: ::AccountId, + destination_hotkey: ::AccountId, + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ); + + #[ink(function = 21)] + fn caller_transfer_stake( + destination_coldkey: ::AccountId, + hotkey: ::AccountId, + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ); + + #[ink(function = 22)] + fn caller_swap_stake( + hotkey: ::AccountId, + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ); + + #[ink(function = 23)] + fn caller_add_stake_limit( + hotkey: ::AccountId, + netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ); + + #[ink(function = 24)] + fn caller_remove_stake_limit( + hotkey: ::AccountId, + netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ); + + #[ink(function = 25)] + fn caller_swap_stake_limit( + hotkey: ::AccountId, + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ); + + #[ink(function = 26)] + fn caller_remove_stake_full_limit( + hotkey: ::AccountId, + netuid: u16, + limit_price: u64, + ); + + #[ink(function = 27)] + fn caller_set_coldkey_auto_stake_hotkey( + netuid: u16, + hotkey: ::AccountId, + ); + + #[ink(function = 28)] + fn caller_add_proxy(delegate: ::AccountId); + + #[ink(function = 29)] + fn caller_remove_proxy(delegate: ::AccountId); } #[ink::scale_derive(Encode, Decode, TypeInfo)] @@ -412,5 +519,203 @@ mod bittensor { .get_alpha_price(netuid) .map_err(|_e| ReadWriteErrorCode::ReadFailed) } + + #[ink(message)] + pub fn caller_add_stake( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_add_stake(hotkey.into(), netuid, amount) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_remove_stake( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_remove_stake(hotkey.into(), netuid, amount) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_unstake_all(&self, hotkey: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_unstake_all(hotkey.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_unstake_all_alpha(&self, hotkey: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_unstake_all_alpha(hotkey.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_move_stake( + &self, + origin_hotkey: [u8; 32], + destination_hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_move_stake( + origin_hotkey.into(), + destination_hotkey.into(), + origin_netuid, + destination_netuid, + amount, + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_transfer_stake( + &self, + destination_coldkey: [u8; 32], + hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_transfer_stake( + destination_coldkey.into(), + hotkey.into(), + origin_netuid, + destination_netuid, + amount, + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_swap_stake( + &self, + hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_swap_stake(hotkey.into(), origin_netuid, destination_netuid, amount) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_add_stake_limit( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_add_stake_limit(hotkey.into(), netuid, amount, limit_price, allow_partial) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_remove_stake_limit( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_remove_stake_limit( + hotkey.into(), + netuid, + amount, + limit_price, + allow_partial, + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_swap_stake_limit( + &self, + hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_swap_stake_limit( + hotkey.into(), + origin_netuid, + destination_netuid, + amount, + limit_price, + allow_partial, + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_remove_stake_full_limit( + &self, + hotkey: [u8; 32], + netuid: u16, + limit_price: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_remove_stake_full_limit(hotkey.into(), netuid, limit_price) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_set_coldkey_auto_stake_hotkey( + &self, + netuid: u16, + hotkey: [u8; 32], + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_set_coldkey_auto_stake_hotkey(netuid, hotkey.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_add_proxy(&self, delegate: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_add_proxy(delegate.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn caller_remove_proxy(&self, delegate: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .caller_remove_proxy(delegate.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } } } diff --git a/contract-tests/package-lock.json b/contract-tests/package-lock.json index 06c722a6de..6aa09a330c 100644 --- a/contract-tests/package-lock.json +++ b/contract-tests/package-lock.json @@ -35,7 +35,7 @@ }, ".papi/descriptors": { "name": "@polkadot-api/descriptors", - "version": "0.1.0-autogenerated.5063582544821983772", + "version": "0.1.0-autogenerated.15397679460818582623", "peerDependencies": { "polkadot-api": ">=1.21.0" } @@ -808,6 +808,7 @@ "resolved": "https://registry.npmjs.org/@polkadot-api/ink-contracts/-/ink-contracts-0.4.3.tgz", "integrity": "sha512-Wl+4Dxjt0GAl+rADZEgrrqEesqX/xygTpX18TmzmspcKhb9QIZf9FJI8A5Sgtq0TKAOwsd1d/hbHVX3LgbXFXg==", "license": "MIT", + "peer": true, "dependencies": { "@polkadot-api/metadata-builders": "0.13.7", "@polkadot-api/substrate-bindings": "0.16.5", @@ -1124,6 +1125,7 @@ "resolved": "https://registry.npmjs.org/@polkadot-api/smoldot/-/smoldot-0.3.14.tgz", "integrity": "sha512-eWqO0xFQaKzqY5mRYxYuZcj1IiaLcQP+J38UQyuJgEorm+9yHVEQ/XBWoM83P+Y8TwE5IWTICp1LCVeiFQTGPQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/node": "^24.5.2", "smoldot": "2.0.39" @@ -1743,6 +1745,7 @@ "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.5.9.tgz", "integrity": "sha512-pIK3XYXo7DKeFRkEBNYhf3GbCHg6dKQisSvdzZwuyzA6m7YxQq4DFw4IE464ve4Z7WsJFt3a6C9uII36hl9EWw==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@polkadot/x-bigint": "13.5.9", "@polkadot/x-global": "13.5.9", @@ -1812,6 +1815,7 @@ "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-14.0.1.tgz", "integrity": "sha512-764HhxkPV3x5rM0/p6QdynC2dw26n+SaE+jisjx556ViCd4E28Ke4xSPef6C0Spy4aoXf2gt0PuLEcBvd6fVZg==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@polkadot/x-bigint": "14.0.1", "@polkadot/x-global": "14.0.1", @@ -2000,6 +2004,7 @@ "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.5.3.tgz", "integrity": "sha512-hBr9bbjS+Yr7DrDUSkIIuvlTSoAlI8WXuo9YEB4C76j130u/cl+zyq6Iy/WnaTE6QH+8i9DhM8QTety6TqYnUQ==", "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.7.0" }, @@ -2054,6 +2059,7 @@ "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.5.9.tgz", "integrity": "sha512-Uuuz3oubf1JCCK97fsnVUnHvk4BGp/W91mQWJlgl5TIOUSSTIRr+lb5GurCfl4kgnQq53Zi5fJV+qR9YumbnZw==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@polkadot/x-global": "13.5.9", "tslib": "^2.8.0" @@ -2623,17 +2629,6 @@ "scale-ts": "^1.6.0" } }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/substrate-client": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz", - "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", - "license": "MIT", - "optional": true, - "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.1", - "@polkadot-api/utils": "0.1.0" - } - }, "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/utils": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz", @@ -2735,6 +2730,7 @@ "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -3134,6 +3130,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=20" } @@ -3357,6 +3354,7 @@ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -4842,6 +4840,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -4874,6 +4873,7 @@ "resolved": "https://registry.npmjs.org/polkadot-api/-/polkadot-api-1.22.0.tgz", "integrity": "sha512-uREBLroPbnJxBBQ+qSkKLF493qukX4PAg32iThlELrZdxfNNgro6nvWRdVmBv73tFHvf+nyWWHKTx1c57nbixg==", "license": "MIT", + "peer": true, "dependencies": { "@polkadot-api/cli": "0.16.3", "@polkadot-api/ink-contracts": "0.4.3", @@ -5140,6 +5140,7 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -5260,16 +5261,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/smoldot": { - "version": "2.0.26", - "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz", - "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", - "license": "GPL-3.0-or-later WITH Classpath-exception-2.0", - "optional": true, - "dependencies": { - "ws": "^8.8.1" - } - }, "node_modules/sort-keys": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", @@ -5675,6 +5666,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6108,6 +6100,7 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", + "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/contract-tests/test/wasm.contract.test.ts b/contract-tests/test/wasm.contract.test.ts index 26d5c87924..5421f4ff14 100644 --- a/contract-tests/test/wasm.contract.test.ts +++ b/contract-tests/test/wasm.contract.test.ts @@ -58,6 +58,38 @@ describe("Test wasm contract", () => { assert.ok(stake > BigInt(0)) } + /** Same as `addStakeWhenWithoutStake` but uses chain extension fn 16 (`CallerAddStakeV1`). */ + async function addStakeWhenWithoutStakeCaller() { + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeBefore !== undefined) + if (stakeBefore > BigInt(0)) { + return; + } + + const amount = tao(100) + const message = inkClient.message("caller_add_stake") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid: netuid, + amount: amount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stake !== undefined) + assert.ok(stake > BigInt(0)) + } + before(async () => { // init variables got from await and async @@ -584,4 +616,319 @@ describe("Test wasm contract", () => { assert.ok(result !== undefined) }) + + it("Caller chain extension: add stake (fn 16)", async () => { + await addStakeWhenWithoutStakeCaller() + }) + + it("Caller chain extension: remove stake (fn 17)", async () => { + await addStakeWhenWithoutStakeCaller() + const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stake !== undefined) + const amount = stake / BigInt(2) + const message = inkClient.message("caller_remove_stake") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid, + amount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeAfter !== undefined && stakeAfter < stake!) + }) + + it("Caller chain extension: unstake_all (fn 18)", async () => { + await addStakeWhenWithoutStakeCaller() + const message = inkClient.message("caller_unstake_all") + const data = message.encode({ hotkey: Binary.fromBytes(hotkey.publicKey) }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeAfter !== undefined) + assert.equal(stakeAfter, BigInt(0)) + }) + + it("Caller chain extension: unstake_all_alpha (fn 19)", async () => { + await addStakeWhenWithoutStakeCaller() + const message = inkClient.message("caller_unstake_all_alpha") + const data = message.encode({ hotkey: Binary.fromBytes(hotkey.publicKey) }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeAfter !== undefined) + assert.equal(stakeAfter, BigInt(0)) + }) + + it("Caller chain extension: move_stake (fn 20)", async () => { + await addStakeWhenWithoutStakeCaller() + const originStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const destStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey2.publicKey), + contractAddress, + netuid, + ))?.stake || BigInt(0) + assert.ok(originStakeBefore !== undefined && originStakeBefore > BigInt(0)) + const moveAmount = originStakeBefore / BigInt(2) + const message = inkClient.message("caller_move_stake") + const data = message.encode({ + origin_hotkey: Binary.fromBytes(hotkey.publicKey), + destination_hotkey: Binary.fromBytes(hotkey2.publicKey), + origin_netuid: netuid, + destination_netuid: netuid, + amount: moveAmount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const originStakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const destStakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey2.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(originStakeAfter !== undefined && destStakeAfter !== undefined) + assert.ok(originStakeAfter < originStakeBefore!) + assert.ok(destStakeAfter > destStakeBefore) + }) + + it("Caller chain extension: transfer_stake (fn 21)", async () => { + await addStakeWhenWithoutStakeCaller() + const stakeBeforeOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const stakeBeforeDest = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + convertPublicKeyToSs58(coldkey2.publicKey), + netuid, + ))?.stake + assert.ok(stakeBeforeOrigin !== undefined && stakeBeforeOrigin > BigInt(0)) + assert.ok(stakeBeforeDest !== undefined) + const transferAmount = stakeBeforeOrigin / BigInt(2) + const message = inkClient.message("caller_transfer_stake") + const data = message.encode({ + destination_coldkey: Binary.fromBytes(coldkey2.publicKey), + hotkey: Binary.fromBytes(hotkey.publicKey), + origin_netuid: netuid, + destination_netuid: netuid, + amount: transferAmount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfterOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const stakeAfterDest = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + convertPublicKeyToSs58(coldkey2.publicKey), + netuid, + ))?.stake + assert.ok(stakeAfterOrigin !== undefined && stakeAfterDest !== undefined) + assert.ok(stakeAfterOrigin < stakeBeforeOrigin!) + assert.ok(stakeAfterDest > stakeBeforeDest!) + }) + + it("Caller chain extension: swap_stake (fn 22)", async () => { + await addStakeWhenWithoutStakeCaller() + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const stakeBefore2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake || BigInt(0) + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + const swapAmount = stakeBefore / BigInt(2) + const message = inkClient.message("caller_swap_stake") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + origin_netuid: netuid, + destination_netuid: netuid + 1, + amount: swapAmount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const stakeAfter2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake + assert.ok(stakeAfter !== undefined && stakeAfter2 !== undefined) + assert.ok(stakeAfter < stakeBefore) + assert.ok(stakeAfter2 > stakeBefore2) + }) + + it("Caller chain extension: add_stake_limit (fn 23)", async () => { + await addStakeWhenWithoutStakeCaller() + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeBefore !== undefined) + const message = inkClient.message("caller_add_stake_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid, + amount: tao(200), + limit_price: tao(100), + allow_partial: false, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeAfter !== undefined && stakeAfter > stakeBefore!) + }) + + it("Caller chain extension: remove_stake_limit (fn 24)", async () => { + await addStakeWhenWithoutStakeCaller() + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + const message = inkClient.message("caller_remove_stake_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid, + amount: stakeBefore / BigInt(2), + limit_price: tao(1), + allow_partial: false, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeAfter !== undefined && stakeAfter < stakeBefore!) + }) + + it("Caller chain extension: swap_stake_limit (fn 25)", async () => { + await addStakeWhenWithoutStakeCaller() + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const stakeBefore2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + assert.ok(stakeBefore2 !== undefined) + const message = inkClient.message("caller_swap_stake_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + origin_netuid: netuid, + destination_netuid: netuid + 1, + amount: stakeBefore / BigInt(2), + limit_price: tao(1), + allow_partial: false, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + const stakeAfter2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake + assert.ok(stakeAfter !== undefined && stakeAfter2 !== undefined) + assert.ok(stakeAfter < stakeBefore) + assert.ok(stakeAfter2 > stakeBefore2!) + }) + + it("Caller chain extension: remove_stake_full_limit (fn 26)", async () => { + await addStakeWhenWithoutStakeCaller() + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + const message = inkClient.message("caller_remove_stake_full_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid, + limit_price: tao(60), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + assert.ok(stakeAfter !== undefined && stakeAfter < stakeBefore!) + }) + + it("Caller chain extension: set_coldkey_auto_stake_hotkey (fn 27)", async () => { + const message = inkClient.message("caller_set_coldkey_auto_stake_hotkey") + const data = message.encode({ + netuid, + hotkey: Binary.fromBytes(hotkey2.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + const autoStakeHotkey = await api.query.SubtensorModule.AutoStakeDestination.getValue( + contractAddress, + netuid, + ) + assert.ok(autoStakeHotkey === convertPublicKeyToSs58(hotkey2.publicKey)) + }) + + it("Caller chain extension: add_proxy and remove_proxy (fn 28-29)", async () => { + const addMessage = inkClient.message("caller_add_proxy") + const addData = addMessage.encode({ + delegate: Binary.fromBytes(hotkey2.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, addData) + let proxies = await api.query.Proxy.Proxies.getValue(contractAddress) + assert.ok(proxies !== undefined && proxies[0].length > 0) + assert.ok(proxies[0][0].delegate === convertPublicKeyToSs58(hotkey2.publicKey)) + + const removeMessage = inkClient.message("caller_remove_proxy") + const removeData = removeMessage.encode({ + delegate: Binary.fromBytes(hotkey2.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, removeData) + proxies = await api.query.Proxy.Proxies.getValue(contractAddress) + assert.ok(proxies !== undefined && proxies[0].length === 0) + }) }); \ No newline at end of file diff --git a/contract-tests/yarn.lock b/contract-tests/yarn.lock index 080ecb1325..ecae01f970 100644 --- a/contract-tests/yarn.lock +++ b/contract-tests/yarn.lock @@ -38,11 +38,136 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@esbuild/aix-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz" + integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== + +"@esbuild/android-arm@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz" + integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== + +"@esbuild/android-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz" + integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== + +"@esbuild/android-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz" + integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== + "@esbuild/darwin-arm64@0.25.12": version "0.25.12" resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz" integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== +"@esbuild/darwin-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz" + integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== + +"@esbuild/freebsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz" + integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== + +"@esbuild/freebsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz" + integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== + +"@esbuild/linux-arm@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz" + integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== + +"@esbuild/linux-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz" + integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== + +"@esbuild/linux-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz" + integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== + +"@esbuild/linux-loong64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz" + integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== + +"@esbuild/linux-mips64el@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz" + integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== + +"@esbuild/linux-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz" + integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== + +"@esbuild/linux-riscv64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz" + integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== + +"@esbuild/linux-s390x@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz" + integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@esbuild/netbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz" + integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== + +"@esbuild/netbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz" + integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== + +"@esbuild/openbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz" + integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== + +"@esbuild/openbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz" + integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== + +"@esbuild/openharmony-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz" + integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== + +"@esbuild/sunos-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz" + integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== + +"@esbuild/win32-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz" + integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== + +"@esbuild/win32-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz" + integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== + "@ethereumjs/rlp@^10.0.0": version "10.1.0" resolved "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-10.1.0.tgz" @@ -255,7 +380,7 @@ integrity sha512-cgA9fh8dfBai9b46XaaQmj9vwzyHStQjc/xrAvQksgF6SqvZ0yAfxVqLvGrsz/Xi3dsAdKLg09PybC7MUAMv9w== "@polkadot-api/descriptors@file:.papi/descriptors": - version "0.1.0-autogenerated.5063582544821983772" + version "0.1.0-autogenerated.15397679460818582623" resolved "file:.papi/descriptors" "@polkadot-api/ink-contracts@^0.4.1", "@polkadot-api/ink-contracts@>=0.4.0", "@polkadot-api/ink-contracts@0.4.3": @@ -277,7 +402,7 @@ resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.2.7.tgz" integrity sha512-+HM4JQXzO2GPUD2++4GOLsmFL6LO8RoLvig0HgCLuypDgfdZMlwd8KnyGHjRnVEHA5X+kvXbk84TDcAXVxTazQ== -"@polkadot-api/json-rpc-provider@^0.0.1", "@polkadot-api/json-rpc-provider@0.0.1": +"@polkadot-api/json-rpc-provider@^0.0.1": version "0.0.1" resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz" integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== @@ -460,15 +585,7 @@ "@scure/base" "^1.1.1" scale-ts "^1.6.0" -"@polkadot-api/substrate-client@^0.1.2", "@polkadot-api/substrate-client@0.1.4": - version "0.1.4" - resolved "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz" - integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== - dependencies: - "@polkadot-api/json-rpc-provider" "0.0.1" - "@polkadot-api/utils" "0.1.0" - -"@polkadot-api/substrate-client@0.4.7": +"@polkadot-api/substrate-client@^0.1.2", "@polkadot-api/substrate-client@0.1.4", "@polkadot-api/substrate-client@0.4.7": version "0.4.7" resolved "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.4.7.tgz" integrity sha512-Mmx9VKincVqfVQmq89gzDk4DN3uKwf8CxoqYvq+EiPUZ1QmMUc7X4QMwG1MXIlYdnm5LSXzn+2Jn8ik8xMgL+w== @@ -950,11 +1067,116 @@ tslib "^2.8.0" ws "^8.18.0" +"@rollup/rollup-android-arm-eabi@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz" + integrity sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w== + +"@rollup/rollup-android-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz" + integrity sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w== + "@rollup/rollup-darwin-arm64@4.53.3": version "4.53.3" resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz" integrity sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA== +"@rollup/rollup-darwin-x64@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz" + integrity sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ== + +"@rollup/rollup-freebsd-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz" + integrity sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w== + +"@rollup/rollup-freebsd-x64@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz" + integrity sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz" + integrity sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw== + +"@rollup/rollup-linux-arm-musleabihf@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz" + integrity sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg== + +"@rollup/rollup-linux-arm64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz" + integrity sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w== + +"@rollup/rollup-linux-arm64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz" + integrity sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A== + +"@rollup/rollup-linux-loong64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz" + integrity sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g== + +"@rollup/rollup-linux-ppc64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz" + integrity sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw== + +"@rollup/rollup-linux-riscv64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz" + integrity sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g== + +"@rollup/rollup-linux-riscv64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz" + integrity sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A== + +"@rollup/rollup-linux-s390x-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz" + integrity sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg== + +"@rollup/rollup-linux-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz" + integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== + +"@rollup/rollup-linux-x64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz" + integrity sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q== + +"@rollup/rollup-openharmony-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz" + integrity sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw== + +"@rollup/rollup-win32-arm64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz" + integrity sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw== + +"@rollup/rollup-win32-ia32-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz" + integrity sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA== + +"@rollup/rollup-win32-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz" + integrity sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg== + +"@rollup/rollup-win32-x64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz" + integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ== + "@rx-state/core@^0.1.4": version "0.1.4" resolved "https://registry.npmjs.org/@rx-state/core/-/core-0.1.4.tgz" @@ -2499,13 +2721,6 @@ signal-exit@^4.0.1, signal-exit@^4.1.0: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -smoldot@2.0.26, smoldot@2.x: - version "2.0.26" - resolved "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz" - integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== - dependencies: - ws "^8.8.1" - smoldot@2.0.39: version "2.0.39" resolved "https://registry.npmjs.org/smoldot/-/smoldot-2.0.39.tgz" From a6d8b6d9a9f2c9b0e5d23d67a66ae63ebb118e5a Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 1 Apr 2026 19:50:24 +0800 Subject: [PATCH 06/12] fix fmt --- chain-extensions/src/tests.rs | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/chain-extensions/src/tests.rs b/chain-extensions/src/tests.rs index a3a7c45939..cb02ec9f0d 100644 --- a/chain-extensions/src/tests.rs +++ b/chain-extensions/src/tests.rs @@ -1146,7 +1146,8 @@ mod caller_dispatch_tests { ); assert!(remaining_alpha <= AlphaBalance::from(1_000)); - let post_balance = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + let post_balance = + pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); assert!(post_balance > pre_balance); }); } @@ -1187,9 +1188,12 @@ mod caller_dispatch_tests { .saturating_add(::DbWeight::get().reads(36)) .saturating_add(::DbWeight::get().writes(21)); - let mut env = - MockEnv::new(FunctionId::CallerUnstakeAllAlphaV1, coldkey, hotkey.encode()) - .with_expected_weight(expected_weight); + let mut env = MockEnv::new( + FunctionId::CallerUnstakeAllAlphaV1, + coldkey, + hotkey.encode(), + ) + .with_expected_weight(expected_weight); let ret = SubtensorChainExtension::::dispatch(&mut env).unwrap(); assert_success(ret); @@ -1486,7 +1490,8 @@ mod caller_dispatch_tests { pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid, ); - let balance_before = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + let balance_before = + pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); let expected_weight = Weight::from_parts(402_900_000, 0) .saturating_add(::DbWeight::get().reads(24)) @@ -1513,7 +1518,8 @@ mod caller_dispatch_tests { pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid, ); - let balance_after = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + let balance_after = + pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); assert!(stake_after > stake_before); assert!(stake_after > AlphaBalance::ZERO); @@ -1571,7 +1577,8 @@ mod caller_dispatch_tests { .saturating_add(::DbWeight::get().reads(28)) .saturating_add(::DbWeight::get().writes(14)); - let balance_before = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + let balance_before = + pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); let mut env = MockEnv::new( FunctionId::CallerRemoveStakeLimitV1, @@ -1588,7 +1595,8 @@ mod caller_dispatch_tests { pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid, ); - let balance_after = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + let balance_after = + pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); assert!(alpha_after < alpha_before); assert!(balance_after > balance_before); @@ -1709,7 +1717,8 @@ mod caller_dispatch_tests { .saturating_add(::DbWeight::get().reads(28)) .saturating_add(::DbWeight::get().writes(14)); - let balance_before = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + let balance_before = + pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); let mut env = MockEnv::new( FunctionId::CallerRemoveStakeFullLimitV1, @@ -1726,7 +1735,8 @@ mod caller_dispatch_tests { pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid, ); - let balance_after = pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); + let balance_after = + pallet_subtensor::Pallet::::get_coldkey_balance(&coldkey); assert!(alpha_after.is_zero()); assert!(balance_after > balance_before); @@ -1810,8 +1820,11 @@ mod caller_dispatch_tests { MockEnv::new(FunctionId::CallerAddProxyV1, delegator, delegate.encode()); assert_success(SubtensorChainExtension::::dispatch(&mut add_env).unwrap()); - let mut remove_env = - MockEnv::new(FunctionId::CallerRemoveProxyV1, delegator, delegate.encode()); + let mut remove_env = MockEnv::new( + FunctionId::CallerRemoveProxyV1, + delegator, + delegate.encode(), + ); let ret = SubtensorChainExtension::::dispatch(&mut remove_env).unwrap(); assert_success(ret); From 7ae21033fbb14a359aa0201206b0078c560efff4 Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 1 Apr 2026 20:01:21 +0800 Subject: [PATCH 07/12] revert package dep --- contract-tests/package-lock.json | 37 +++-- contract-tests/yarn.lock | 251 +++---------------------------- 2 files changed, 40 insertions(+), 248 deletions(-) diff --git a/contract-tests/package-lock.json b/contract-tests/package-lock.json index 6aa09a330c..06c722a6de 100644 --- a/contract-tests/package-lock.json +++ b/contract-tests/package-lock.json @@ -35,7 +35,7 @@ }, ".papi/descriptors": { "name": "@polkadot-api/descriptors", - "version": "0.1.0-autogenerated.15397679460818582623", + "version": "0.1.0-autogenerated.5063582544821983772", "peerDependencies": { "polkadot-api": ">=1.21.0" } @@ -808,7 +808,6 @@ "resolved": "https://registry.npmjs.org/@polkadot-api/ink-contracts/-/ink-contracts-0.4.3.tgz", "integrity": "sha512-Wl+4Dxjt0GAl+rADZEgrrqEesqX/xygTpX18TmzmspcKhb9QIZf9FJI8A5Sgtq0TKAOwsd1d/hbHVX3LgbXFXg==", "license": "MIT", - "peer": true, "dependencies": { "@polkadot-api/metadata-builders": "0.13.7", "@polkadot-api/substrate-bindings": "0.16.5", @@ -1125,7 +1124,6 @@ "resolved": "https://registry.npmjs.org/@polkadot-api/smoldot/-/smoldot-0.3.14.tgz", "integrity": "sha512-eWqO0xFQaKzqY5mRYxYuZcj1IiaLcQP+J38UQyuJgEorm+9yHVEQ/XBWoM83P+Y8TwE5IWTICp1LCVeiFQTGPQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/node": "^24.5.2", "smoldot": "2.0.39" @@ -1745,7 +1743,6 @@ "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.5.9.tgz", "integrity": "sha512-pIK3XYXo7DKeFRkEBNYhf3GbCHg6dKQisSvdzZwuyzA6m7YxQq4DFw4IE464ve4Z7WsJFt3a6C9uII36hl9EWw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@polkadot/x-bigint": "13.5.9", "@polkadot/x-global": "13.5.9", @@ -1815,7 +1812,6 @@ "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-14.0.1.tgz", "integrity": "sha512-764HhxkPV3x5rM0/p6QdynC2dw26n+SaE+jisjx556ViCd4E28Ke4xSPef6C0Spy4aoXf2gt0PuLEcBvd6fVZg==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@polkadot/x-bigint": "14.0.1", "@polkadot/x-global": "14.0.1", @@ -2004,7 +2000,6 @@ "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.5.3.tgz", "integrity": "sha512-hBr9bbjS+Yr7DrDUSkIIuvlTSoAlI8WXuo9YEB4C76j130u/cl+zyq6Iy/WnaTE6QH+8i9DhM8QTety6TqYnUQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.7.0" }, @@ -2059,7 +2054,6 @@ "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.5.9.tgz", "integrity": "sha512-Uuuz3oubf1JCCK97fsnVUnHvk4BGp/W91mQWJlgl5TIOUSSTIRr+lb5GurCfl4kgnQq53Zi5fJV+qR9YumbnZw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@polkadot/x-global": "13.5.9", "tslib": "^2.8.0" @@ -2629,6 +2623,17 @@ "scale-ts": "^1.6.0" } }, + "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/substrate-client": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz", + "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "@polkadot-api/json-rpc-provider": "0.0.1", + "@polkadot-api/utils": "0.1.0" + } + }, "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/utils": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz", @@ -2730,7 +2735,6 @@ "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -3130,7 +3134,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=20" } @@ -3354,7 +3357,6 @@ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -4840,7 +4842,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -4873,7 +4874,6 @@ "resolved": "https://registry.npmjs.org/polkadot-api/-/polkadot-api-1.22.0.tgz", "integrity": "sha512-uREBLroPbnJxBBQ+qSkKLF493qukX4PAg32iThlELrZdxfNNgro6nvWRdVmBv73tFHvf+nyWWHKTx1c57nbixg==", "license": "MIT", - "peer": true, "dependencies": { "@polkadot-api/cli": "0.16.3", "@polkadot-api/ink-contracts": "0.4.3", @@ -5140,7 +5140,6 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -5261,6 +5260,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/smoldot": { + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz", + "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", + "license": "GPL-3.0-or-later WITH Classpath-exception-2.0", + "optional": true, + "dependencies": { + "ws": "^8.8.1" + } + }, "node_modules/sort-keys": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", @@ -5666,7 +5675,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6100,7 +6108,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/contract-tests/yarn.lock b/contract-tests/yarn.lock index ecae01f970..080ecb1325 100644 --- a/contract-tests/yarn.lock +++ b/contract-tests/yarn.lock @@ -38,136 +38,11 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@esbuild/aix-ppc64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz" - integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== - -"@esbuild/android-arm@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz" - integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== - -"@esbuild/android-arm64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz" - integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== - -"@esbuild/android-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz" - integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== - "@esbuild/darwin-arm64@0.25.12": version "0.25.12" resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz" integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== -"@esbuild/darwin-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz" - integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== - -"@esbuild/freebsd-arm64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz" - integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== - -"@esbuild/freebsd-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz" - integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== - -"@esbuild/linux-arm@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz" - integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== - -"@esbuild/linux-arm64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz" - integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== - -"@esbuild/linux-ia32@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz" - integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== - -"@esbuild/linux-loong64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz" - integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== - -"@esbuild/linux-mips64el@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz" - integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== - -"@esbuild/linux-ppc64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz" - integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== - -"@esbuild/linux-riscv64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz" - integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== - -"@esbuild/linux-s390x@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz" - integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== - -"@esbuild/linux-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz" - integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== - -"@esbuild/netbsd-arm64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz" - integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== - -"@esbuild/netbsd-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz" - integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== - -"@esbuild/openbsd-arm64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz" - integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== - -"@esbuild/openbsd-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz" - integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== - -"@esbuild/openharmony-arm64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz" - integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== - -"@esbuild/sunos-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz" - integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== - -"@esbuild/win32-arm64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz" - integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== - -"@esbuild/win32-ia32@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz" - integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== - -"@esbuild/win32-x64@0.25.12": - version "0.25.12" - resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz" - integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== - "@ethereumjs/rlp@^10.0.0": version "10.1.0" resolved "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-10.1.0.tgz" @@ -380,7 +255,7 @@ integrity sha512-cgA9fh8dfBai9b46XaaQmj9vwzyHStQjc/xrAvQksgF6SqvZ0yAfxVqLvGrsz/Xi3dsAdKLg09PybC7MUAMv9w== "@polkadot-api/descriptors@file:.papi/descriptors": - version "0.1.0-autogenerated.15397679460818582623" + version "0.1.0-autogenerated.5063582544821983772" resolved "file:.papi/descriptors" "@polkadot-api/ink-contracts@^0.4.1", "@polkadot-api/ink-contracts@>=0.4.0", "@polkadot-api/ink-contracts@0.4.3": @@ -402,7 +277,7 @@ resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.2.7.tgz" integrity sha512-+HM4JQXzO2GPUD2++4GOLsmFL6LO8RoLvig0HgCLuypDgfdZMlwd8KnyGHjRnVEHA5X+kvXbk84TDcAXVxTazQ== -"@polkadot-api/json-rpc-provider@^0.0.1": +"@polkadot-api/json-rpc-provider@^0.0.1", "@polkadot-api/json-rpc-provider@0.0.1": version "0.0.1" resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz" integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== @@ -585,7 +460,15 @@ "@scure/base" "^1.1.1" scale-ts "^1.6.0" -"@polkadot-api/substrate-client@^0.1.2", "@polkadot-api/substrate-client@0.1.4", "@polkadot-api/substrate-client@0.4.7": +"@polkadot-api/substrate-client@^0.1.2", "@polkadot-api/substrate-client@0.1.4": + version "0.1.4" + resolved "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz" + integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.1" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/substrate-client@0.4.7": version "0.4.7" resolved "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.4.7.tgz" integrity sha512-Mmx9VKincVqfVQmq89gzDk4DN3uKwf8CxoqYvq+EiPUZ1QmMUc7X4QMwG1MXIlYdnm5LSXzn+2Jn8ik8xMgL+w== @@ -1067,116 +950,11 @@ tslib "^2.8.0" ws "^8.18.0" -"@rollup/rollup-android-arm-eabi@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz" - integrity sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w== - -"@rollup/rollup-android-arm64@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz" - integrity sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w== - "@rollup/rollup-darwin-arm64@4.53.3": version "4.53.3" resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz" integrity sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA== -"@rollup/rollup-darwin-x64@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz" - integrity sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ== - -"@rollup/rollup-freebsd-arm64@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz" - integrity sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w== - -"@rollup/rollup-freebsd-x64@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz" - integrity sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q== - -"@rollup/rollup-linux-arm-gnueabihf@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz" - integrity sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw== - -"@rollup/rollup-linux-arm-musleabihf@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz" - integrity sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg== - -"@rollup/rollup-linux-arm64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz" - integrity sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w== - -"@rollup/rollup-linux-arm64-musl@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz" - integrity sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A== - -"@rollup/rollup-linux-loong64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz" - integrity sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g== - -"@rollup/rollup-linux-ppc64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz" - integrity sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw== - -"@rollup/rollup-linux-riscv64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz" - integrity sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g== - -"@rollup/rollup-linux-riscv64-musl@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz" - integrity sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A== - -"@rollup/rollup-linux-s390x-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz" - integrity sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg== - -"@rollup/rollup-linux-x64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz" - integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== - -"@rollup/rollup-linux-x64-musl@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz" - integrity sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q== - -"@rollup/rollup-openharmony-arm64@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz" - integrity sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw== - -"@rollup/rollup-win32-arm64-msvc@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz" - integrity sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw== - -"@rollup/rollup-win32-ia32-msvc@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz" - integrity sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA== - -"@rollup/rollup-win32-x64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz" - integrity sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg== - -"@rollup/rollup-win32-x64-msvc@4.53.3": - version "4.53.3" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz" - integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ== - "@rx-state/core@^0.1.4": version "0.1.4" resolved "https://registry.npmjs.org/@rx-state/core/-/core-0.1.4.tgz" @@ -2721,6 +2499,13 @@ signal-exit@^4.0.1, signal-exit@^4.1.0: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +smoldot@2.0.26, smoldot@2.x: + version "2.0.26" + resolved "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz" + integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== + dependencies: + ws "^8.8.1" + smoldot@2.0.39: version "2.0.39" resolved "https://registry.npmjs.org/smoldot/-/smoldot-2.0.39.tgz" From f42df7cf7b870adcf30cd26d6089b1c30e5ad0ef Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 2 Apr 2026 16:35:52 +0800 Subject: [PATCH 08/12] refactor --- chain-extensions/src/lib.rs | 1354 ++++++++++++++------------------- chain-extensions/src/tests.rs | 10 +- 2 files changed, 572 insertions(+), 792 deletions(-) diff --git a/chain-extensions/src/lib.rs b/chain-extensions/src/lib.rs index 824d30eb8d..7f9694c654 100644 --- a/chain-extensions/src/lib.rs +++ b/chain-extensions/src/lib.rs @@ -61,883 +61,663 @@ where + pallet_subtensor_swap::Config, T::AccountId: Clone, { - fn dispatch(env: &mut Env) -> Result + fn dispatch_add_stake_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { - let func_id: FunctionId = env.func_id().try_into().map_err(|_| { - DispatchError::Other( - "Invalid function id - does not correspond to any registered function", - ) - })?; + let weight = Weight::from_parts(340_800_000, 0) + .saturating_add(T::DbWeight::get().reads(24_u64)) + .saturating_add(T::DbWeight::get().writes(15)); - match func_id { - FunctionId::GetStakeInfoForHotkeyColdkeyNetuidV1 => { - let (hotkey, coldkey, netuid): (T::AccountId, T::AccountId, NetUid) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - - let stake_info = - pallet_subtensor::Pallet::::get_stake_info_for_hotkey_coldkey_netuid( - hotkey, coldkey, netuid, - ); + env.charge_weight(weight)?; - let encoded_result = stake_info.encode(); + let (hotkey, netuid, amount_staked): (T::AccountId, NetUid, TaoBalance) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - env.write_output(&encoded_result) - .map_err(|_| DispatchError::Other("Failed to write output"))?; + let call_result = + pallet_subtensor::Pallet::::add_stake(origin.into(), hotkey, netuid, amount_staked); - Ok(RetVal::Converging(Output::Success as u32)) + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::AddStakeV1 => { - let weight = Weight::from_parts(340_800_000, 0) - .saturating_add(T::DbWeight::get().reads(24_u64)) - .saturating_add(T::DbWeight::get().writes(15)); + } + } - env.charge_weight(weight)?; + fn dispatch_remove_stake_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(196_800_000, 0) + .saturating_add(T::DbWeight::get().reads(19)) + .saturating_add(T::DbWeight::get().writes(10)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, amount_unstaked): (T::AccountId, NetUid, AlphaBalance) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::remove_stake( + origin.into(), + hotkey, + netuid, + amount_unstaked, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } - let (hotkey, netuid, amount_staked): (T::AccountId, NetUid, TaoBalance) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + fn dispatch_unstake_all_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(28_830_000, 0) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(0)); - let call_result = pallet_subtensor::Pallet::::add_stake( - RawOrigin::Signed(env.caller()).into(), - hotkey, - netuid, - amount_staked, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } - } - FunctionId::RemoveStakeV1 => { - let weight = Weight::from_parts(196_800_000, 0) - .saturating_add(T::DbWeight::get().reads(19)) - .saturating_add(T::DbWeight::get().writes(10)); + env.charge_weight(weight)?; - env.charge_weight(weight)?; + let hotkey: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let (hotkey, netuid, amount_unstaked): (T::AccountId, NetUid, AlphaBalance) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + let call_result = pallet_subtensor::Pallet::::unstake_all(origin.into(), hotkey); - let call_result = pallet_subtensor::Pallet::::remove_stake( - RawOrigin::Signed(env.caller()).into(), - hotkey, - netuid, - amount_unstaked, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::UnstakeAllV1 => { - let weight = Weight::from_parts(28_830_000, 0) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(0)); - - env.charge_weight(weight)?; + } + } - let hotkey: T::AccountId = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + fn dispatch_unstake_all_alpha_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(358_500_000, 0) + .saturating_add(T::DbWeight::get().reads(36_u64)) + .saturating_add(T::DbWeight::get().writes(21_u64)); - let call_result = pallet_subtensor::Pallet::::unstake_all( - RawOrigin::Signed(env.caller()).into(), - hotkey, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } - } - FunctionId::UnstakeAllAlphaV1 => { - let weight = Weight::from_parts(358_500_000, 0) - .saturating_add(T::DbWeight::get().reads(36_u64)) - .saturating_add(T::DbWeight::get().writes(21_u64)); + env.charge_weight(weight)?; - env.charge_weight(weight)?; + let hotkey: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let hotkey: T::AccountId = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + let call_result = pallet_subtensor::Pallet::::unstake_all_alpha(origin.into(), hotkey); - let call_result = pallet_subtensor::Pallet::::unstake_all_alpha( - RawOrigin::Signed(env.caller()).into(), - hotkey, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::MoveStakeV1 => { - let weight = Weight::from_parts(164_300_000, 0) - .saturating_add(T::DbWeight::get().reads(15_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)); - - env.charge_weight(weight)?; - - let ( - origin_hotkey, - destination_hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ): (T::AccountId, T::AccountId, NetUid, NetUid, AlphaBalance) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + } + } - let call_result = pallet_subtensor::Pallet::::move_stake( - RawOrigin::Signed(env.caller()).into(), - origin_hotkey, - destination_hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + fn dispatch_move_stake_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(164_300_000, 0) + .saturating_add(T::DbWeight::get().reads(15_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)); + + env.charge_weight(weight)?; + + let (origin_hotkey, destination_hotkey, origin_netuid, destination_netuid, alpha_amount): ( + T::AccountId, + T::AccountId, + NetUid, + NetUid, + AlphaBalance, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::move_stake( + origin.into(), + origin_hotkey, + destination_hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::TransferStakeV1 => { - let weight = Weight::from_parts(160_300_000, 0) - .saturating_add(T::DbWeight::get().reads(13_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)); - - env.charge_weight(weight)?; - - let (destination_coldkey, hotkey, origin_netuid, destination_netuid, alpha_amount): ( - T::AccountId, - T::AccountId, - NetUid, - NetUid, - AlphaBalance, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + } + } - let call_result = pallet_subtensor::Pallet::::transfer_stake( - RawOrigin::Signed(env.caller()).into(), - destination_coldkey, - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + fn dispatch_transfer_stake_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(160_300_000, 0) + .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)); + + env.charge_weight(weight)?; + + let (destination_coldkey, hotkey, origin_netuid, destination_netuid, alpha_amount): ( + T::AccountId, + T::AccountId, + NetUid, + NetUid, + AlphaBalance, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::transfer_stake( + origin.into(), + destination_coldkey, + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::SwapStakeV1 => { - let weight = Weight::from_parts(351_300_000, 0) - .saturating_add(T::DbWeight::get().reads(35_u64)) - .saturating_add(T::DbWeight::get().writes(22_u64)); - - env.charge_weight(weight)?; - - let (hotkey, origin_netuid, destination_netuid, alpha_amount): ( - T::AccountId, - NetUid, - NetUid, - AlphaBalance, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + } + } - let call_result = pallet_subtensor::Pallet::::swap_stake( - RawOrigin::Signed(env.caller()).into(), - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + fn dispatch_swap_stake_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(351_300_000, 0) + .saturating_add(T::DbWeight::get().reads(35_u64)) + .saturating_add(T::DbWeight::get().writes(22_u64)); + + env.charge_weight(weight)?; + + let (hotkey, origin_netuid, destination_netuid, alpha_amount): ( + T::AccountId, + NetUid, + NetUid, + AlphaBalance, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::swap_stake( + origin.into(), + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::AddStakeLimitV1 => { - let weight = Weight::from_parts(402_900_000, 0) - .saturating_add(T::DbWeight::get().reads(24_u64)) - .saturating_add(T::DbWeight::get().writes(15)); - - env.charge_weight(weight)?; - - let (hotkey, netuid, amount_staked, limit_price, allow_partial): ( - T::AccountId, - NetUid, - TaoBalance, - TaoBalance, - bool, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + } + } - let call_result = pallet_subtensor::Pallet::::add_stake_limit( - RawOrigin::Signed(env.caller()).into(), - hotkey, - netuid, - amount_staked, - limit_price, - allow_partial, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + fn dispatch_add_stake_limit_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(402_900_000, 0) + .saturating_add(T::DbWeight::get().reads(24_u64)) + .saturating_add(T::DbWeight::get().writes(15)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, amount_staked, limit_price, allow_partial): ( + T::AccountId, + NetUid, + TaoBalance, + TaoBalance, + bool, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::add_stake_limit( + origin.into(), + hotkey, + netuid, + amount_staked, + limit_price, + allow_partial, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::RemoveStakeLimitV1 => { - let weight = Weight::from_parts(377_400_000, 0) - .saturating_add(T::DbWeight::get().reads(28_u64)) - .saturating_add(T::DbWeight::get().writes(14)); - - env.charge_weight(weight)?; - - let (hotkey, netuid, amount_unstaked, limit_price, allow_partial): ( - T::AccountId, - NetUid, - AlphaBalance, - TaoBalance, - bool, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + } + } - let call_result = pallet_subtensor::Pallet::::remove_stake_limit( - RawOrigin::Signed(env.caller()).into(), - hotkey, - netuid, - amount_unstaked, - limit_price, - allow_partial, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } - } - FunctionId::SwapStakeLimitV1 => { - let weight = Weight::from_parts(411_500_000, 0) - .saturating_add(T::DbWeight::get().reads(35_u64)) - .saturating_add(T::DbWeight::get().writes(22_u64)); - - env.charge_weight(weight)?; - - let ( - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - limit_price, - allow_partial, - ): (T::AccountId, NetUid, NetUid, AlphaBalance, TaoBalance, bool) = - env.read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - - let call_result = pallet_subtensor::Pallet::::swap_stake_limit( - RawOrigin::Signed(env.caller()).into(), - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - limit_price, - allow_partial, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + fn dispatch_remove_stake_limit_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(377_400_000, 0) + .saturating_add(T::DbWeight::get().reads(28_u64)) + .saturating_add(T::DbWeight::get().writes(14)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, amount_unstaked, limit_price, allow_partial): ( + T::AccountId, + NetUid, + AlphaBalance, + TaoBalance, + bool, + ) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::remove_stake_limit( + origin.into(), + hotkey, + netuid, + amount_unstaked, + limit_price, + allow_partial, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::RemoveStakeFullLimitV1 => { - let weight = Weight::from_parts(395_300_000, 0) - .saturating_add(T::DbWeight::get().reads(28_u64)) - .saturating_add(T::DbWeight::get().writes(14_u64)); - - env.charge_weight(weight)?; + } + } - let (hotkey, netuid, limit_price): (T::AccountId, NetUid, Option) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + fn dispatch_swap_stake_limit_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(411_500_000, 0) + .saturating_add(T::DbWeight::get().reads(35_u64)) + .saturating_add(T::DbWeight::get().writes(22_u64)); + + env.charge_weight(weight)?; + + let ( + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + limit_price, + allow_partial, + ): (T::AccountId, NetUid, NetUid, AlphaBalance, TaoBalance, bool) = + env.read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::swap_stake_limit( + origin.into(), + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + limit_price, + allow_partial, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } - let call_result = pallet_subtensor::Pallet::::remove_stake_full_limit( - RawOrigin::Signed(env.caller()).into(), - hotkey, - netuid, - limit_price, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + fn dispatch_remove_stake_full_limit_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(395_300_000, 0) + .saturating_add(T::DbWeight::get().reads(28_u64)) + .saturating_add(T::DbWeight::get().writes(14_u64)); + + env.charge_weight(weight)?; + + let (hotkey, netuid, limit_price): (T::AccountId, NetUid, Option) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::remove_stake_full_limit( + origin.into(), + hotkey, + netuid, + limit_price, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::SetColdkeyAutoStakeHotkeyV1 => { - let weight = Weight::from_parts(29_930_000, 0) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)); + } + } - env.charge_weight(weight)?; + fn dispatch_set_coldkey_auto_stake_hotkey_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = Weight::from_parts(29_930_000, 0) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)); + + env.charge_weight(weight)?; + + let (netuid, hotkey): (NetUid, T::AccountId) = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let call_result = pallet_subtensor::Pallet::::set_coldkey_auto_stake_hotkey( + origin.into(), + netuid, + hotkey, + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } - let (netuid, hotkey): (NetUid, T::AccountId) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + fn dispatch_add_proxy_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = ::WeightInfo::add_proxy( + ::MaxProxies::get(), + ); + + env.charge_weight(weight)?; + + let delegate: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let delegate_lookup = + <::Lookup as StaticLookup>::Source::from(delegate); + + let call_result = pallet_proxy::Pallet::::add_proxy( + origin.into(), + delegate_lookup, + ProxyType::Staking, + 0u32.into(), + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) + } + } + } - let call_result = pallet_subtensor::Pallet::::set_coldkey_auto_stake_hotkey( - RawOrigin::Signed(env.caller()).into(), - netuid, - hotkey, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + fn dispatch_remove_proxy_v1( + env: &mut Env, + origin: RawOrigin, + ) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let weight = ::WeightInfo::remove_proxy( + ::MaxProxies::get(), + ); + + env.charge_weight(weight)?; + + let delegate: T::AccountId = env + .read_as() + .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + + let delegate_lookup = + <::Lookup as StaticLookup>::Source::from(delegate); + + let call_result = pallet_proxy::Pallet::::remove_proxy( + origin.into(), + delegate_lookup, + ProxyType::Staking, + 0u32.into(), + ); + + match call_result { + Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), + Err(e) => { + let error_code = Output::from(e) as u32; + Ok(RetVal::Converging(error_code)) } - FunctionId::AddProxyV1 => { - let weight = ::WeightInfo::add_proxy( - ::MaxProxies::get(), - ); + } + } - env.charge_weight(weight)?; + fn dispatch(env: &mut Env) -> Result + where + Env: SubtensorExtensionEnv, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + { + let func_id: FunctionId = env.func_id().try_into().map_err(|_| { + DispatchError::Other( + "Invalid function id - does not correspond to any registered function", + ) + })?; - let delegate: T::AccountId = env + match func_id { + FunctionId::GetStakeInfoForHotkeyColdkeyNetuidV1 => { + let (hotkey, coldkey, netuid): (T::AccountId, T::AccountId, NetUid) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let delegate_lookup = - <::Lookup as StaticLookup>::Source::from(delegate); - - let call_result = pallet_proxy::Pallet::::add_proxy( - RawOrigin::Signed(env.caller()).into(), - delegate_lookup, - ProxyType::Staking, - 0u32.into(), - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } - } - FunctionId::RemoveProxyV1 => { - let weight = ::WeightInfo::remove_proxy( - ::MaxProxies::get(), - ); + let stake_info = + pallet_subtensor::Pallet::::get_stake_info_for_hotkey_coldkey_netuid( + hotkey, coldkey, netuid, + ); - env.charge_weight(weight)?; + let encoded_result = stake_info.encode(); - let delegate: T::AccountId = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + env.write_output(&encoded_result) + .map_err(|_| DispatchError::Other("Failed to write output"))?; - let delegate_lookup = - <::Lookup as StaticLookup>::Source::from(delegate); - - let call_result = pallet_proxy::Pallet::::remove_proxy( - RawOrigin::Signed(env.caller()).into(), - delegate_lookup, - ProxyType::Staking, - 0u32.into(), - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Ok(RetVal::Converging(Output::Success as u32)) + } + FunctionId::AddStakeV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_add_stake_v1(env, origin) } - FunctionId::CallerAddStakeV1 => { - let weight = Weight::from_parts(394_300_000, 0) - .saturating_add(T::DbWeight::get().reads(18)) - .saturating_add(T::DbWeight::get().writes(9)); - - env.charge_weight(weight)?; - - let (hotkey, netuid, amount_staked): (T::AccountId, NetUid, TaoBalance) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; + FunctionId::CallerAddStakeV1 => { let origin = convert_origin(env.origin()); + Self::dispatch_add_stake_v1(env, origin) + } - let call_result = pallet_subtensor::Pallet::::add_stake( - origin.into(), - hotkey, - netuid, - amount_staked, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + FunctionId::RemoveStakeV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_remove_stake_v1(env, origin) } FunctionId::CallerRemoveStakeV1 => { - let weight = Weight::from_parts(196_800_000, 0) - .saturating_add(T::DbWeight::get().reads(19)) - .saturating_add(T::DbWeight::get().writes(10)); - - env.charge_weight(weight)?; - - let (hotkey, netuid, amount_unstaked): (T::AccountId, NetUid, AlphaBalance) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::remove_stake( - origin.into(), - hotkey, - netuid, - amount_unstaked, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_remove_stake_v1(env, origin) + } + FunctionId::UnstakeAllV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_unstake_all_v1(env, origin) } FunctionId::CallerUnstakeAllV1 => { - let weight = Weight::from_parts(28_830_000, 0) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(0)); - - env.charge_weight(weight)?; - - let hotkey: T::AccountId = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::unstake_all(origin.into(), hotkey); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_unstake_all_v1(env, origin) + } + FunctionId::UnstakeAllAlphaV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_unstake_all_alpha_v1(env, origin) } FunctionId::CallerUnstakeAllAlphaV1 => { - let weight = Weight::from_parts(358_500_000, 0) - .saturating_add(T::DbWeight::get().reads(36_u64)) - .saturating_add(T::DbWeight::get().writes(21_u64)); - - env.charge_weight(weight)?; - - let hotkey: T::AccountId = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = - pallet_subtensor::Pallet::::unstake_all_alpha(origin.into(), hotkey); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_unstake_all_alpha_v1(env, origin) + } + FunctionId::MoveStakeV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_move_stake_v1(env, origin) } FunctionId::CallerMoveStakeV1 => { - let weight = Weight::from_parts(164_300_000, 0) - .saturating_add(T::DbWeight::get().reads(15_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)); - - env.charge_weight(weight)?; - - let ( - origin_hotkey, - destination_hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ): (T::AccountId, T::AccountId, NetUid, NetUid, AlphaBalance) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::move_stake( - origin.into(), - origin_hotkey, - destination_hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_move_stake_v1(env, origin) + } + FunctionId::TransferStakeV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_transfer_stake_v1(env, origin) } FunctionId::CallerTransferStakeV1 => { - let weight = Weight::from_parts(160_300_000, 0) - .saturating_add(T::DbWeight::get().reads(13_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)); - - env.charge_weight(weight)?; - - let (destination_coldkey, hotkey, origin_netuid, destination_netuid, alpha_amount): ( - T::AccountId, - T::AccountId, - NetUid, - NetUid, - AlphaBalance, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::transfer_stake( - origin.into(), - destination_coldkey, - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_transfer_stake_v1(env, origin) + } + FunctionId::SwapStakeV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_swap_stake_v1(env, origin) } FunctionId::CallerSwapStakeV1 => { - let weight = Weight::from_parts(351_300_000, 0) - .saturating_add(T::DbWeight::get().reads(35_u64)) - .saturating_add(T::DbWeight::get().writes(22_u64)); - - env.charge_weight(weight)?; - - let (hotkey, origin_netuid, destination_netuid, alpha_amount): ( - T::AccountId, - NetUid, - NetUid, - AlphaBalance, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::swap_stake( - origin.into(), - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_swap_stake_v1(env, origin) + } + FunctionId::AddStakeLimitV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_add_stake_limit_v1(env, origin) } FunctionId::CallerAddStakeLimitV1 => { - let weight = Weight::from_parts(402_900_000, 0) - .saturating_add(T::DbWeight::get().reads(24_u64)) - .saturating_add(T::DbWeight::get().writes(15)); - - env.charge_weight(weight)?; - - let (hotkey, netuid, amount_staked, limit_price, allow_partial): ( - T::AccountId, - NetUid, - TaoBalance, - TaoBalance, - bool, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::add_stake_limit( - origin.into(), - hotkey, - netuid, - amount_staked, - limit_price, - allow_partial, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_add_stake_limit_v1(env, origin) + } + FunctionId::RemoveStakeLimitV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_remove_stake_limit_v1(env, origin) } FunctionId::CallerRemoveStakeLimitV1 => { - let weight = Weight::from_parts(377_400_000, 0) - .saturating_add(T::DbWeight::get().reads(28_u64)) - .saturating_add(T::DbWeight::get().writes(14)); - - env.charge_weight(weight)?; - - let (hotkey, netuid, amount_unstaked, limit_price, allow_partial): ( - T::AccountId, - NetUid, - AlphaBalance, - TaoBalance, - bool, - ) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::remove_stake_limit( - origin.into(), - hotkey, - netuid, - amount_unstaked, - limit_price, - allow_partial, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_remove_stake_limit_v1(env, origin) + } + FunctionId::SwapStakeLimitV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_swap_stake_limit_v1(env, origin) } FunctionId::CallerSwapStakeLimitV1 => { - let weight = Weight::from_parts(411_500_000, 0) - .saturating_add(T::DbWeight::get().reads(35_u64)) - .saturating_add(T::DbWeight::get().writes(22_u64)); - - env.charge_weight(weight)?; - - let ( - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - limit_price, - allow_partial, - ): (T::AccountId, NetUid, NetUid, AlphaBalance, TaoBalance, bool) = - env.read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::swap_stake_limit( - origin.into(), - hotkey, - origin_netuid, - destination_netuid, - alpha_amount, - limit_price, - allow_partial, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_swap_stake_limit_v1(env, origin) + } + FunctionId::RemoveStakeFullLimitV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_remove_stake_full_limit_v1(env, origin) } FunctionId::CallerRemoveStakeFullLimitV1 => { - let weight = Weight::from_parts(395_300_000, 0) - .saturating_add(T::DbWeight::get().reads(28_u64)) - .saturating_add(T::DbWeight::get().writes(14_u64)); - - env.charge_weight(weight)?; - - let (hotkey, netuid, limit_price): (T::AccountId, NetUid, Option) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::remove_stake_full_limit( - origin.into(), - hotkey, - netuid, - limit_price, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_remove_stake_full_limit_v1(env, origin) + } + FunctionId::SetColdkeyAutoStakeHotkeyV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_set_coldkey_auto_stake_hotkey_v1(env, origin) } FunctionId::CallerSetColdkeyAutoStakeHotkeyV1 => { - let weight = Weight::from_parts(29_930_000, 0) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)); - - env.charge_weight(weight)?; - - let (netuid, hotkey): (NetUid, T::AccountId) = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - let origin = convert_origin(env.origin()); - - let call_result = pallet_subtensor::Pallet::::set_coldkey_auto_stake_hotkey( - origin.into(), - netuid, - hotkey, - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_set_coldkey_auto_stake_hotkey_v1(env, origin) + } + FunctionId::AddProxyV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_add_proxy_v1(env, origin) } FunctionId::CallerAddProxyV1 => { - let weight = ::WeightInfo::add_proxy( - ::MaxProxies::get(), - ); - - env.charge_weight(weight)?; - - let delegate: T::AccountId = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - - let delegate_lookup = - <::Lookup as StaticLookup>::Source::from(delegate); - let origin = convert_origin(env.origin()); - - let call_result = pallet_proxy::Pallet::::add_proxy( - origin.into(), - delegate_lookup, - ProxyType::Staking, - 0u32.into(), - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_add_proxy_v1(env, origin) + } + FunctionId::RemoveProxyV1 => { + let origin = RawOrigin::Signed(env.caller()); + Self::dispatch_remove_proxy_v1(env, origin) } FunctionId::CallerRemoveProxyV1 => { - let weight = ::WeightInfo::remove_proxy( - ::MaxProxies::get(), - ); - - env.charge_weight(weight)?; - - let delegate: T::AccountId = env - .read_as() - .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; - - let delegate_lookup = - <::Lookup as StaticLookup>::Source::from(delegate); - let origin = convert_origin(env.origin()); - - let call_result = pallet_proxy::Pallet::::remove_proxy( - origin.into(), - delegate_lookup, - ProxyType::Staking, - 0u32.into(), - ); - - match call_result { - Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), - Err(e) => { - let error_code = Output::from(e) as u32; - Ok(RetVal::Converging(error_code)) - } - } + Self::dispatch_remove_proxy_v1(env, origin) } FunctionId::GetAlphaPriceV1 => { let netuid: NetUid = env diff --git a/chain-extensions/src/tests.rs b/chain-extensions/src/tests.rs index cb02ec9f0d..0f218c546e 100644 --- a/chain-extensions/src/tests.rs +++ b/chain-extensions/src/tests.rs @@ -1011,8 +1011,8 @@ fn get_alpha_price_returns_encoded_price() { } /// `Caller*` dispatch uses `env.origin()` via `convert_origin`; with [`MockEnv`] both match -/// `Signed(caller)`, so outcomes align with non-`Caller` arms while charging Caller weights where -/// they differ. +/// `Signed(caller)`, so outcomes align with non-`Caller` arms. Weight expectations match the shared +/// `dispatch_*_v1` helpers used by each pair. mod caller_dispatch_tests { use super::*; @@ -1040,9 +1040,9 @@ mod caller_dispatch_tests { amount_raw.into(), ); - let expected_weight = Weight::from_parts(394_300_000, 0) - .saturating_add(::DbWeight::get().reads(18)) - .saturating_add(::DbWeight::get().writes(9)); + let expected_weight = Weight::from_parts(340_800_000, 0) + .saturating_add(::DbWeight::get().reads(24)) + .saturating_add(::DbWeight::get().writes(15)); let mut env = MockEnv::new( FunctionId::CallerAddStakeV1, From 8a3547d2b49905f0c1de68cedd2c389ea60f23a3 Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 2 Apr 2026 17:44:03 +0800 Subject: [PATCH 09/12] update test case --- contract-tests/test/wasm.contract.test.ts | 78 +++++++++++------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/contract-tests/test/wasm.contract.test.ts b/contract-tests/test/wasm.contract.test.ts index 5421f4ff14..d85b236c3f 100644 --- a/contract-tests/test/wasm.contract.test.ts +++ b/contract-tests/test/wasm.contract.test.ts @@ -62,7 +62,7 @@ describe("Test wasm contract", () => { async function addStakeWhenWithoutStakeCaller() { const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake @@ -82,7 +82,7 @@ describe("Test wasm contract", () => { const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake @@ -617,15 +617,15 @@ describe("Test wasm contract", () => { assert.ok(result !== undefined) }) - it("Caller chain extension: add stake (fn 16)", async () => { + it("Can caller add stake (fn 16)", async () => { await addStakeWhenWithoutStakeCaller() }) - it("Caller chain extension: remove stake (fn 17)", async () => { + it("Can caller remove stake (fn 17)", async () => { await addStakeWhenWithoutStakeCaller() const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stake !== undefined) @@ -639,50 +639,50 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeAfter !== undefined && stakeAfter < stake!) }) - it("Caller chain extension: unstake_all (fn 18)", async () => { + it("Can caller unstake_all (fn 18)", async () => { await addStakeWhenWithoutStakeCaller() const message = inkClient.message("caller_unstake_all") const data = message.encode({ hotkey: Binary.fromBytes(hotkey.publicKey) }) await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeAfter !== undefined) assert.equal(stakeAfter, BigInt(0)) }) - it("Caller chain extension: unstake_all_alpha (fn 19)", async () => { + it("Can caller unstake_all_alpha (fn 19)", async () => { await addStakeWhenWithoutStakeCaller() const message = inkClient.message("caller_unstake_all_alpha") const data = message.encode({ hotkey: Binary.fromBytes(hotkey.publicKey) }) await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeAfter !== undefined) assert.equal(stakeAfter, BigInt(0)) }) - it("Caller chain extension: move_stake (fn 20)", async () => { + it("Can caller move_stake (fn 20)", async () => { await addStakeWhenWithoutStakeCaller() const originStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const destStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey2.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake || BigInt(0) assert.ok(originStakeBefore !== undefined && originStakeBefore > BigInt(0)) @@ -698,12 +698,12 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const originStakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const destStakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey2.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(originStakeAfter !== undefined && destStakeAfter !== undefined) @@ -711,11 +711,11 @@ describe("Test wasm contract", () => { assert.ok(destStakeAfter > destStakeBefore) }) - it("Caller chain extension: transfer_stake (fn 21)", async () => { + it("Can caller transfer_stake (fn 21)", async () => { await addStakeWhenWithoutStakeCaller() const stakeBeforeOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const stakeBeforeDest = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( @@ -737,7 +737,7 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfterOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const stakeAfterDest = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( @@ -750,16 +750,16 @@ describe("Test wasm contract", () => { assert.ok(stakeAfterDest > stakeBeforeDest!) }) - it("Caller chain extension: swap_stake (fn 22)", async () => { + it("Can caller swap_stake (fn 22)", async () => { await addStakeWhenWithoutStakeCaller() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const stakeBefore2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid + 1, ))?.stake || BigInt(0) assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) @@ -774,12 +774,12 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const stakeAfter2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid + 1, ))?.stake assert.ok(stakeAfter !== undefined && stakeAfter2 !== undefined) @@ -787,11 +787,11 @@ describe("Test wasm contract", () => { assert.ok(stakeAfter2 > stakeBefore2) }) - it("Caller chain extension: add_stake_limit (fn 23)", async () => { + it("Can caller add_stake_limit (fn 23)", async () => { await addStakeWhenWithoutStakeCaller() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeBefore !== undefined) @@ -806,17 +806,17 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeAfter !== undefined && stakeAfter > stakeBefore!) }) - it("Caller chain extension: remove_stake_limit (fn 24)", async () => { + it("Can caller remove_stake_limit (fn 24)", async () => { await addStakeWhenWithoutStakeCaller() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) @@ -831,22 +831,22 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeAfter !== undefined && stakeAfter < stakeBefore!) }) - it("Caller chain extension: swap_stake_limit (fn 25)", async () => { + it("Can caller swap_stake_limit (fn 25)", async () => { await addStakeWhenWithoutStakeCaller() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const stakeBefore2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid + 1, ))?.stake assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) @@ -863,12 +863,12 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake const stakeAfter2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid + 1, ))?.stake assert.ok(stakeAfter !== undefined && stakeAfter2 !== undefined) @@ -876,11 +876,11 @@ describe("Test wasm contract", () => { assert.ok(stakeAfter2 > stakeBefore2!) }) - it("Caller chain extension: remove_stake_full_limit (fn 26)", async () => { + it("Can caller remove_stake_full_limit (fn 26)", async () => { await addStakeWhenWithoutStakeCaller() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) @@ -893,13 +893,13 @@ describe("Test wasm contract", () => { await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ))?.stake assert.ok(stakeAfter !== undefined && stakeAfter < stakeBefore!) }) - it("Caller chain extension: set_coldkey_auto_stake_hotkey (fn 27)", async () => { + it("Can caller set_coldkey_auto_stake_hotkey (fn 27)", async () => { const message = inkClient.message("caller_set_coldkey_auto_stake_hotkey") const data = message.encode({ netuid, @@ -913,7 +913,7 @@ describe("Test wasm contract", () => { assert.ok(autoStakeHotkey === convertPublicKeyToSs58(hotkey2.publicKey)) }) - it("Caller chain extension: add_proxy and remove_proxy (fn 28-29)", async () => { + it("Can caller add_proxy and remove_proxy (fn 28-29)", async () => { const addMessage = inkClient.message("caller_add_proxy") const addData = addMessage.encode({ delegate: Binary.fromBytes(hotkey2.publicKey), From d756d4847f105a04d7ff2607238330822cd99ff7 Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 2 Apr 2026 18:22:30 +0800 Subject: [PATCH 10/12] fix proxy e2e --- contract-tests/test/wasm.contract.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contract-tests/test/wasm.contract.test.ts b/contract-tests/test/wasm.contract.test.ts index d85b236c3f..0a30b63ffc 100644 --- a/contract-tests/test/wasm.contract.test.ts +++ b/contract-tests/test/wasm.contract.test.ts @@ -919,7 +919,7 @@ describe("Test wasm contract", () => { delegate: Binary.fromBytes(hotkey2.publicKey), }) await sendWasmContractExtrinsic(api, coldkey, contractAddress, addData) - let proxies = await api.query.Proxy.Proxies.getValue(contractAddress) + let proxies = await api.query.Proxy.Proxies.getValue(convertPublicKeyToSs58(coldkey.publicKey)) assert.ok(proxies !== undefined && proxies[0].length > 0) assert.ok(proxies[0][0].delegate === convertPublicKeyToSs58(hotkey2.publicKey)) @@ -928,7 +928,7 @@ describe("Test wasm contract", () => { delegate: Binary.fromBytes(hotkey2.publicKey), }) await sendWasmContractExtrinsic(api, coldkey, contractAddress, removeData) - proxies = await api.query.Proxy.Proxies.getValue(contractAddress) + proxies = await api.query.Proxy.Proxies.getValue(convertPublicKeyToSs58(coldkey.publicKey)) assert.ok(proxies !== undefined && proxies[0].length === 0) }) }); \ No newline at end of file From d1257583202c7709d50c5e4f9500b053b4f831a8 Mon Sep 17 00:00:00 2001 From: open-junius Date: Fri, 3 Apr 2026 01:14:56 +0800 Subject: [PATCH 11/12] test passed --- contract-tests/src/subtensor.ts | 12 ++ contract-tests/test/wasm.contract.test.ts | 165 +++++++++++----------- 2 files changed, 94 insertions(+), 83 deletions(-) diff --git a/contract-tests/src/subtensor.ts b/contract-tests/src/subtensor.ts index 2b3b5d8be1..3feade6fcc 100644 --- a/contract-tests/src/subtensor.ts +++ b/contract-tests/src/subtensor.ts @@ -365,6 +365,9 @@ export async function setTargetRegistrationsPerInterval( call: internal_tx.decodedCall, }); await waitForTransactionWithRetry(api, tx, alice); + + const value = await api.query.SubtensorModule.TargetRegistrationsPerInterval.getValue(netuid) + assert.equal(1000, value) } // Disable admin freeze window and owner hyperparam rate limiting for tests @@ -437,4 +440,13 @@ export async function getStake(api: TypedApi, hotkey: string, col } return result; +} + +export async function setAdminFreezeWindow(api: TypedApi) { + const alice = getAliceSigner() + const window = 0; + const internalCall = api.tx.AdminUtils.sudo_set_admin_freeze_window({ window: window }) + const tx = api.tx.Sudo.sudo({ call: internalCall.decodedCall }) + await waitForTransactionWithRetry(api, tx, alice) + assert.equal(window, await api.query.SubtensorModule.AdminFreezeWindow.getValue()) } \ No newline at end of file diff --git a/contract-tests/test/wasm.contract.test.ts b/contract-tests/test/wasm.contract.test.ts index 0a30b63ffc..0ee2b0ab26 100644 --- a/contract-tests/test/wasm.contract.test.ts +++ b/contract-tests/test/wasm.contract.test.ts @@ -4,11 +4,12 @@ import { Binary, TypedApi } from "polkadot-api"; import * as assert from "assert"; import { contracts } from "../.papi/descriptors"; import { getInkClient, InkClient, } from "@polkadot-api/ink-contracts" -import { forceSetBalanceToSs58Address, startCall, burnedRegister } from "../src/subtensor"; +import { forceSetBalanceToSs58Address, startCall, burnedRegister, setTargetRegistrationsPerInterval, setAdminFreezeWindow } from "../src/subtensor"; import fs from "fs" import { convertPublicKeyToSs58 } from "../src/address-utils"; import { addNewSubnetwork, sendWasmContractExtrinsic } from "../src/subtensor"; import { tao } from "../src/balance-math"; +import { KeyPair } from "@polkadot-labs/hdkd-helpers" const bittensorWasmPath = "./bittensor/target/ink/bittensor.wasm" const bittensorBytecode = fs.readFileSync(bittensorWasmPath) @@ -16,63 +17,33 @@ const bittensorBytecode = fs.readFileSync(bittensorWasmPath) describe("Test wasm contract", () => { let api: TypedApi - const hotkey = getRandomSubstrateKeypair(); - const coldkey = getRandomSubstrateKeypair(); + let hotkey: KeyPair; + let coldkey: KeyPair; - const hotkey2 = getRandomSubstrateKeypair(); - const coldkey2 = getRandomSubstrateKeypair(); + let hotkey2: KeyPair; + let coldkey2: KeyPair; // set initial netuid to 0 to avoid warning let netuid: number = 0; - let contractAddress: string; + let contractAddress = ""; let inkClient: InkClient; - async function addStakeWhenWithoutStake() { - const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( - convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, - netuid, - ))?.stake - - assert.ok(stakeBefore !== undefined) - if (stakeBefore > BigInt(0)) { + async function addStakeViaContract(addStakeToContract: boolean) { + if (contractAddress === "") { return; } const amount = tao(100) - const message = inkClient.message("add_stake") - const data = message.encode({ - hotkey: Binary.fromBytes(hotkey.publicKey), - netuid: netuid, - amount: amount, - }) - await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) - - const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( - convertPublicKeyToSs58(hotkey.publicKey), - contractAddress, - netuid, - ))?.stake - - assert.ok(stake !== undefined) - assert.ok(stake > BigInt(0)) - } - - /** Same as `addStakeWhenWithoutStake` but uses chain extension fn 16 (`CallerAddStakeV1`). */ - async function addStakeWhenWithoutStakeCaller() { - const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( - convertPublicKeyToSs58(hotkey.publicKey), - convertPublicKeyToSs58(coldkey.publicKey), - netuid, - ))?.stake - - assert.ok(stakeBefore !== undefined) - if (stakeBefore > BigInt(0)) { - return; + let message + let dest + if (addStakeToContract) { + message = inkClient.message("add_stake") + dest = contractAddress; + } else { + message = inkClient.message("caller_add_stake") + dest = convertPublicKeyToSs58(coldkey.publicKey); } - const amount = tao(100) - const message = inkClient.message("caller_add_stake") const data = message.encode({ hotkey: Binary.fromBytes(hotkey.publicKey), netuid: netuid, @@ -82,7 +53,7 @@ describe("Test wasm contract", () => { const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), - convertPublicKeyToSs58(coldkey.publicKey), + dest, netuid, ))?.stake @@ -90,25 +61,42 @@ describe("Test wasm contract", () => { assert.ok(stake > BigInt(0)) } + async function initSecondColdAndHotkey() { + hotkey2 = getRandomSubstrateKeypair(); + coldkey2 = getRandomSubstrateKeypair(); + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey2.publicKey)) + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey2.publicKey)) + await burnedRegister(api, netuid, convertPublicKeyToSs58(hotkey2.publicKey), coldkey2) + } before(async () => { // init variables got from await and async api = await getDevnetApi() + await setAdminFreezeWindow(api); inkClient = getInkClient(contracts.bittensor) + hotkey = getRandomSubstrateKeypair(); + coldkey = getRandomSubstrateKeypair(); await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey.publicKey)) - await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey2.publicKey)) await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey.publicKey)) - await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey2.publicKey)) + netuid = await addNewSubnetwork(api, hotkey, coldkey) await startCall(api, netuid, coldkey) console.log("test the case on subnet ", netuid) - await burnedRegister(api, netuid, convertPublicKeyToSs58(hotkey2.publicKey), coldkey2) - await addNewSubnetwork(api, hotkey, coldkey) await startCall(api, netuid + 1, coldkey) + await setTargetRegistrationsPerInterval(api, netuid) }) + beforeEach(async () => { + hotkey = getRandomSubstrateKeypair(); + coldkey = getRandomSubstrateKeypair(); + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey.publicKey)) + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey.publicKey)) + await burnedRegister(api, netuid, convertPublicKeyToSs58(hotkey.publicKey), coldkey) + + }); + it("Can instantiate contract", async () => { const signer = getSignerFromKeypair(coldkey); const constructor = inkClient.constructor('new') @@ -137,12 +125,11 @@ describe("Test wasm contract", () => { value: tao(2000), }) await waitForTransactionWithRetry(api, transfer, signer) - - console.log("===== contractAddress", contractAddress) }) it("Can query stake info from contract", async () => { + const queryMessage = inkClient.message("get_stake_info_for_hotkey_coldkey_netuid") const data = queryMessage.encode({ @@ -175,11 +162,11 @@ describe("Test wasm contract", () => { }) it("Can add stake to contract", async () => { - await addStakeWhenWithoutStake() + await addStakeViaContract(true) }) it("Can remove stake to contract", async () => { - await addStakeWhenWithoutStake() + await addStakeViaContract(true) const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), contractAddress, @@ -210,8 +197,7 @@ describe("Test wasm contract", () => { }) it("Can unstake all from contract", async () => { - await addStakeWhenWithoutStake() - + await addStakeViaContract(true) // Get stake before unstake_all const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), @@ -240,7 +226,7 @@ describe("Test wasm contract", () => { }) it("Can unstake all alpha from contract", async () => { - await addStakeWhenWithoutStake() + await addStakeViaContract(true) // Get stake before unstake_all_alpha const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), @@ -269,8 +255,8 @@ describe("Test wasm contract", () => { }) it("Can move stake between hotkeys", async () => { - await addStakeWhenWithoutStake() - + await addStakeViaContract(true) + await initSecondColdAndHotkey() // Get initial stakes const originStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), @@ -318,8 +304,8 @@ describe("Test wasm contract", () => { }) it("Can transfer stake between coldkeys", async () => { - await addStakeWhenWithoutStake() - + await addStakeViaContract(true) + await initSecondColdAndHotkey() // Get initial stake const stakeBeforeOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), @@ -368,8 +354,7 @@ describe("Test wasm contract", () => { }) it("Can swap stake between networks", async () => { - await addStakeWhenWithoutStake() - + await addStakeViaContract(true) // Get initial stakes const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), @@ -416,7 +401,6 @@ describe("Test wasm contract", () => { }) it("Can add stake with limit", async () => { - await addStakeWhenWithoutStake() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), contractAddress, @@ -447,7 +431,7 @@ describe("Test wasm contract", () => { }) it("Can remove stake with limit", async () => { - await addStakeWhenWithoutStake() + await addStakeViaContract(true) const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), contractAddress, @@ -477,7 +461,7 @@ describe("Test wasm contract", () => { }) it("Can swap stake with limit", async () => { - await addStakeWhenWithoutStake() + await addStakeViaContract(true) const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), @@ -524,8 +508,7 @@ describe("Test wasm contract", () => { }) it("Can remove stake full limit", async () => { - await addStakeWhenWithoutStake() - + await addStakeViaContract(true) const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), contractAddress, @@ -618,11 +601,11 @@ describe("Test wasm contract", () => { }) it("Can caller add stake (fn 16)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) }) it("Can caller remove stake (fn 17)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -646,7 +629,13 @@ describe("Test wasm contract", () => { }) it("Can caller unstake_all (fn 18)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + convertPublicKeyToSs58(coldkey.publicKey), + netuid, + ))?.stake + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) const message = inkClient.message("caller_unstake_all") const data = message.encode({ hotkey: Binary.fromBytes(hotkey.publicKey) }) await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) @@ -656,11 +645,17 @@ describe("Test wasm contract", () => { netuid, ))?.stake assert.ok(stakeAfter !== undefined) - assert.equal(stakeAfter, BigInt(0)) + assert.ok(stakeAfter < stakeBefore!) }) it("Can caller unstake_all_alpha (fn 19)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + convertPublicKeyToSs58(coldkey.publicKey), + netuid, + ))?.stake + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) const message = inkClient.message("caller_unstake_all_alpha") const data = message.encode({ hotkey: Binary.fromBytes(hotkey.publicKey) }) await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) @@ -670,11 +665,12 @@ describe("Test wasm contract", () => { netuid, ))?.stake assert.ok(stakeAfter !== undefined) - assert.equal(stakeAfter, BigInt(0)) + assert.ok(stakeAfter < stakeBefore!) }) it("Can caller move_stake (fn 20)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) + await initSecondColdAndHotkey() const originStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -712,7 +708,8 @@ describe("Test wasm contract", () => { }) it("Can caller transfer_stake (fn 21)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) + await initSecondColdAndHotkey() const stakeBeforeOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -751,7 +748,8 @@ describe("Test wasm contract", () => { }) it("Can caller swap_stake (fn 22)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) + await initSecondColdAndHotkey() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -788,7 +786,6 @@ describe("Test wasm contract", () => { }) it("Can caller add_stake_limit (fn 23)", async () => { - await addStakeWhenWithoutStakeCaller() const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -813,7 +810,7 @@ describe("Test wasm contract", () => { }) it("Can caller remove_stake_limit (fn 24)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -838,7 +835,7 @@ describe("Test wasm contract", () => { }) it("Can caller swap_stake_limit (fn 25)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -877,7 +874,7 @@ describe("Test wasm contract", () => { }) it("Can caller remove_stake_full_limit (fn 26)", async () => { - await addStakeWhenWithoutStakeCaller() + await addStakeViaContract(false) const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( convertPublicKeyToSs58(hotkey.publicKey), convertPublicKeyToSs58(coldkey.publicKey), @@ -900,6 +897,8 @@ describe("Test wasm contract", () => { }) it("Can caller set_coldkey_auto_stake_hotkey (fn 27)", async () => { + await addStakeViaContract(false) + await initSecondColdAndHotkey() const message = inkClient.message("caller_set_coldkey_auto_stake_hotkey") const data = message.encode({ netuid, @@ -907,7 +906,7 @@ describe("Test wasm contract", () => { }) await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) const autoStakeHotkey = await api.query.SubtensorModule.AutoStakeDestination.getValue( - contractAddress, + convertPublicKeyToSs58(coldkey.publicKey), netuid, ) assert.ok(autoStakeHotkey === convertPublicKeyToSs58(hotkey2.publicKey)) From 735e2de6628bd6a7324bf27943add39da678d69a Mon Sep 17 00:00:00 2001 From: open-junius Date: Fri, 3 Apr 2026 14:44:17 +0800 Subject: [PATCH 12/12] bump version --- 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 5dc47c65b0..bbc466b838 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -268,7 +268,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: 395, + spec_version: 396, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,