pallet_torus0/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3pub mod agent;
4pub mod burn;
5mod ext;
6pub mod fee;
7pub mod migrations;
8pub mod namespace;
9pub mod stake;
10
11pub mod benchmarking;
12pub mod weights;
13
14pub(crate) use ext::*;
15use frame::{
16    arithmetic::Percent,
17    prelude::{ensure_root, ensure_signed},
18};
19use namespace::{NamespaceMetadata, NamespaceOwnership, NamespacePath};
20pub use pallet::*;
21use polkadot_sdk::{
22    frame_support::{
23        dispatch::DispatchResult,
24        pallet_prelude::{ValueQuery, *},
25        traits::Currency,
26        Identity,
27    },
28    frame_system::pallet_prelude::OriginFor,
29    polkadot_sdk_frame as frame, sp_std,
30};
31use scale_info::prelude::vec::Vec;
32
33use crate::{agent::Agent, burn::BurnConfiguration, fee::ValidatorFeeConstraints};
34
35#[frame::pallet]
36pub mod pallet {
37    const STORAGE_VERSION: StorageVersion = StorageVersion::new(5);
38
39    use frame::prelude::BlockNumberFor;
40    use pallet_emission0_api::Emission0Api;
41    use pallet_governance_api::GovernanceApi;
42    use pallet_permission0_api::Permission0NamespacesApi;
43    use pallet_torus0_api::NamespacePathInner;
44    use polkadot_sdk::frame_support::traits::ReservableCurrency;
45    use weights::WeightInfo;
46
47    use super::*;
48
49    /// Max allowed of validators. This is used then calculating emissions, only
50    /// the top staked agents up to this value will have their weights
51    /// considered.
52    #[pallet::storage]
53    pub type MaxAllowedValidators<T: Config> =
54        StorageValue<_, u16, ValueQuery, T::DefaultMaxAllowedValidators>;
55
56    /// Amount of tokens to burn from a payer key when registering new agents.
57    #[pallet::storage]
58    pub type Burn<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
59
60    /// Number of agent registrations that happened in the last
61    /// [`BurnConfiguration::target_registrations_interval`] blocks.
62    #[pallet::storage]
63    pub type RegistrationsThisInterval<T: Config> = StorageValue<_, u16, ValueQuery>;
64
65    /// Minimum required stake for an agent to be considered a validator.
66    #[pallet::storage]
67    pub type MinValidatorStake<T: Config> =
68        StorageValue<_, BalanceOf<T>, ValueQuery, T::DefaultMinValidatorStake>;
69
70    /// Number of blocks between emissions.
71    #[pallet::storage]
72    pub type RewardInterval<T: Config> = StorageValue<_, u16, ValueQuery, T::DefaultRewardInterval>;
73
74    /// Known registered network agents indexed by the owner's key.
75    #[pallet::storage]
76    pub type Agents<T: Config> = StorageMap<_, Identity, AccountIdOf<T>, Agent<T>>;
77
78    /// Maximum number of characters allowed in an agent name.
79    #[pallet::storage]
80    pub type MaxNameLength<T: Config> = StorageValue<_, u16, ValueQuery, T::DefaultMaxNameLength>;
81
82    /// Minimum number of characters required in an agent name.
83    #[pallet::storage]
84    pub type MinNameLength<T: Config> = StorageValue<_, u16, ValueQuery, T::DefaultMinNameLength>;
85
86    /// Maximum number of characters allowed in an agent URL.
87    #[pallet::storage]
88    pub type MaxAgentUrlLength<T: Config> =
89        StorageValue<_, u16, ValueQuery, T::DefaultMaxAgentUrlLength>;
90
91    /// Number of agent registrations that happened this block.
92    #[pallet::storage]
93    pub type RegistrationsThisBlock<T> = StorageValue<_, u16, ValueQuery>;
94
95    /// Maximum amount of agent registrations per block, tracked by
96    /// [`RegistrationsThisBlock`].
97    #[pallet::storage]
98    pub type MaxRegistrationsPerBlock<T: Config> =
99        StorageValue<_, u16, ValueQuery, T::DefaultMaxRegistrationsPerBlock>;
100
101    // Map of staked tokens prefixed by the staker, and indexed by the staked agents
102    // mapping to the amount in tokens.
103    #[pallet::storage]
104    pub type StakingTo<T: Config> =
105        StorageDoubleMap<_, Identity, T::AccountId, Identity, T::AccountId, BalanceOf<T>>;
106
107    // Map of staked tokens prefixed by the staked agent, and indexed by the staker
108    // keys mapping to the amount in tokens.
109    #[pallet::storage]
110    pub type StakedBy<T: Config> =
111        StorageDoubleMap<_, Identity, T::AccountId, Identity, T::AccountId, BalanceOf<T>>;
112
113    /// The total amount of stake in the network.
114    #[pallet::storage]
115    pub type TotalStake<T> = StorageValue<_, BalanceOf<T>, ValueQuery>;
116
117    /// Minimum amount of stake in tokens a key has to deposit in an agent.
118    #[pallet::storage]
119    pub type MinAllowedStake<T: Config> =
120        StorageValue<_, BalanceOf<T>, ValueQuery, T::DefaultMinAllowedStake>;
121
122    /// The weight dividends have when finding agents to prune. 100% meaning it
123    /// is taking fully into account.
124    #[pallet::storage]
125    pub type DividendsParticipationWeight<T: Config> =
126        StorageValue<_, Percent, ValueQuery, T::DefaultDividendsParticipationWeight>;
127
128    /// Constraints defining validation of agent fees.
129    #[pallet::storage]
130    pub type FeeConstraints<T: Config> = StorageValue<_, ValidatorFeeConstraints<T>, ValueQuery>;
131
132    /// [`Burn`] configuration values.
133    #[pallet::storage]
134    pub type BurnConfig<T: Config> = StorageValue<_, BurnConfiguration<T>, ValueQuery>;
135
136    /// Cooldown (in blocks) in which an agent needs to wait between each `update_agent` call.
137    #[pallet::storage]
138    pub type AgentUpdateCooldown<T: Config> =
139        StorageValue<_, BlockNumberFor<T>, ValueQuery, T::DefaultAgentUpdateCooldown>;
140
141    /// Namespace registry - maps (owner, path) to metadata
142    #[pallet::storage]
143    pub type Namespaces<T: Config> = StorageDoubleMap<
144        _,
145        Blake2_128Concat,
146        NamespaceOwnership<T>,
147        Blake2_128Concat,
148        NamespacePath,
149        NamespaceMetadata<T>,
150    >;
151
152    /// Count of namespaces registered per account
153    #[pallet::storage]
154    pub type NamespaceCount<T: Config> =
155        StorageMap<_, Blake2_128Concat, NamespaceOwnership<T>, u32, ValueQuery>;
156
157    #[pallet::storage]
158    pub type NamespacePricingConfig<T: Config> = StorageValue<
159        _,
160        namespace::NamespacePricingConfig<T>,
161        ValueQuery,
162        T::DefaultNamespacePricingConfig,
163    >;
164
165    #[pallet::hooks]
166    impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
167        fn on_initialize(block_number: BlockNumberFor<T>) -> Weight {
168            let current_block: u64 = block_number
169                .try_into()
170                .ok()
171                .expect("blockchain won't pass 2 ^ 64 blocks");
172
173            burn::adjust_burn::<T>(current_block);
174
175            RegistrationsThisBlock::<T>::set(0);
176
177            Weight::default()
178        }
179    }
180
181    #[pallet::config]
182    pub trait Config: polkadot_sdk::frame_system::Config {
183        #[pallet::constant]
184        type DefaultMaxAllowedValidators: Get<u16>;
185
186        #[pallet::constant]
187        type DefaultMinValidatorStake: Get<BalanceOf<Self>>;
188
189        #[pallet::constant]
190        type DefaultRewardInterval: Get<u16>;
191
192        #[pallet::constant]
193        type DefaultMinNameLength: Get<u16>;
194
195        #[pallet::constant]
196        type DefaultMaxNameLength: Get<u16>;
197
198        #[pallet::constant]
199        type DefaultMaxAgentUrlLength: Get<u16>;
200
201        #[pallet::constant]
202        type DefaultMaxRegistrationsPerBlock: Get<u16>;
203
204        #[pallet::constant]
205        type DefaultMinAllowedStake: Get<BalanceOf<Self>>;
206
207        #[pallet::constant]
208        type DefaultMinStakingFee: Get<u8>;
209
210        #[pallet::constant]
211        type DefaultMinWeightControlFee: Get<u8>;
212
213        #[pallet::constant]
214        type DefaultMinBurn: Get<BalanceOf<Self>>;
215
216        #[pallet::constant]
217        type DefaultMaxBurn: Get<BalanceOf<Self>>;
218
219        #[pallet::constant]
220        type DefaultAdjustmentAlpha: Get<u64>;
221
222        #[pallet::constant]
223        type DefaultTargetRegistrationsInterval: Get<BlockNumberFor<Self>>;
224
225        #[pallet::constant]
226        type DefaultTargetRegistrationsPerInterval: Get<u16>;
227
228        #[pallet::constant]
229        type DefaultMaxRegistrationsPerInterval: Get<u16>;
230
231        /// The storage MaxNameLength should be constrained to be no more than
232        /// the value of this. This is needed on agent::Agent to set the
233        /// `name` field BoundedVec max length.
234        #[pallet::constant]
235        type MaxAgentNameLengthConstraint: Get<u32>;
236
237        /// This is needed on agent::Agent to set the `url` field BoundedVec max
238        /// length.
239        #[pallet::constant]
240        type MaxAgentUrlLengthConstraint: Get<u32>;
241
242        #[pallet::constant]
243        type MaxAgentMetadataLengthConstraint: Get<u32>;
244
245        #[pallet::constant]
246        type DefaultDividendsParticipationWeight: Get<Percent>;
247
248        /// Default Cooldown (in blocks) in which an agent needs to wait between each `update_agent` call.
249        #[pallet::constant]
250        type DefaultAgentUpdateCooldown: Get<BlockNumberFor<Self>>;
251
252        #[pallet::constant]
253        type DefaultNamespacePricingConfig: Get<namespace::NamespacePricingConfig<Self>>;
254
255        type RuntimeEvent: From<Event<Self>>
256            + IsType<<Self as polkadot_sdk::frame_system::Config>::RuntimeEvent>;
257
258        type Currency: Currency<Self::AccountId, Balance = u128>
259            + ReservableCurrency<Self::AccountId>
260            + Send
261            + Sync;
262
263        type Governance: GovernanceApi<Self::AccountId>;
264
265        type Emission: Emission0Api<Self::AccountId>;
266        type Permission0: Permission0NamespacesApi<Self::AccountId, NamespacePath>;
267
268        type WeightInfo: WeightInfo;
269    }
270
271    #[pallet::pallet]
272    #[pallet::storage_version(STORAGE_VERSION)]
273    pub struct Pallet<T>(_);
274
275    #[pallet::call]
276    impl<T: Config> Pallet<T> {
277        /// Adds stakes from origin to the agent key.
278        #[pallet::call_index(0)]
279        #[pallet::weight((T::WeightInfo::add_stake(), DispatchClass::Normal, Pays::Yes))]
280        pub fn add_stake(
281            origin: OriginFor<T>,
282            agent_key: AccountIdOf<T>,
283            amount: BalanceOf<T>,
284        ) -> DispatchResult {
285            let key = ensure_signed(origin)?;
286            ensure!(
287                amount >= crate::MinAllowedStake::<T>::get(),
288                crate::Error::<T>::StakeTooSmall
289            );
290            stake::add_stake::<T>(key, agent_key, amount)
291        }
292
293        /// Removes stakes from origin to the agent key.
294        #[pallet::call_index(1)]
295        #[pallet::weight((T::WeightInfo::remove_stake(), DispatchClass::Normal, Pays::Yes))]
296        pub fn remove_stake(
297            origin: OriginFor<T>,
298            agent_key: AccountIdOf<T>,
299            amount: BalanceOf<T>,
300        ) -> DispatchResult {
301            let key = ensure_signed(origin)?;
302            stake::remove_stake::<T>(key, agent_key, amount)
303        }
304
305        /// Transfers origin's stakes from an agent to another.
306        #[pallet::call_index(2)]
307        #[pallet::weight((T::WeightInfo::transfer_stake(), DispatchClass::Normal, Pays::Yes))]
308        pub fn transfer_stake(
309            origin: OriginFor<T>,
310            agent_key: AccountIdOf<T>,
311            new_agent_key: AccountIdOf<T>,
312            amount: BalanceOf<T>,
313        ) -> DispatchResult {
314            let key = ensure_signed(origin)?;
315            stake::transfer_stake::<T>(key, agent_key, new_agent_key, amount)
316        }
317
318        /// Registers a new agent on behalf of an arbitrary key.
319        #[pallet::call_index(3)]
320        #[pallet::weight((T::WeightInfo::register_agent(), DispatchClass::Normal, Pays::Yes))]
321        pub fn register_agent(
322            origin: OriginFor<T>,
323            agent_key: T::AccountId,
324            name: Vec<u8>,
325            url: Vec<u8>,
326            metadata: Vec<u8>,
327        ) -> DispatchResult {
328            let payer = ensure_signed(origin)?;
329            agent::register::<T>(payer, agent_key, name, url, metadata)
330        }
331
332        /// Unregister origin's key agent.
333        #[pallet::call_index(4)]
334        #[pallet::weight((T::WeightInfo::unregister_agent(), DispatchClass::Normal, Pays::Yes))]
335        pub fn unregister_agent(origin: OriginFor<T>) -> DispatchResult {
336            let agent_key = ensure_signed(origin)?;
337            agent::unregister::<T>(agent_key)
338        }
339
340        /// Updates origin's key agent metadata.
341        #[pallet::call_index(5)]
342        #[pallet::weight((T::WeightInfo::update_agent(), DispatchClass::Normal, Pays::Yes))]
343        pub fn update_agent(
344            origin: OriginFor<T>,
345            url: Vec<u8>,
346            metadata: Option<Vec<u8>>,
347            staking_fee: Option<Percent>,
348            weight_control_fee: Option<Percent>,
349        ) -> DispatchResult {
350            let agent_key = ensure_signed(origin)?;
351            agent::update::<T>(agent_key, url, metadata, staking_fee, weight_control_fee)
352        }
353
354        /// Updates origin's key agent metadata.
355        #[pallet::call_index(6)]
356        #[pallet::weight((T::WeightInfo::set_agent_update_cooldown(), DispatchClass::Normal, Pays::Yes))]
357        pub fn set_agent_update_cooldown(
358            origin: OriginFor<T>,
359            new_cooldown: BlockNumberFor<T>,
360        ) -> DispatchResult {
361            ensure_root(origin)?;
362            AgentUpdateCooldown::<T>::set(new_cooldown);
363            Ok(())
364        }
365
366        /// Create a new namespace, automatically creating missing intermediate nodes
367        #[pallet::call_index(7)]
368        #[pallet::weight(Weight::default())]
369        pub fn create_namespace(origin: OriginFor<T>, path: NamespacePathInner) -> DispatchResult {
370            let owner = ensure_signed(origin)?;
371
372            ensure!(
373                <T as pallet::Config>::Governance::can_create_namespace(&owner),
374                Error::<T>::NamespacesFrozen
375            );
376
377            let namespace_path =
378                NamespacePath::new_agent(&path).map_err(|_| Error::<T>::InvalidNamespacePath)?;
379
380            namespace::create_namespace::<T>(NamespaceOwnership::Account(owner), namespace_path)
381        }
382
383        /// Delete a namespace and all its children
384        #[pallet::call_index(8)]
385        #[pallet::weight(Weight::default())]
386        pub fn delete_namespace(origin: OriginFor<T>, path: NamespacePathInner) -> DispatchResult {
387            let owner = ensure_signed(origin)?;
388
389            let namespace_path =
390                NamespacePath::new_agent(&path).map_err(|_| Error::<T>::InvalidNamespacePath)?;
391
392            ensure!(
393                !namespace_path.is_agent_root(),
394                Error::<T>::InvalidNamespacePath
395            );
396
397            namespace::delete_namespace::<T>(NamespaceOwnership::Account(owner), namespace_path)
398        }
399    }
400
401    #[pallet::event]
402    #[pallet::generate_deposit(pub fn deposit_event)]
403    pub enum Event<T: Config> {
404        /// Event created when stake has been transferred from the coldkey
405        /// account onto the key staking account
406        StakeAdded(AccountIdOf<T>, AccountIdOf<T>, BalanceOf<T>),
407        /// Event created when stake has been removed from the key staking
408        /// account onto the coldkey account
409        StakeRemoved(AccountIdOf<T>, AccountIdOf<T>, BalanceOf<T>),
410        /// Event created when a new agent account has been registered to the
411        /// chain
412        AgentRegistered(AccountIdOf<T>),
413        /// Event created when a agent account has been deregistered from the
414        /// chain
415        AgentUnregistered(AccountIdOf<T>),
416        /// Event created when the agent's updated information is added to the
417        /// network
418        AgentUpdated(AccountIdOf<T>),
419        /// Namespace created
420        NamespaceCreated {
421            owner: NamespaceOwnership<T>,
422            path: NamespacePath,
423        },
424        /// Namespace deleted
425        NamespaceDeleted {
426            owner: NamespaceOwnership<T>,
427            path: NamespacePath,
428        },
429    }
430
431    #[pallet::error]
432    pub enum Error<T> {
433        /// The specified agent does not exist.
434        AgentDoesNotExist,
435        /// Insufficient stake to withdraw the requested amount.
436        NotEnoughStakeToWithdraw,
437        /// Insufficient balance in the cold key account to stake the requested
438        /// amount.
439        NotEnoughBalanceToStake,
440        /// The number of agent registrations in this block exceeds the allowed
441        /// limit.
442        TooManyAgentRegistrationsThisBlock,
443        /// The number of agent registrations in this interval exceeds the
444        /// allowed limit.
445        TooManyAgentRegistrationsThisInterval,
446        /// The agent is already registered in the active set.
447        AgentAlreadyRegistered,
448        /// Failed to convert between u128 and T::Balance.
449        CouldNotConvertToBalance,
450        /// Failed to add balance to the account.
451        BalanceNotAdded,
452        /// Failed to remove stake from the account.
453        StakeNotRemoved,
454        /// Invalid shares distribution.
455        InvalidShares,
456        /// Insufficient balance to register.
457        NotEnoughBalanceToRegisterAgent,
458        /// Failed to add stake to the account.
459        StakeNotAdded,
460        /// Failed to remove balance from the account.
461        BalanceNotRemoved,
462        /// Balance could not be removed from the account.
463        BalanceCouldNotBeRemoved,
464        /// Insufficient stake to register.
465        NotEnoughStakeToRegister,
466        /// The entity is still registered and cannot be modified.
467        StillRegistered,
468        /// Insufficient balance to transfer.
469        NotEnoughBalanceToTransfer,
470        /// The agent metadata is invalid.
471        InvalidAgentMetadata,
472        /// The agent metadata is too long.
473        AgentMetadataTooLong,
474        /// The agent metadata is too long.
475        AgentMetadataTooShort,
476        /// The minimum burn value is invalid, likely too small.
477        InvalidMinBurn,
478        /// The maximum burn value is invalid.
479        InvalidMaxBurn,
480        /// The agent name is too long.
481        AgentNameTooLong,
482        /// The agent name is too short.
483        AgentNameTooShort,
484        /// The agent name is invalid. It must be a UTF-8 encoded string.
485        InvalidAgentName,
486        /// The agent url is too long.
487        AgentUrlTooLong,
488        /// The agent url is too short.
489        AgentUrlTooShort,
490        /// The agent ur; is invalid.
491        InvalidAgentUrl,
492        /// A agent with this name already exists in the subnet.
493        AgentNameAlreadyExists,
494        /// The stake amount to add or remove is too small. Minimum is 0.5 unit.
495        StakeTooSmall,
496        /// Key is not present in Whitelist, it needs to be whitelisted by a
497        /// Curator
498        AgentKeyNotWhitelisted,
499        /// The amount given is 0
500        InvalidAmount,
501        /// The staking fee given is lower than the minimum fee
502        InvalidStakingFee,
503        /// The weight control fee given is lower than the minimum fee
504        InvalidWeightControlFee,
505        /// The agent already updated recently
506        AgentUpdateOnCooldown,
507        /// Invalid namespace path
508        InvalidNamespacePath,
509        /// Namespace already exists
510        NamespaceAlreadyExists,
511        /// Namespace not found
512        NamespaceNotFound,
513        /// Parent namespace not found
514        ParentNamespaceNotFound,
515        /// Not the owner of the namespace
516        NotNamespaceOwner,
517        /// Cannot delete namespace with children
518        NamespaceHasChildren,
519        /// Namespace depth exceeded
520        NamespaceDepthExceeded,
521        /// The namespace is being delegated through a permission. Revoke that first.
522        NamespaceBeingDelegated,
523        /// Agent Creation was disabled by a curator.
524        AgentsFrozen,
525        /// Namespace Creation was disabled by a curator.
526        NamespacesFrozen,
527    }
528}
529
530impl<T: Config>
531    pallet_torus0_api::Torus0Api<T::AccountId, <T::Currency as Currency<T::AccountId>>::Balance>
532    for Pallet<T>
533{
534    fn reward_interval() -> u16 {
535        RewardInterval::<T>::get()
536    }
537
538    fn min_validator_stake() -> u128 {
539        MinValidatorStake::<T>::get()
540    }
541
542    fn max_validators() -> u16 {
543        MaxAllowedValidators::<T>::get()
544    }
545
546    fn weight_control_fee(who: &T::AccountId) -> Percent {
547        Agents::<T>::get(who)
548            .map(|agent| agent.fees.weight_control_fee)
549            .unwrap_or_else(|| FeeConstraints::<T>::get().min_weight_control_fee)
550    }
551
552    fn weight_penalty_factor(who: &T::AccountId) -> Percent {
553        Agents::<T>::get(who)
554            .map(|agent| agent.weight_penalty_factor)
555            .unwrap_or_default()
556    }
557
558    fn staking_fee(who: &T::AccountId) -> Percent {
559        Agents::<T>::get(who)
560            .map(|agent| agent.fees.staking_fee)
561            .unwrap_or_else(|| FeeConstraints::<T>::get().min_staking_fee)
562    }
563
564    fn sum_staking_to(staker: &T::AccountId) -> BalanceOf<T> {
565        stake::sum_staking_to::<T>(staker)
566    }
567
568    fn staked_by(
569        staked: &T::AccountId,
570    ) -> sp_std::vec::Vec<(
571        T::AccountId,
572        <T::Currency as Currency<T::AccountId>>::Balance,
573    )> {
574        stake::get_staked_by_vector::<T>(staked)
575    }
576
577    fn stake_to(
578        staker: &T::AccountId,
579        staked: &T::AccountId,
580        amount: <T::Currency as Currency<T::AccountId>>::Balance,
581    ) -> Result<(), <T::Currency as Currency<T::AccountId>>::Balance> {
582        stake::add_stake::<T>(staker.clone(), staked.clone(), amount).map_err(|_| amount)
583    }
584
585    fn agent_ids() -> impl Iterator<Item = T::AccountId> {
586        Agents::<T>::iter_keys()
587    }
588
589    fn is_agent_registered(agent: &T::AccountId) -> bool {
590        Agents::<T>::contains_key(agent)
591    }
592
593    fn namespace_exists(agent: &T::AccountId, path: &NamespacePath) -> bool {
594        Namespaces::<T>::contains_key(NamespaceOwnership::Account(agent.clone()), path)
595    }
596
597    #[cfg(feature = "runtime-benchmarks")]
598    fn force_register_agent(
599        id: &T::AccountId,
600        name: Vec<u8>,
601        url: Vec<u8>,
602        metadata: Vec<u8>,
603    ) -> DispatchResult {
604        crate::Agents::<T>::set(
605            id,
606            Some(Agent {
607                key: id.clone(),
608                name: name
609                    .try_into()
610                    .map_err(|_| DispatchError::Other("failed to trim fields"))?,
611                url: url
612                    .try_into()
613                    .map_err(|_| DispatchError::Other("failed to trim fields"))?,
614                metadata: metadata
615                    .try_into()
616                    .map_err(|_| DispatchError::Other("failed to trim fields"))?,
617                weight_penalty_factor: Default::default(),
618                registration_block: Default::default(),
619                fees: Default::default(),
620                last_update_block: Default::default(),
621            }),
622        );
623
624        Ok(())
625    }
626
627    #[cfg(feature = "runtime-benchmarks")]
628    fn force_set_stake(
629        staker: &T::AccountId,
630        staked: &T::AccountId,
631        amount: BalanceOf<T>,
632    ) -> DispatchResult {
633        stake::add_stake::<T>(staker.clone(), staked.clone(), amount)
634    }
635}