1#![cfg_attr(not(feature = "std"), no_std)]
31
32mod benchmarking;
33mod tests;
34pub mod weights;
35
36extern crate alloc;
37use alloc::{boxed::Box, vec};
38use frame::{
39 prelude::*,
40 traits::{Currency, InstanceFilter, ReservableCurrency},
41};
42pub use pallet::*;
43pub use weights::WeightInfo;
44
45type CallHashOf<T> = <<T as Config>::CallHasher as Hash>::Output;
46
47type BalanceOf<T> =
48 <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
49
50pub type BlockNumberFor<T> =
51 <<T as Config>::BlockNumberProvider as BlockNumberProvider>::BlockNumber;
52
53type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
54
55#[derive(
58 Encode,
59 Decode,
60 Clone,
61 Copy,
62 Eq,
63 PartialEq,
64 Ord,
65 PartialOrd,
66 RuntimeDebug,
67 MaxEncodedLen,
68 TypeInfo,
69)]
70pub struct ProxyDefinition<AccountId, ProxyType, BlockNumber> {
71 pub delegate: AccountId,
73 pub proxy_type: ProxyType,
75 pub delay: BlockNumber,
78}
79
80#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
82pub struct Announcement<AccountId, Hash, BlockNumber> {
83 real: AccountId,
85 call_hash: Hash,
87 height: BlockNumber,
89}
90
91#[derive(
93 Encode,
94 Decode,
95 Clone,
96 Copy,
97 Eq,
98 PartialEq,
99 RuntimeDebug,
100 MaxEncodedLen,
101 TypeInfo,
102 DecodeWithMemTracking,
103)]
104pub enum DepositKind {
105 Proxies,
107 Announcements,
109}
110
111#[frame::pallet]
112pub mod pallet {
113 use super::*;
114
115 #[pallet::pallet]
116 pub struct Pallet<T>(_);
117
118 #[pallet::config]
120 pub trait Config: frame_system::Config {
121 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
123
124 type RuntimeCall: Parameter
126 + Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
127 + GetDispatchInfo
128 + From<frame_system::Call<Self>>
129 + IsSubType<Call<Self>>
130 + IsType<<Self as frame_system::Config>::RuntimeCall>;
131
132 type Currency: ReservableCurrency<Self::AccountId>;
134
135 type ProxyType: Parameter
140 + Member
141 + Ord
142 + PartialOrd
143 + frame::traits::InstanceFilter<<Self as Config>::RuntimeCall>
144 + Default
145 + MaxEncodedLen;
146
147 #[pallet::constant]
152 type ProxyDepositBase: Get<BalanceOf<Self>>;
153
154 #[pallet::constant]
160 type ProxyDepositFactor: Get<BalanceOf<Self>>;
161
162 #[pallet::constant]
164 type MaxProxies: Get<u32>;
165
166 type WeightInfo: WeightInfo;
168
169 #[pallet::constant]
171 type MaxPending: Get<u32>;
172
173 type CallHasher: Hash;
175
176 #[pallet::constant]
181 type AnnouncementDepositBase: Get<BalanceOf<Self>>;
182
183 #[pallet::constant]
188 type AnnouncementDepositFactor: Get<BalanceOf<Self>>;
189
190 type BlockNumberProvider: BlockNumberProvider;
213 }
214
215 #[pallet::call]
216 impl<T: Config> Pallet<T> {
217 #[pallet::call_index(0)]
227 #[pallet::weight({
228 let di = call.get_dispatch_info();
229 (T::WeightInfo::proxy(T::MaxProxies::get())
230 .saturating_add(T::DbWeight::get().reads_writes(1, 1))
232 .saturating_add(di.call_weight),
233 di.class)
234 })]
235 pub fn proxy(
236 origin: OriginFor<T>,
237 real: AccountIdLookupOf<T>,
238 force_proxy_type: Option<T::ProxyType>,
239 call: Box<<T as Config>::RuntimeCall>,
240 ) -> DispatchResult {
241 let who = ensure_signed(origin)?;
242 let real = T::Lookup::lookup(real)?;
243 let def = Self::find_proxy(&real, &who, force_proxy_type)?;
244 ensure!(def.delay.is_zero(), Error::<T>::Unannounced);
245
246 Self::do_proxy(def, real, *call);
247
248 Ok(())
249 }
250
251 #[pallet::call_index(1)]
261 #[pallet::weight(T::WeightInfo::add_proxy(T::MaxProxies::get()))]
262 pub fn add_proxy(
263 origin: OriginFor<T>,
264 delegate: AccountIdLookupOf<T>,
265 proxy_type: T::ProxyType,
266 delay: BlockNumberFor<T>,
267 ) -> DispatchResult {
268 let who = ensure_signed(origin)?;
269 let delegate = T::Lookup::lookup(delegate)?;
270 Self::add_proxy_delegate(&who, delegate, proxy_type, delay)
271 }
272
273 #[pallet::call_index(2)]
281 #[pallet::weight(T::WeightInfo::remove_proxy(T::MaxProxies::get()))]
282 pub fn remove_proxy(
283 origin: OriginFor<T>,
284 delegate: AccountIdLookupOf<T>,
285 proxy_type: T::ProxyType,
286 delay: BlockNumberFor<T>,
287 ) -> DispatchResult {
288 let who = ensure_signed(origin)?;
289 let delegate = T::Lookup::lookup(delegate)?;
290 Self::remove_proxy_delegate(&who, delegate, proxy_type, delay)
291 }
292
293 #[pallet::call_index(3)]
300 #[pallet::weight(T::WeightInfo::remove_proxies(T::MaxProxies::get()))]
301 pub fn remove_proxies(origin: OriginFor<T>) -> DispatchResult {
302 let who = ensure_signed(origin)?;
303 Self::remove_all_proxy_delegates(&who);
304 Ok(())
305 }
306
307 #[pallet::call_index(4)]
326 #[pallet::weight(T::WeightInfo::create_pure(T::MaxProxies::get()))]
327 pub fn create_pure(
328 origin: OriginFor<T>,
329 proxy_type: T::ProxyType,
330 delay: BlockNumberFor<T>,
331 index: u16,
332 ) -> DispatchResult {
333 let who = ensure_signed(origin)?;
334
335 let pure = Self::pure_account(&who, &proxy_type, index, None);
336 ensure!(!Proxies::<T>::contains_key(&pure), Error::<T>::Duplicate);
337
338 let proxy_def =
339 ProxyDefinition { delegate: who.clone(), proxy_type: proxy_type.clone(), delay };
340 let bounded_proxies: BoundedVec<_, T::MaxProxies> =
341 vec![proxy_def].try_into().map_err(|_| Error::<T>::TooMany)?;
342
343 let deposit = T::ProxyDepositBase::get() + T::ProxyDepositFactor::get();
344 T::Currency::reserve(&who, deposit)?;
345
346 Proxies::<T>::insert(&pure, (bounded_proxies, deposit));
347 Self::deposit_event(Event::PureCreated {
348 pure,
349 who,
350 proxy_type,
351 disambiguation_index: index,
352 });
353
354 Ok(())
355 }
356
357 #[pallet::call_index(5)]
374 #[pallet::weight(T::WeightInfo::kill_pure(T::MaxProxies::get()))]
375 pub fn kill_pure(
376 origin: OriginFor<T>,
377 spawner: AccountIdLookupOf<T>,
378 proxy_type: T::ProxyType,
379 index: u16,
380 #[pallet::compact] height: BlockNumberFor<T>,
381 #[pallet::compact] ext_index: u32,
382 ) -> DispatchResult {
383 let who = ensure_signed(origin)?;
384 let spawner = T::Lookup::lookup(spawner)?;
385
386 let when = (height, ext_index);
387 let proxy = Self::pure_account(&spawner, &proxy_type, index, Some(when));
388 ensure!(proxy == who, Error::<T>::NoPermission);
389
390 let (_, deposit) = Proxies::<T>::take(&who);
391 T::Currency::unreserve(&spawner, deposit);
392
393 Ok(())
394 }
395
396 #[pallet::call_index(6)]
412 #[pallet::weight(T::WeightInfo::announce(T::MaxPending::get(), T::MaxProxies::get()))]
413 pub fn announce(
414 origin: OriginFor<T>,
415 real: AccountIdLookupOf<T>,
416 call_hash: CallHashOf<T>,
417 ) -> DispatchResult {
418 let who = ensure_signed(origin)?;
419 let real = T::Lookup::lookup(real)?;
420 Proxies::<T>::get(&real)
421 .0
422 .into_iter()
423 .find(|x| x.delegate == who)
424 .ok_or(Error::<T>::NotProxy)?;
425
426 let announcement = Announcement {
427 real: real.clone(),
428 call_hash,
429 height: T::BlockNumberProvider::current_block_number(),
430 };
431
432 Announcements::<T>::try_mutate(&who, |(ref mut pending, ref mut deposit)| {
433 pending.try_push(announcement).map_err(|_| Error::<T>::TooMany)?;
434 Self::rejig_deposit(
435 &who,
436 *deposit,
437 T::AnnouncementDepositBase::get(),
438 T::AnnouncementDepositFactor::get(),
439 pending.len(),
440 )
441 .map(|d| {
442 d.expect("Just pushed; pending.len() > 0; rejig_deposit returns Some; qed")
443 })
444 .map(|d| *deposit = d)
445 })?;
446 Self::deposit_event(Event::Announced { real, proxy: who, call_hash });
447
448 Ok(())
449 }
450
451 #[pallet::call_index(7)]
462 #[pallet::weight(T::WeightInfo::remove_announcement(
463 T::MaxPending::get(),
464 T::MaxProxies::get()
465 ))]
466 pub fn remove_announcement(
467 origin: OriginFor<T>,
468 real: AccountIdLookupOf<T>,
469 call_hash: CallHashOf<T>,
470 ) -> DispatchResult {
471 let who = ensure_signed(origin)?;
472 let real = T::Lookup::lookup(real)?;
473 Self::edit_announcements(&who, |ann| ann.real != real || ann.call_hash != call_hash)?;
474
475 Ok(())
476 }
477
478 #[pallet::call_index(8)]
489 #[pallet::weight(T::WeightInfo::reject_announcement(
490 T::MaxPending::get(),
491 T::MaxProxies::get()
492 ))]
493 pub fn reject_announcement(
494 origin: OriginFor<T>,
495 delegate: AccountIdLookupOf<T>,
496 call_hash: CallHashOf<T>,
497 ) -> DispatchResult {
498 let who = ensure_signed(origin)?;
499 let delegate = T::Lookup::lookup(delegate)?;
500 Self::edit_announcements(&delegate, |ann| {
501 ann.real != who || ann.call_hash != call_hash
502 })?;
503
504 Ok(())
505 }
506
507 #[pallet::call_index(9)]
519 #[pallet::weight({
520 let di = call.get_dispatch_info();
521 (T::WeightInfo::proxy_announced(T::MaxPending::get(), T::MaxProxies::get())
522 .saturating_add(T::DbWeight::get().reads_writes(1, 1))
524 .saturating_add(di.call_weight),
525 di.class)
526 })]
527 pub fn proxy_announced(
528 origin: OriginFor<T>,
529 delegate: AccountIdLookupOf<T>,
530 real: AccountIdLookupOf<T>,
531 force_proxy_type: Option<T::ProxyType>,
532 call: Box<<T as Config>::RuntimeCall>,
533 ) -> DispatchResult {
534 ensure_signed(origin)?;
535 let delegate = T::Lookup::lookup(delegate)?;
536 let real = T::Lookup::lookup(real)?;
537 let def = Self::find_proxy(&real, &delegate, force_proxy_type)?;
538
539 let call_hash = T::CallHasher::hash_of(&call);
540 let now = T::BlockNumberProvider::current_block_number();
541 Self::edit_announcements(&delegate, |ann| {
542 ann.real != real ||
543 ann.call_hash != call_hash ||
544 now.saturating_sub(ann.height) < def.delay
545 })
546 .map_err(|_| Error::<T>::Unannounced)?;
547
548 Self::do_proxy(def, real, *call);
549
550 Ok(())
551 }
552
553 #[pallet::call_index(10)]
562 #[pallet::weight(T::WeightInfo::poke_deposit())]
563 pub fn poke_deposit(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
564 let who = ensure_signed(origin)?;
565 let mut deposit_updated = false;
566
567 Proxies::<T>::try_mutate_exists(&who, |maybe_proxies| -> DispatchResult {
569 let (proxies, old_deposit) = maybe_proxies.take().unwrap_or_default();
570 let maybe_new_deposit = Self::rejig_deposit(
571 &who,
572 old_deposit,
573 T::ProxyDepositBase::get(),
574 T::ProxyDepositFactor::get(),
575 proxies.len(),
576 )?;
577
578 match maybe_new_deposit {
579 Some(new_deposit) if new_deposit != old_deposit => {
580 *maybe_proxies = Some((proxies, new_deposit));
581 deposit_updated = true;
582 Self::deposit_event(Event::DepositPoked {
583 who: who.clone(),
584 kind: DepositKind::Proxies,
585 old_deposit,
586 new_deposit,
587 });
588 },
589 Some(_) => {
590 *maybe_proxies = Some((proxies, old_deposit));
591 },
592 None => {
593 *maybe_proxies = None;
594 if !old_deposit.is_zero() {
595 deposit_updated = true;
596 Self::deposit_event(Event::DepositPoked {
597 who: who.clone(),
598 kind: DepositKind::Proxies,
599 old_deposit,
600 new_deposit: BalanceOf::<T>::zero(),
601 });
602 }
603 },
604 }
605 Ok(())
606 })?;
607
608 Announcements::<T>::try_mutate_exists(&who, |maybe_announcements| -> DispatchResult {
610 let (announcements, old_deposit) = maybe_announcements.take().unwrap_or_default();
611 let maybe_new_deposit = Self::rejig_deposit(
612 &who,
613 old_deposit,
614 T::AnnouncementDepositBase::get(),
615 T::AnnouncementDepositFactor::get(),
616 announcements.len(),
617 )?;
618
619 match maybe_new_deposit {
620 Some(new_deposit) if new_deposit != old_deposit => {
621 *maybe_announcements = Some((announcements, new_deposit));
622 deposit_updated = true;
623 Self::deposit_event(Event::DepositPoked {
624 who: who.clone(),
625 kind: DepositKind::Announcements,
626 old_deposit,
627 new_deposit,
628 });
629 },
630 Some(_) => {
631 *maybe_announcements = Some((announcements, old_deposit));
632 },
633 None => {
634 *maybe_announcements = None;
635 if !old_deposit.is_zero() {
636 deposit_updated = true;
637 Self::deposit_event(Event::DepositPoked {
638 who: who.clone(),
639 kind: DepositKind::Announcements,
640 old_deposit,
641 new_deposit: BalanceOf::<T>::zero(),
642 });
643 }
644 },
645 }
646 Ok(())
647 })?;
648
649 Ok(if deposit_updated { Pays::No.into() } else { Pays::Yes.into() })
650 }
651 }
652
653 #[pallet::event]
654 #[pallet::generate_deposit(pub(super) fn deposit_event)]
655 pub enum Event<T: Config> {
656 ProxyExecuted { result: DispatchResult },
658 PureCreated {
661 pure: T::AccountId,
662 who: T::AccountId,
663 proxy_type: T::ProxyType,
664 disambiguation_index: u16,
665 },
666 Announced { real: T::AccountId, proxy: T::AccountId, call_hash: CallHashOf<T> },
668 ProxyAdded {
670 delegator: T::AccountId,
671 delegatee: T::AccountId,
672 proxy_type: T::ProxyType,
673 delay: BlockNumberFor<T>,
674 },
675 ProxyRemoved {
677 delegator: T::AccountId,
678 delegatee: T::AccountId,
679 proxy_type: T::ProxyType,
680 delay: BlockNumberFor<T>,
681 },
682 DepositPoked {
684 who: T::AccountId,
685 kind: DepositKind,
686 old_deposit: BalanceOf<T>,
687 new_deposit: BalanceOf<T>,
688 },
689 }
690
691 #[pallet::error]
692 pub enum Error<T> {
693 TooMany,
695 NotFound,
697 NotProxy,
699 Unproxyable,
701 Duplicate,
703 NoPermission,
705 Unannounced,
707 NoSelfProxy,
709 }
710
711 #[pallet::storage]
714 pub type Proxies<T: Config> = StorageMap<
715 _,
716 Twox64Concat,
717 T::AccountId,
718 (
719 BoundedVec<
720 ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>,
721 T::MaxProxies,
722 >,
723 BalanceOf<T>,
724 ),
725 ValueQuery,
726 >;
727
728 #[pallet::storage]
730 pub type Announcements<T: Config> = StorageMap<
731 _,
732 Twox64Concat,
733 T::AccountId,
734 (
735 BoundedVec<Announcement<T::AccountId, CallHashOf<T>, BlockNumberFor<T>>, T::MaxPending>,
736 BalanceOf<T>,
737 ),
738 ValueQuery,
739 >;
740
741 #[pallet::view_functions_experimental]
742 impl<T: Config> Pallet<T> {
743 pub fn check_permissions(
745 call: <T as Config>::RuntimeCall,
746 proxy_type: T::ProxyType,
747 ) -> bool {
748 proxy_type.filter(&call)
749 }
750
751 pub fn is_superset(to_check: T::ProxyType, against: T::ProxyType) -> bool {
753 to_check.is_superset(&against)
754 }
755 }
756}
757
758impl<T: Config> Pallet<T> {
759 pub fn proxies(
761 account: T::AccountId,
762 ) -> (
763 BoundedVec<ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>, T::MaxProxies>,
764 BalanceOf<T>,
765 ) {
766 Proxies::<T>::get(account)
767 }
768
769 pub fn announcements(
771 account: T::AccountId,
772 ) -> (
773 BoundedVec<Announcement<T::AccountId, CallHashOf<T>, BlockNumberFor<T>>, T::MaxPending>,
774 BalanceOf<T>,
775 ) {
776 Announcements::<T>::get(account)
777 }
778
779 pub fn pure_account(
791 who: &T::AccountId,
792 proxy_type: &T::ProxyType,
793 index: u16,
794 maybe_when: Option<(BlockNumberFor<T>, u32)>,
795 ) -> T::AccountId {
796 let (height, ext_index) = maybe_when.unwrap_or_else(|| {
797 (
798 T::BlockNumberProvider::current_block_number(),
799 frame_system::Pallet::<T>::extrinsic_index().unwrap_or_default(),
800 )
801 });
802 let entropy = (b"modlpy/proxy____", who, height, ext_index, proxy_type, index)
803 .using_encoded(blake2_256);
804 Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
805 .expect("infinite length input; no invalid inputs for type; qed")
806 }
807
808 pub fn add_proxy_delegate(
817 delegator: &T::AccountId,
818 delegatee: T::AccountId,
819 proxy_type: T::ProxyType,
820 delay: BlockNumberFor<T>,
821 ) -> DispatchResult {
822 ensure!(delegator != &delegatee, Error::<T>::NoSelfProxy);
823 Proxies::<T>::try_mutate(delegator, |(ref mut proxies, ref mut deposit)| {
824 let proxy_def = ProxyDefinition {
825 delegate: delegatee.clone(),
826 proxy_type: proxy_type.clone(),
827 delay,
828 };
829 let i = proxies.binary_search(&proxy_def).err().ok_or(Error::<T>::Duplicate)?;
830 proxies.try_insert(i, proxy_def).map_err(|_| Error::<T>::TooMany)?;
831 let new_deposit = Self::deposit(proxies.len() as u32);
832 if new_deposit > *deposit {
833 T::Currency::reserve(delegator, new_deposit - *deposit)?;
834 } else if new_deposit < *deposit {
835 T::Currency::unreserve(delegator, *deposit - new_deposit);
836 }
837 *deposit = new_deposit;
838 Self::deposit_event(Event::<T>::ProxyAdded {
839 delegator: delegator.clone(),
840 delegatee,
841 proxy_type,
842 delay,
843 });
844 Ok(())
845 })
846 }
847
848 pub fn remove_proxy_delegate(
857 delegator: &T::AccountId,
858 delegatee: T::AccountId,
859 proxy_type: T::ProxyType,
860 delay: BlockNumberFor<T>,
861 ) -> DispatchResult {
862 Proxies::<T>::try_mutate_exists(delegator, |x| {
863 let (mut proxies, old_deposit) = x.take().ok_or(Error::<T>::NotFound)?;
864 let proxy_def = ProxyDefinition {
865 delegate: delegatee.clone(),
866 proxy_type: proxy_type.clone(),
867 delay,
868 };
869 let i = proxies.binary_search(&proxy_def).ok().ok_or(Error::<T>::NotFound)?;
870 proxies.remove(i);
871 let new_deposit = Self::deposit(proxies.len() as u32);
872 if new_deposit > old_deposit {
873 T::Currency::reserve(delegator, new_deposit - old_deposit)?;
874 } else if new_deposit < old_deposit {
875 T::Currency::unreserve(delegator, old_deposit - new_deposit);
876 }
877 if !proxies.is_empty() {
878 *x = Some((proxies, new_deposit))
879 }
880 Self::deposit_event(Event::<T>::ProxyRemoved {
881 delegator: delegator.clone(),
882 delegatee,
883 proxy_type,
884 delay,
885 });
886 Ok(())
887 })
888 }
889
890 pub fn deposit(num_proxies: u32) -> BalanceOf<T> {
891 if num_proxies == 0 {
892 Zero::zero()
893 } else {
894 T::ProxyDepositBase::get() + T::ProxyDepositFactor::get() * num_proxies.into()
895 }
896 }
897
898 fn rejig_deposit(
899 who: &T::AccountId,
900 old_deposit: BalanceOf<T>,
901 base: BalanceOf<T>,
902 factor: BalanceOf<T>,
903 len: usize,
904 ) -> Result<Option<BalanceOf<T>>, DispatchError> {
905 let new_deposit =
906 if len == 0 { BalanceOf::<T>::zero() } else { base + factor * (len as u32).into() };
907 if new_deposit > old_deposit {
908 T::Currency::reserve(who, new_deposit.saturating_sub(old_deposit))?;
909 } else if new_deposit < old_deposit {
910 let excess = old_deposit.saturating_sub(new_deposit);
911 let remaining_unreserved = T::Currency::unreserve(who, excess);
912 if !remaining_unreserved.is_zero() {
913 defensive!(
914 "Failed to unreserve full amount. (Requested, Actual)",
915 (excess, excess.saturating_sub(remaining_unreserved))
916 );
917 }
918 }
919 Ok(if len == 0 { None } else { Some(new_deposit) })
920 }
921
922 fn edit_announcements<
923 F: FnMut(&Announcement<T::AccountId, CallHashOf<T>, BlockNumberFor<T>>) -> bool,
924 >(
925 delegate: &T::AccountId,
926 f: F,
927 ) -> DispatchResult {
928 Announcements::<T>::try_mutate_exists(delegate, |x| {
929 let (mut pending, old_deposit) = x.take().ok_or(Error::<T>::NotFound)?;
930 let orig_pending_len = pending.len();
931 pending.retain(f);
932 ensure!(orig_pending_len > pending.len(), Error::<T>::NotFound);
933 *x = Self::rejig_deposit(
934 delegate,
935 old_deposit,
936 T::AnnouncementDepositBase::get(),
937 T::AnnouncementDepositFactor::get(),
938 pending.len(),
939 )?
940 .map(|deposit| (pending, deposit));
941 Ok(())
942 })
943 }
944
945 pub fn find_proxy(
946 real: &T::AccountId,
947 delegate: &T::AccountId,
948 force_proxy_type: Option<T::ProxyType>,
949 ) -> Result<ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>, DispatchError> {
950 let f = |x: &ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>| -> bool {
951 &x.delegate == delegate &&
952 force_proxy_type.as_ref().map_or(true, |y| &x.proxy_type == y)
953 };
954 Ok(Proxies::<T>::get(real).0.into_iter().find(f).ok_or(Error::<T>::NotProxy)?)
955 }
956
957 fn do_proxy(
958 def: ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>,
959 real: T::AccountId,
960 call: <T as Config>::RuntimeCall,
961 ) {
962 use frame::traits::{InstanceFilter as _, OriginTrait as _};
963 let mut origin: T::RuntimeOrigin = frame_system::RawOrigin::Signed(real).into();
965 origin.add_filter(move |c: &<T as frame_system::Config>::RuntimeCall| {
966 let c = <T as Config>::RuntimeCall::from_ref(c);
967 match c.is_sub_type() {
969 Some(Call::add_proxy { ref proxy_type, .. }) |
972 Some(Call::remove_proxy { ref proxy_type, .. })
973 if !def.proxy_type.is_superset(proxy_type) =>
974 false,
975 Some(Call::remove_proxies { .. }) | Some(Call::kill_pure { .. })
978 if def.proxy_type != T::ProxyType::default() =>
979 false,
980 _ => def.proxy_type.filter(c),
981 }
982 });
983 let e = call.dispatch(origin);
984 Self::deposit_event(Event::ProxyExecuted { result: e.map(|_| ()).map_err(|e| e.error) });
985 }
986
987 pub fn remove_all_proxy_delegates(delegator: &T::AccountId) {
992 let (_, old_deposit) = Proxies::<T>::take(&delegator);
993 T::Currency::unreserve(&delegator, old_deposit);
994 }
995}