From 3755341fcf066c441ed9d44acf1ae4b4d9be952c Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Tue, 25 Nov 2025 07:50:16 +0100 Subject: [PATCH 1/9] setup try_state checks for whitelist --- Cargo.lock | 1 + substrate/frame/whitelist/Cargo.toml | 1 + substrate/frame/whitelist/src/lib.rs | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index f51b14678ae44..aac49f5a03a2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14294,6 +14294,7 @@ dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", "scale-info", + "sp-runtime", ] [[package]] diff --git a/substrate/frame/whitelist/Cargo.toml b/substrate/frame/whitelist/Cargo.toml index 8a233d8bcf05c..0ce90d980ccc5 100644 --- a/substrate/frame/whitelist/Cargo.toml +++ b/substrate/frame/whitelist/Cargo.toml @@ -18,6 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { features = ["derive", "max-encoded-len"], workspace = true } frame = { workspace = true, features = ["runtime"] } scale-info = { features = ["derive"], workspace = true } +sp-runtime = { workspace = true } [dev-dependencies] pallet-balances = { workspace = true, default-features = true } diff --git a/substrate/frame/whitelist/src/lib.rs b/substrate/frame/whitelist/src/lib.rs index 74bd051358a7c..5b071e744e982 100644 --- a/substrate/frame/whitelist/src/lib.rs +++ b/substrate/frame/whitelist/src/lib.rs @@ -40,6 +40,9 @@ mod tests; pub mod weights; pub use weights::WeightInfo; +#[cfg(any(feature = "try-runtime", test))] +use sp_runtime::TryRuntimeError; + extern crate alloc; use alloc::boxed::Box; @@ -109,6 +112,14 @@ pub mod pallet { CallAlreadyWhitelisted, } + #[pallet::hooks] + impl Hooks> for Pallet { + #[cfg(feature = "try-runtime")] + fn try_state(_n: BlockNumberFor) -> Result<(), TryRuntimeError> { + Self::do_try_state() + } + } + #[pallet::storage] pub type WhitelistedCall = StorageMap<_, Twox64Concat, T::Hash, (), OptionQuery>; @@ -236,4 +247,13 @@ impl Pallet { call_actual_weight } + + /// Ensure the correctness of the state of this pallet + /// + /// The following conditions must apply. + #[cfg(any(feature = "try-runtime", test))] + fn do_try_state() -> Result<(), TryRuntimeError> { + + Ok(()) + } } From bb55907087b9d0db4c7ddda6acf07195e4c0407e Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 00:15:35 +0100 Subject: [PATCH 2/9] switch pallet --- substrate/frame/timestamp/src/lib.rs | 8 ++++++++ substrate/frame/whitelist/src/lib.rs | 17 ----------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/substrate/frame/timestamp/src/lib.rs b/substrate/frame/timestamp/src/lib.rs index dc3f29fded938..bb206ec7994be 100644 --- a/substrate/frame/timestamp/src/lib.rs +++ b/substrate/frame/timestamp/src/lib.rs @@ -126,6 +126,9 @@ #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(any(feature = "try-runtime", test))] +use sp_runtime::TryRuntimeError; + mod benchmarking; #[cfg(test)] mod mock; @@ -229,6 +232,11 @@ pub mod pallet { fn on_finalize(_n: BlockNumberFor) { assert!(DidUpdate::::take(), "Timestamp must be updated once in the block"); } + + #[cfg(feature = "try-runtime")] + fn try_state(_n: BlockNumberFor) -> Result<(), TryRuntimeError> { + Ok(()) + } } #[pallet::call] diff --git a/substrate/frame/whitelist/src/lib.rs b/substrate/frame/whitelist/src/lib.rs index 5b071e744e982..f71b54a4a6003 100644 --- a/substrate/frame/whitelist/src/lib.rs +++ b/substrate/frame/whitelist/src/lib.rs @@ -112,14 +112,6 @@ pub mod pallet { CallAlreadyWhitelisted, } - #[pallet::hooks] - impl Hooks> for Pallet { - #[cfg(feature = "try-runtime")] - fn try_state(_n: BlockNumberFor) -> Result<(), TryRuntimeError> { - Self::do_try_state() - } - } - #[pallet::storage] pub type WhitelistedCall = StorageMap<_, Twox64Concat, T::Hash, (), OptionQuery>; @@ -247,13 +239,4 @@ impl Pallet { call_actual_weight } - - /// Ensure the correctness of the state of this pallet - /// - /// The following conditions must apply. - #[cfg(any(feature = "try-runtime", test))] - fn do_try_state() -> Result<(), TryRuntimeError> { - - Ok(()) - } } From fc88c00b84f3ac0e095492c8e32321ea4cbba764 Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 00:33:14 +0100 Subject: [PATCH 3/9] add do_try_state logic for timestamp pallet --- substrate/frame/timestamp/src/lib.rs | 29 +++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/substrate/frame/timestamp/src/lib.rs b/substrate/frame/timestamp/src/lib.rs index bb206ec7994be..2333ff280ba56 100644 --- a/substrate/frame/timestamp/src/lib.rs +++ b/substrate/frame/timestamp/src/lib.rs @@ -235,7 +235,7 @@ pub mod pallet { #[cfg(feature = "try-runtime")] fn try_state(_n: BlockNumberFor) -> Result<(), TryRuntimeError> { - Ok(()) + Self::do_try_state() } } @@ -356,6 +356,33 @@ impl Pallet { DidUpdate::::put(true); >::on_timestamp_set(now); } + + /// Ensure the correctness of the state of this pallet + /// + /// The following conditions must apply. + /// + /// ## Expectations: + /// + /// * If `Now` exists, `DidUpdate` must be true. + /// * If `Now` does not exist, `DidUpdate` must be false. + #[cfg(any(feature = "try-runtime", test))] + fn do_try_state() -> Result<(), TryRuntimeError> { + if Now::::exists() { + ensure!( + DidUpdate::::get(), + "`Now` exists but `DidUpdate` is not true" + ); + } + + if !Now::::exists() { + ensure!( + !DidUpdate::::get(), + "`Now` does not exist but `DidUpdate` is not false" + ); + } + + Ok(()) + } } impl Time for Pallet { From 0f85d17e800f866f74ac0e97b48537ddfb3b17e1 Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 00:40:13 +0100 Subject: [PATCH 4/9] import ensure into timestamp lib.rs --- substrate/frame/timestamp/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/timestamp/src/lib.rs b/substrate/frame/timestamp/src/lib.rs index 2333ff280ba56..2c49cb763e5ff 100644 --- a/substrate/frame/timestamp/src/lib.rs +++ b/substrate/frame/timestamp/src/lib.rs @@ -137,7 +137,7 @@ mod tests; pub mod weights; use core::{cmp, result}; -use frame_support::traits::{OnTimestampSet, Time, UnixTime}; +use frame_support::{ensure, traits::{OnTimestampSet, Time, UnixTime}}; use sp_runtime::traits::{AtLeast32Bit, SaturatedConversion, Scale, Zero}; use sp_timestamp::{InherentError, InherentType, INHERENT_IDENTIFIER}; pub use weights::WeightInfo; From c7a6a4b96a9f0563c60f095fd10dbf210a2541e5 Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 01:00:12 +0100 Subject: [PATCH 5/9] update pallet-timestamp tests --- substrate/frame/timestamp/src/mock.rs | 10 +++++++++- substrate/frame/timestamp/src/tests.rs | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/substrate/frame/timestamp/src/mock.rs b/substrate/frame/timestamp/src/mock.rs index eb4fdbe71fa7f..8933eefefec5b 100644 --- a/substrate/frame/timestamp/src/mock.rs +++ b/substrate/frame/timestamp/src/mock.rs @@ -66,8 +66,16 @@ pub(crate) fn get_captured_moment() -> Option { CapturedMoment::get() } -pub(crate) fn new_test_ext() -> TestExternalities { +pub(crate) fn build_ext() -> TestExternalities { let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); clear_captured_moment(); TestExternalities::new(t) } + +pub(crate) fn build_ext_and_execute_test(test: impl FnOnce() -> ()) { + let mut ext = build_ext(); + ext.execute_with(|| { + test(); + Timestamp::do_try_state().expect("Storage invariants should hold") + }); +} \ No newline at end of file diff --git a/substrate/frame/timestamp/src/tests.rs b/substrate/frame/timestamp/src/tests.rs index a83855561889f..e9cfe93d82f0c 100644 --- a/substrate/frame/timestamp/src/tests.rs +++ b/substrate/frame/timestamp/src/tests.rs @@ -22,7 +22,7 @@ use frame_support::assert_ok; #[test] fn timestamp_works() { - new_test_ext().execute_with(|| { + build_ext_and_execute_test(|| { crate::Now::::put(46); assert_ok!(Timestamp::set(RuntimeOrigin::none(), 69)); assert_eq!(crate::Now::::get(), 69); @@ -34,7 +34,7 @@ fn timestamp_works() { #[test] #[should_panic(expected = "Timestamp must be updated only once in the block")] fn double_timestamp_should_fail() { - new_test_ext().execute_with(|| { + build_ext_and_execute_test(|| { Timestamp::set_timestamp(42); assert_ok!(Timestamp::set(RuntimeOrigin::none(), 69)); }); @@ -46,7 +46,7 @@ fn double_timestamp_should_fail() { expected = "Timestamp must increment by at least between sequential blocks" )] fn block_period_minimum_enforced() { - new_test_ext().execute_with(|| { + build_ext_and_execute_test(|| { crate::Now::::put(44); let _ = Timestamp::set(RuntimeOrigin::none(), 46); }); From 7fbb58d93944908926d15a4cd78551cd15d3a69a Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 01:10:35 +0100 Subject: [PATCH 6/9] fix ensure import warning --- substrate/frame/timestamp/src/lib.rs | 4 +++- substrate/frame/timestamp/src/mock.rs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/substrate/frame/timestamp/src/lib.rs b/substrate/frame/timestamp/src/lib.rs index 2c49cb763e5ff..1e6cc41bcd789 100644 --- a/substrate/frame/timestamp/src/lib.rs +++ b/substrate/frame/timestamp/src/lib.rs @@ -137,7 +137,9 @@ mod tests; pub mod weights; use core::{cmp, result}; -use frame_support::{ensure, traits::{OnTimestampSet, Time, UnixTime}}; +#[cfg(any(feature = "try-runtime", test))] +use frame_support::ensure; +use frame_support::traits::{OnTimestampSet, Time, UnixTime}; use sp_runtime::traits::{AtLeast32Bit, SaturatedConversion, Scale, Zero}; use sp_timestamp::{InherentError, InherentType, INHERENT_IDENTIFIER}; pub use weights::WeightInfo; diff --git a/substrate/frame/timestamp/src/mock.rs b/substrate/frame/timestamp/src/mock.rs index 8933eefefec5b..3d87b397dd125 100644 --- a/substrate/frame/timestamp/src/mock.rs +++ b/substrate/frame/timestamp/src/mock.rs @@ -66,14 +66,14 @@ pub(crate) fn get_captured_moment() -> Option { CapturedMoment::get() } -pub(crate) fn build_ext() -> TestExternalities { +pub(crate) fn new_test_ext() -> TestExternalities { let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); clear_captured_moment(); TestExternalities::new(t) } pub(crate) fn build_ext_and_execute_test(test: impl FnOnce() -> ()) { - let mut ext = build_ext(); + let mut ext = new_test_ext(); ext.execute_with(|| { test(); Timestamp::do_try_state().expect("Storage invariants should hold") From f0efd11e09dcb7945b7ea9128e08b7b9ea0d68fe Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 02:22:30 +0100 Subject: [PATCH 7/9] newline --- substrate/frame/timestamp/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/timestamp/src/mock.rs b/substrate/frame/timestamp/src/mock.rs index 3d87b397dd125..abd4da2cb1de3 100644 --- a/substrate/frame/timestamp/src/mock.rs +++ b/substrate/frame/timestamp/src/mock.rs @@ -78,4 +78,4 @@ pub(crate) fn build_ext_and_execute_test(test: impl FnOnce() -> ()) { test(); Timestamp::do_try_state().expect("Storage invariants should hold") }); -} \ No newline at end of file +} From ea24002c43c66df4da8a1fad2b24dd66aa4e335a Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 02:24:14 +0100 Subject: [PATCH 8/9] remove sp-runtime from whitelist --- substrate/frame/whitelist/Cargo.toml | 1 - substrate/frame/whitelist/src/lib.rs | 3 --- 2 files changed, 4 deletions(-) diff --git a/substrate/frame/whitelist/Cargo.toml b/substrate/frame/whitelist/Cargo.toml index 0ce90d980ccc5..8a233d8bcf05c 100644 --- a/substrate/frame/whitelist/Cargo.toml +++ b/substrate/frame/whitelist/Cargo.toml @@ -18,7 +18,6 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { features = ["derive", "max-encoded-len"], workspace = true } frame = { workspace = true, features = ["runtime"] } scale-info = { features = ["derive"], workspace = true } -sp-runtime = { workspace = true } [dev-dependencies] pallet-balances = { workspace = true, default-features = true } diff --git a/substrate/frame/whitelist/src/lib.rs b/substrate/frame/whitelist/src/lib.rs index f71b54a4a6003..74bd051358a7c 100644 --- a/substrate/frame/whitelist/src/lib.rs +++ b/substrate/frame/whitelist/src/lib.rs @@ -40,9 +40,6 @@ mod tests; pub mod weights; pub use weights::WeightInfo; -#[cfg(any(feature = "try-runtime", test))] -use sp_runtime::TryRuntimeError; - extern crate alloc; use alloc::boxed::Box; From b98cf1c2c7c6f94b39a418e71b05932d1eef68d4 Mon Sep 17 00:00:00 2001 From: Nnamdi Aninye Date: Wed, 26 Nov 2025 02:25:55 +0100 Subject: [PATCH 9/9] update --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index aac49f5a03a2c..f51b14678ae44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14294,7 +14294,6 @@ dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", "scale-info", - "sp-runtime", ] [[package]]