@@ -41,7 +41,7 @@ use polkadot_sdk_frame::{
4141 deps:: { sp_core:: sp_std:: prelude:: * , * } ,
4242 prelude:: * ,
4343 traits:: {
44- fungible:: { Balanced , Credit , Inspect , Mutate , MutateHold } ,
44+ fungible:: { hold :: Balanced , Credit , Inspect , Mutate , MutateHold } ,
4545 parameter_types,
4646 } ,
4747} ;
@@ -187,6 +187,9 @@ pub mod pallet {
187187 + Dispatchable < RuntimeOrigin = Self :: RuntimeOrigin >
188188 + GetDispatchInfo
189189 + From < frame_system:: Call < Self > > ;
190+ /// Whether storage-related extrinsics charge a storage fee.
191+ #[ pallet:: constant]
192+ type ChargeStorageFee : Get < bool > ;
190193 /// The fungible type for this pallet.
191194 type Currency : Mutate < Self :: AccountId >
192195 + MutateHold < Self :: AccountId , Reason = Self :: RuntimeHoldReason >
@@ -344,11 +347,15 @@ pub mod pallet {
344347 #[ pallet:: call_index( 0 ) ]
345348 #[ pallet:: weight( T :: WeightInfo :: store( data. len( ) as u32 ) ) ]
346349 #[ pallet:: feeless_if( |origin: & OriginFor <T >, data: & Vec <u8 >| -> bool { /*TODO: add here correct validation */ true } ) ]
347- pub fn store ( _origin : OriginFor < T > , data : Vec < u8 > ) -> DispatchResult {
350+ pub fn store ( origin : OriginFor < T > , data : Vec < u8 > ) -> DispatchResult {
348351 // In the case of a regular unsigned transaction, this should have been checked by
349352 // pre_dispatch. In the case of a regular signed transaction, this should have been
350353 // checked by pre_dispatch_signed.
351354 Self :: ensure_data_size_ok ( data. len ( ) ) ?;
355+ if T :: ChargeStorageFee :: get ( ) {
356+ let sender = ensure_signed ( origin) ?;
357+ Self :: apply_fee ( sender, data. len ( ) as u32 ) ?;
358+ }
352359
353360 // Chunk data and compute storage root
354361 let chunks: Vec < _ > = data. chunks ( CHUNK_SIZE ) . map ( |c| c. to_vec ( ) ) . collect ( ) ;
@@ -889,6 +896,18 @@ pub mod pallet {
889896 RetentionPeriod :: < T > :: get ( )
890897 }
891898
899+ fn apply_fee ( sender : T :: AccountId , size : u32 ) -> DispatchResult {
900+ let byte_fee = ByteFee :: < T > :: get ( ) . ok_or ( Error :: < T > :: NotConfigured ) ?;
901+ let entry_fee = EntryFee :: < T > :: get ( ) . ok_or ( Error :: < T > :: NotConfigured ) ?;
902+ let fee = byte_fee. saturating_mul ( size. into ( ) ) . saturating_add ( entry_fee) ;
903+ T :: Currency :: hold ( & HoldReason :: StorageFeeHold . into ( ) , & sender, fee) ?;
904+ let ( credit, _remainder) =
905+ T :: Currency :: slash ( & HoldReason :: StorageFeeHold . into ( ) , & sender, fee) ;
906+ debug_assert ! ( _remainder. is_zero( ) ) ;
907+ T :: FeeDestination :: on_unbalanced ( credit) ;
908+ Ok ( ( ) )
909+ }
910+
892911 /// Returns `true` if a blob of the given size can be stored.
893912 fn data_size_ok ( size : usize ) -> bool {
894913 ( size > 0 ) && ( size <= T :: MaxTransactionSize :: get ( ) as usize )
0 commit comments