1use frame_support::{dispatch::DispatchResult, traits::Currency, weights::Weight};
29pub use pallet::*;
30use pallet_identity;
31use sp_core::Get;
32
33#[cfg(feature = "runtime-benchmarks")]
34use frame_benchmarking::{account, v2::*, BenchmarkError};
35
36pub trait WeightInfo {
37 fn reap_identity(r: u32, s: u32) -> Weight;
38 fn poke_deposit() -> Weight;
39}
40
41impl WeightInfo for () {
42 fn reap_identity(_r: u32, _s: u32) -> Weight {
43 Weight::MAX
44 }
45 fn poke_deposit() -> Weight {
46 Weight::MAX
47 }
48}
49
50pub struct TestWeightInfo;
51impl WeightInfo for TestWeightInfo {
52 fn reap_identity(_r: u32, _s: u32) -> Weight {
53 Weight::zero()
54 }
55 fn poke_deposit() -> Weight {
56 Weight::zero()
57 }
58}
59
60type BalanceOf<T> = <<T as pallet_identity::Config>::Currency as Currency<
62 <T as frame_system::Config>::AccountId,
63>>::Balance;
64
65#[frame_support::pallet]
66pub mod pallet {
67 use super::*;
68 use frame_support::{
69 dispatch::{DispatchResultWithPostInfo, PostDispatchInfo},
70 pallet_prelude::*,
71 traits::EnsureOrigin,
72 };
73 use frame_system::pallet_prelude::*;
74
75 #[pallet::pallet]
76 pub struct Pallet<T>(_);
77
78 #[pallet::config]
79 pub trait Config: frame_system::Config + pallet_identity::Config {
80 #[allow(deprecated)]
82 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
83
84 type Reaper: EnsureOrigin<Self::RuntimeOrigin>;
87
88 type ReapIdentityHandler: OnReapIdentity<Self::AccountId>;
90
91 type WeightInfo: WeightInfo;
93 }
94
95 #[pallet::event]
96 #[pallet::generate_deposit(pub(super) fn deposit_event)]
97 pub enum Event<T: Config> {
98 IdentityReaped { who: T::AccountId },
100 DepositUpdated { who: T::AccountId, identity: BalanceOf<T>, subs: BalanceOf<T> },
103 }
104
105 #[pallet::call]
106 impl<T: Config> Pallet<T> {
107 #[pallet::call_index(0)]
110 #[pallet::weight(<T as pallet::Config>::WeightInfo::reap_identity(
111 T::MaxRegistrars::get(),
112 T::MaxSubAccounts::get()
113 ))]
114 pub fn reap_identity(
115 origin: OriginFor<T>,
116 who: T::AccountId,
117 ) -> DispatchResultWithPostInfo {
118 T::Reaper::ensure_origin(origin)?;
119 let (registrars, bytes, subs) = pallet_identity::Pallet::<T>::reap_identity(&who)?;
123 T::ReapIdentityHandler::on_reap_identity(&who, bytes, subs)?;
124 Self::deposit_event(Event::IdentityReaped { who });
125 let post = PostDispatchInfo {
126 actual_weight: Some(<T as pallet::Config>::WeightInfo::reap_identity(
127 registrars, subs,
128 )),
129 pays_fee: Pays::No,
130 };
131 Ok(post)
132 }
133
134 #[pallet::call_index(1)]
137 #[pallet::weight(<T as pallet::Config>::WeightInfo::poke_deposit())]
138 pub fn poke_deposit(origin: OriginFor<T>, who: T::AccountId) -> DispatchResultWithPostInfo {
139 ensure_root(origin)?;
140 let (id_deposit, subs_deposit) = pallet_identity::Pallet::<T>::poke_deposit(&who)?;
141 Self::deposit_event(Event::DepositUpdated {
142 who,
143 identity: id_deposit,
144 subs: subs_deposit,
145 });
146 Ok(Pays::No.into())
147 }
148 }
149}
150
151pub trait OnReapIdentity<AccountId> {
153 fn on_reap_identity(who: &AccountId, bytes: u32, subs: u32) -> DispatchResult;
164
165 #[cfg(feature = "runtime-benchmarks")]
170 fn ensure_successful_identity_reaping(who: &AccountId, bytes: u32, subs: u32);
171}
172
173impl<AccountId> OnReapIdentity<AccountId> for () {
174 fn on_reap_identity(_who: &AccountId, _bytes: u32, _subs: u32) -> DispatchResult {
175 Ok(())
176 }
177
178 #[cfg(feature = "runtime-benchmarks")]
179 fn ensure_successful_identity_reaping(_: &AccountId, _: u32, _: u32) {}
180}
181
182#[cfg(feature = "runtime-benchmarks")]
183#[benchmarks]
184mod benchmarks {
185 use super::*;
186 use alloc::{boxed::Box, vec, vec::Vec};
187 use codec::Encode;
188 use frame_support::traits::EnsureOrigin;
189 use frame_system::RawOrigin;
190 use pallet_identity::{Data, IdentityInformationProvider, Judgement, Pallet as Identity};
191 use sp_runtime::{
192 traits::{Bounded, Hash, StaticLookup},
193 Saturating,
194 };
195
196 const SEED: u32 = 0;
197
198 fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
199 let events = frame_system::Pallet::<T>::events();
200 let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
201 let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
202 assert_eq!(event, &system_event);
203 }
204
205 #[benchmark]
206 fn reap_identity(
207 r: Linear<0, { T::MaxRegistrars::get() }>,
208 s: Linear<0, { T::MaxSubAccounts::get() }>,
209 ) -> Result<(), BenchmarkError> {
210 let target: T::AccountId = account("target", 0, SEED);
212 let target_origin =
213 <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(target.clone()));
214 let target_lookup = T::Lookup::unlookup(target.clone());
215 let _ = T::Currency::make_free_balance_be(&target, BalanceOf::<T>::max_value());
216
217 let info = <T as pallet_identity::Config>::IdentityInformation::create_identity_info();
219 Identity::<T>::set_identity(
220 RawOrigin::Signed(target.clone()).into(),
221 Box::new(info.clone()),
222 )?;
223
224 let mut subs = Vec::new();
226 let data = Data::Raw(vec![0; 32].try_into().unwrap());
227 for ii in 0..s {
228 let sub_account = account("sub", ii, SEED);
229 subs.push((sub_account, data.clone()));
230 }
231 Identity::<T>::set_subs(target_origin.clone(), subs.clone())?;
232
233 T::ReapIdentityHandler::ensure_successful_identity_reaping(
234 &target,
235 info.encoded_size() as u32,
236 subs.len() as u32,
237 );
238
239 let registrar_origin = T::RegistrarOrigin::try_successful_origin()
241 .expect("RegistrarOrigin has no successful origin required for the benchmark");
242 for ii in 0..r {
243 let registrar: T::AccountId = account("registrar", ii, SEED);
245 let registrar_lookup = T::Lookup::unlookup(registrar.clone());
246 let _ = <T as pallet_identity::Config>::Currency::make_free_balance_be(
247 ®istrar,
248 <T as pallet_identity::Config>::Currency::minimum_balance(),
249 );
250
251 Identity::<T>::add_registrar(registrar_origin.clone(), registrar_lookup)?;
253 Identity::<T>::set_fee(RawOrigin::Signed(registrar.clone()).into(), ii, 10u32.into())?;
254 let fields = <T as pallet_identity::Config>::IdentityInformation::all_fields();
255 Identity::<T>::set_fields(RawOrigin::Signed(registrar.clone()).into(), ii, fields)?;
256
257 Identity::<T>::request_judgement(target_origin.clone(), ii, 10u32.into())?;
259 Identity::<T>::provide_judgement(
260 RawOrigin::Signed(registrar).into(),
261 ii,
262 target_lookup.clone(),
263 Judgement::Reasonable,
264 <T as frame_system::Config>::Hashing::hash_of(&info),
265 )?;
266 }
267
268 let origin = T::Reaper::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
269
270 #[extrinsic_call]
271 _(origin as T::RuntimeOrigin, target.clone());
272
273 assert_last_event::<T>(Event::<T>::IdentityReaped { who: target.clone() }.into());
274
275 let fields = <T as pallet_identity::Config>::IdentityInformation::all_fields();
276 assert!(!Identity::<T>::has_identity(&target, fields));
277 assert_eq!(Identity::<T>::subs(&target).len(), 0);
278
279 Ok(())
280 }
281
282 #[benchmark]
283 fn poke_deposit() -> Result<(), BenchmarkError> {
284 let target: T::AccountId = account("target", 0, SEED);
285 let _ = T::Currency::make_free_balance_be(&target, BalanceOf::<T>::max_value());
286 let info = <T as pallet_identity::Config>::IdentityInformation::create_identity_info();
287
288 let _ = Identity::<T>::set_identity_no_deposit(&target, info.clone());
289
290 let sub_account: T::AccountId = account("sub", 0, SEED);
291 let name = Data::Raw(b"benchsub".to_vec().try_into().unwrap());
292 let _ = Identity::<T>::set_subs_no_deposit(&target, vec![(sub_account.clone(), name)]);
293
294 let expected_id_deposit = <T as pallet_identity::Config>::BasicDeposit::get()
296 .saturating_add(
297 <T as pallet_identity::Config>::ByteDeposit::get()
298 .saturating_mul(<BalanceOf<T>>::from(info.encoded_size() as u32)),
299 );
300 let expected_sub_deposit = <T as pallet_identity::Config>::SubAccountDeposit::get();
302
303 #[extrinsic_call]
304 _(RawOrigin::Root, target.clone());
305
306 assert_last_event::<T>(
307 Event::<T>::DepositUpdated {
308 who: target,
309 identity: expected_id_deposit,
310 subs: expected_sub_deposit,
311 }
312 .into(),
313 );
314
315 Ok(())
316 }
317
318 impl_benchmark_test_suite!(
319 Pallet,
320 crate::integration_tests::new_test_ext(),
321 crate::integration_tests::Test,
322 );
323}