frame_system/extensions/
check_non_zero_sender.rs1use crate::Config;
19use codec::{Decode, Encode};
20use core::marker::PhantomData;
21use frame_support::{dispatch::DispatchInfo, DefaultNoBound};
22use scale_info::TypeInfo;
23use sp_runtime::{
24 traits::{DispatchInfoOf, Dispatchable, SignedExtension},
25 transaction_validity::{
26 InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
27 },
28};
29
30#[derive(Encode, Decode, DefaultNoBound, Clone, Eq, PartialEq, TypeInfo)]
32#[scale_info(skip_type_params(T))]
33pub struct CheckNonZeroSender<T>(PhantomData<T>);
34
35impl<T: Config + Send + Sync> core::fmt::Debug for CheckNonZeroSender<T> {
36 #[cfg(feature = "std")]
37 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
38 write!(f, "CheckNonZeroSender")
39 }
40
41 #[cfg(not(feature = "std"))]
42 fn fmt(&self, _: &mut core::fmt::Formatter) -> core::fmt::Result {
43 Ok(())
44 }
45}
46
47impl<T: Config + Send + Sync> CheckNonZeroSender<T> {
48 pub fn new() -> Self {
50 Self(core::marker::PhantomData)
51 }
52}
53
54impl<T: Config + Send + Sync> SignedExtension for CheckNonZeroSender<T>
55where
56 T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
57{
58 type AccountId = T::AccountId;
59 type Call = T::RuntimeCall;
60 type AdditionalSigned = ();
61 type Pre = ();
62 const IDENTIFIER: &'static str = "CheckNonZeroSender";
63
64 fn additional_signed(&self) -> core::result::Result<(), TransactionValidityError> {
65 Ok(())
66 }
67
68 fn pre_dispatch(
69 self,
70 who: &Self::AccountId,
71 call: &Self::Call,
72 info: &DispatchInfoOf<Self::Call>,
73 len: usize,
74 ) -> Result<Self::Pre, TransactionValidityError> {
75 self.validate(who, call, info, len).map(|_| ())
76 }
77
78 fn validate(
79 &self,
80 who: &Self::AccountId,
81 _call: &Self::Call,
82 _info: &DispatchInfoOf<Self::Call>,
83 _len: usize,
84 ) -> TransactionValidity {
85 if who.using_encoded(|d| d.iter().all(|x| *x == 0)) {
86 return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner))
87 }
88 Ok(ValidTransaction::default())
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use crate::mock::{new_test_ext, Test, CALL};
96 use frame_support::{assert_noop, assert_ok};
97
98 #[test]
99 fn zero_account_ban_works() {
100 new_test_ext().execute_with(|| {
101 let info = DispatchInfo::default();
102 let len = 0_usize;
103 assert_noop!(
104 CheckNonZeroSender::<Test>::new().validate(&0, CALL, &info, len),
105 InvalidTransaction::BadSigner
106 );
107 assert_ok!(CheckNonZeroSender::<Test>::new().validate(&1, CALL, &info, len));
108 })
109 }
110}