@@ -89,7 +89,8 @@ use sp_runtime::{
8989use sp_std:: { collections:: btree_map:: BTreeMap , prelude:: * } ;
9090
9191use frame_support:: {
92- print,
92+ dispatch:: { DispatchResult , DispatchResultWithPostInfo } ,
93+ ensure, print,
9394 traits:: {
9495 tokens:: Pay , Currency , ExistenceRequirement :: KeepAlive , Get , Imbalance , OnUnbalanced ,
9596 ReservableCurrency , WithdrawReasons ,
@@ -456,6 +457,14 @@ pub mod pallet {
456457 Weight :: zero ( )
457458 }
458459 }
460+
461+ #[ cfg( feature = "try-runtime" ) ]
462+ fn try_state (
463+ _: frame_system:: pallet_prelude:: BlockNumberFor < T > ,
464+ ) -> Result < ( ) , sp_runtime:: TryRuntimeError > {
465+ Self :: do_try_state ( ) ?;
466+ Ok ( ( ) )
467+ }
459468 }
460469
461470 #[ derive( Default ) ]
@@ -1020,6 +1029,85 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
10201029 // Must never be less than 0 but better be safe.
10211030 . saturating_sub ( T :: Currency :: minimum_balance ( ) )
10221031 }
1032+
1033+ /// Ensure the correctness of the state of this pallet.
1034+ #[ cfg( any( feature = "try-runtime" , test) ) ]
1035+ fn do_try_state ( ) -> Result < ( ) , sp_runtime:: TryRuntimeError > {
1036+ Self :: try_state_proposals ( ) ?;
1037+ Self :: try_state_spends ( ) ?;
1038+
1039+ Ok ( ( ) )
1040+ }
1041+
1042+ /// ### Invariants of proposal storage items
1043+ ///
1044+ /// 1. [`ProposalCount`] >= Number of elements in [`Proposals`].
1045+ /// 2. Each entry in [`Proposals`] should be saved under a key stricly less than current
1046+ /// [`ProposalCount`].
1047+ /// 3. Each [`ProposalIndex`] contained in [`Approvals`] should exist in [`Proposals`].
1048+ /// Note, that this automatically implies [`Approvals`].count() <= [`Proposals`].count().
1049+ #[ cfg( any( feature = "try-runtime" , test) ) ]
1050+ fn try_state_proposals ( ) -> Result < ( ) , sp_runtime:: TryRuntimeError > {
1051+ let current_proposal_count = ProposalCount :: < T , I > :: get ( ) ;
1052+ ensure ! (
1053+ current_proposal_count as usize >= Proposals :: <T , I >:: iter( ) . count( ) ,
1054+ "Actual number of proposals exceeds `ProposalCount`."
1055+ ) ;
1056+
1057+ Proposals :: < T , I > :: iter_keys ( ) . try_for_each ( |proposal_index| -> DispatchResult {
1058+ ensure ! (
1059+ current_proposal_count as u32 > proposal_index,
1060+ "`ProposalCount` should by strictly greater than any ProposalIndex used as a key for `Proposals`."
1061+ ) ;
1062+ Ok ( ( ) )
1063+ } ) ?;
1064+
1065+ Approvals :: < T , I > :: get ( )
1066+ . iter ( )
1067+ . try_for_each ( |proposal_index| -> DispatchResult {
1068+ ensure ! (
1069+ Proposals :: <T , I >:: contains_key( proposal_index) ,
1070+ "Proposal indices in `Approvals` must also be contained in `Proposals`."
1071+ ) ;
1072+ Ok ( ( ) )
1073+ } ) ?;
1074+
1075+ Ok ( ( ) )
1076+ }
1077+
1078+ /// ## Invariants of spend storage items
1079+ ///
1080+ /// 1. [`SpendCount`] >= Number of elements in [`Spends`].
1081+ /// 2. Each entry in [`Spends`] should be saved under a key stricly less than current
1082+ /// [`SpendCount`].
1083+ /// 3. For each spend entry contained in [`Spends`] we should have spend.expire_at
1084+ /// > spend.valid_from.
1085+ #[ cfg( any( feature = "try-runtime" , test) ) ]
1086+ fn try_state_spends ( ) -> Result < ( ) , sp_runtime:: TryRuntimeError > {
1087+ let current_spend_count = SpendCount :: < T , I > :: get ( ) ;
1088+ ensure ! (
1089+ current_spend_count as usize >= Spends :: <T , I >:: iter( ) . count( ) ,
1090+ "Actual number of spends exceeds `SpendCount`."
1091+ ) ;
1092+
1093+ Spends :: < T , I > :: iter_keys ( ) . try_for_each ( |spend_index| -> DispatchResult {
1094+ ensure ! (
1095+ current_spend_count > spend_index,
1096+ "`SpendCount` should by strictly greater than any SpendIndex used as a key for `Spends`."
1097+ ) ;
1098+ Ok ( ( ) )
1099+ } ) ?;
1100+
1101+ Spends :: < T , I > :: iter ( ) . try_for_each ( |( _index, spend) | -> DispatchResult {
1102+ ensure ! (
1103+ spend. valid_from < spend. expire_at,
1104+ "Spend cannot expire before it becomes valid."
1105+ ) ;
1106+ Ok ( ( ) )
1107+ } ) ?;
1108+
1109+ Ok ( ( ) )
1110+ }
10231111}
10241112
10251113impl < T : Config < I > , I : ' static > OnUnbalanced < NegativeImbalanceOf < T , I > > for Pallet < T , I > {
0 commit comments