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        Identity,
24        dispatch::DispatchResult,
25        pallet_prelude::{ValueQuery, *},
26        traits::Currency,
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(6);
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::{NamedReservableCurrency, 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            + NamedReservableCurrency<Self::AccountId, ReserveIdentifier = [u8; 8]>
261            + Send
262            + Sync;
263        type ExistentialDeposit: Get<BalanceOf<Self>>;
264
265        type Governance: GovernanceApi<Self::AccountId>;
266
267        type Emission: Emission0Api<Self::AccountId>;
268        type Permission0: Permission0NamespacesApi<Self::AccountId, NamespacePath>;
269
270        type WeightInfo: WeightInfo;
271    }
272
273    #[pallet::pallet]
274    #[pallet::storage_version(STORAGE_VERSION)]
275    pub struct Pallet<T>(_);
276
277    #[pallet::call]
278    impl<T: Config> Pallet<T> {
279        /// Adds stakes from origin to the agent key.
280        #[pallet::call_index(0)]
281        #[pallet::weight((T::WeightInfo::add_stake(), DispatchClass::Normal, Pays::Yes))]
282        pub fn add_stake(
283            origin: OriginFor<T>,
284            agent_key: AccountIdOf<T>,
285            amount: BalanceOf<T>,
286        ) -> DispatchResult {
287            let key = ensure_signed(origin)?;
288            ensure!(
289                amount >= crate::MinAllowedStake::<T>::get(),
290                crate::Error::<T>::StakeTooSmall
291            );
292            stake::add_stake::<T>(key, agent_key, amount)
293        }
294
295        /// Removes stakes from origin to the agent key.
296        #[pallet::call_index(1)]
297        #[pallet::weight((T::WeightInfo::remove_stake(), DispatchClass::Normal, Pays::Yes))]
298        pub fn remove_stake(
299            origin: OriginFor<T>,
300            agent_key: AccountIdOf<T>,
301            amount: BalanceOf<T>,
302        ) -> DispatchResult {
303            let key = ensure_signed(origin)?;
304            stake::remove_stake::<T>(key, agent_key, amount)
305        }
306
307        /// Transfers origin's stakes from an agent to another.
308        #[pallet::call_index(2)]
309        #[pallet::weight((T::WeightInfo::transfer_stake(), DispatchClass::Normal, Pays::Yes))]
310        pub fn transfer_stake(
311            origin: OriginFor<T>,
312            agent_key: AccountIdOf<T>,
313            new_agent_key: AccountIdOf<T>,
314            amount: BalanceOf<T>,
315        ) -> DispatchResult {
316            let key = ensure_signed(origin)?;
317            stake::transfer_stake::<T>(key, agent_key, new_agent_key, amount)
318        }
319
320        /// Registers a new agent on behalf of an arbitrary key.
321        #[pallet::call_index(3)]
322        #[pallet::weight((T::WeightInfo::register_agent(), DispatchClass::Normal, Pays::Yes))]
323        pub fn register_agent(
324            origin: OriginFor<T>,
325            name: Vec<u8>,
326            url: Vec<u8>,
327            metadata: Vec<u8>,
328        ) -> DispatchResult {
329            let agent_key = ensure_signed(origin)?;
330            agent::register::<T>(agent_key, name, url, metadata)
331        }
332
333        /// Unregister origin's key agent.
334        #[pallet::call_index(4)]
335        #[pallet::weight((T::WeightInfo::deregister_agent(), DispatchClass::Normal, Pays::Yes))]
336        pub fn deregister_agent(origin: OriginFor<T>) -> DispatchResult {
337            let agent_key = ensure_signed(origin)?;
338            agent::deregister::<T>(agent_key)
339        }
340
341        /// Updates origin's key agent metadata.
342        #[pallet::call_index(5)]
343        #[pallet::weight((T::WeightInfo::update_agent(), DispatchClass::Normal, Pays::Yes))]
344        pub fn update_agent(
345            origin: OriginFor<T>,
346            url: Vec<u8>,
347            metadata: Option<Vec<u8>>,
348            staking_fee: Option<Percent>,
349            weight_control_fee: Option<Percent>,
350        ) -> DispatchResult {
351            let agent_key = ensure_signed(origin)?;
352            agent::update::<T>(agent_key, url, metadata, staking_fee, weight_control_fee)
353        }
354
355        /// Updates origin's key agent metadata.
356        #[pallet::call_index(6)]
357        #[pallet::weight((T::WeightInfo::set_agent_update_cooldown(), DispatchClass::Normal, Pays::Yes))]
358        pub fn set_agent_update_cooldown(
359            origin: OriginFor<T>,
360            new_cooldown: BlockNumberFor<T>,
361        ) -> DispatchResult {
362            ensure_root(origin)?;
363            AgentUpdateCooldown::<T>::set(new_cooldown);
364            Ok(())
365        }
366
367        /// Create a new namespace, automatically creating missing intermediate nodes
368        #[pallet::call_index(7)]
369        #[pallet::weight(Weight::default())]
370        pub fn create_namespace(origin: OriginFor<T>, path: NamespacePathInner) -> DispatchResult {
371            let owner = ensure_signed(origin)?;
372
373            ensure!(
374                <T as pallet::Config>::Governance::can_create_namespace(&owner),
375                Error::<T>::NamespacesFrozen
376            );
377
378            let namespace_path =
379                NamespacePath::new_agent(&path).map_err(|_| Error::<T>::InvalidNamespacePath)?;
380
381            namespace::create_namespace::<T>(NamespaceOwnership::Account(owner), namespace_path)
382        }
383
384        /// Delete a namespace and all its children
385        #[pallet::call_index(8)]
386        #[pallet::weight(Weight::default())]
387        pub fn delete_namespace(origin: OriginFor<T>, path: NamespacePathInner) -> DispatchResult {
388            let owner = ensure_signed(origin)?;
389
390            let namespace_path =
391                NamespacePath::new_agent(&path).map_err(|_| Error::<T>::InvalidNamespacePath)?;
392
393            ensure!(
394                !namespace_path.is_agent_root(),
395                Error::<T>::InvalidNamespacePath
396            );
397
398            namespace::delete_namespace::<T>(NamespaceOwnership::Account(owner), namespace_path)
399        }
400    }
401
402    #[pallet::event]
403    #[pallet::generate_deposit(pub fn deposit_event)]
404    pub enum Event<T: Config> {
405        /// Event created when stake has been transferred from the coldkey
406        /// account onto the key staking account
407        StakeAdded(AccountIdOf<T>, AccountIdOf<T>, BalanceOf<T>),
408        /// Event created when stake has been removed from the key staking
409        /// account onto the coldkey account
410        StakeRemoved(AccountIdOf<T>, AccountIdOf<T>, BalanceOf<T>),
411        /// Event created when a new agent account has been registered to the
412        /// chain
413        AgentRegistered(AccountIdOf<T>),
414        /// Event created when a agent account has been deregistered from the
415        /// chain
416        AgentUnregistered(AccountIdOf<T>),
417        /// Event created when the agent's updated information is added to the
418        /// network
419        AgentUpdated(AccountIdOf<T>),
420        /// Namespace created
421        NamespaceCreated {
422            owner: NamespaceOwnership<T>,
423            path: NamespacePath,
424        },
425        /// Namespace deleted
426        NamespaceDeleted {
427            owner: NamespaceOwnership<T>,
428            path: NamespacePath,
429        },
430    }
431
432    #[pallet::error]
433    pub enum Error<T> {
434        /// The specified agent does not exist.
435        AgentDoesNotExist,
436        /// Insufficient stake to withdraw the requested amount.
437        NotEnoughStakeToWithdraw,
438        /// Insufficient balance in the cold key account to stake the requested
439        /// amount.
440        NotEnoughBalanceToStake,
441        /// The number of agent registrations in this block exceeds the allowed
442        /// limit.
443        TooManyAgentRegistrationsThisBlock,
444        /// The number of agent registrations in this interval exceeds the
445        /// allowed limit.
446        TooManyAgentRegistrationsThisInterval,
447        /// The agent is already registered in the active set.
448        AgentAlreadyRegistered,
449        /// Failed to convert between u128 and T::Balance.
450        CouldNotConvertToBalance,
451        /// Failed to add balance to the account.
452        BalanceNotAdded,
453        /// Failed to remove stake from the account.
454        StakeNotRemoved,
455        /// Invalid shares distribution.
456        InvalidShares,
457        /// Insufficient balance to register.
458        NotEnoughBalanceToRegisterAgent,
459        /// Failed to add stake to the account.
460        StakeNotAdded,
461        /// Failed to remove balance from the account.
462        BalanceNotRemoved,
463        /// Balance could not be removed from the account.
464        BalanceCouldNotBeRemoved,
465        /// Insufficient stake to register.
466        NotEnoughStakeToRegister,
467        /// The entity is still registered and cannot be modified.
468        StillRegistered,
469        /// Insufficient balance to transfer.
470        NotEnoughBalanceToTransfer,
471        /// The agent metadata is invalid.
472        InvalidAgentMetadata,
473        /// The agent metadata is too long.
474        AgentMetadataTooLong,
475        /// The agent metadata is too long.
476        AgentMetadataTooShort,
477        /// The minimum burn value is invalid, likely too small.
478        InvalidMinBurn,
479        /// The maximum burn value is invalid.
480        InvalidMaxBurn,
481        /// The agent name is too long.
482        AgentNameTooLong,
483        /// The agent name is too short.
484        AgentNameTooShort,
485        /// The agent name is invalid. It must be a UTF-8 encoded string.
486        InvalidAgentName,
487        /// The agent url is too long.
488        AgentUrlTooLong,
489        /// The agent url is too short.
490        AgentUrlTooShort,
491        /// The agent ur; is invalid.
492        InvalidAgentUrl,
493        /// A agent with this name already exists in the subnet.
494        AgentNameAlreadyExists,
495        /// The stake amount to add or remove is too small. Minimum is 0.5 unit.
496        StakeTooSmall,
497        /// Key is not present in Whitelist, it needs to be whitelisted by a
498        /// Curator
499        AgentKeyNotWhitelisted,
500        /// The amount given is 0
501        InvalidAmount,
502        /// The staking fee given is lower than the minimum fee
503        InvalidStakingFee,
504        /// The weight control fee given is lower than the minimum fee
505        InvalidWeightControlFee,
506        /// The agent already updated recently
507        AgentUpdateOnCooldown,
508        /// Invalid namespace path
509        InvalidNamespacePath,
510        /// Namespace already exists
511        NamespaceAlreadyExists,
512        /// Namespace not found
513        NamespaceNotFound,
514        /// Parent namespace not found
515        ParentNamespaceNotFound,
516        /// Not the owner of the namespace
517        NotNamespaceOwner,
518        /// Cannot delete namespace with children
519        NamespaceHasChildren,
520        /// Namespace depth exceeded
521        NamespaceDepthExceeded,
522        /// The namespace is being delegated through a permission. Revoke that first.
523        NamespaceBeingDelegated,
524        /// Agent Creation was disabled by a curator.
525        AgentsFrozen,
526        /// Namespace Creation was disabled by a curator.
527        NamespacesFrozen,
528    }
529}
530
531impl<T: Config>
532    pallet_torus0_api::Torus0Api<T::AccountId, <T::Currency as Currency<T::AccountId>>::Balance>
533    for Pallet<T>
534{
535    fn reward_interval() -> u16 {
536        RewardInterval::<T>::get()
537    }
538
539    fn min_validator_stake() -> u128 {
540        MinValidatorStake::<T>::get()
541    }
542
543    fn max_validators() -> u16 {
544        MaxAllowedValidators::<T>::get()
545    }
546
547    fn weight_control_fee(who: &T::AccountId) -> Percent {
548        Agents::<T>::get(who)
549            .map(|agent| agent.fees.weight_control_fee)
550            .unwrap_or_else(|| FeeConstraints::<T>::get().min_weight_control_fee)
551    }
552
553    fn weight_penalty_factor(who: &T::AccountId) -> Percent {
554        Agents::<T>::get(who)
555            .map(|agent| agent.weight_penalty_factor)
556            .unwrap_or_default()
557    }
558
559    fn staking_fee(who: &T::AccountId) -> Percent {
560        Agents::<T>::get(who)
561            .map(|agent| agent.fees.staking_fee)
562            .unwrap_or_else(|| FeeConstraints::<T>::get().min_staking_fee)
563    }
564
565    fn sum_staking_to(staker: &T::AccountId) -> BalanceOf<T> {
566        stake::sum_staking_to::<T>(staker)
567    }
568
569    fn staked_by(
570        staked: &T::AccountId,
571    ) -> sp_std::vec::Vec<(
572        T::AccountId,
573        <T::Currency as Currency<T::AccountId>>::Balance,
574    )> {
575        stake::get_staked_by_vector::<T>(staked)
576    }
577
578    fn stake_to(
579        staker: &T::AccountId,
580        staked: &T::AccountId,
581        amount: <T::Currency as Currency<T::AccountId>>::Balance,
582    ) -> DispatchResult {
583        stake::add_stake::<T>(staker.clone(), staked.clone(), amount)
584    }
585
586    fn agent_ids() -> impl Iterator<Item = T::AccountId> {
587        Agents::<T>::iter_keys()
588    }
589
590    fn find_agent_by_name(name: &[u8]) -> Option<T::AccountId> {
591        Agents::<T>::iter()
592            .find(|(_, agent)| *agent.name == name)
593            .map(|(id, _)| id)
594    }
595
596    fn is_agent_registered(agent: &T::AccountId) -> bool {
597        Agents::<T>::contains_key(agent)
598    }
599
600    fn namespace_exists(agent: &T::AccountId, path: &NamespacePath) -> bool {
601        Namespaces::<T>::contains_key(NamespaceOwnership::Account(agent.clone()), path)
602    }
603
604    #[cfg(feature = "runtime-benchmarks")]
605    fn force_register_agent(
606        id: &T::AccountId,
607        name: Vec<u8>,
608        url: Vec<u8>,
609        metadata: Vec<u8>,
610    ) -> DispatchResult {
611        crate::Agents::<T>::set(
612            id,
613            Some(Agent {
614                key: id.clone(),
615                name: name
616                    .try_into()
617                    .map_err(|_| DispatchError::Other("failed to trim fields"))?,
618                url: url
619                    .try_into()
620                    .map_err(|_| DispatchError::Other("failed to trim fields"))?,
621                metadata: metadata
622                    .try_into()
623                    .map_err(|_| DispatchError::Other("failed to trim fields"))?,
624                weight_penalty_factor: Default::default(),
625                registration_block: Default::default(),
626                fees: Default::default(),
627                last_update_block: Default::default(),
628            }),
629        );
630
631        Ok(())
632    }
633
634    #[cfg(feature = "runtime-benchmarks")]
635    fn force_set_stake(
636        staker: &T::AccountId,
637        staked: &T::AccountId,
638        amount: BalanceOf<T>,
639    ) -> DispatchResult {
640        stake::add_stake::<T>(staker.clone(), staked.clone(), amount)
641    }
642}