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 DecodeWithMemTracking,
61 Clone,
62 Copy,
63 Eq,
64 PartialEq,
65 Ord,
66 PartialOrd,
67 RuntimeDebug,
68 MaxEncodedLen,
69 TypeInfo,
70)]
71pub struct ProxyDefinition<AccountId, ProxyType, BlockNumber> {
72 pub delegate: AccountId,
74 pub proxy_type: ProxyType,
76 pub delay: BlockNumber,
79}
80
81#[derive(
83 Encode,
84 Decode,
85 DecodeWithMemTracking,
86 Clone,
87 Copy,
88 Eq,
89 PartialEq,
90 RuntimeDebug,
91 MaxEncodedLen,
92 TypeInfo,
93)]
94pub struct Announcement<AccountId, Hash, BlockNumber> {
95 real: AccountId,
97 call_hash: Hash,
99 height: BlockNumber,
101}
102
103#[derive(
105 Encode,
106 Decode,
107 Clone,
108 Copy,
109 Eq,
110 PartialEq,
111 RuntimeDebug,
112 MaxEncodedLen,
113 TypeInfo,
114 DecodeWithMemTracking,
115)]
116pub enum DepositKind {
117 Proxies,
119 Announcements,
121}
122
123#[frame::pallet]
124pub mod pallet {
125 use super::*;
126
127 #[pallet::pallet]
128 pub struct Pallet<T>(_);
129
130 #[pallet::config]
132 pub trait Config: frame_system::Config {
133 #[allow(deprecated)]
135 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
136
137 type RuntimeCall: Parameter
139 + Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
140 + GetDispatchInfo
141 + From<frame_system::Call<Self>>
142 + IsSubType<Call<Self>>
143 + IsType<<Self as frame_system::Config>::RuntimeCall>;
144
145 type Currency: ReservableCurrency<Self::AccountId>;
147
148 type ProxyType: Parameter
153 + Member
154 + Ord
155 + PartialOrd
156 + frame::traits::InstanceFilter<<Self as Config>::RuntimeCall>
157 + Default
158 + MaxEncodedLen;
159
160 #[pallet::constant]
165 type ProxyDepositBase: Get<BalanceOf<Self>>;
166
167 #[pallet::constant]
173 type ProxyDepositFactor: Get<BalanceOf<Self>>;
174
175 #[pallet::constant]
177 type MaxProxies: Get<u32>;
178
179 type WeightInfo: WeightInfo;
181
182 #[pallet::constant]
184 type MaxPending: Get<u32>;
185
186 type CallHasher: Hash;
188
189 #[pallet::constant]
194 type AnnouncementDepositBase: Get<BalanceOf<Self>>;
195
196 #[pallet::constant]
201 type AnnouncementDepositFactor: Get<BalanceOf<Self>>;
202
203 type BlockNumberProvider: BlockNumberProvider;
226 }
227
228 #[pallet::call]
229 impl<T: Config> Pallet<T> {
230 #[pallet::call_index(0)]
240 #[pallet::weight({
241 let di = call.get_dispatch_info();
242 (T::WeightInfo::proxy(T::MaxProxies::get())
243 .saturating_add(T::DbWeight::get().reads_writes(1, 1))
245 .saturating_add(di.call_weight),
246 di.class)
247 })]
248 pub fn proxy(
249 origin: OriginFor<T>,
250 real: AccountIdLookupOf<T>,
251 force_proxy_type: Option<T::ProxyType>,
252 call: Box<<T as Config>::RuntimeCall>,
253 ) -> DispatchResult {
254 let who = ensure_signed(origin)?;
255 let real = T::Lookup::lookup(real)?;
256 let def = Self::find_proxy(&real, &who, force_proxy_type)?;
257 ensure!(def.delay.is_zero(), Error::<T>::Unannounced);
258
259 Self::do_proxy(def, real, *call);
260
261 Ok(())
262 }
263
264 #[pallet::call_index(1)]
274 #[pallet::weight(T::WeightInfo::add_proxy(T::MaxProxies::get()))]
275 pub fn add_proxy(
276 origin: OriginFor<T>,
277 delegate: AccountIdLookupOf<T>,
278 proxy_type: T::ProxyType,
279 delay: BlockNumberFor<T>,
280 ) -> DispatchResult {
281 let who = ensure_signed(origin)?;
282 let delegate = T::Lookup::lookup(delegate)?;
283 Self::add_proxy_delegate(&who, delegate, proxy_type, delay)
284 }
285
286 #[pallet::call_index(2)]
294 #[pallet::weight(T::WeightInfo::remove_proxy(T::MaxProxies::get()))]
295 pub fn remove_proxy(
296 origin: OriginFor<T>,
297 delegate: AccountIdLookupOf<T>,
298 proxy_type: T::ProxyType,
299 delay: BlockNumberFor<T>,
300 ) -> DispatchResult {
301 let who = ensure_signed(origin)?;
302 let delegate = T::Lookup::lookup(delegate)?;
303 Self::remove_proxy_delegate(&who, delegate, proxy_type, delay)
304 }
305
306 #[pallet::call_index(3)]
313 #[pallet::weight(T::WeightInfo::remove_proxies(T::MaxProxies::get()))]
314 pub fn remove_proxies(origin: OriginFor<T>) -> DispatchResult {
315 let who = ensure_signed(origin)?;
316 Self::remove_all_proxy_delegates(&who);
317 Ok(())
318 }
319
320 #[pallet::call_index(4)]
339 #[pallet::weight(T::WeightInfo::create_pure(T::MaxProxies::get()))]
340 pub fn create_pure(
341 origin: OriginFor<T>,
342 proxy_type: T::ProxyType,
343 delay: BlockNumberFor<T>,
344 index: u16,
345 ) -> DispatchResult {
346 let who = ensure_signed(origin)?;
347
348 let pure = Self::pure_account(&who, &proxy_type, index, None);
349 ensure!(!Proxies::<T>::contains_key(&pure), Error::<T>::Duplicate);
350
351 let proxy_def =
352 ProxyDefinition { delegate: who.clone(), proxy_type: proxy_type.clone(), delay };
353 let bounded_proxies: BoundedVec<_, T::MaxProxies> =
354 vec![proxy_def].try_into().map_err(|_| Error::<T>::TooMany)?;
355
356 let deposit = T::ProxyDepositBase::get() + T::ProxyDepositFactor::get();
357 T::Currency::reserve(&who, deposit)?;
358
359 Proxies::<T>::insert(&pure, (bounded_proxies, deposit));
360 Self::deposit_event(Event::PureCreated {
361 pure,
362 who,
363 proxy_type,
364 disambiguation_index: index,
365 });
366
367 Ok(())
368 }
369
370 #[pallet::call_index(5)]
387 #[pallet::weight(T::WeightInfo::kill_pure(T::MaxProxies::get()))]
388 pub fn kill_pure(
389 origin: OriginFor<T>,
390 spawner: AccountIdLookupOf<T>,
391 proxy_type: T::ProxyType,
392 index: u16,
393 #[pallet::compact] height: BlockNumberFor<T>,
394 #[pallet::compact] ext_index: u32,
395 ) -> DispatchResult {
396 let who = ensure_signed(origin)?;
397 let spawner = T::Lookup::lookup(spawner)?;
398
399 let when = (height, ext_index);
400 let proxy = Self::pure_account(&spawner, &proxy_type, index, Some(when));
401 ensure!(proxy == who, Error::<T>::NoPermission);
402
403 let (_, deposit) = Proxies::<T>::take(&who);
404 T::Currency::unreserve(&spawner, deposit);
405
406 Self::deposit_event(Event::PureKilled {
407 pure: who,
408 spawner,
409 proxy_type,
410 disambiguation_index: index,
411 });
412
413 Ok(())
414 }
415
416 #[pallet::call_index(6)]
432 #[pallet::weight(T::WeightInfo::announce(T::MaxPending::get(), T::MaxProxies::get()))]
433 pub fn announce(
434 origin: OriginFor<T>,
435 real: AccountIdLookupOf<T>,
436 call_hash: CallHashOf<T>,
437 ) -> DispatchResult {
438 let who = ensure_signed(origin)?;
439 let real = T::Lookup::lookup(real)?;
440 Proxies::<T>::get(&real)
441 .0
442 .into_iter()
443 .find(|x| x.delegate == who)
444 .ok_or(Error::<T>::NotProxy)?;
445
446 let announcement = Announcement {
447 real: real.clone(),
448 call_hash,
449 height: T::BlockNumberProvider::current_block_number(),
450 };
451
452 Announcements::<T>::try_mutate(&who, |(ref mut pending, ref mut deposit)| {
453 pending.try_push(announcement).map_err(|_| Error::<T>::TooMany)?;
454 Self::rejig_deposit(
455 &who,
456 *deposit,
457 T::AnnouncementDepositBase::get(),
458 T::AnnouncementDepositFactor::get(),
459 pending.len(),
460 )
461 .map(|d| {
462 d.expect("Just pushed; pending.len() > 0; rejig_deposit returns Some; qed")
463 })
464 .map(|d| *deposit = d)
465 })?;
466 Self::deposit_event(Event::Announced { real, proxy: who, call_hash });
467
468 Ok(())
469 }
470
471 #[pallet::call_index(7)]
482 #[pallet::weight(T::WeightInfo::remove_announcement(
483 T::MaxPending::get(),
484 T::MaxProxies::get()
485 ))]
486 pub fn remove_announcement(
487 origin: OriginFor<T>,
488 real: AccountIdLookupOf<T>,
489 call_hash: CallHashOf<T>,
490 ) -> DispatchResult {
491 let who = ensure_signed(origin)?;
492 let real = T::Lookup::lookup(real)?;
493 Self::edit_announcements(&who, |ann| ann.real != real || ann.call_hash != call_hash)?;
494
495 Ok(())
496 }
497
498 #[pallet::call_index(8)]
509 #[pallet::weight(T::WeightInfo::reject_announcement(
510 T::MaxPending::get(),
511 T::MaxProxies::get()
512 ))]
513 pub fn reject_announcement(
514 origin: OriginFor<T>,
515 delegate: AccountIdLookupOf<T>,
516 call_hash: CallHashOf<T>,
517 ) -> DispatchResult {
518 let who = ensure_signed(origin)?;
519 let delegate = T::Lookup::lookup(delegate)?;
520 Self::edit_announcements(&delegate, |ann| {
521 ann.real != who || ann.call_hash != call_hash
522 })?;
523
524 Ok(())
525 }
526
527 #[pallet::call_index(9)]
539 #[pallet::weight({
540 let di = call.get_dispatch_info();
541 (T::WeightInfo::proxy_announced(T::MaxPending::get(), T::MaxProxies::get())
542 .saturating_add(T::DbWeight::get().reads_writes(1, 1))
544 .saturating_add(di.call_weight),
545 di.class)
546 })]
547 pub fn proxy_announced(
548 origin: OriginFor<T>,
549 delegate: AccountIdLookupOf<T>,
550 real: AccountIdLookupOf<T>,
551 force_proxy_type: Option<T::ProxyType>,
552 call: Box<<T as Config>::RuntimeCall>,
553 ) -> DispatchResult {
554 ensure_signed(origin)?;
555 let delegate = T::Lookup::lookup(delegate)?;
556 let real = T::Lookup::lookup(real)?;
557 let def = Self::find_proxy(&real, &delegate, force_proxy_type)?;
558
559 let call_hash = T::CallHasher::hash_of(&call);
560 let now = T::BlockNumberProvider::current_block_number();
561 Self::edit_announcements(&delegate, |ann| {
562 ann.real != real ||
563 ann.call_hash != call_hash ||
564 now.saturating_sub(ann.height) < def.delay
565 })
566 .map_err(|_| Error::<T>::Unannounced)?;
567
568 Self::do_proxy(def, real, *call);
569
570 Ok(())
571 }
572
573 #[pallet::call_index(10)]
582 #[pallet::weight(T::WeightInfo::poke_deposit())]
583 pub fn poke_deposit(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
584 let who = ensure_signed(origin)?;
585 let mut deposit_updated = false;
586
587 Proxies::<T>::try_mutate_exists(&who, |maybe_proxies| -> DispatchResult {
589 let (proxies, old_deposit) = maybe_proxies.take().unwrap_or_default();
590 let maybe_new_deposit = Self::rejig_deposit(
591 &who,
592 old_deposit,
593 T::ProxyDepositBase::get(),
594 T::ProxyDepositFactor::get(),
595 proxies.len(),
596 )?;
597
598 match maybe_new_deposit {
599 Some(new_deposit) if new_deposit != old_deposit => {
600 *maybe_proxies = Some((proxies, new_deposit));
601 deposit_updated = true;
602 Self::deposit_event(Event::DepositPoked {
603 who: who.clone(),
604 kind: DepositKind::Proxies,
605 old_deposit,
606 new_deposit,
607 });
608 },
609 Some(_) => {
610 *maybe_proxies = Some((proxies, old_deposit));
611 },
612 None => {
613 *maybe_proxies = None;
614 if !old_deposit.is_zero() {
615 deposit_updated = true;
616 Self::deposit_event(Event::DepositPoked {
617 who: who.clone(),
618 kind: DepositKind::Proxies,
619 old_deposit,
620 new_deposit: BalanceOf::<T>::zero(),
621 });
622 }
623 },
624 }
625 Ok(())
626 })?;
627
628 Announcements::<T>::try_mutate_exists(&who, |maybe_announcements| -> DispatchResult {
630 let (announcements, old_deposit) = maybe_announcements.take().unwrap_or_default();
631 let maybe_new_deposit = Self::rejig_deposit(
632 &who,
633 old_deposit,
634 T::AnnouncementDepositBase::get(),
635 T::AnnouncementDepositFactor::get(),
636 announcements.len(),
637 )?;
638
639 match maybe_new_deposit {
640 Some(new_deposit) if new_deposit != old_deposit => {
641 *maybe_announcements = Some((announcements, new_deposit));
642 deposit_updated = true;
643 Self::deposit_event(Event::DepositPoked {
644 who: who.clone(),
645 kind: DepositKind::Announcements,
646 old_deposit,
647 new_deposit,
648 });
649 },
650 Some(_) => {
651 *maybe_announcements = Some((announcements, old_deposit));
652 },
653 None => {
654 *maybe_announcements = None;
655 if !old_deposit.is_zero() {
656 deposit_updated = true;
657 Self::deposit_event(Event::DepositPoked {
658 who: who.clone(),
659 kind: DepositKind::Announcements,
660 old_deposit,
661 new_deposit: BalanceOf::<T>::zero(),
662 });
663 }
664 },
665 }
666 Ok(())
667 })?;
668
669 Ok(if deposit_updated { Pays::No.into() } else { Pays::Yes.into() })
670 }
671 }
672
673 #[pallet::event]
674 #[pallet::generate_deposit(pub(super) fn deposit_event)]
675 pub enum Event<T: Config> {
676 ProxyExecuted { result: DispatchResult },
678 PureCreated {
681 pure: T::AccountId,
682 who: T::AccountId,
683 proxy_type: T::ProxyType,
684 disambiguation_index: u16,
685 },
686 PureKilled {
688 pure: T::AccountId,
690 spawner: T::AccountId,
692 proxy_type: T::ProxyType,
694 disambiguation_index: u16,
696 },
697 Announced { real: T::AccountId, proxy: T::AccountId, call_hash: CallHashOf<T> },
699 ProxyAdded {
701 delegator: T::AccountId,
702 delegatee: T::AccountId,
703 proxy_type: T::ProxyType,
704 delay: BlockNumberFor<T>,
705 },
706 ProxyRemoved {
708 delegator: T::AccountId,
709 delegatee: T::AccountId,
710 proxy_type: T::ProxyType,
711 delay: BlockNumberFor<T>,
712 },
713 DepositPoked {
715 who: T::AccountId,
716 kind: DepositKind,
717 old_deposit: BalanceOf<T>,
718 new_deposit: BalanceOf<T>,
719 },
720 }
721
722 #[pallet::error]
723 pub enum Error<T> {
724 TooMany,
726 NotFound,
728 NotProxy,
730 Unproxyable,
732 Duplicate,
734 NoPermission,
736 Unannounced,
738 NoSelfProxy,
740 }
741
742 #[pallet::storage]
745 pub type Proxies<T: Config> = StorageMap<
746 _,
747 Twox64Concat,
748 T::AccountId,
749 (
750 BoundedVec<
751 ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>,
752 T::MaxProxies,
753 >,
754 BalanceOf<T>,
755 ),
756 ValueQuery,
757 >;
758
759 #[pallet::storage]
761 pub type Announcements<T: Config> = StorageMap<
762 _,
763 Twox64Concat,
764 T::AccountId,
765 (
766 BoundedVec<Announcement<T::AccountId, CallHashOf<T>, BlockNumberFor<T>>, T::MaxPending>,
767 BalanceOf<T>,
768 ),
769 ValueQuery,
770 >;
771
772 #[pallet::view_functions]
773 impl<T: Config> Pallet<T> {
774 pub fn check_permissions(
776 call: <T as Config>::RuntimeCall,
777 proxy_type: T::ProxyType,
778 ) -> bool {
779 proxy_type.filter(&call)
780 }
781
782 pub fn is_superset(to_check: T::ProxyType, against: T::ProxyType) -> bool {
784 to_check.is_superset(&against)
785 }
786 }
787}
788
789impl<T: Config> Pallet<T> {
790 pub fn proxies(
792 account: T::AccountId,
793 ) -> (
794 BoundedVec<ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>, T::MaxProxies>,
795 BalanceOf<T>,
796 ) {
797 Proxies::<T>::get(account)
798 }
799
800 pub fn announcements(
802 account: T::AccountId,
803 ) -> (
804 BoundedVec<Announcement<T::AccountId, CallHashOf<T>, BlockNumberFor<T>>, T::MaxPending>,
805 BalanceOf<T>,
806 ) {
807 Announcements::<T>::get(account)
808 }
809
810 pub fn pure_account(
822 who: &T::AccountId,
823 proxy_type: &T::ProxyType,
824 index: u16,
825 maybe_when: Option<(BlockNumberFor<T>, u32)>,
826 ) -> T::AccountId {
827 let (height, ext_index) = maybe_when.unwrap_or_else(|| {
828 (
829 T::BlockNumberProvider::current_block_number(),
830 frame_system::Pallet::<T>::extrinsic_index().unwrap_or_default(),
831 )
832 });
833
834 let entropy = (b"modlpy/proxy____", who, height, ext_index, proxy_type, index)
835 .using_encoded(blake2_256);
836 Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
837 .expect("infinite length input; no invalid inputs for type; qed")
838 }
839
840 pub fn add_proxy_delegate(
849 delegator: &T::AccountId,
850 delegatee: T::AccountId,
851 proxy_type: T::ProxyType,
852 delay: BlockNumberFor<T>,
853 ) -> DispatchResult {
854 ensure!(delegator != &delegatee, Error::<T>::NoSelfProxy);
855 Proxies::<T>::try_mutate(delegator, |(ref mut proxies, ref mut deposit)| {
856 let proxy_def = ProxyDefinition {
857 delegate: delegatee.clone(),
858 proxy_type: proxy_type.clone(),
859 delay,
860 };
861 let i = proxies.binary_search(&proxy_def).err().ok_or(Error::<T>::Duplicate)?;
862 proxies.try_insert(i, proxy_def).map_err(|_| Error::<T>::TooMany)?;
863 let new_deposit = Self::deposit(proxies.len() as u32);
864 if new_deposit > *deposit {
865 T::Currency::reserve(delegator, new_deposit - *deposit)?;
866 } else if new_deposit < *deposit {
867 T::Currency::unreserve(delegator, *deposit - new_deposit);
868 }
869 *deposit = new_deposit;
870 Self::deposit_event(Event::<T>::ProxyAdded {
871 delegator: delegator.clone(),
872 delegatee,
873 proxy_type,
874 delay,
875 });
876 Ok(())
877 })
878 }
879
880 pub fn remove_proxy_delegate(
889 delegator: &T::AccountId,
890 delegatee: T::AccountId,
891 proxy_type: T::ProxyType,
892 delay: BlockNumberFor<T>,
893 ) -> DispatchResult {
894 Proxies::<T>::try_mutate_exists(delegator, |x| {
895 let (mut proxies, old_deposit) = x.take().ok_or(Error::<T>::NotFound)?;
896 let proxy_def = ProxyDefinition {
897 delegate: delegatee.clone(),
898 proxy_type: proxy_type.clone(),
899 delay,
900 };
901 let i = proxies.binary_search(&proxy_def).ok().ok_or(Error::<T>::NotFound)?;
902 proxies.remove(i);
903 let new_deposit = Self::deposit(proxies.len() as u32);
904 if new_deposit > old_deposit {
905 T::Currency::reserve(delegator, new_deposit - old_deposit)?;
906 } else if new_deposit < old_deposit {
907 T::Currency::unreserve(delegator, old_deposit - new_deposit);
908 }
909 if !proxies.is_empty() {
910 *x = Some((proxies, new_deposit))
911 }
912 Self::deposit_event(Event::<T>::ProxyRemoved {
913 delegator: delegator.clone(),
914 delegatee,
915 proxy_type,
916 delay,
917 });
918 Ok(())
919 })
920 }
921
922 pub fn deposit(num_proxies: u32) -> BalanceOf<T> {
923 if num_proxies == 0 {
924 Zero::zero()
925 } else {
926 T::ProxyDepositBase::get() + T::ProxyDepositFactor::get() * num_proxies.into()
927 }
928 }
929
930 fn rejig_deposit(
931 who: &T::AccountId,
932 old_deposit: BalanceOf<T>,
933 base: BalanceOf<T>,
934 factor: BalanceOf<T>,
935 len: usize,
936 ) -> Result<Option<BalanceOf<T>>, DispatchError> {
937 let new_deposit =
938 if len == 0 { BalanceOf::<T>::zero() } else { base + factor * (len as u32).into() };
939 if new_deposit > old_deposit {
940 T::Currency::reserve(who, new_deposit.saturating_sub(old_deposit))?;
941 } else if new_deposit < old_deposit {
942 let excess = old_deposit.saturating_sub(new_deposit);
943 let remaining_unreserved = T::Currency::unreserve(who, excess);
944 if !remaining_unreserved.is_zero() {
945 defensive!(
946 "Failed to unreserve full amount. (Requested, Actual)",
947 (excess, excess.saturating_sub(remaining_unreserved))
948 );
949 }
950 }
951 Ok(if len == 0 { None } else { Some(new_deposit) })
952 }
953
954 fn edit_announcements<
955 F: FnMut(&Announcement<T::AccountId, CallHashOf<T>, BlockNumberFor<T>>) -> bool,
956 >(
957 delegate: &T::AccountId,
958 f: F,
959 ) -> DispatchResult {
960 Announcements::<T>::try_mutate_exists(delegate, |x| {
961 let (mut pending, old_deposit) = x.take().ok_or(Error::<T>::NotFound)?;
962 let orig_pending_len = pending.len();
963 pending.retain(f);
964 ensure!(orig_pending_len > pending.len(), Error::<T>::NotFound);
965 *x = Self::rejig_deposit(
966 delegate,
967 old_deposit,
968 T::AnnouncementDepositBase::get(),
969 T::AnnouncementDepositFactor::get(),
970 pending.len(),
971 )?
972 .map(|deposit| (pending, deposit));
973 Ok(())
974 })
975 }
976
977 pub fn find_proxy(
978 real: &T::AccountId,
979 delegate: &T::AccountId,
980 force_proxy_type: Option<T::ProxyType>,
981 ) -> Result<ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>, DispatchError> {
982 let f = |x: &ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>| -> bool {
983 &x.delegate == delegate &&
984 force_proxy_type.as_ref().map_or(true, |y| &x.proxy_type == y)
985 };
986 Ok(Proxies::<T>::get(real).0.into_iter().find(f).ok_or(Error::<T>::NotProxy)?)
987 }
988
989 fn do_proxy(
990 def: ProxyDefinition<T::AccountId, T::ProxyType, BlockNumberFor<T>>,
991 real: T::AccountId,
992 call: <T as Config>::RuntimeCall,
993 ) {
994 use frame::traits::{InstanceFilter as _, OriginTrait as _};
995 let mut origin: T::RuntimeOrigin = frame_system::RawOrigin::Signed(real).into();
997 origin.add_filter(move |c: &<T as frame_system::Config>::RuntimeCall| {
998 let c = <T as Config>::RuntimeCall::from_ref(c);
999 match c.is_sub_type() {
1001 Some(Call::add_proxy { ref proxy_type, .. }) |
1004 Some(Call::remove_proxy { ref proxy_type, .. })
1005 if !def.proxy_type.is_superset(proxy_type) =>
1006 false,
1007 Some(Call::remove_proxies { .. }) | Some(Call::kill_pure { .. })
1010 if def.proxy_type != T::ProxyType::default() =>
1011 false,
1012 _ => def.proxy_type.filter(c),
1013 }
1014 });
1015 let e = call.dispatch(origin);
1016 Self::deposit_event(Event::ProxyExecuted { result: e.map(|_| ()).map_err(|e| e.error) });
1017 }
1018
1019 pub fn remove_all_proxy_delegates(delegator: &T::AccountId) {
1024 let (_, old_deposit) = Proxies::<T>::take(&delegator);
1025 T::Currency::unreserve(&delegator, old_deposit);
1026 }
1027}