diff --git a/Cargo.lock b/Cargo.lock
index 978f2b98dcff96c574c0b44678eab7f942c59e74..5a1e5d4a744e2fcfbe145451a37e54cc3e012160 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4788,12 +4788,9 @@ dependencies = [
 
 [[package]]
 name = "deranged"
-version = "0.3.11"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
-dependencies = [
- "powerfmt",
-]
+checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
 
 [[package]]
 name = "derivative"
@@ -9410,12 +9407,6 @@ dependencies = [
  "num-traits",
 ]
 
-[[package]]
-name = "num-conv"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
-
 [[package]]
 name = "num-derive"
 version = "0.4.2"
@@ -15296,12 +15287,6 @@ dependencies = [
  "rand",
 ]
 
-[[package]]
-name = "powerfmt"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
-
 [[package]]
 name = "pprof"
 version = "0.12.1"
@@ -22179,16 +22164,14 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.36"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
+checksum = "0bb39ee79a6d8de55f48f2293a830e040392f1c5f16e336bdd1788cd0aadce07"
 dependencies = [
  "deranged",
  "itoa",
  "libc",
- "num-conv",
  "num_threads",
- "powerfmt",
  "serde",
  "time-core",
  "time-macros",
@@ -22196,17 +22179,16 @@ dependencies = [
 
 [[package]]
 name = "time-core"
-version = "0.1.2"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
 
 [[package]]
 name = "time-macros"
-version = "0.2.18"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
+checksum = "733d258752e9303d392b94b75230d07b0b9c489350c69b851fc6c065fde3e8f9"
 dependencies = [
- "num-conv",
  "time-core",
 ]
 
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
index ebc0053308194e41bdd47a879e599c8826cdcc60..ce6bdcdf4f239e71eeeb40091a22040665674b1d 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
@@ -199,4 +199,6 @@ try-runtime = [
 	"sp-runtime/try-runtime",
 ]
 
-fast-runtime = []
+fast-runtime = [
+	"rococo-runtime-constants/fast-runtime",
+]
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs
index ec3a4f31202fd5f5333a1057bb06ca5dde247619..fa0c2644421e7ebc3f34a562e6aa2ea0b255df12 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs
@@ -21,22 +21,65 @@ use cumulus_primitives_core::relay_chain;
 use frame_support::{
 	parameter_types,
 	traits::{
-		fungible::{Balanced, Credit},
-		OnUnbalanced,
+		fungible::{Balanced, Credit, Inspect},
+		tokens::{Fortitude, Preservation},
+		DefensiveResult, OnUnbalanced,
 	},
 };
+use frame_system::Pallet as System;
 use pallet_broker::{CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600, RCBlockNumberOf};
-use parachains_common::{AccountId, Balance, BlockNumber};
+use parachains_common::{AccountId, Balance};
+use rococo_runtime_constants::system_parachain::coretime;
+use sp_runtime::traits::AccountIdConversion;
 use xcm::latest::prelude::*;
+use xcm_executor::traits::TransactAsset;
 
-pub struct CreditToCollatorPot;
-impl OnUnbalanced<Credit<AccountId, Balances>> for CreditToCollatorPot {
-	fn on_nonzero_unbalanced(credit: Credit<AccountId, Balances>) {
-		let staking_pot = CollatorSelection::account_id();
-		let _ = <Balances as Balanced<_>>::resolve(&staking_pot, credit);
+pub struct BurnCoretimeRevenue;
+impl OnUnbalanced<Credit<AccountId, Balances>> for BurnCoretimeRevenue {
+	fn on_nonzero_unbalanced(amount: Credit<AccountId, Balances>) {
+		let acc = RevenueAccumulationAccount::get();
+		if !System::<Runtime>::account_exists(&acc) {
+			System::<Runtime>::inc_providers(&acc);
+		}
+		Balances::resolve(&acc, amount).defensive_ok();
 	}
 }
 
+type AssetTransactor = <xcm_config::XcmConfig as xcm_executor::Config>::AssetTransactor;
+
+fn burn_at_relay(stash: &AccountId, value: Balance) -> Result<(), XcmError> {
+	let dest = Location::parent();
+	let stash_location =
+		Junction::AccountId32 { network: None, id: stash.clone().into() }.into_location();
+	let asset = Asset { id: AssetId(Location::parent()), fun: Fungible(value) };
+	let dummy_xcm_context = XcmContext { origin: None, message_id: [0; 32], topic: None };
+
+	let withdrawn = AssetTransactor::withdraw_asset(&asset, &stash_location, None)?;
+
+	AssetTransactor::can_check_out(&dest, &asset, &dummy_xcm_context)?;
+
+	let parent_assets = Into::<Assets>::into(withdrawn)
+		.reanchored(&dest, &Here.into())
+		.defensive_map_err(|_| XcmError::ReanchorFailed)?;
+
+	PolkadotXcm::send_xcm(
+		Here,
+		Location::parent(),
+		Xcm(vec![
+			Instruction::UnpaidExecution {
+				weight_limit: WeightLimit::Unlimited,
+				check_origin: None,
+			},
+			ReceiveTeleportedAsset(parent_assets.clone()),
+			BurnAsset(parent_assets),
+		]),
+	)?;
+
+	AssetTransactor::check_out(&dest, &asset, &dummy_xcm_context);
+
+	Ok(())
+}
+
 /// A type containing the encoding of the coretime pallet in the Relay chain runtime. Used to
 /// construct any remote calls. The codec index must correspond to the index of `Coretime` in the
 /// `construct_runtime` of the Relay chain.
@@ -66,11 +109,7 @@ enum CoretimeProviderCalls {
 
 parameter_types! {
 	pub const BrokerPalletId: PalletId = PalletId(*b"py/broke");
-}
-
-parameter_types! {
-	pub storage CoreCount: Option<CoreIndex> = None;
-	pub storage CoretimeRevenue: Option<(BlockNumber, Balance)> = None;
+	pub RevenueAccumulationAccount: AccountId = BrokerPalletId::get().into_sub_account_truncating(b"burnstash");
 }
 
 /// Type that implements the `CoretimeInterface` for the allocation of Coretime. Meant to operate
@@ -205,26 +244,30 @@ impl CoretimeInterface for CoretimeAllocator {
 		}
 	}
 
-	fn check_notify_revenue_info() -> Option<(RCBlockNumberOf<Self>, Self::Balance)> {
-		let revenue = CoretimeRevenue::get();
-		CoretimeRevenue::set(&None);
-		revenue
-	}
+	fn on_new_timeslice(_t: pallet_broker::Timeslice) {
+		let stash = RevenueAccumulationAccount::get();
+		let value =
+			Balances::reducible_balance(&stash, Preservation::Expendable, Fortitude::Polite);
 
-	#[cfg(feature = "runtime-benchmarks")]
-	fn ensure_notify_revenue_info(when: RCBlockNumberOf<Self>, revenue: Self::Balance) {
-		CoretimeRevenue::set(&Some((when, revenue)));
+		if value > 0 {
+			log::debug!(target: "runtime::coretime", "Going to burn {value} stashed tokens at RC");
+			match burn_at_relay(&stash, value) {
+				Ok(()) => {
+					log::debug!(target: "runtime::coretime", "Succesfully burnt {value} tokens");
+				},
+				Err(err) => {
+					log::error!(target: "runtime::coretime", "burn_at_relay failed: {err:?}");
+				},
+			}
+		}
 	}
 }
 
 impl pallet_broker::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type Currency = Balances;
-	type OnRevenue = CreditToCollatorPot;
-	#[cfg(feature = "fast-runtime")]
-	type TimeslicePeriod = ConstU32<10>;
-	#[cfg(not(feature = "fast-runtime"))]
-	type TimeslicePeriod = ConstU32<80>;
+	type OnRevenue = BurnCoretimeRevenue;
+	type TimeslicePeriod = ConstU32<{ coretime::TIMESLICE_PERIOD }>;
 	type MaxLeasedCores = ConstU32<50>;
 	type MaxReservedCores = ConstU32<10>;
 	type Coretime = CoretimeAllocator;
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
index 34f7fa4d3ecc1329baa08f602aaca562e7ed28e9..7bd3c67546872ea548fc7305cacca300d153b0b4 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
@@ -117,6 +117,7 @@ pub type Migrations = (
 	cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5<Runtime>,
 	pallet_broker::migration::MigrateV0ToV1<Runtime>,
 	pallet_broker::migration::MigrateV1ToV2<Runtime>,
+	pallet_broker::migration::MigrateV2ToV3<Runtime>,
 	// permanent
 	pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
 );
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs
index 5c9175a18d98a0b6c0c791945dcd9f2cd1892cc4..83e80e2e91e737827fce0b90fad0ec3d70ce3c33 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs
@@ -17,9 +17,9 @@
 //! Autogenerated weights for `pallet_broker`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-06-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-x5tnzzy-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024
 
 // Executed Command:
@@ -54,8 +54,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_918_000 picoseconds.
-		Weight::from_parts(2_092_000, 0)
+		// Minimum execution time: 2_024_000 picoseconds.
+		Weight::from_parts(2_121_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -65,8 +65,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `10888`
 		//  Estimated: `13506`
-		// Minimum execution time: 21_943_000 picoseconds.
-		Weight::from_parts(22_570_000, 0)
+		// Minimum execution time: 21_654_000 picoseconds.
+		Weight::from_parts(22_591_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -77,8 +77,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `12090`
 		//  Estimated: `13506`
-		// Minimum execution time: 20_923_000 picoseconds.
-		Weight::from_parts(21_354_000, 0)
+		// Minimum execution time: 20_769_000 picoseconds.
+		Weight::from_parts(21_328_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -93,24 +93,34 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `466`
 		//  Estimated: `1951`
-		// Minimum execution time: 10_687_000 picoseconds.
-		Weight::from_parts(11_409_000, 0)
+		// Minimum execution time: 10_404_000 picoseconds.
+		Weight::from_parts(10_941_000, 0)
 			.saturating_add(Weight::from_parts(0, 1951))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Configuration` (r:1 w:0)
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
+	/// Storage: `Broker::Leases` (r:1 w:1)
+	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(401), added: 896, mode: `MaxEncodedLen`)
+	/// Storage: `Broker::Reservations` (r:1 w:0)
+	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
+	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
+	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
+	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
+	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
+	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
+	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::ValidationData` (r:1 w:0)
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::LastRelayChainBlockNumber` (r:1 w:0)
 	/// Proof: `ParachainSystem::LastRelayChainBlockNumber` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `Broker::InstaPoolIo` (r:3 w:3)
 	/// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
-	/// Storage: `Broker::Reservations` (r:1 w:0)
-	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
-	/// Storage: `Broker::Leases` (r:1 w:1)
-	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(401), added: 896, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::SaleInfo` (r:0 w:1)
 	/// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Status` (r:0 w:1)
@@ -120,33 +130,34 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// The range of component `n` is `[0, 1000]`.
 	fn start_sales(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `12567`
-		//  Estimated: `14052`
-		// Minimum execution time: 111_288_000 picoseconds.
-		Weight::from_parts(117_804_282, 0)
-			.saturating_add(Weight::from_parts(0, 14052))
-			// Standard Error: 391
-			.saturating_add(Weight::from_parts(1_243, 0).saturating_mul(n.into()))
-			.saturating_add(T::DbWeight::get().reads(8))
-			.saturating_add(T::DbWeight::get().writes(66))
+		//  Measured:  `12599`
+		//  Estimated: `15065 + n * (1 ±0)`
+		// Minimum execution time: 44_085_000 picoseconds.
+		Weight::from_parts(127_668_002, 0)
+			.saturating_add(Weight::from_parts(0, 15065))
+			// Standard Error: 2_231
+			.saturating_add(Weight::from_parts(20_604, 0).saturating_mul(n.into()))
+			.saturating_add(T::DbWeight::get().reads(13))
+			.saturating_add(T::DbWeight::get().writes(59))
+			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::SaleInfo` (r:1 w:1)
 	/// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`)
-	/// Storage: `System::Account` (r:1 w:0)
+	/// Storage: `System::Account` (r:1 w:1)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:0 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn purchase() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `316`
+		//  Measured:  `332`
 		//  Estimated: `3593`
-		// Minimum execution time: 33_006_000 picoseconds.
-		Weight::from_parts(34_256_000, 0)
+		// Minimum execution time: 45_100_000 picoseconds.
+		Weight::from_parts(46_263_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(2))
+			.saturating_add(T::DbWeight::get().writes(3))
 	}
 	/// Storage: `Broker::Configuration` (r:1 w:0)
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
@@ -156,53 +167,53 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::PotentialRenewals` (r:1 w:2)
 	/// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`)
-	/// Storage: `System::Account` (r:1 w:0)
+	/// Storage: `System::Account` (r:1 w:1)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Workplan` (r:0 w:1)
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `434`
+		//  Measured:  `553`
 		//  Estimated: `4698`
-		// Minimum execution time: 61_473_000 picoseconds.
-		Weight::from_parts(66_476_000, 0)
+		// Minimum execution time: 65_944_000 picoseconds.
+		Weight::from_parts(68_666_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(5))
-			.saturating_add(T::DbWeight::get().writes(4))
+			.saturating_add(T::DbWeight::get().writes(5))
 	}
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `357`
-		//  Estimated: `3550`
-		// Minimum execution time: 13_771_000 picoseconds.
-		Weight::from_parts(14_374_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `358`
+		//  Estimated: `3551`
+		// Minimum execution time: 13_794_000 picoseconds.
+		Weight::from_parts(14_450_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Regions` (r:1 w:2)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn partition() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `357`
-		//  Estimated: `3550`
-		// Minimum execution time: 15_162_000 picoseconds.
-		Weight::from_parts(15_742_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `358`
+		//  Estimated: `3551`
+		// Minimum execution time: 15_316_000 picoseconds.
+		Weight::from_parts(15_787_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
 	/// Storage: `Broker::Regions` (r:1 w:3)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn interlace() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `357`
-		//  Estimated: `3550`
-		// Minimum execution time: 16_196_000 picoseconds.
-		Weight::from_parts(16_796_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `358`
+		//  Estimated: `3551`
+		// Minimum execution time: 16_375_000 picoseconds.
+		Weight::from_parts(17_113_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(3))
 	}
@@ -211,15 +222,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Workplan` (r:1 w:1)
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn assign() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `936`
+		//  Measured:  `937`
 		//  Estimated: `4681`
-		// Minimum execution time: 25_653_000 picoseconds.
-		Weight::from_parts(27_006_000, 0)
+		// Minimum execution time: 25_952_000 picoseconds.
+		Weight::from_parts(27_198_000, 0)
 			.saturating_add(Weight::from_parts(0, 4681))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -227,7 +238,7 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Workplan` (r:1 w:1)
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::InstaPoolIo` (r:2 w:2)
@@ -236,10 +247,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1002`
+		//  Measured:  `1003`
 		//  Estimated: `5996`
-		// Minimum execution time: 31_114_000 picoseconds.
-		Weight::from_parts(32_235_000, 0)
+		// Minimum execution time: 31_790_000 picoseconds.
+		Weight::from_parts(32_920_000, 0)
 			.saturating_add(Weight::from_parts(0, 5996))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -255,11 +266,11 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `652`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 57_280_000 picoseconds.
-		Weight::from_parts(58_127_480, 0)
+		// Minimum execution time: 56_286_000 picoseconds.
+		Weight::from_parts(56_946_240, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
-			// Standard Error: 41_670
-			.saturating_add(Weight::from_parts(1_203_066, 0).saturating_mul(m.into()))
+			// Standard Error: 44_472
+			.saturating_add(Weight::from_parts(1_684_838, 0).saturating_mul(m.into()))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -279,25 +290,25 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn purchase_credit() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `215`
-		//  Estimated: `3680`
-		// Minimum execution time: 59_968_000 picoseconds.
-		Weight::from_parts(62_315_000, 0)
-			.saturating_add(Weight::from_parts(0, 3680))
+		//  Measured:  `322`
+		//  Estimated: `3787`
+		// Minimum execution time: 64_967_000 picoseconds.
+		Weight::from_parts(66_504_000, 0)
+			.saturating_add(Weight::from_parts(0, 3787))
 			.saturating_add(T::DbWeight::get().reads(6))
 			.saturating_add(T::DbWeight::get().writes(3))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn drop_region() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `465`
-		//  Estimated: `3550`
-		// Minimum execution time: 50_887_000 picoseconds.
-		Weight::from_parts(57_366_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `466`
+		//  Estimated: `3551`
+		// Minimum execution time: 37_552_000 picoseconds.
+		Weight::from_parts(46_263_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -311,8 +322,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `463`
 		//  Estimated: `3533`
-		// Minimum execution time: 84_472_000 picoseconds.
-		Weight::from_parts(96_536_000, 0)
+		// Minimum execution time: 79_625_000 picoseconds.
+		Weight::from_parts(86_227_000, 0)
 			.saturating_add(Weight::from_parts(0, 3533))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -329,8 +340,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `857`
 		//  Estimated: `3593`
-		// Minimum execution time: 96_371_000 picoseconds.
-		Weight::from_parts(104_659_000, 0)
+		// Minimum execution time: 88_005_000 picoseconds.
+		Weight::from_parts(92_984_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -343,8 +354,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `957`
 		//  Estimated: `4698`
-		// Minimum execution time: 51_741_000 picoseconds.
-		Weight::from_parts(54_461_000, 0)
+		// Minimum execution time: 38_877_000 picoseconds.
+		Weight::from_parts(40_408_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -360,13 +371,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
 	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `74`
 		//  Estimated: `3539`
-		// Minimum execution time: 19_901_000 picoseconds.
-		Weight::from_parts(21_028_116, 0)
+		// Minimum execution time: 20_581_000 picoseconds.
+		Weight::from_parts(21_610_297, 0)
 			.saturating_add(Weight::from_parts(0, 3539))
+			// Standard Error: 119
+			.saturating_add(Weight::from_parts(144, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
@@ -377,29 +390,29 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `266`
 		//  Estimated: `1487`
-		// Minimum execution time: 5_987_000 picoseconds.
-		Weight::from_parts(6_412_478, 0)
+		// Minimum execution time: 6_079_000 picoseconds.
+		Weight::from_parts(6_540_110, 0)
 			.saturating_add(Weight::from_parts(0, 1487))
-			// Standard Error: 16
-			.saturating_add(Weight::from_parts(47, 0).saturating_mul(n.into()))
+			// Standard Error: 14
+			.saturating_add(Weight::from_parts(10, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::InstaPoolHistory` (r:1 w:1)
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
-	/// Storage: `System::Account` (r:2 w:1)
+	/// Storage: `System::Account` (r:2 w:2)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `447`
+		//  Measured:  `442`
 		//  Estimated: `6196`
-		// Minimum execution time: 38_623_000 picoseconds.
-		Weight::from_parts(39_773_000, 0)
+		// Minimum execution time: 42_947_000 picoseconds.
+		Weight::from_parts(43_767_000, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
 			.saturating_add(T::DbWeight::get().reads(4))
-			.saturating_add(T::DbWeight::get().writes(3))
+			.saturating_add(T::DbWeight::get().writes(4))
 	}
 	/// Storage: `Broker::InstaPoolIo` (r:3 w:3)
 	/// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
@@ -412,13 +425,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `Broker::Workplan` (r:0 w:60)
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn rotate_sale(_n: u32, ) -> Weight {
+	fn rotate_sale(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `12514`
 		//  Estimated: `13506`
-		// Minimum execution time: 97_074_000 picoseconds.
-		Weight::from_parts(101_247_740, 0)
+		// Minimum execution time: 93_426_000 picoseconds.
+		Weight::from_parts(96_185_447, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
+			// Standard Error: 116
+			.saturating_add(Weight::from_parts(4, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(65))
 	}
@@ -430,8 +445,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `42`
 		//  Estimated: `3493`
-		// Minimum execution time: 6_317_000 picoseconds.
-		Weight::from_parts(6_521_000, 0)
+		// Minimum execution time: 5_842_000 picoseconds.
+		Weight::from_parts(6_077_000, 0)
 			.saturating_add(Weight::from_parts(0, 3493))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -454,8 +469,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `1321`
 		//  Estimated: `4786`
-		// Minimum execution time: 32_575_000 picoseconds.
-		Weight::from_parts(33_299_000, 0)
+		// Minimum execution time: 33_278_000 picoseconds.
+		Weight::from_parts(34_076_000, 0)
 			.saturating_add(Weight::from_parts(0, 4786))
 			.saturating_add(T::DbWeight::get().reads(7))
 			.saturating_add(T::DbWeight::get().writes(4))
@@ -474,8 +489,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `74`
 		//  Estimated: `3539`
-		// Minimum execution time: 15_256_000 picoseconds.
-		Weight::from_parts(15_927_000, 0)
+		// Minimum execution time: 15_779_000 picoseconds.
+		Weight::from_parts(16_213_000, 0)
 			.saturating_add(Weight::from_parts(0, 3539))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -486,8 +501,19 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_783_000 picoseconds.
-		Weight::from_parts(1_904_000, 0)
+		// Minimum execution time: 1_774_000 picoseconds.
+		Weight::from_parts(1_873_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
+	/// Storage: `Broker::RevenueInbox` (r:0 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
+	fn notify_revenue() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 1_858_000 picoseconds.
+		Weight::from_parts(1_991_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -497,19 +523,19 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:0)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:0)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	/// Storage: `ParachainSystem::ValidationData` (r:1 w:0)
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `398`
-		//  Estimated: `3863`
-		// Minimum execution time: 12_307_000 picoseconds.
-		Weight::from_parts(12_967_000, 0)
-			.saturating_add(Weight::from_parts(0, 3863))
+		//  Measured:  `408`
+		//  Estimated: `1893`
+		// Minimum execution time: 10_874_000 picoseconds.
+		Weight::from_parts(11_265_000, 0)
+			.saturating_add(Weight::from_parts(0, 1893))
 			.saturating_add(T::DbWeight::get().reads(5))
-			.saturating_add(T::DbWeight::get().writes(2))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Leases` (r:1 w:1)
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(401), added: 896, mode: `MaxEncodedLen`)
@@ -517,10 +543,32 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `470`
 		//  Estimated: `1886`
-		// Minimum execution time: 6_597_000 picoseconds.
-		Weight::from_parts(6_969_000, 0)
+		// Minimum execution time: 6_525_000 picoseconds.
+		Weight::from_parts(6_769_000, 0)
 			.saturating_add(Weight::from_parts(0, 1886))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
+	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
+	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
+	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
+	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
+	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	fn on_new_timeslice() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `322`
+		//  Estimated: `3787`
+		// Minimum execution time: 45_561_000 picoseconds.
+		Weight::from_parts(47_306_000, 0)
+			.saturating_add(Weight::from_parts(0, 3787))
+			.saturating_add(T::DbWeight::get().reads(6))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
 }
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
index 10edf7fac8536af4e26234420e541c2622615308..735e9542197d89438569d93dbaa9c7515e531937 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
@@ -196,4 +196,6 @@ try-runtime = [
 	"sp-runtime/try-runtime",
 ]
 
-fast-runtime = []
+fast-runtime = [
+	"westend-runtime-constants/fast-runtime",
+]
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs
index a5e219b9897e0710e008ffa6b800624710877bcc..4f06e3e3669c8d69fcb990e55eb7c9e83432e96f 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs
@@ -21,22 +21,67 @@ use cumulus_primitives_core::relay_chain;
 use frame_support::{
 	parameter_types,
 	traits::{
-		fungible::{Balanced, Credit},
-		OnUnbalanced,
+		fungible::{Balanced, Credit, Inspect},
+		tokens::{Fortitude, Preservation},
+		DefensiveResult, OnUnbalanced,
 	},
 };
-use pallet_broker::{CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600, RCBlockNumberOf};
-use parachains_common::{AccountId, Balance, BlockNumber};
+use frame_system::Pallet as System;
+use pallet_broker::{
+	CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600, RCBlockNumberOf, Timeslice,
+};
+use parachains_common::{AccountId, Balance};
+use sp_runtime::traits::AccountIdConversion;
+use westend_runtime_constants::system_parachain::coretime;
 use xcm::latest::prelude::*;
+use xcm_executor::traits::TransactAsset;
 
-pub struct CreditToCollatorPot;
-impl OnUnbalanced<Credit<AccountId, Balances>> for CreditToCollatorPot {
-	fn on_nonzero_unbalanced(credit: Credit<AccountId, Balances>) {
-		let staking_pot = CollatorSelection::account_id();
-		let _ = <Balances as Balanced<_>>::resolve(&staking_pot, credit);
+pub struct BurnCoretimeRevenue;
+impl OnUnbalanced<Credit<AccountId, Balances>> for BurnCoretimeRevenue {
+	fn on_nonzero_unbalanced(amount: Credit<AccountId, Balances>) {
+		let acc = RevenueAccumulationAccount::get();
+		if !System::<Runtime>::account_exists(&acc) {
+			System::<Runtime>::inc_providers(&acc);
+		}
+		Balances::resolve(&acc, amount).defensive_ok();
 	}
 }
 
+type AssetTransactor = <xcm_config::XcmConfig as xcm_executor::Config>::AssetTransactor;
+
+fn burn_at_relay(stash: &AccountId, value: Balance) -> Result<(), XcmError> {
+	let dest = Location::parent();
+	let stash_location =
+		Junction::AccountId32 { network: None, id: stash.clone().into() }.into_location();
+	let asset = Asset { id: AssetId(Location::parent()), fun: Fungible(value) };
+	let dummy_xcm_context = XcmContext { origin: None, message_id: [0; 32], topic: None };
+
+	let withdrawn = AssetTransactor::withdraw_asset(&asset, &stash_location, None)?;
+
+	AssetTransactor::can_check_out(&dest, &asset, &dummy_xcm_context)?;
+
+	let parent_assets = Into::<Assets>::into(withdrawn)
+		.reanchored(&dest, &Here.into())
+		.defensive_map_err(|_| XcmError::ReanchorFailed)?;
+
+	PolkadotXcm::send_xcm(
+		Here,
+		Location::parent(),
+		Xcm(vec![
+			Instruction::UnpaidExecution {
+				weight_limit: WeightLimit::Unlimited,
+				check_origin: None,
+			},
+			ReceiveTeleportedAsset(parent_assets.clone()),
+			BurnAsset(parent_assets),
+		]),
+	)?;
+
+	AssetTransactor::check_out(&dest, &asset, &dummy_xcm_context);
+
+	Ok(())
+}
+
 /// A type containing the encoding of the coretime pallet in the Relay chain runtime. Used to
 /// construct any remote calls. The codec index must correspond to the index of `Coretime` in the
 /// `construct_runtime` of the Relay chain.
@@ -66,11 +111,7 @@ enum CoretimeProviderCalls {
 
 parameter_types! {
 	pub const BrokerPalletId: PalletId = PalletId(*b"py/broke");
-}
-
-parameter_types! {
-	pub storage CoreCount: Option<CoreIndex> = None;
-	pub storage CoretimeRevenue: Option<(BlockNumber, Balance)> = None;
+	pub RevenueAccumulationAccount: AccountId = BrokerPalletId::get().into_sub_account_truncating(b"burnstash");
 }
 
 /// Type that implements the `CoretimeInterface` for the allocation of Coretime. Meant to operate
@@ -217,26 +258,30 @@ impl CoretimeInterface for CoretimeAllocator {
 		}
 	}
 
-	fn check_notify_revenue_info() -> Option<(RCBlockNumberOf<Self>, Self::Balance)> {
-		let revenue = CoretimeRevenue::get();
-		CoretimeRevenue::set(&None);
-		revenue
-	}
+	fn on_new_timeslice(_timeslice: Timeslice) {
+		let stash = RevenueAccumulationAccount::get();
+		let value =
+			Balances::reducible_balance(&stash, Preservation::Expendable, Fortitude::Polite);
 
-	#[cfg(feature = "runtime-benchmarks")]
-	fn ensure_notify_revenue_info(when: RCBlockNumberOf<Self>, revenue: Self::Balance) {
-		CoretimeRevenue::set(&Some((when, revenue)));
+		if value > 0 {
+			log::debug!(target: "runtime::coretime", "Going to burn {value} stashed tokens at RC");
+			match burn_at_relay(&stash, value) {
+				Ok(()) => {
+					log::debug!(target: "runtime::coretime", "Succesfully burnt {value} tokens");
+				},
+				Err(err) => {
+					log::error!(target: "runtime::coretime", "burn_at_relay failed: {err:?}");
+				},
+			}
+		}
 	}
 }
 
 impl pallet_broker::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type Currency = Balances;
-	type OnRevenue = CreditToCollatorPot;
-	#[cfg(feature = "fast-runtime")]
-	type TimeslicePeriod = ConstU32<10>;
-	#[cfg(not(feature = "fast-runtime"))]
-	type TimeslicePeriod = ConstU32<80>;
+	type OnRevenue = BurnCoretimeRevenue;
+	type TimeslicePeriod = ConstU32<{ coretime::TIMESLICE_PERIOD }>;
 	// We don't actually need any leases at launch but set to 10 in case we want to sudo some in.
 	type MaxLeasedCores = ConstU32<10>;
 	type MaxReservedCores = ConstU32<10>;
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
index 4b2f494c8909991fa6722e25d16ce1a2bc5d9f4b..bc71ee705e9cc8869c99e9997da7680258e6b270 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
@@ -116,6 +116,7 @@ pub type Migrations = (
 	cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4<Runtime>,
 	pallet_broker::migration::MigrateV0ToV1<Runtime>,
 	pallet_broker::migration::MigrateV1ToV2<Runtime>,
+	pallet_broker::migration::MigrateV2ToV3<Runtime>,
 	// permanent
 	pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
 );
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs
index 7e1c832a90924e39c7bc7d7b24d8163ce5d65589..d130b306f7a52b75958db353aea24e9e113c82d5 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs
@@ -17,9 +17,9 @@
 //! Autogenerated weights for `pallet_broker`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-06-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-x5tnzzy-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024
 
 // Executed Command:
@@ -54,8 +54,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_897_000 picoseconds.
-		Weight::from_parts(2_053_000, 0)
+		// Minimum execution time: 1_899_000 picoseconds.
+		Weight::from_parts(2_051_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -65,8 +65,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `10888`
 		//  Estimated: `13506`
-		// Minimum execution time: 22_550_000 picoseconds.
-		Weight::from_parts(22_871_000, 0)
+		// Minimum execution time: 21_965_000 picoseconds.
+		Weight::from_parts(22_774_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -77,8 +77,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `12090`
 		//  Estimated: `13506`
-		// Minimum execution time: 21_170_000 picoseconds.
-		Weight::from_parts(21_645_000, 0)
+		// Minimum execution time: 20_748_000 picoseconds.
+		Weight::from_parts(21_464_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -93,24 +93,34 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `146`
 		//  Estimated: `1631`
-		// Minimum execution time: 10_494_000 picoseconds.
-		Weight::from_parts(10_942_000, 0)
+		// Minimum execution time: 10_269_000 picoseconds.
+		Weight::from_parts(10_508_000, 0)
 			.saturating_add(Weight::from_parts(0, 1631))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Configuration` (r:1 w:0)
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
+	/// Storage: `Broker::Leases` (r:1 w:1)
+	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(81), added: 576, mode: `MaxEncodedLen`)
+	/// Storage: `Broker::Reservations` (r:1 w:0)
+	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
+	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
+	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
+	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
+	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
+	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
+	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::ValidationData` (r:1 w:0)
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::LastRelayChainBlockNumber` (r:1 w:0)
 	/// Proof: `ParachainSystem::LastRelayChainBlockNumber` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `Broker::InstaPoolIo` (r:3 w:3)
 	/// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
-	/// Storage: `Broker::Reservations` (r:1 w:0)
-	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
-	/// Storage: `Broker::Leases` (r:1 w:1)
-	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(81), added: 576, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::SaleInfo` (r:0 w:1)
 	/// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Status` (r:0 w:1)
@@ -118,15 +128,18 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `Broker::Workplan` (r:0 w:20)
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn start_sales(_n: u32, ) -> Weight {
+	fn start_sales(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `12247`
-		//  Estimated: `13732`
-		// Minimum execution time: 61_014_000 picoseconds.
-		Weight::from_parts(63_267_651, 0)
-			.saturating_add(Weight::from_parts(0, 13732))
-			.saturating_add(T::DbWeight::get().reads(8))
+		//  Measured:  `12279`
+		//  Estimated: `14805 + n * (1 ±0)`
+		// Minimum execution time: 41_900_000 picoseconds.
+		Weight::from_parts(80_392_728, 0)
+			.saturating_add(Weight::from_parts(0, 14805))
+			// Standard Error: 870
+			.saturating_add(Weight::from_parts(4_361, 0).saturating_mul(n.into()))
+			.saturating_add(T::DbWeight::get().reads(13))
 			.saturating_add(T::DbWeight::get().writes(26))
+			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
@@ -135,13 +148,13 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `System::Account` (r:1 w:0)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:0 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn purchase() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `316`
+		//  Measured:  `332`
 		//  Estimated: `3593`
-		// Minimum execution time: 30_931_000 picoseconds.
-		Weight::from_parts(31_941_000, 0)
+		// Minimum execution time: 40_911_000 picoseconds.
+		Weight::from_parts(43_102_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -160,47 +173,47 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `434`
+		//  Measured:  `450`
 		//  Estimated: `4698`
-		// Minimum execution time: 57_466_000 picoseconds.
-		Weight::from_parts(65_042_000, 0)
+		// Minimum execution time: 70_257_000 picoseconds.
+		Weight::from_parts(73_889_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(4))
 	}
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `357`
-		//  Estimated: `3550`
-		// Minimum execution time: 12_799_000 picoseconds.
-		Weight::from_parts(13_401_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `358`
+		//  Estimated: `3551`
+		// Minimum execution time: 13_302_000 picoseconds.
+		Weight::from_parts(13_852_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Regions` (r:1 w:2)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn partition() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `357`
-		//  Estimated: `3550`
-		// Minimum execution time: 14_107_000 picoseconds.
-		Weight::from_parts(14_630_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `358`
+		//  Estimated: `3551`
+		// Minimum execution time: 14_927_000 picoseconds.
+		Weight::from_parts(15_553_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
 	/// Storage: `Broker::Regions` (r:1 w:3)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn interlace() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `357`
-		//  Estimated: `3550`
-		// Minimum execution time: 15_254_000 picoseconds.
-		Weight::from_parts(16_062_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `358`
+		//  Estimated: `3551`
+		// Minimum execution time: 16_237_000 picoseconds.
+		Weight::from_parts(16_995_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(3))
 	}
@@ -209,15 +222,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Workplan` (r:1 w:1)
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn assign() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `735`
+		//  Measured:  `736`
 		//  Estimated: `4681`
-		// Minimum execution time: 23_557_000 picoseconds.
-		Weight::from_parts(24_382_000, 0)
+		// Minimum execution time: 24_621_000 picoseconds.
+		Weight::from_parts(25_165_000, 0)
 			.saturating_add(Weight::from_parts(0, 4681))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -225,7 +238,7 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Workplan` (r:1 w:1)
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::InstaPoolIo` (r:2 w:2)
@@ -234,10 +247,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `801`
+		//  Measured:  `802`
 		//  Estimated: `5996`
-		// Minimum execution time: 29_371_000 picoseconds.
-		Weight::from_parts(30_200_000, 0)
+		// Minimum execution time: 29_832_000 picoseconds.
+		Weight::from_parts(30_894_000, 0)
 			.saturating_add(Weight::from_parts(0, 5996))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -253,11 +266,11 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `652`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 54_331_000 picoseconds.
-		Weight::from_parts(55_322_165, 0)
+		// Minimum execution time: 55_390_000 picoseconds.
+		Weight::from_parts(56_124_789, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
-			// Standard Error: 35_225
-			.saturating_add(Weight::from_parts(1_099_614, 0).saturating_mul(m.into()))
+			// Standard Error: 41_724
+			.saturating_add(Weight::from_parts(1_551_266, 0).saturating_mul(m.into()))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -277,25 +290,25 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn purchase_credit() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `215`
-		//  Estimated: `3680`
-		// Minimum execution time: 53_789_000 picoseconds.
-		Weight::from_parts(55_439_000, 0)
-			.saturating_add(Weight::from_parts(0, 3680))
+		//  Measured:  `320`
+		//  Estimated: `3785`
+		// Minimum execution time: 59_759_000 picoseconds.
+		Weight::from_parts(61_310_000, 0)
+			.saturating_add(Weight::from_parts(0, 3785))
 			.saturating_add(T::DbWeight::get().reads(6))
 			.saturating_add(T::DbWeight::get().writes(3))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Regions` (r:1 w:1)
-	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`)
+	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn drop_region() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `465`
-		//  Estimated: `3550`
-		// Minimum execution time: 43_941_000 picoseconds.
-		Weight::from_parts(49_776_000, 0)
-			.saturating_add(Weight::from_parts(0, 3550))
+		//  Measured:  `466`
+		//  Estimated: `3551`
+		// Minimum execution time: 37_007_000 picoseconds.
+		Weight::from_parts(51_927_000, 0)
+			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -309,8 +322,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `463`
 		//  Estimated: `3533`
-		// Minimum execution time: 64_917_000 picoseconds.
-		Weight::from_parts(70_403_000, 0)
+		// Minimum execution time: 86_563_000 picoseconds.
+		Weight::from_parts(91_274_000, 0)
 			.saturating_add(Weight::from_parts(0, 3533))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -327,8 +340,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `857`
 		//  Estimated: `3593`
-		// Minimum execution time: 72_633_000 picoseconds.
-		Weight::from_parts(79_305_000, 0)
+		// Minimum execution time: 93_655_000 picoseconds.
+		Weight::from_parts(98_160_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -341,8 +354,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `556`
 		//  Estimated: `4698`
-		// Minimum execution time: 36_643_000 picoseconds.
-		Weight::from_parts(48_218_000, 0)
+		// Minimum execution time: 33_985_000 picoseconds.
+		Weight::from_parts(43_618_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -358,13 +371,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
 	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `74`
 		//  Estimated: `3539`
-		// Minimum execution time: 17_617_000 picoseconds.
-		Weight::from_parts(18_904_788, 0)
+		// Minimum execution time: 18_778_000 picoseconds.
+		Weight::from_parts(19_543_425, 0)
 			.saturating_add(Weight::from_parts(0, 3539))
+			// Standard Error: 41
+			.saturating_add(Weight::from_parts(33, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
@@ -375,26 +390,26 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `266`
 		//  Estimated: `1487`
-		// Minimum execution time: 5_575_000 picoseconds.
-		Weight::from_parts(5_887_598, 0)
+		// Minimum execution time: 5_505_000 picoseconds.
+		Weight::from_parts(5_982_015, 0)
 			.saturating_add(Weight::from_parts(0, 1487))
-			// Standard Error: 16
-			.saturating_add(Weight::from_parts(41, 0).saturating_mul(n.into()))
+			// Standard Error: 13
+			.saturating_add(Weight::from_parts(44, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::InstaPoolHistory` (r:1 w:1)
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
 	/// Storage: `System::Account` (r:2 w:1)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `447`
+		//  Measured:  `442`
 		//  Estimated: `6196`
-		// Minimum execution time: 36_415_000 picoseconds.
-		Weight::from_parts(37_588_000, 0)
+		// Minimum execution time: 38_128_000 picoseconds.
+		Weight::from_parts(40_979_000, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(3))
@@ -414,11 +429,11 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `12194`
 		//  Estimated: `13506`
-		// Minimum execution time: 48_362_000 picoseconds.
-		Weight::from_parts(49_616_106, 0)
+		// Minimum execution time: 49_041_000 picoseconds.
+		Weight::from_parts(50_522_788, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
-			// Standard Error: 61
-			.saturating_add(Weight::from_parts(59, 0).saturating_mul(n.into()))
+			// Standard Error: 72
+			.saturating_add(Weight::from_parts(78, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(25))
 	}
@@ -430,8 +445,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `42`
 		//  Estimated: `3493`
-		// Minimum execution time: 6_148_000 picoseconds.
-		Weight::from_parts(6_374_000, 0)
+		// Minimum execution time: 5_903_000 picoseconds.
+		Weight::from_parts(6_202_000, 0)
 			.saturating_add(Weight::from_parts(0, 3493))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -454,8 +469,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `1321`
 		//  Estimated: `4786`
-		// Minimum execution time: 30_267_000 picoseconds.
-		Weight::from_parts(30_825_000, 0)
+		// Minimum execution time: 31_412_000 picoseconds.
+		Weight::from_parts(31_964_000, 0)
 			.saturating_add(Weight::from_parts(0, 4786))
 			.saturating_add(T::DbWeight::get().reads(7))
 			.saturating_add(T::DbWeight::get().writes(4))
@@ -474,8 +489,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `74`
 		//  Estimated: `3539`
-		// Minimum execution time: 13_491_000 picoseconds.
-		Weight::from_parts(13_949_000, 0)
+		// Minimum execution time: 14_098_000 picoseconds.
+		Weight::from_parts(14_554_000, 0)
 			.saturating_add(Weight::from_parts(0, 3539))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -486,8 +501,19 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_711_000 picoseconds.
-		Weight::from_parts(1_913_000, 0)
+		// Minimum execution time: 1_723_000 picoseconds.
+		Weight::from_parts(1_822_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
+	/// Storage: `Broker::RevenueInbox` (r:0 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
+	fn notify_revenue() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 1_865_000 picoseconds.
+		Weight::from_parts(1_983_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -497,19 +523,19 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:0)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:0)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	/// Storage: `ParachainSystem::ValidationData` (r:1 w:0)
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `398`
-		//  Estimated: `3863`
-		// Minimum execution time: 12_035_000 picoseconds.
-		Weight::from_parts(12_383_000, 0)
-			.saturating_add(Weight::from_parts(0, 3863))
+		//  Measured:  `408`
+		//  Estimated: `1893`
+		// Minimum execution time: 10_387_000 picoseconds.
+		Weight::from_parts(10_819_000, 0)
+			.saturating_add(Weight::from_parts(0, 1893))
 			.saturating_add(T::DbWeight::get().reads(5))
-			.saturating_add(T::DbWeight::get().writes(2))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Leases` (r:1 w:1)
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(81), added: 576, mode: `MaxEncodedLen`)
@@ -517,10 +543,21 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `150`
 		//  Estimated: `1566`
-		// Minimum execution time: 6_142_000 picoseconds.
-		Weight::from_parts(6_538_000, 0)
+		// Minimum execution time: 5_996_000 picoseconds.
+		Weight::from_parts(6_278_000, 0)
 			.saturating_add(Weight::from_parts(0, 1566))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
+	/// Storage: `System::Account` (r:1 w:0)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	fn on_new_timeslice() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `3593`
+		// Minimum execution time: 2_187_000 picoseconds.
+		Weight::from_parts(2_372_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(1))
+	}
 }
diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml
index 89364ff7fab6423cf09d9b26dd6135afc6988c0b..ae5abdcfab6a33c17affb3f28e0afa4dd9a137db 100644
--- a/cumulus/polkadot-parachain/Cargo.toml
+++ b/cumulus/polkadot-parachain/Cargo.toml
@@ -171,4 +171,8 @@ try-runtime = [
 	"shell-runtime/try-runtime",
 	"sp-runtime/try-runtime",
 ]
-fast-runtime = ["bridge-hub-rococo-runtime/fast-runtime"]
+fast-runtime = [
+	"bridge-hub-rococo-runtime/fast-runtime",
+	"coretime-rococo-runtime/fast-runtime",
+	"coretime-westend-runtime/fast-runtime",
+]
diff --git a/polkadot/runtime/parachains/src/assigner_coretime/tests.rs b/polkadot/runtime/parachains/src/assigner_coretime/tests.rs
index 81a0988ea67cd3eb3b76784d360d46a1ddf1633e..bab09eda52c2d630171bb790831152d945b718db 100644
--- a/polkadot/runtime/parachains/src/assigner_coretime/tests.rs
+++ b/polkadot/runtime/parachains/src/assigner_coretime/tests.rs
@@ -74,6 +74,9 @@ fn run_to_block(
 		Paras::initializer_initialize(b + 1);
 		Scheduler::initializer_initialize(b + 1);
 
+		// Update the spot traffic and revenue on every block.
+		OnDemandAssigner::on_initialize(b + 1);
+
 		// In the real runtime this is expected to be called by the `InclusionInherent` pallet.
 		Scheduler::free_cores_and_fill_claim_queue(BTreeMap::new(), b + 1);
 	}
diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs
index 043a36d99c4974c5dd75f3f4172848a4707c871a..03f05842bca498a26518bbeb0e8f957f2fa5783c 100644
--- a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs
+++ b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs
@@ -31,38 +31,40 @@
 //! occupying multiple cores in on-demand, we will likely add a separate order type, where the
 //! intent can be made explicit.
 
+use sp_runtime::traits::Zero;
 mod benchmarking;
 pub mod migration;
 mod mock_helpers;
+mod types;
 
 extern crate alloc;
 
 #[cfg(test)]
 mod tests;
 
-use core::mem::take;
-
 use crate::{configuration, paras, scheduler::common::Assignment};
-
+use alloc::collections::BinaryHeap;
+use core::mem::take;
 use frame_support::{
 	pallet_prelude::*,
 	traits::{
+		defensive_prelude::*,
 		Currency,
 		ExistenceRequirement::{self, AllowDeath, KeepAlive},
 		WithdrawReasons,
 	},
+	PalletId,
 };
-use frame_system::pallet_prelude::*;
-use polkadot_primitives::{CoreIndex, Id as ParaId, ON_DEMAND_MAX_QUEUE_MAX_SIZE};
+use frame_system::{pallet_prelude::*, Pallet as System};
+use polkadot_primitives::{CoreIndex, Id as ParaId};
 use sp_runtime::{
-	traits::{One, SaturatedConversion},
+	traits::{AccountIdConversion, One, SaturatedConversion},
 	FixedPointNumber, FixedPointOperand, FixedU128, Perbill, Saturating,
 };
-
-use alloc::collections::BinaryHeap;
-use sp_std::{
-	cmp::{Ord, Ordering, PartialOrd},
-	prelude::*,
+use sp_std::prelude::*;
+use types::{
+	BalanceOf, CoreAffinityCount, EnqueuedOrder, QueuePushDirection, QueueStatusType,
+	SpotTrafficCalculationErr,
 };
 
 const LOG_TARGET: &str = "runtime::parachains::assigner-on-demand";
@@ -87,217 +89,6 @@ impl WeightInfo for TestWeightInfo {
 	}
 }
 
-/// Meta data for full queue.
-///
-/// This includes elements with affinity and free entries.
-///
-/// The actual queue is implemented via multiple priority queues. One for each core, for entries
-/// which currently have a core affinity and one free queue, with entries without any affinity yet.
-///
-/// The design aims to have most queue accessess be O(1) or O(log(N)). Absolute worst case is O(N).
-/// Importantly this includes all accessess that happen in a single block. Even with 50 cores, the
-/// total complexity of all operations in the block should maintain above complexities. In
-/// particular O(N) stays O(N), it should never be O(N*cores).
-///
-/// More concrete rundown on complexity:
-///
-///  - insert: O(1) for placing an order, O(log(N)) for push backs.
-///  - pop_assignment_for_core: O(log(N)), O(N) worst case: Can only happen for one core, next core
-///  is already less work.
-///  - report_processed & push back: If affinity dropped to 0, then O(N) in the worst case. Again
-///  this divides per core.
-///
-///  Reads still exist, also improved slightly, but worst case we fetch all entries.
-#[derive(Encode, Decode, TypeInfo)]
-struct QueueStatusType {
-	/// Last calculated traffic value.
-	traffic: FixedU128,
-	/// The next index to use.
-	next_index: QueueIndex,
-	/// Smallest index still in use.
-	///
-	/// In case of a completely empty queue (free + affinity queues), `next_index - smallest_index
-	/// == 0`.
-	smallest_index: QueueIndex,
-	/// Indices that have been freed already.
-	///
-	/// But have a hole to `smallest_index`, so we can not yet bump `smallest_index`. This binary
-	/// heap is roughly bounded in the number of on demand cores:
-	///
-	/// For a single core, elements will always be processed in order. With each core added, a
-	/// level of out of order execution is added.
-	freed_indices: BinaryHeap<ReverseQueueIndex>,
-}
-
-impl Default for QueueStatusType {
-	fn default() -> QueueStatusType {
-		QueueStatusType {
-			traffic: FixedU128::default(),
-			next_index: QueueIndex(0),
-			smallest_index: QueueIndex(0),
-			freed_indices: BinaryHeap::new(),
-		}
-	}
-}
-
-impl QueueStatusType {
-	/// How many orders are queued in total?
-	///
-	/// This includes entries which have core affinity.
-	fn size(&self) -> u32 {
-		self.next_index
-			.0
-			.overflowing_sub(self.smallest_index.0)
-			.0
-			.saturating_sub(self.freed_indices.len() as u32)
-	}
-
-	/// Get current next index
-	///
-	/// to use for an element newly pushed to the back of the queue.
-	fn push_back(&mut self) -> QueueIndex {
-		let QueueIndex(next_index) = self.next_index;
-		self.next_index = QueueIndex(next_index.overflowing_add(1).0);
-		QueueIndex(next_index)
-	}
-
-	/// Push something to the front of the queue
-	fn push_front(&mut self) -> QueueIndex {
-		self.smallest_index = QueueIndex(self.smallest_index.0.overflowing_sub(1).0);
-		self.smallest_index
-	}
-
-	/// The given index is no longer part of the queue.
-	///
-	/// This updates `smallest_index` if need be.
-	fn consume_index(&mut self, removed_index: QueueIndex) {
-		if removed_index != self.smallest_index {
-			self.freed_indices.push(removed_index.reverse());
-			return;
-		}
-		let mut index = self.smallest_index.0.overflowing_add(1).0;
-		// Even more to advance?
-		while self.freed_indices.peek() == Some(&ReverseQueueIndex(index)) {
-			index = index.overflowing_add(1).0;
-			self.freed_indices.pop();
-		}
-		self.smallest_index = QueueIndex(index);
-	}
-}
-
-/// Keeps track of how many assignments a scheduler currently has at a specific `CoreIndex` for a
-/// specific `ParaId`.
-#[derive(Encode, Decode, Default, Clone, Copy, TypeInfo)]
-#[cfg_attr(test, derive(PartialEq, RuntimeDebug))]
-struct CoreAffinityCount {
-	core_index: CoreIndex,
-	count: u32,
-}
-
-/// An indicator as to which end of the `OnDemandQueue` an assignment will be placed.
-#[cfg_attr(test, derive(RuntimeDebug))]
-enum QueuePushDirection {
-	Back,
-	Front,
-}
-
-/// Shorthand for the Balance type the runtime is using.
-type BalanceOf<T> =
-	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
-
-/// Errors that can happen during spot traffic calculation.
-#[derive(PartialEq, RuntimeDebug)]
-enum SpotTrafficCalculationErr {
-	/// The order queue capacity is at 0.
-	QueueCapacityIsZero,
-	/// The queue size is larger than the queue capacity.
-	QueueSizeLargerThanCapacity,
-	/// Arithmetic error during division, either division by 0 or over/underflow.
-	Division,
-}
-
-/// Type used for priority indices.
-//  NOTE: The `Ord` implementation for this type is unsound in the general case.
-//        Do not use it for anything but it's intended purpose.
-#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq, Copy)]
-struct QueueIndex(u32);
-
-/// QueueIndex with reverse ordering.
-///
-/// Same as `Reverse(QueueIndex)`, but with all the needed traits implemented.
-#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq, Copy)]
-struct ReverseQueueIndex(u32);
-
-impl QueueIndex {
-	fn reverse(self) -> ReverseQueueIndex {
-		ReverseQueueIndex(self.0)
-	}
-}
-
-impl Ord for QueueIndex {
-	fn cmp(&self, other: &Self) -> Ordering {
-		let diff = self.0.overflowing_sub(other.0).0;
-		if diff == 0 {
-			Ordering::Equal
-		} else if diff <= ON_DEMAND_MAX_QUEUE_MAX_SIZE {
-			Ordering::Greater
-		} else {
-			Ordering::Less
-		}
-	}
-}
-
-impl PartialOrd for QueueIndex {
-	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-		Some(self.cmp(other))
-	}
-}
-
-impl Ord for ReverseQueueIndex {
-	fn cmp(&self, other: &Self) -> Ordering {
-		QueueIndex(other.0).cmp(&QueueIndex(self.0))
-	}
-}
-impl PartialOrd for ReverseQueueIndex {
-	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-		Some(self.cmp(&other))
-	}
-}
-
-/// Internal representation of an order after it has been enqueued already.
-///
-/// This data structure is provided for a min BinaryHeap (Ord compares in reverse order with regards
-/// to its elements)
-#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq)]
-struct EnqueuedOrder {
-	para_id: ParaId,
-	idx: QueueIndex,
-}
-
-impl EnqueuedOrder {
-	fn new(idx: QueueIndex, para_id: ParaId) -> Self {
-		Self { idx, para_id }
-	}
-}
-
-impl PartialOrd for EnqueuedOrder {
-	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-		match other.idx.partial_cmp(&self.idx) {
-			Some(Ordering::Equal) => other.para_id.partial_cmp(&self.para_id),
-			o => o,
-		}
-	}
-}
-
-impl Ord for EnqueuedOrder {
-	fn cmp(&self, other: &Self) -> Ordering {
-		match other.idx.cmp(&self.idx) {
-			Ordering::Equal => other.para_id.cmp(&self.para_id),
-			o => o,
-		}
-	}
-}
-
 #[frame_support::pallet]
 pub mod pallet {
 
@@ -324,6 +115,15 @@ pub mod pallet {
 		/// The default value for the spot traffic multiplier.
 		#[pallet::constant]
 		type TrafficDefaultValue: Get<FixedU128>;
+
+		/// The maximum number of blocks some historical revenue
+		/// information stored for.
+		#[pallet::constant]
+		type MaxHistoricalRevenue: Get<u32>;
+
+		/// Identifier for the internal revenue balance.
+		#[pallet::constant]
+		type PalletId: Get<PalletId>;
 	}
 
 	/// Creates an empty queue status for an empty queue with initial traffic value.
@@ -365,6 +165,11 @@ pub mod pallet {
 		EntriesOnEmpty<T>,
 	>;
 
+	/// Keeps track of accumulated revenue from on demand order sales.
+	#[pallet::storage]
+	pub type Revenue<T: Config> =
+		StorageValue<_, BoundedVec<BalanceOf<T>, T::MaxHistoricalRevenue>, ValueQuery>;
+
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
@@ -386,6 +191,19 @@ pub mod pallet {
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
 		fn on_initialize(_now: BlockNumberFor<T>) -> Weight {
+			// Update revenue information storage.
+			Revenue::<T>::mutate(|revenue| {
+				if let Some(overdue) =
+					revenue.force_insert_keep_left(0, 0u32.into()).defensive_unwrap_or(None)
+				{
+					// We have some overdue revenue not claimed by the Coretime Chain, let's
+					// accumulate it at the oldest stored block
+					if let Some(last) = revenue.last_mut() {
+						*last = last.saturating_add(overdue);
+					}
+				}
+			});
+
 			let config = configuration::ActiveConfig::<T>::get();
 			// We need to update the spot traffic on block initialize in order to account for idle
 			// blocks.
@@ -393,8 +211,9 @@ pub mod pallet {
 				Self::update_spot_traffic(&config, queue_status);
 			});
 
-			// 2 reads in config and queuestatus, at maximum 1 write to queuestatus.
-			T::DbWeight::get().reads_writes(2, 1)
+			// Reads: `Revenue`, `ActiveConfig`, `QueueStatus`
+			// Writes: `Revenue`, `QueueStatus`
+			T::DbWeight::get().reads_writes(3, 2)
 		}
 	}
 
@@ -527,7 +346,8 @@ where
 	}
 
 	/// Helper function for `place_order_*` calls. Used to differentiate between placing orders
-	/// with a keep alive check or to allow the account to be reaped.
+	/// with a keep alive check or to allow the account to be reaped. The amount charged is
+	/// stored to the pallet account to be later paid out as revenue.
 	///
 	/// Parameters:
 	/// - `sender`: The sender of the call, funds will be withdrawn from this account.
@@ -562,18 +382,40 @@ where
 			// Is the current price higher than `max_amount`
 			ensure!(spot_price.le(&max_amount), Error::<T>::SpotPriceHigherThanMaxAmount);
 
-			// Charge the sending account the spot price
-			let _ = T::Currency::withdraw(
+			ensure!(
+				queue_status.size() < config.scheduler_params.on_demand_queue_max_size,
+				Error::<T>::QueueFull
+			);
+
+			// Charge the sending account the spot price. The amount will be teleported to the
+			// broker chain once it requests revenue information.
+			let amt = T::Currency::withdraw(
 				&sender,
 				spot_price,
 				WithdrawReasons::FEE,
 				existence_requirement,
 			)?;
 
-			ensure!(
-				queue_status.size() < config.scheduler_params.on_demand_queue_max_size,
-				Error::<T>::QueueFull
-			);
+			// Consume the negative imbalance and deposit it into the pallet account. Make sure the
+			// account preserves even without the existential deposit.
+			let pot = Self::account_id();
+			if !System::<T>::account_exists(&pot) {
+				System::<T>::inc_providers(&pot);
+			}
+			T::Currency::resolve_creating(&pot, amt);
+
+			// Add the amount to the current block's (index 0) revenue information.
+			Revenue::<T>::mutate(|bounded_revenue| {
+				if let Some(current_block) = bounded_revenue.get_mut(0) {
+					*current_block = current_block.saturating_add(spot_price);
+				} else {
+					// Revenue has already been claimed in the same block, including the block
+					// itself. It shouldn't normally happen as revenue claims in the future are
+					// not allowed.
+					bounded_revenue.try_push(spot_price).defensive_ok();
+				}
+			});
+
 			Pallet::<T>::add_on_demand_order(queue_status, para_id, QueuePushDirection::Back);
 			Pallet::<T>::deposit_event(Event::<T>::OnDemandOrderPlaced {
 				para_id,
@@ -790,6 +632,29 @@ where
 		})
 	}
 
+	/// Collect the revenue from the `when` blockheight
+	pub fn claim_revenue_until(when: BlockNumberFor<T>) -> BalanceOf<T> {
+		let now = <frame_system::Pallet<T>>::block_number();
+		let mut amount: BalanceOf<T> = BalanceOf::<T>::zero();
+		Revenue::<T>::mutate(|revenue| {
+			while !revenue.is_empty() {
+				let index = (revenue.len() - 1) as u32;
+				if when > now.saturating_sub(index.into()) {
+					amount = amount.saturating_add(revenue.pop().defensive_unwrap_or(0u32.into()));
+				} else {
+					break
+				}
+			}
+		});
+
+		amount
+	}
+
+	/// Account of the pallet pot, where the funds from instantaneous coretime sale are accumulated.
+	pub fn account_id() -> T::AccountId {
+		T::PalletId::get().into_account_truncating()
+	}
+
 	/// Getter for the affinity tracker.
 	#[cfg(test)]
 	fn get_affinity_map(para_id: ParaId) -> Option<CoreAffinityCount> {
@@ -831,4 +696,9 @@ where
 	fn get_traffic_default_value() -> FixedU128 {
 		<T as Config>::TrafficDefaultValue::get()
 	}
+
+	#[cfg(test)]
+	fn get_revenue() -> Vec<BalanceOf<T>> {
+		Revenue::<T>::get().to_vec()
+	}
 }
diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs b/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs
index 5747413e71478eeb5b65984b58c3fe35beecadab..3d01ba655d3f404ac0e5b09d7ef590b175779534 100644
--- a/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs
+++ b/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs
@@ -17,7 +17,12 @@
 use super::*;
 
 use crate::{
-	assigner_on_demand::{mock_helpers::GenesisConfigBuilder, Error},
+	assigner_on_demand::{
+		self,
+		mock_helpers::GenesisConfigBuilder,
+		types::{QueueIndex, ReverseQueueIndex},
+		Error,
+	},
 	initializer::SessionChangeNotification,
 	mock::{
 		new_test_ext, Balances, OnDemandAssigner, Paras, ParasShared, RuntimeOrigin, Scheduler,
@@ -27,8 +32,13 @@ use crate::{
 };
 use frame_support::{assert_noop, assert_ok, error::BadOrigin};
 use pallet_balances::Error as BalancesError;
-use polkadot_primitives::{BlockNumber, SessionIndex, ValidationCode};
-use sp_std::collections::btree_map::BTreeMap;
+use polkadot_primitives::{
+	BlockNumber, SessionIndex, ValidationCode, ON_DEMAND_MAX_QUEUE_MAX_SIZE,
+};
+use sp_std::{
+	cmp::{Ord, Ordering},
+	collections::btree_map::BTreeMap,
+};
 
 fn schedule_blank_para(id: ParaId, parakind: ParaKind) {
 	let validation_code: ValidationCode = vec![1, 2, 3].into();
@@ -73,7 +83,7 @@ fn run_to_block(
 		Paras::initializer_initialize(b + 1);
 		Scheduler::initializer_initialize(b + 1);
 
-		// We need to update the spot traffic on every block.
+		// Update the spot traffic and revenue on every block.
 		OnDemandAssigner::on_initialize(b + 1);
 
 		// In the real runtime this is expected to be called by the `InclusionInherent` pallet.
@@ -81,16 +91,26 @@ fn run_to_block(
 	}
 }
 
-fn place_order(para_id: ParaId) {
+fn place_order_run_to_blocknumber(para_id: ParaId, blocknumber: Option<BlockNumber>) {
 	let alice = 100u64;
 	let amt = 10_000_000u128;
 
 	Balances::make_free_balance_be(&alice, amt);
 
-	run_to_block(101, |n| if n == 101 { Some(Default::default()) } else { None });
+	if let Some(bn) = blocknumber {
+		run_to_block(bn, |n| if n == bn { Some(Default::default()) } else { None });
+	}
 	OnDemandAssigner::place_order_allow_death(RuntimeOrigin::signed(alice), amt, para_id).unwrap()
 }
 
+fn place_order_run_to_101(para_id: ParaId) {
+	place_order_run_to_blocknumber(para_id, Some(101));
+}
+
+fn place_order(para_id: ParaId) {
+	place_order_run_to_blocknumber(para_id, None);
+}
+
 #[test]
 fn spot_traffic_capacity_zero_returns_none() {
 	match OnDemandAssigner::calculate_spot_traffic(
@@ -377,8 +397,8 @@ fn push_back_assignment_works() {
 		run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None });
 
 		// Add enough assignments to the order queue.
-		place_order(para_a);
-		place_order(para_b);
+		place_order_run_to_101(para_a);
+		place_order_run_to_101(para_b);
 
 		// Pop order a
 		assert_eq!(
@@ -424,9 +444,9 @@ fn affinity_prohibits_parallel_scheduling() {
 		assert!(OnDemandAssigner::get_affinity_map(para_b).is_none());
 
 		// Add 2 assignments for para_a for every para_b.
-		place_order(para_a);
-		place_order(para_a);
-		place_order(para_b);
+		place_order_run_to_101(para_a);
+		place_order_run_to_101(para_a);
+		place_order_run_to_101(para_b);
 
 		// Approximate having 1 core.
 		for _ in 0..3 {
@@ -448,9 +468,9 @@ fn affinity_prohibits_parallel_scheduling() {
 		OnDemandAssigner::report_processed(para_b, 0.into());
 
 		// Add 2 assignments for para_a for every para_b.
-		place_order(para_a);
-		place_order(para_a);
-		place_order(para_b);
+		place_order_run_to_101(para_a);
+		place_order_run_to_101(para_a);
+		place_order_run_to_101(para_b);
 
 		// Approximate having 3 cores. CoreIndex 2 should be unable to obtain an assignment
 		for _ in 0..3 {
@@ -490,7 +510,7 @@ fn affinity_changes_work() {
 
 		// Add enough assignments to the order queue.
 		for _ in 0..10 {
-			place_order(para_a);
+			place_order_run_to_101(para_a);
 		}
 
 		// There should be no affinity before the scheduler pops.
@@ -554,7 +574,7 @@ fn new_affinity_for_a_core_must_come_from_free_entries() {
 
 		// Place orders for all chains.
 		parachains.iter().for_each(|chain| {
-			place_order(*chain);
+			place_order_run_to_101(*chain);
 		});
 
 		// There are 4 entries in free_entries.
@@ -679,8 +699,8 @@ fn queue_status_size_fn_works() {
 		// Place orders for all chains.
 		parachains.iter().for_each(|chain| {
 			// 2 per chain for a total of 6
-			place_order(*chain);
-			place_order(*chain);
+			place_order_run_to_101(*chain);
+			place_order_run_to_101(*chain);
 		});
 
 		// 6 orders in free entries
@@ -707,3 +727,112 @@ fn queue_status_size_fn_works() {
 		assert_eq!(OnDemandAssigner::get_queue_status().size(), 4)
 	});
 }
+
+#[test]
+fn revenue_information_fetching_works() {
+	new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
+		let para_a = ParaId::from(111);
+		schedule_blank_para(para_a, ParaKind::Parathread);
+		// Mock assigner sets max revenue history to 10.
+		run_to_block(10, |n| if n == 10 { Some(Default::default()) } else { None });
+		let revenue = OnDemandAssigner::claim_revenue_until(10);
+
+		// No revenue should be recorded.
+		assert_eq!(revenue, 0);
+
+		// Place one order
+		place_order_run_to_blocknumber(para_a, Some(11));
+		let revenue = OnDemandAssigner::get_revenue();
+		let claim = OnDemandAssigner::claim_revenue_until(11);
+
+		// Revenue until the current block is still zero as "until" is non-inclusive
+		assert_eq!(claim, 0);
+
+		run_to_block(12, |n| if n == 12 { Some(Default::default()) } else { None });
+		let claim = OnDemandAssigner::claim_revenue_until(12);
+
+		// Revenue for a single order should be recorded and shouldn't have been pruned by the
+		// previous call
+		assert_eq!(claim, revenue[0]);
+
+		// Place many orders
+		place_order(para_a);
+		place_order(para_a);
+
+		run_to_block(13, |n| if n == 13 { Some(Default::default()) } else { None });
+
+		place_order(para_a);
+
+		run_to_block(15, |n| if n == 14 { Some(Default::default()) } else { None });
+
+		let revenue = OnDemandAssigner::claim_revenue_until(15);
+
+		// All 3 orders should be accounted for.
+		assert_eq!(revenue, 30_000);
+
+		// Place one order
+		place_order_run_to_blocknumber(para_a, Some(16));
+
+		let revenue = OnDemandAssigner::claim_revenue_until(15);
+
+		// Order is not in range of  the revenue_until call
+		assert_eq!(revenue, 0);
+
+		run_to_block(21, |n| if n == 20 { Some(Default::default()) } else { None });
+		let revenue = OnDemandAssigner::claim_revenue_until(21);
+		assert_eq!(revenue, 10_000);
+
+		// Make sure overdue revenue is accumulated
+		for i in 21..=35 {
+			run_to_block(i, |n| if n % 10 == 0 { Some(Default::default()) } else { None });
+			place_order(para_a);
+		}
+		run_to_block(36, |_| None);
+		let revenue = OnDemandAssigner::claim_revenue_until(36);
+		assert_eq!(revenue, 150_000);
+	});
+}
+
+#[test]
+fn pot_account_is_immortal() {
+	new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
+		let para_a = ParaId::from(111);
+		let pot = OnDemandAssigner::account_id();
+		assert!(!System::account_exists(&pot));
+		schedule_blank_para(para_a, ParaKind::Parathread);
+		// Mock assigner sets max revenue history to 10.
+
+		run_to_block(10, |n| if n == 10 { Some(Default::default()) } else { None });
+		place_order_run_to_blocknumber(para_a, Some(12));
+		let purchase_revenue = Balances::free_balance(&pot);
+		assert!(purchase_revenue > 0);
+
+		run_to_block(15, |_| None);
+		let _imb = <Test as assigner_on_demand::Config>::Currency::withdraw(
+			&pot,
+			purchase_revenue,
+			WithdrawReasons::FEE,
+			ExistenceRequirement::AllowDeath,
+		);
+		assert_eq!(Balances::free_balance(&pot), 0);
+		assert!(System::account_exists(&pot));
+		assert_eq!(System::providers(&pot), 1);
+
+		// One more cycle to make sure providers are not increased on every transition from zero
+		run_to_block(20, |n| if n == 20 { Some(Default::default()) } else { None });
+		place_order_run_to_blocknumber(para_a, Some(22));
+		let purchase_revenue = Balances::free_balance(&pot);
+		assert!(purchase_revenue > 0);
+
+		run_to_block(25, |_| None);
+		let _imb = <Test as assigner_on_demand::Config>::Currency::withdraw(
+			&pot,
+			purchase_revenue,
+			WithdrawReasons::FEE,
+			ExistenceRequirement::AllowDeath,
+		);
+		assert_eq!(Balances::free_balance(&pot), 0);
+		assert!(System::account_exists(&pot));
+		assert_eq!(System::providers(&pot), 1);
+	});
+}
diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/types.rs b/polkadot/runtime/parachains/src/assigner_on_demand/types.rs
new file mode 100644
index 0000000000000000000000000000000000000000..51d586a77a1784c905469dc48ed58fd382a1186b
--- /dev/null
+++ b/polkadot/runtime/parachains/src/assigner_on_demand/types.rs
@@ -0,0 +1,241 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
+
+//! On demand module types.
+
+use super::{alloc, pallet::Config};
+use alloc::collections::BinaryHeap;
+use frame_support::{
+	pallet_prelude::{Decode, Encode, RuntimeDebug, TypeInfo},
+	traits::Currency,
+};
+use polkadot_primitives::{CoreIndex, Id as ParaId, ON_DEMAND_MAX_QUEUE_MAX_SIZE};
+use sp_runtime::FixedU128;
+use sp_std::{
+	cmp::{Ord, Ordering, PartialOrd},
+	prelude::*,
+};
+
+/// Shorthand for the Balance type the runtime is using.
+pub type BalanceOf<T> =
+	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+
+/// Meta data for full queue.
+///
+/// This includes elements with affinity and free entries.
+///
+/// The actual queue is implemented via multiple priority queues. One for each core, for entries
+/// which currently have a core affinity and one free queue, with entries without any affinity yet.
+///
+/// The design aims to have most queue accessess be O(1) or O(log(N)). Absolute worst case is O(N).
+/// Importantly this includes all accessess that happen in a single block. Even with 50 cores, the
+/// total complexity of all operations in the block should maintain above complexities. In
+/// particular O(N) stays O(N), it should never be O(N*cores).
+///
+/// More concrete rundown on complexity:
+///
+///  - insert: O(1) for placing an order, O(log(N)) for push backs.
+///  - pop_assignment_for_core: O(log(N)), O(N) worst case: Can only happen for one core, next core
+///  is already less work.
+///  - report_processed & push back: If affinity dropped to 0, then O(N) in the worst case. Again
+///  this divides per core.
+///
+///  Reads still exist, also improved slightly, but worst case we fetch all entries.
+#[derive(Encode, Decode, TypeInfo)]
+pub struct QueueStatusType {
+	/// Last calculated traffic value.
+	pub traffic: FixedU128,
+	/// The next index to use.
+	pub next_index: QueueIndex,
+	/// Smallest index still in use.
+	///
+	/// In case of a completely empty queue (free + affinity queues), `next_index - smallest_index
+	/// == 0`.
+	pub smallest_index: QueueIndex,
+	/// Indices that have been freed already.
+	///
+	/// But have a hole to `smallest_index`, so we can not yet bump `smallest_index`. This binary
+	/// heap is roughly bounded in the number of on demand cores:
+	///
+	/// For a single core, elements will always be processed in order. With each core added, a
+	/// level of out of order execution is added.
+	pub freed_indices: BinaryHeap<ReverseQueueIndex>,
+}
+
+impl Default for QueueStatusType {
+	fn default() -> QueueStatusType {
+		QueueStatusType {
+			traffic: FixedU128::default(),
+			next_index: QueueIndex(0),
+			smallest_index: QueueIndex(0),
+			freed_indices: BinaryHeap::new(),
+		}
+	}
+}
+
+impl QueueStatusType {
+	/// How many orders are queued in total?
+	///
+	/// This includes entries which have core affinity.
+	pub fn size(&self) -> u32 {
+		self.next_index
+			.0
+			.overflowing_sub(self.smallest_index.0)
+			.0
+			.saturating_sub(self.freed_indices.len() as u32)
+	}
+
+	/// Get current next index
+	///
+	/// to use for an element newly pushed to the back of the queue.
+	pub fn push_back(&mut self) -> QueueIndex {
+		let QueueIndex(next_index) = self.next_index;
+		self.next_index = QueueIndex(next_index.overflowing_add(1).0);
+		QueueIndex(next_index)
+	}
+
+	/// Push something to the front of the queue
+	pub fn push_front(&mut self) -> QueueIndex {
+		self.smallest_index = QueueIndex(self.smallest_index.0.overflowing_sub(1).0);
+		self.smallest_index
+	}
+
+	/// The given index is no longer part of the queue.
+	///
+	/// This updates `smallest_index` if need be.
+	pub fn consume_index(&mut self, removed_index: QueueIndex) {
+		if removed_index != self.smallest_index {
+			self.freed_indices.push(removed_index.reverse());
+			return;
+		}
+		let mut index = self.smallest_index.0.overflowing_add(1).0;
+		// Even more to advance?
+		while self.freed_indices.peek() == Some(&ReverseQueueIndex(index)) {
+			index = index.overflowing_add(1).0;
+			self.freed_indices.pop();
+		}
+		self.smallest_index = QueueIndex(index);
+	}
+}
+
+/// Type used for priority indices.
+//  NOTE: The `Ord` implementation for this type is unsound in the general case.
+//        Do not use it for anything but it's intended purpose.
+#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq, Copy)]
+pub struct QueueIndex(pub u32);
+
+/// QueueIndex with reverse ordering.
+///
+/// Same as `Reverse(QueueIndex)`, but with all the needed traits implemented.
+#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq, Copy)]
+pub struct ReverseQueueIndex(pub u32);
+
+impl QueueIndex {
+	fn reverse(self) -> ReverseQueueIndex {
+		ReverseQueueIndex(self.0)
+	}
+}
+
+impl Ord for QueueIndex {
+	fn cmp(&self, other: &Self) -> Ordering {
+		let diff = self.0.overflowing_sub(other.0).0;
+		if diff == 0 {
+			Ordering::Equal
+		} else if diff <= ON_DEMAND_MAX_QUEUE_MAX_SIZE {
+			Ordering::Greater
+		} else {
+			Ordering::Less
+		}
+	}
+}
+
+impl PartialOrd for QueueIndex {
+	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+		Some(self.cmp(other))
+	}
+}
+
+impl Ord for ReverseQueueIndex {
+	fn cmp(&self, other: &Self) -> Ordering {
+		QueueIndex(other.0).cmp(&QueueIndex(self.0))
+	}
+}
+impl PartialOrd for ReverseQueueIndex {
+	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+		Some(self.cmp(&other))
+	}
+}
+
+/// Internal representation of an order after it has been enqueued already.
+///
+/// This data structure is provided for a min BinaryHeap (Ord compares in reverse order with regards
+/// to its elements)
+#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq)]
+pub struct EnqueuedOrder {
+	pub para_id: ParaId,
+	pub idx: QueueIndex,
+}
+
+impl EnqueuedOrder {
+	pub fn new(idx: QueueIndex, para_id: ParaId) -> Self {
+		Self { idx, para_id }
+	}
+}
+
+impl PartialOrd for EnqueuedOrder {
+	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+		match other.idx.partial_cmp(&self.idx) {
+			Some(Ordering::Equal) => other.para_id.partial_cmp(&self.para_id),
+			o => o,
+		}
+	}
+}
+
+impl Ord for EnqueuedOrder {
+	fn cmp(&self, other: &Self) -> Ordering {
+		match other.idx.cmp(&self.idx) {
+			Ordering::Equal => other.para_id.cmp(&self.para_id),
+			o => o,
+		}
+	}
+}
+
+/// Keeps track of how many assignments a scheduler currently has at a specific `CoreIndex` for a
+/// specific `ParaId`.
+#[derive(Encode, Decode, Default, Clone, Copy, TypeInfo)]
+#[cfg_attr(test, derive(PartialEq, RuntimeDebug))]
+pub struct CoreAffinityCount {
+	pub core_index: CoreIndex,
+	pub count: u32,
+}
+
+/// An indicator as to which end of the `OnDemandQueue` an assignment will be placed.
+#[cfg_attr(test, derive(RuntimeDebug))]
+pub enum QueuePushDirection {
+	Back,
+	Front,
+}
+
+/// Errors that can happen during spot traffic calculation.
+#[derive(PartialEq, RuntimeDebug)]
+pub enum SpotTrafficCalculationErr {
+	/// The order queue capacity is at 0.
+	QueueCapacityIsZero,
+	/// The queue size is larger than the queue capacity.
+	QueueSizeLargerThanCapacity,
+	/// Arithmetic error during division, either division by 0 or over/underflow.
+	Division,
+}
diff --git a/polkadot/runtime/parachains/src/coretime/benchmarking.rs b/polkadot/runtime/parachains/src/coretime/benchmarking.rs
index d1ac71f580ee0e70015bf130b6836519005ee280..028250e188ee9885ad9c2c80d66ffa12f41be9e2 100644
--- a/polkadot/runtime/parachains/src/coretime/benchmarking.rs
+++ b/polkadot/runtime/parachains/src/coretime/benchmarking.rs
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
-//! On demand assigner pallet benchmarking.
+//! Coretime pallet benchmarking.
 
 #![cfg(feature = "runtime-benchmarks")]
 
@@ -28,6 +28,30 @@ mod benchmarks {
 	use super::*;
 	use assigner_coretime::PartsOf57600;
 
+	#[benchmark]
+	fn request_revenue_at() {
+		let root_origin = <T as frame_system::Config>::RuntimeOrigin::root();
+		let mhr = <T as assigner_on_demand::Config>::MaxHistoricalRevenue::get();
+		frame_system::Pallet::<T>::set_block_number((mhr + 2).into());
+		let minimum_balance = <T as assigner_on_demand::Config>::Currency::minimum_balance();
+		let rev: BoundedVec<
+			<<T as assigner_on_demand::Config>::Currency as frame_support::traits::Currency<
+				T::AccountId,
+			>>::Balance,
+			T::MaxHistoricalRevenue,
+		> = BoundedVec::try_from((1..=mhr).map(|v| minimum_balance * v.into()).collect::<Vec<_>>())
+			.unwrap();
+		assigner_on_demand::Revenue::<T>::put(rev);
+
+		<T as assigner_on_demand::Config>::Currency::make_free_balance_be(
+			&<assigner_on_demand::Pallet<T>>::account_id(),
+			minimum_balance * (mhr * (mhr + 1)).into(),
+		);
+
+		#[extrinsic_call]
+		_(root_origin as <T as frame_system::Config>::RuntimeOrigin, mhr + 1)
+	}
+
 	#[benchmark]
 	fn request_core_count() {
 		// Setup
diff --git a/polkadot/runtime/parachains/src/coretime/mod.rs b/polkadot/runtime/parachains/src/coretime/mod.rs
index dedffb733d33ef120f6b220afc550f04b77f0979..fc8a3c7d9d24b217d1de883c6cb3ed8b3f7be6e2 100644
--- a/polkadot/runtime/parachains/src/coretime/mod.rs
+++ b/polkadot/runtime/parachains/src/coretime/mod.rs
@@ -18,20 +18,36 @@
 //!
 //! <https://github.com/polkadot-fellows/RFCs/blob/main/text/0005-coretime-interface.md>
 
-use sp_std::{prelude::*, result};
-
-use frame_support::{pallet_prelude::*, traits::Currency};
+use frame_support::{
+	pallet_prelude::*,
+	traits::{defensive_prelude::*, Currency},
+};
 use frame_system::pallet_prelude::*;
 pub use pallet::*;
 use pallet_broker::{CoreAssignment, CoreIndex as BrokerCoreIndex};
-use polkadot_primitives::{CoreIndex, Id as ParaId};
+use polkadot_primitives::{Balance, BlockNumber, CoreIndex, Id as ParaId};
 use sp_arithmetic::traits::SaturatedConversion;
-use xcm::prelude::{
-	send_xcm, Instruction, Junction, Location, OriginKind, SendXcm, WeightLimit, Xcm,
+use sp_runtime::traits::TryConvert;
+use sp_std::{prelude::*, result};
+use xcm::{
+	prelude::{send_xcm, Instruction, Junction, Location, OriginKind, SendXcm, WeightLimit, Xcm},
+	v4::{
+		Asset,
+		AssetFilter::Wild,
+		AssetId, Assets, Error as XcmError,
+		Fungibility::Fungible,
+		Instruction::{DepositAsset, ReceiveTeleportedAsset},
+		Junctions::Here,
+		Reanchorable,
+		WildAsset::AllCounted,
+		XcmContext,
+	},
 };
+use xcm_executor::traits::TransactAsset;
 
 use crate::{
 	assigner_coretime::{self, PartsOf57600},
+	assigner_on_demand,
 	initializer::{OnNewSession, SessionChangeNotification},
 	origin::{ensure_parachain, Origin},
 };
@@ -39,9 +55,11 @@ use crate::{
 mod benchmarking;
 pub mod migration;
 
+const LOG_TARGET: &str = "runtime::parachains::coretime";
+
 pub trait WeightInfo {
 	fn request_core_count() -> Weight;
-	//fn request_revenue_info_at() -> Weight;
+	fn request_revenue_at() -> Weight;
 	//fn credit_account() -> Weight;
 	fn assign_core(s: u32) -> Weight;
 }
@@ -53,19 +71,23 @@ impl WeightInfo for TestWeightInfo {
 	fn request_core_count() -> Weight {
 		Weight::MAX
 	}
-	// TODO: Add real benchmarking functionality for each of these to
-	// benchmarking.rs, then uncomment here and in trait definition.
-	/*fn request_revenue_info_at() -> Weight {
+	fn request_revenue_at() -> Weight {
 		Weight::MAX
 	}
-	fn credit_account() -> Weight {
-		Weight::MAX
-	}*/
+	// TODO: Add real benchmarking functionality for each of these to
+	// benchmarking.rs, then uncomment here and in trait definition.
+	//fn credit_account() -> Weight {
+	//	Weight::MAX
+	//}
 	fn assign_core(_s: u32) -> Weight {
 		Weight::MAX
 	}
 }
 
+/// Shorthand for the Balance type the runtime is using.
+pub type BalanceOf<T> =
+	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+
 /// Broker pallet index on the coretime chain. Used to
 ///
 /// construct remote calls. The codec index must correspond to the index of `Broker` in the
@@ -85,6 +107,8 @@ enum CoretimeCalls {
 	SetLease(pallet_broker::TaskId, pallet_broker::Timeslice),
 	#[codec(index = 19)]
 	NotifyCoreCount(u16),
+	#[codec(index = 20)]
+	NotifyRevenue((BlockNumber, Balance)),
 	#[codec(index = 99)]
 	SwapLeases(ParaId, ParaId),
 }
@@ -92,6 +116,9 @@ enum CoretimeCalls {
 #[frame_support::pallet]
 pub mod pallet {
 	use crate::configuration;
+	use sp_runtime::traits::TryConvert;
+	use xcm::v4::InteriorLocation;
+	use xcm_executor::traits::TransactAsset;
 
 	use super::*;
 
@@ -100,7 +127,9 @@ pub mod pallet {
 	pub struct Pallet<T>(_);
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + assigner_coretime::Config {
+	pub trait Config:
+		frame_system::Config + assigner_coretime::Config + assigner_on_demand::Config
+	{
 		type RuntimeOrigin: From<<Self as frame_system::Config>::RuntimeOrigin>
 			+ Into<result::Result<Origin, <Self as Config>::RuntimeOrigin>>;
 		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
@@ -109,9 +138,17 @@ pub mod pallet {
 		/// The ParaId of the coretime chain.
 		#[pallet::constant]
 		type BrokerId: Get<u32>;
+		/// The coretime chain pot location.
+		#[pallet::constant]
+		type BrokerPotLocation: Get<InteriorLocation>;
 		/// Something that provides the weight of this pallet.
 		type WeightInfo: WeightInfo;
+		/// The XCM sender.
 		type SendXcm: SendXcm;
+		/// The asset transactor.
+		type AssetTransactor: TransactAsset;
+		/// AccountId to Location converter
+		type AccountToLocation: for<'a> TryConvert<&'a Self::AccountId, Location>;
 
 		/// Maximum weight for any XCM transact call that should be executed on the coretime chain.
 		///
@@ -132,6 +169,11 @@ pub mod pallet {
 	pub enum Error<T> {
 		/// The paraid making the call is not the coretime brokerage system parachain.
 		NotBroker,
+		/// Requested revenue information `when` parameter was in the future from the current
+		/// block height.
+		RequestedFutureRevenue,
+		/// Failed to transfer assets to the coretime chain
+		AssetTransferFailed,
 	}
 
 	#[pallet::hooks]
@@ -154,17 +196,17 @@ pub mod pallet {
 			configuration::Pallet::<T>::set_coretime_cores_unchecked(u32::from(count))
 		}
 
-		//// TODO Impl me!
-		////#[pallet::weight(<T as Config>::WeightInfo::request_revenue_info_at())]
-		//#[pallet::call_index(2)]
-		//pub fn request_revenue_info_at(
-		//	origin: OriginFor<T>,
-		//	_when: BlockNumberFor<T>,
-		//) -> DispatchResult {
-		//	// Ignore requests not coming from the coretime chain or root.
-		//	Self::ensure_root_or_para(origin, <T as Config>::BrokerId::get().into())?;
-		//	Ok(())
-		//}
+		/// Request to claim the instantaneous coretime sales revenue starting from the block it was
+		/// last claimed until and up to the block specified. The claimed amount value is sent back
+		/// to the Coretime chain in a `notify_revenue` message. At the same time, the amount is
+		/// teleported to the Coretime chain.
+		#[pallet::weight(<T as Config>::WeightInfo::request_revenue_at())]
+		#[pallet::call_index(2)]
+		pub fn request_revenue_at(origin: OriginFor<T>, when: BlockNumber) -> DispatchResult {
+			// Ignore requests not coming from the Coretime Chain or Root.
+			Self::ensure_root_or_para(origin, <T as Config>::BrokerId::get().into())?;
+			Self::notify_revenue(when)
+		}
 
 		//// TODO Impl me!
 		////#[pallet::weight(<T as Config>::WeightInfo::credit_account())]
@@ -244,11 +286,43 @@ impl<T: Config> Pallet<T> {
 				Location::new(0, [Junction::Parachain(T::BrokerId::get())]),
 				message,
 			) {
-				log::error!("Sending `NotifyCoreCount` to coretime chain failed: {:?}", err);
+				log::error!(target: LOG_TARGET, "Sending `NotifyCoreCount` to coretime chain failed: {:?}", err);
 			}
 		}
 	}
 
+	/// Provide the amount of revenue accumulated from Instantaneous Coretime Sales from Relay-chain
+	/// block number last_until to until, not including until itself. last_until is defined as being
+	/// the until argument of the last notify_revenue message sent, or zero for the first call. If
+	/// revenue is None, this indicates that the information is no longer available. This explicitly
+	/// disregards the possibility of multiple parachains requesting and being notified of revenue
+	/// information.
+	///
+	/// The Relay-chain must be configured to ensure that only a single revenue information
+	/// destination exists.
+	pub fn notify_revenue(until: BlockNumber) -> DispatchResult {
+		let now = <frame_system::Pallet<T>>::block_number();
+		let until_bnf: BlockNumberFor<T> = until.into();
+
+		// When cannot be in the future.
+		ensure!(until_bnf <= now, Error::<T>::RequestedFutureRevenue);
+
+		let amount = <assigner_on_demand::Pallet<T>>::claim_revenue_until(until_bnf);
+		log::debug!(target: LOG_TARGET, "Revenue info requested: {:?}", amount);
+
+		let raw_revenue: Balance = amount.try_into().map_err(|_| {
+			log::error!(target: LOG_TARGET, "Converting on demand revenue for `NotifyRevenue` failed");
+			Error::<T>::AssetTransferFailed
+		})?;
+
+		do_notify_revenue::<T>(until, raw_revenue).map_err(|err| {
+			log::error!(target: LOG_TARGET, "notify_revenue failed: {err:?}");
+			Error::<T>::AssetTransferFailed
+		})?;
+
+		Ok(())
+	}
+
 	// Handle legacy swaps in coretime. Notifies coretime chain that a lease swap has occurred via
 	// XCM message. This function is meant to be used in an implementation of `OnSwap` trait.
 	pub fn on_legacy_lease_swap(one: ParaId, other: ParaId) {
@@ -263,7 +337,7 @@ impl<T: Config> Pallet<T> {
 			Location::new(0, [Junction::Parachain(T::BrokerId::get())]),
 			message,
 		) {
-			log::error!("Sending `SwapLeases` to coretime chain failed: {:?}", err);
+			log::error!(target: LOG_TARGET, "Sending `SwapLeases` to coretime chain failed: {:?}", err);
 		}
 	}
 }
@@ -281,3 +355,55 @@ fn mk_coretime_call<T: Config>(call: crate::coretime::CoretimeCalls) -> Instruct
 		call: BrokerRuntimePallets::Broker(call).encode().into(),
 	}
 }
+
+fn do_notify_revenue<T: Config>(when: BlockNumber, raw_revenue: Balance) -> Result<(), XcmError> {
+	let dest = Junction::Parachain(T::BrokerId::get()).into_location();
+	let mut message = Vec::new();
+	let asset = Asset { id: AssetId(Location::here()), fun: Fungible(raw_revenue) };
+	let dummy_xcm_context = XcmContext { origin: None, message_id: [0; 32], topic: None };
+
+	if raw_revenue > 0 {
+		let on_demand_pot =
+			T::AccountToLocation::try_convert(&<assigner_on_demand::Pallet<T>>::account_id())
+				.map_err(|err| {
+					log::error!(
+						target: LOG_TARGET,
+						"Failed to convert on-demand pot account to XCM location: {err:?}",
+					);
+					XcmError::InvalidLocation
+				})?;
+
+		let withdrawn = T::AssetTransactor::withdraw_asset(&asset, &on_demand_pot, None)?;
+
+		T::AssetTransactor::can_check_out(&dest, &asset, &dummy_xcm_context)?;
+
+		let assets_reanchored = Into::<Assets>::into(withdrawn)
+			.reanchored(&dest, &Here.into())
+			.defensive_map_err(|_| XcmError::ReanchorFailed)?;
+
+		message.extend(
+			[
+				Instruction::UnpaidExecution {
+					weight_limit: WeightLimit::Unlimited,
+					check_origin: None,
+				},
+				ReceiveTeleportedAsset(assets_reanchored),
+				DepositAsset {
+					assets: Wild(AllCounted(1)),
+					beneficiary: T::BrokerPotLocation::get().into_location(),
+				},
+			]
+			.into_iter(),
+		);
+	}
+
+	message.push(mk_coretime_call::<T>(CoretimeCalls::NotifyRevenue((when, raw_revenue))));
+
+	send_xcm::<T::SendXcm>(dest.clone(), Xcm(message))?;
+
+	if raw_revenue > 0 {
+		T::AssetTransactor::check_out(&dest, &asset, &dummy_xcm_context);
+	}
+
+	Ok(())
+}
diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs
index 18722ff463cf2398a209bf5589d5acea3283ac84..9c23347ebb58bb93bf72e2d94a1f95defcea27b9 100644
--- a/polkadot/runtime/parachains/src/mock.rs
+++ b/polkadot/runtime/parachains/src/mock.rs
@@ -36,6 +36,7 @@ use frame_support::{
 		Currency, ProcessMessage, ProcessMessageError, ValidatorSet, ValidatorSetWithIdentification,
 	},
 	weights::{Weight, WeightMeter},
+	PalletId,
 };
 use frame_support_test::TestRandomness;
 use frame_system::limits;
@@ -57,7 +58,7 @@ use sp_std::{
 use std::collections::HashMap;
 use xcm::{
 	prelude::XcmVersion,
-	v4::{Assets, Location, SendError, SendResult, SendXcm, Xcm, XcmHash},
+	v4::{Assets, InteriorLocation, Location, SendError, SendResult, SendXcm, Xcm, XcmHash},
 	IntoVersion, VersionedXcm, WrapVersion,
 };
 
@@ -391,17 +392,23 @@ impl pallet_message_queue::Config for Test {
 	type IdleMaxServiceWeight = ();
 }
 
+impl assigner_parachains::Config for Test {}
+
 parameter_types! {
 	pub const OnDemandTrafficDefaultValue: FixedU128 = FixedU128::from_u32(1);
+	// Production chains should keep this numbar around twice the
+	// defined Timeslice for Coretime.
+	pub const MaxHistoricalRevenue: BlockNumber = 2 * 5;
+	pub const OnDemandPalletId: PalletId = PalletId(*b"py/ondmd");
 }
 
-impl assigner_parachains::Config for Test {}
-
 impl assigner_on_demand::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
 	type Currency = Balances;
 	type TrafficDefaultValue = OnDemandTrafficDefaultValue;
 	type WeightInfo = crate::assigner_on_demand::TestWeightInfo;
+	type MaxHistoricalRevenue = MaxHistoricalRevenue;
+	type PalletId = OnDemandPalletId;
 }
 
 impl assigner_coretime::Config for Test {}
@@ -411,6 +418,13 @@ parameter_types! {
 	pub MaxXcmTransactWeight: Weight = Weight::from_parts(10_000_000, 10_000);
 }
 
+pub struct BrokerPot;
+impl Get<InteriorLocation> for BrokerPot {
+	fn get() -> InteriorLocation {
+		unimplemented!()
+	}
+}
+
 impl coretime::Config for Test {
 	type RuntimeOrigin = RuntimeOrigin;
 	type RuntimeEvent = RuntimeEvent;
@@ -419,6 +433,9 @@ impl coretime::Config for Test {
 	type WeightInfo = crate::coretime::TestWeightInfo;
 	type SendXcm = DummyXcmSender;
 	type MaxXcmTransactWeight = MaxXcmTransactWeight;
+	type BrokerPotLocation = BrokerPot;
+	type AssetTransactor = ();
+	type AccountToLocation = ();
 }
 
 pub struct DummyXcmSender;
diff --git a/polkadot/runtime/rococo/constants/src/lib.rs b/polkadot/runtime/rococo/constants/src/lib.rs
index 1dcafdcbc4d9a6fe48fd460e3ac836d95bb3372b..47b50bf6c106918c5539cb327dd02af617de8c45 100644
--- a/polkadot/runtime/rococo/constants/src/lib.rs
+++ b/polkadot/runtime/rococo/constants/src/lib.rs
@@ -121,6 +121,17 @@ pub mod system_parachain {
 
 	/// All system parachains of Rococo.
 	pub type SystemParachains = IsChildSystemParachain<Id>;
+
+	/// Coretime constants
+	pub mod coretime {
+		/// Coretime timeslice period in blocks
+		/// WARNING: This constant is used accross chains, so additional care should be taken
+		/// when changing it.
+		#[cfg(feature = "fast-runtime")]
+		pub const TIMESLICE_PERIOD: u32 = 20;
+		#[cfg(not(feature = "fast-runtime"))]
+		pub const TIMESLICE_PERIOD: u32 = 80;
+	}
 }
 
 /// Rococo Treasury pallet instance.
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index bbec754387e736fe93a5ac3e012224fa9f4f011e..c91a712cce0df65db2e4dc4481588876676cb5a0 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -60,7 +60,7 @@ use polkadot_runtime_parachains::{
 	scheduler as parachains_scheduler, session_info as parachains_session_info,
 	shared as parachains_shared,
 };
-use rococo_runtime_constants::system_parachain::BROKER_ID;
+use rococo_runtime_constants::system_parachain::{coretime::TIMESLICE_PERIOD, BROKER_ID};
 use scale_info::TypeInfo;
 use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
 use sp_consensus_beefy::{
@@ -92,12 +92,13 @@ use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId};
 use pallet_identity::legacy::IdentityInfo;
 use pallet_session::historical as session_historical;
 use pallet_transaction_payment::{FeeDetails, FungibleAdapter, RuntimeDispatchInfo};
-use sp_core::{ConstU128, ConstU8, OpaqueMetadata, H256};
+use sp_core::{ConstU128, ConstU8, Get, OpaqueMetadata, H256};
 use sp_runtime::{
 	create_runtime_str, generic, impl_opaque_keys,
 	traits::{
-		BlakeTwo256, Block as BlockT, ConstU32, ConvertInto, Extrinsic as ExtrinsicT,
-		IdentityLookup, Keccak256, OpaqueKeys, SaturatedConversion, Verify,
+		AccountIdConversion, BlakeTwo256, Block as BlockT, ConstU32, ConvertInto,
+		Extrinsic as ExtrinsicT, IdentityLookup, Keccak256, OpaqueKeys, SaturatedConversion,
+		Verify,
 	},
 	transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
 	ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill, Percent, Permill, RuntimeDebug,
@@ -1057,21 +1058,39 @@ impl parachains_scheduler::Config for Runtime {
 
 parameter_types! {
 	pub const BrokerId: u32 = BROKER_ID;
+	pub const BrokerPalletId: PalletId = PalletId(*b"py/broke");
 	pub MaxXcmTransactWeight: Weight = Weight::from_parts(200_000_000, 20_000);
 }
 
+pub struct BrokerPot;
+impl Get<InteriorLocation> for BrokerPot {
+	fn get() -> InteriorLocation {
+		Junction::AccountId32 { network: None, id: BrokerPalletId::get().into_account_truncating() }
+			.into()
+	}
+}
+
 impl coretime::Config for Runtime {
 	type RuntimeOrigin = RuntimeOrigin;
 	type RuntimeEvent = RuntimeEvent;
 	type Currency = Balances;
 	type BrokerId = BrokerId;
+	type BrokerPotLocation = BrokerPot;
 	type WeightInfo = weights::runtime_parachains_coretime::WeightInfo<Runtime>;
 	type SendXcm = crate::xcm_config::XcmRouter;
+	type AssetTransactor = crate::xcm_config::LocalAssetTransactor;
+	type AccountToLocation = xcm_builder::AliasesIntoAccountId32<
+		xcm_config::ThisNetwork,
+		<Runtime as frame_system::Config>::AccountId,
+	>;
 	type MaxXcmTransactWeight = MaxXcmTransactWeight;
 }
 
 parameter_types! {
 	pub const OnDemandTrafficDefaultValue: FixedU128 = FixedU128::from_u32(1);
+	// Keep 2 timeslices worth of revenue information.
+	pub const MaxHistoricalRevenue: BlockNumber = 2 * TIMESLICE_PERIOD;
+	pub const OnDemandPalletId: PalletId = PalletId(*b"py/ondmd");
 }
 
 impl parachains_assigner_on_demand::Config for Runtime {
@@ -1079,6 +1098,8 @@ impl parachains_assigner_on_demand::Config for Runtime {
 	type Currency = Balances;
 	type TrafficDefaultValue = OnDemandTrafficDefaultValue;
 	type WeightInfo = weights::runtime_parachains_assigner_on_demand::WeightInfo<Runtime>;
+	type MaxHistoricalRevenue = MaxHistoricalRevenue;
+	type PalletId = OnDemandPalletId;
 }
 
 impl parachains_assigner_coretime::Config for Runtime {}
@@ -1696,13 +1717,13 @@ mod benches {
 		// the that path resolves correctly in the generated file.
 		[polkadot_runtime_common::assigned_slots, AssignedSlots]
 		[polkadot_runtime_common::auctions, Auctions]
-		[polkadot_runtime_common::coretime, Coretime]
 		[polkadot_runtime_common::crowdloan, Crowdloan]
 		[polkadot_runtime_common::claims, Claims]
 		[polkadot_runtime_common::identity_migrator, IdentityMigrator]
 		[polkadot_runtime_common::slots, Slots]
 		[polkadot_runtime_common::paras_registrar, Registrar]
 		[polkadot_runtime_parachains::configuration, Configuration]
+		[polkadot_runtime_parachains::coretime, Coretime]
 		[polkadot_runtime_parachains::hrmp, Hrmp]
 		[polkadot_runtime_parachains::disputes, ParasDisputes]
 		[polkadot_runtime_parachains::inclusion, ParaInclusion]
diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs
index 9f275e7b8cdc24fdcb251ef95beca3eb2b81be25..abcc1893c29b1273bdde09a3f38f12c174bc84cc 100644
--- a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs
+++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs
@@ -17,9 +17,9 @@
 //! Autogenerated weights for `runtime_parachains::assigner_on_demand`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-1pho9goo-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024
 
 // Executed Command:
@@ -50,6 +50,10 @@ pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> polkadot_runtime_parachains::assigner_on_demand::WeightInfo for WeightInfo<T> {
 	/// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1)
 	/// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `System::Account` (r:1 w:0)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	/// Storage: `OnDemandAssignmentProvider::Revenue` (r:1 w:1)
+	/// Proof: `OnDemandAssignmentProvider::Revenue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0)
 	/// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1)
@@ -57,19 +61,23 @@ impl<T: frame_system::Config> polkadot_runtime_parachains::assigner_on_demand::W
 	/// The range of component `s` is `[1, 9999]`.
 	fn place_order_keep_alive(s: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `218 + s * (8 ±0)`
-		//  Estimated: `3681 + s * (8 ±0)`
-		// Minimum execution time: 21_053_000 picoseconds.
-		Weight::from_parts(17_291_897, 0)
-			.saturating_add(Weight::from_parts(0, 3681))
-			// Standard Error: 104
-			.saturating_add(Weight::from_parts(18_779, 0).saturating_mul(s.into()))
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `270 + s * (8 ±0)`
+		//  Estimated: `3733 + s * (8 ±0)`
+		// Minimum execution time: 28_422_000 picoseconds.
+		Weight::from_parts(28_146_882, 0)
+			.saturating_add(Weight::from_parts(0, 3733))
+			// Standard Error: 140
+			.saturating_add(Weight::from_parts(21_283, 0).saturating_mul(s.into()))
+			.saturating_add(T::DbWeight::get().reads(5))
+			.saturating_add(T::DbWeight::get().writes(3))
 			.saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into()))
 	}
 	/// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1)
 	/// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `System::Account` (r:1 w:0)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	/// Storage: `OnDemandAssignmentProvider::Revenue` (r:1 w:1)
+	/// Proof: `OnDemandAssignmentProvider::Revenue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0)
 	/// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1)
@@ -77,15 +85,15 @@ impl<T: frame_system::Config> polkadot_runtime_parachains::assigner_on_demand::W
 	/// The range of component `s` is `[1, 9999]`.
 	fn place_order_allow_death(s: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `218 + s * (8 ±0)`
-		//  Estimated: `3681 + s * (8 ±0)`
-		// Minimum execution time: 20_843_000 picoseconds.
-		Weight::from_parts(16_881_986, 0)
-			.saturating_add(Weight::from_parts(0, 3681))
-			// Standard Error: 104
-			.saturating_add(Weight::from_parts(18_788, 0).saturating_mul(s.into()))
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `270 + s * (8 ±0)`
+		//  Estimated: `3733 + s * (8 ±0)`
+		// Minimum execution time: 28_680_000 picoseconds.
+		Weight::from_parts(31_024_579, 0)
+			.saturating_add(Weight::from_parts(0, 3733))
+			// Standard Error: 119
+			.saturating_add(Weight::from_parts(20_989, 0).saturating_mul(s.into()))
+			.saturating_add(T::DbWeight::get().reads(5))
+			.saturating_add(T::DbWeight::get().writes(3))
 			.saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into()))
 	}
 }
diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_coretime.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_coretime.rs
index 0ad32996c49595db1a414e4d0c0fc5961ea2d3e7..b2329c098cead5d2780b6ac44a1d6b5963efcaf8 100644
--- a/polkadot/runtime/rococo/src/weights/runtime_parachains_coretime.rs
+++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_coretime.rs
@@ -14,12 +14,12 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
-//! Autogenerated weights for `runtime_parachains::coretime`
+//! Autogenerated weights for `runtime_common::coretime`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-12-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-r43aesjn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-1pho9goo-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024
 
 // Executed Command:
@@ -45,28 +45,61 @@
 use frame_support::{traits::Get, weights::Weight};
 use core::marker::PhantomData;
 
-use polkadot_runtime_parachains::configuration::{self, WeightInfo as ConfigWeightInfo};
-
 /// Weight functions for `runtime_common::coretime`.
 pub struct WeightInfo<T>(PhantomData<T>);
-impl<T: frame_system::Config + configuration::Config> polkadot_runtime_parachains::coretime::WeightInfo for WeightInfo<T> {
+impl<T: frame_system::Config> polkadot_runtime_parachains::coretime::WeightInfo for WeightInfo<T> {
+	/// Storage: `OnDemandAssignmentProvider::Revenue` (r:1 w:1)
+	/// Proof: `OnDemandAssignmentProvider::Revenue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `System::Account` (r:1 w:0)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0)
+	/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `XcmPallet::SupportedVersion` (r:1 w:0)
+	/// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
+	/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1)
+	/// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	fn request_revenue_at() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2963`
+		//  Estimated: `6428`
+		// Minimum execution time: 36_613_000 picoseconds.
+		Weight::from_parts(37_637_000, 0)
+			.saturating_add(Weight::from_parts(0, 6428))
+			.saturating_add(T::DbWeight::get().reads(6))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
+	/// Storage: `Configuration::PendingConfigs` (r:1 w:1)
+	/// Proof: `Configuration::PendingConfigs` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `Configuration::BypassConsistencyCheck` (r:1 w:0)
+	/// Proof: `Configuration::BypassConsistencyCheck` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
+	/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn request_core_count() -> Weight {
-		<T as configuration::Config>::WeightInfo::set_config_with_u32()
+		// Proof Size summary in bytes:
+		//  Measured:  `151`
+		//  Estimated: `1636`
+		// Minimum execution time: 7_527_000 picoseconds.
+		Weight::from_parts(7_784_000, 0)
+			.saturating_add(Weight::from_parts(0, 1636))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	/// Storage: `CoreTimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
-	/// Proof: `CoreTimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `CoreTimeAssignmentProvider::CoreSchedules` (r:0 w:1)
-	/// Proof: `CoreTimeAssignmentProvider::CoreSchedules` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
+	/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `CoretimeAssignmentProvider::CoreSchedules` (r:0 w:1)
+	/// Proof: `CoretimeAssignmentProvider::CoreSchedules` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// The range of component `s` is `[1, 100]`.
 	fn assign_core(s: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `76`
-		//  Estimated: `3541`
-		// Minimum execution time: 6_275_000 picoseconds.
-		Weight::from_parts(6_883_543, 0)
-			.saturating_add(Weight::from_parts(0, 3541))
-			// Standard Error: 202
-			.saturating_add(Weight::from_parts(15_028, 0).saturating_mul(s.into()))
+		//  Measured:  `180`
+		//  Estimated: `3645`
+		// Minimum execution time: 9_220_000 picoseconds.
+		Weight::from_parts(9_905_773, 0)
+			.saturating_add(Weight::from_parts(0, 3645))
+			// Standard Error: 257
+			.saturating_add(Weight::from_parts(12_400, 0).saturating_mul(s.into()))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
diff --git a/polkadot/runtime/westend/constants/Cargo.toml b/polkadot/runtime/westend/constants/Cargo.toml
index b40846455bf55f234ee9bae2a9385f0e3ca9a74f..f9b99ea5284d3322b6e0bf100f8314000a4b5bce 100644
--- a/polkadot/runtime/westend/constants/Cargo.toml
+++ b/polkadot/runtime/westend/constants/Cargo.toml
@@ -34,3 +34,6 @@ std = [
 	"xcm-builder/std",
 	"xcm/std",
 ]
+
+# Set timing constants (e.g. session period) to faster versions to speed up testing.
+fast-runtime = []
diff --git a/polkadot/runtime/westend/constants/src/lib.rs b/polkadot/runtime/westend/constants/src/lib.rs
index 58048272e791a06b9169bf2ccf59a5e8d005c2d6..8d66ac2868d0b7a53011b8624c41161860b2cd42 100644
--- a/polkadot/runtime/westend/constants/src/lib.rs
+++ b/polkadot/runtime/westend/constants/src/lib.rs
@@ -116,6 +116,17 @@ pub mod system_parachain {
 
 	/// All system parachains of Westend.
 	pub type SystemParachains = IsChildSystemParachain<Id>;
+
+	/// Coretime constants
+	pub mod coretime {
+		/// Coretime timeslice period in blocks
+		/// WARNING: This constant is used accross chains, so additional care should be taken
+		/// when changing it.
+		#[cfg(feature = "fast-runtime")]
+		pub const TIMESLICE_PERIOD: u32 = 20;
+		#[cfg(not(feature = "fast-runtime"))]
+		pub const TIMESLICE_PERIOD: u32 = 80;
+	}
 }
 
 /// Westend Treasury pallet instance.
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index 59789ed16cbb47707bb4f0867f40c782e48b2bcd..5b50a078539effcdaf11c3c2836f887a86a124a0 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -88,8 +88,8 @@ use sp_runtime::{
 	curve::PiecewiseLinear,
 	generic, impl_opaque_keys,
 	traits::{
-		BlakeTwo256, Block as BlockT, ConvertInto, Extrinsic as ExtrinsicT, IdentityLookup,
-		Keccak256, OpaqueKeys, SaturatedConversion, Verify,
+		AccountIdConversion, BlakeTwo256, Block as BlockT, ConvertInto, Extrinsic as ExtrinsicT,
+		IdentityLookup, Keccak256, OpaqueKeys, SaturatedConversion, Verify,
 	},
 	transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
 	ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill, Percent, Permill,
@@ -122,7 +122,12 @@ use sp_runtime::traits::Get;
 pub use sp_runtime::BuildStorage;
 
 /// Constant values used within the runtime.
-use westend_runtime_constants::{currency::*, fee::*, system_parachain::BROKER_ID, time::*};
+use westend_runtime_constants::{
+	currency::*,
+	fee::*,
+	system_parachain::{coretime::TIMESLICE_PERIOD, BROKER_ID},
+	time::*,
+};
 
 mod bag_thresholds;
 mod weights;
@@ -1185,21 +1190,39 @@ impl parachains_scheduler::Config for Runtime {
 
 parameter_types! {
 	pub const BrokerId: u32 = BROKER_ID;
+	pub const BrokerPalletId: PalletId = PalletId(*b"py/broke");
 	pub MaxXcmTransactWeight: Weight = Weight::from_parts(200_000_000, 20_000);
 }
 
+pub struct BrokerPot;
+impl Get<InteriorLocation> for BrokerPot {
+	fn get() -> InteriorLocation {
+		Junction::AccountId32 { network: None, id: BrokerPalletId::get().into_account_truncating() }
+			.into()
+	}
+}
+
 impl coretime::Config for Runtime {
 	type RuntimeOrigin = RuntimeOrigin;
 	type RuntimeEvent = RuntimeEvent;
 	type Currency = Balances;
 	type BrokerId = BrokerId;
+	type BrokerPotLocation = BrokerPot;
 	type WeightInfo = weights::runtime_parachains_coretime::WeightInfo<Runtime>;
 	type SendXcm = crate::xcm_config::XcmRouter;
+	type AssetTransactor = crate::xcm_config::LocalAssetTransactor;
+	type AccountToLocation = xcm_builder::AliasesIntoAccountId32<
+		xcm_config::ThisNetwork,
+		<Runtime as frame_system::Config>::AccountId,
+	>;
 	type MaxXcmTransactWeight = MaxXcmTransactWeight;
 }
 
 parameter_types! {
 	pub const OnDemandTrafficDefaultValue: FixedU128 = FixedU128::from_u32(1);
+	// Keep 2 timeslices worth of revenue information.
+	pub const MaxHistoricalRevenue: BlockNumber = 2 * TIMESLICE_PERIOD;
+	pub const OnDemandPalletId: PalletId = PalletId(*b"py/ondmd");
 }
 
 impl parachains_assigner_on_demand::Config for Runtime {
@@ -1207,6 +1230,8 @@ impl parachains_assigner_on_demand::Config for Runtime {
 	type Currency = Balances;
 	type TrafficDefaultValue = OnDemandTrafficDefaultValue;
 	type WeightInfo = weights::runtime_parachains_assigner_on_demand::WeightInfo<Runtime>;
+	type MaxHistoricalRevenue = MaxHistoricalRevenue;
+	type PalletId = OnDemandPalletId;
 }
 
 impl parachains_assigner_coretime::Config for Runtime {}
diff --git a/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs b/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs
index 8b046f5d34ad7d3f0800b6d48f2cbb83cd5ab010..1bd9fa31b81b29fc581475991115a86c7e4ecf5d 100644
--- a/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs
+++ b/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs
@@ -17,9 +17,9 @@
 //! Autogenerated weights for `runtime_parachains::assigner_on_demand`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-1pho9goo-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024
 
 // Executed Command:
@@ -50,6 +50,10 @@ pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> polkadot_runtime_parachains::assigner_on_demand::WeightInfo for WeightInfo<T> {
 	/// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1)
 	/// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `System::Account` (r:1 w:0)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	/// Storage: `OnDemandAssignmentProvider::Revenue` (r:1 w:1)
+	/// Proof: `OnDemandAssignmentProvider::Revenue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0)
 	/// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1)
@@ -57,19 +61,23 @@ impl<T: frame_system::Config> polkadot_runtime_parachains::assigner_on_demand::W
 	/// The range of component `s` is `[1, 9999]`.
 	fn place_order_keep_alive(s: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `218 + s * (8 ±0)`
-		//  Estimated: `3681 + s * (8 ±0)`
-		// Minimum execution time: 21_396_000 picoseconds.
-		Weight::from_parts(20_585_695, 0)
-			.saturating_add(Weight::from_parts(0, 3681))
-			// Standard Error: 127
-			.saturating_add(Weight::from_parts(20_951, 0).saturating_mul(s.into()))
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `270 + s * (8 ±0)`
+		//  Estimated: `3733 + s * (8 ±0)`
+		// Minimum execution time: 29_427_000 picoseconds.
+		Weight::from_parts(26_756_913, 0)
+			.saturating_add(Weight::from_parts(0, 3733))
+			// Standard Error: 121
+			.saturating_add(Weight::from_parts(20_849, 0).saturating_mul(s.into()))
+			.saturating_add(T::DbWeight::get().reads(5))
+			.saturating_add(T::DbWeight::get().writes(3))
 			.saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into()))
 	}
 	/// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1)
 	/// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `System::Account` (r:1 w:0)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	/// Storage: `OnDemandAssignmentProvider::Revenue` (r:1 w:1)
+	/// Proof: `OnDemandAssignmentProvider::Revenue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0)
 	/// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1)
@@ -77,15 +85,15 @@ impl<T: frame_system::Config> polkadot_runtime_parachains::assigner_on_demand::W
 	/// The range of component `s` is `[1, 9999]`.
 	fn place_order_allow_death(s: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `218 + s * (8 ±0)`
-		//  Estimated: `3681 + s * (8 ±0)`
-		// Minimum execution time: 21_412_000 picoseconds.
-		Weight::from_parts(19_731_554, 0)
-			.saturating_add(Weight::from_parts(0, 3681))
-			// Standard Error: 128
-			.saturating_add(Weight::from_parts(21_055, 0).saturating_mul(s.into()))
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `270 + s * (8 ±0)`
+		//  Estimated: `3733 + s * (8 ±0)`
+		// Minimum execution time: 29_329_000 picoseconds.
+		Weight::from_parts(26_415_340, 0)
+			.saturating_add(Weight::from_parts(0, 3733))
+			// Standard Error: 129
+			.saturating_add(Weight::from_parts(20_909, 0).saturating_mul(s.into()))
+			.saturating_add(T::DbWeight::get().reads(5))
+			.saturating_add(T::DbWeight::get().writes(3))
 			.saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into()))
 	}
 }
diff --git a/polkadot/runtime/westend/src/weights/runtime_parachains_coretime.rs b/polkadot/runtime/westend/src/weights/runtime_parachains_coretime.rs
index 443651a6fda44380d89b02c53dc70338bdc7f4ee..9df382875f5f12ddee62751eeca5feb16dfece41 100644
--- a/polkadot/runtime/westend/src/weights/runtime_parachains_coretime.rs
+++ b/polkadot/runtime/westend/src/weights/runtime_parachains_coretime.rs
@@ -17,9 +17,9 @@
 //! Autogenerated weights for `runtime_parachains::coretime`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-02-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-06-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-1pho9goo-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024
 
 // Executed Command:
@@ -48,6 +48,28 @@ use core::marker::PhantomData;
 /// Weight functions for `runtime_parachains::coretime`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> polkadot_runtime_parachains::coretime::WeightInfo for WeightInfo<T> {
+	/// Storage: `OnDemandAssignmentProvider::Revenue` (r:1 w:1)
+	/// Proof: `OnDemandAssignmentProvider::Revenue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+	/// Storage: `System::Account` (r:1 w:0)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0)
+	/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `XcmPallet::SupportedVersion` (r:1 w:0)
+	/// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
+	/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	/// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1)
+	/// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	fn request_revenue_at() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2930`
+		//  Estimated: `6395`
+		// Minimum execution time: 34_947_000 picoseconds.
+		Weight::from_parts(35_550_000, 0)
+			.saturating_add(Weight::from_parts(0, 6395))
+			.saturating_add(T::DbWeight::get().reads(6))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
 	/// Storage: `Configuration::PendingConfigs` (r:1 w:1)
 	/// Proof: `Configuration::PendingConfigs` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `Configuration::BypassConsistencyCheck` (r:1 w:0)
@@ -58,8 +80,8 @@ impl<T: frame_system::Config> polkadot_runtime_parachains::coretime::WeightInfo
 		// Proof Size summary in bytes:
 		//  Measured:  `151`
 		//  Estimated: `1636`
-		// Minimum execution time: 7_486_000 picoseconds.
-		Weight::from_parts(7_889_000, 0)
+		// Minimum execution time: 7_519_000 picoseconds.
+		Weight::from_parts(7_803_000, 0)
 			.saturating_add(Weight::from_parts(0, 1636))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -73,11 +95,11 @@ impl<T: frame_system::Config> polkadot_runtime_parachains::coretime::WeightInfo
 		// Proof Size summary in bytes:
 		//  Measured:  `147`
 		//  Estimated: `3612`
-		// Minimum execution time: 9_409_000 picoseconds.
-		Weight::from_parts(10_177_115, 0)
+		// Minimum execution time: 9_697_000 picoseconds.
+		Weight::from_parts(10_610_219, 0)
 			.saturating_add(Weight::from_parts(0, 3612))
-			// Standard Error: 259
-			.saturating_add(Weight::from_parts(13_932, 0).saturating_mul(s.into()))
+			// Standard Error: 732
+			.saturating_add(Weight::from_parts(10_364, 0).saturating_mul(s.into()))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
diff --git a/prdoc/pr_3940.prdoc b/prdoc/pr_3940.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..590afa77bb1ed8ec41958d87279e7be969f55ade
--- /dev/null
+++ b/prdoc/pr_3940.prdoc
@@ -0,0 +1,31 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: "RFC-5: Add request revenue info"
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Partially implemented RFC-5 in terms of revenue requests and notifications
+  - audience: Runtime User
+    description: |
+      Instantaneous Coretime sold on the relay chain now generates revenue for its provider.
+      The revenue may be claimed by its provider on the Coretime chain.
+
+crates:
+  - name: polkadot-runtime-parachains
+    bump: minor
+  - name: rococo-runtime
+    bump: minor
+  - name: westend-runtime
+    bump: minor
+  - name: pallet-broker
+    bump: minor
+  - name: rococo-runtime-constants
+    bump: minor
+  - name: westend-runtime-constants
+    bump: minor
+  - name: coretime-rococo-runtime
+    bump: minor
+  - name: coretime-westend-runtime
+    bump: minor
diff --git a/substrate/bin/node/cli/tests/res/default_genesis_config.json b/substrate/bin/node/cli/tests/res/default_genesis_config.json
index d8713764ab21d516851fddff04734f37e03c9bfe..bba2076f40097d7cb5380e7d9d8075fd0fae9223 100644
--- a/substrate/bin/node/cli/tests/res/default_genesis_config.json
+++ b/substrate/bin/node/cli/tests/res/default_genesis_config.json
@@ -16,6 +16,7 @@
   "balances": {
     "balances": []
   },
+  "broker": {},
   "transactionPayment": {
     "multiplier": "1000000000000000000"
   },
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index a3dc7decd1076f47f0d95609a95aab4ea1c6ee2c..839e157ae76453fc69df35f90c494c97a97a6d2f 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -2097,10 +2097,6 @@ impl OnUnbalanced<Credit<AccountId, Balances>> for IntoAuthor {
 	}
 }
 
-parameter_types! {
-	pub storage CoretimeRevenue: Option<(BlockNumber, Balance)> = None;
-}
-
 pub struct CoretimeProvider;
 impl CoretimeInterface for CoretimeProvider {
 	type AccountId = AccountId;
@@ -2116,15 +2112,6 @@ impl CoretimeInterface for CoretimeProvider {
 		_end_hint: Option<u32>,
 	) {
 	}
-	fn check_notify_revenue_info() -> Option<(u32, Self::Balance)> {
-		let revenue = CoretimeRevenue::get();
-		CoretimeRevenue::set(&None);
-		revenue
-	}
-	#[cfg(feature = "runtime-benchmarks")]
-	fn ensure_notify_revenue_info(when: u32, revenue: Self::Balance) {
-		CoretimeRevenue::set(&Some((when, revenue)));
-	}
 }
 
 impl pallet_broker::Config for Runtime {
diff --git a/substrate/frame/broker/src/benchmarking.rs b/substrate/frame/broker/src/benchmarking.rs
index 9cb5ad096c83b74e50a77993c2c3e0049ec2c876..3c9ea4cdba4e74da1df2fe343bc8412da2fe5466 100644
--- a/substrate/frame/broker/src/benchmarking.rs
+++ b/substrate/frame/broker/src/benchmarking.rs
@@ -99,7 +99,7 @@ fn setup_and_start_sale<T: Config>() -> Result<u16, BenchmarkError> {
 	// Assume Leases to be filled for worst case
 	setup_leases::<T>(T::MaxLeasedCores::get(), 1, 10);
 
-	Broker::<T>::do_start_sales(10u32.into(), MAX_CORE_COUNT.into())
+	Broker::<T>::do_start_sales(10_000_000u32.into(), MAX_CORE_COUNT.into())
 		.map_err(|_| BenchmarkError::Weightless)?;
 
 	Ok(T::MaxReservedCores::get()
@@ -201,7 +201,7 @@ mod benches {
 
 		let latest_region_begin = Broker::<T>::latest_timeslice_ready_to_commit(&config);
 
-		let initial_price = 10u32.into();
+		let initial_price = 10_000_000u32.into();
 
 		let origin =
 			T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
@@ -214,8 +214,8 @@ mod benches {
 			Event::SaleInitialized {
 				sale_start: 2u32.into(),
 				leadin_length: 1u32.into(),
-				start_price: 1000u32.into(),
-				end_price: 10u32.into(),
+				start_price: 1_000_000_000u32.into(),
+				end_price: 10_000_000u32.into(),
 				region_begin: latest_region_begin + config.region_length,
 				region_end: latest_region_begin + config.region_length * 2,
 				ideal_cores_sold: 0,
@@ -240,13 +240,13 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
 		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), 10u32.into());
+		_(RawOrigin::Signed(caller.clone()), 10_000_000u32.into());
 
-		assert_eq!(SaleInfo::<T>::get().unwrap().sellout_price, Some(10u32.into()));
+		assert_eq!(SaleInfo::<T>::get().unwrap().sellout_price, Some(10_000_000u32.into()));
 		assert_last_event::<T>(
 			Event::Purchased {
 				who: caller,
@@ -255,7 +255,7 @@ mod benches {
 					core,
 					mask: CoreMask::complete(),
 				},
-				price: 10u32.into(),
+				price: 10_000_000u32.into(),
 				duration: 3u32.into(),
 			}
 			.into(),
@@ -274,10 +274,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(20u32.into()),
+			T::Currency::minimum_balance().saturating_add(20_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		Broker::<T>::do_assign(region, None, 1001, Final)
@@ -303,10 +303,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		let recipient: T::AccountId = account("recipient", 0, SEED);
@@ -336,10 +336,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		#[extrinsic_call]
@@ -368,10 +368,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		#[extrinsic_call]
@@ -404,10 +404,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		#[extrinsic_call]
@@ -439,10 +439,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		let recipient: T::AccountId = account("recipient", 0, SEED);
@@ -475,14 +475,14 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 		T::Currency::set_balance(
 			&Broker::<T>::account_id(),
-			T::Currency::minimum_balance().saturating_add(200u32.into()),
+			T::Currency::minimum_balance().saturating_add(200_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		let recipient: T::AccountId = account("recipient", 0, SEED);
@@ -491,7 +491,7 @@ mod benches {
 		Broker::<T>::do_pool(region, None, recipient.clone(), Final)
 			.map_err(|_| BenchmarkError::Weightless)?;
 
-		let revenue = 10u32.into();
+		let revenue = 10_000_000u32.into();
 		InstaPoolHistory::<T>::insert(
 			region.begin,
 			InstaPoolHistoryRecord {
@@ -508,7 +508,7 @@ mod benches {
 		assert_last_event::<T>(
 			Event::RevenueClaimPaid {
 				who: recipient,
-				amount: 200u32.into(),
+				amount: 200_000_000u32.into(),
 				next: if m < new_config_record::<T>().region_length {
 					Some(RegionId {
 						begin: region.begin.saturating_add(m),
@@ -534,11 +534,11 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(30u32.into()),
+			T::Currency::minimum_balance().saturating_add(30_000_000u32.into()),
 		);
 		T::Currency::set_balance(&Broker::<T>::account_id(), T::Currency::minimum_balance());
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		let recipient: T::AccountId = account("recipient", 0, SEED);
@@ -549,10 +549,11 @@ mod benches {
 		let beneficiary: RelayAccountIdOf<T> = account("beneficiary", 0, SEED);
 
 		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), 20u32.into(), beneficiary.clone());
+		_(RawOrigin::Signed(caller.clone()), 20_000_000u32.into(), beneficiary.clone());
 
 		assert_last_event::<T>(
-			Event::CreditPurchased { who: caller, beneficiary, amount: 20u32.into() }.into(),
+			Event::CreditPurchased { who: caller, beneficiary, amount: 20_000_000u32.into() }
+				.into(),
 		);
 
 		Ok(())
@@ -568,10 +569,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		advance_to::<T>(
@@ -602,10 +603,10 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(10u32.into()),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
 		);
 
-		let region = Broker::<T>::do_purchase(caller.clone(), 10u32.into())
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
 			.map_err(|_| BenchmarkError::Weightless)?;
 
 		let recipient: T::AccountId = account("recipient", 0, SEED);
@@ -634,7 +635,7 @@ mod benches {
 	fn drop_history() -> Result<(), BenchmarkError> {
 		setup_and_start_sale::<T>()?;
 		let when = 5u32.into();
-		let revenue = 10u32.into();
+		let revenue = 10_000_000u32.into();
 		let region_len = Configuration::<T>::get().unwrap().region_length;
 
 		advance_to::<T>(
@@ -672,7 +673,7 @@ mod benches {
 
 		let id = PotentialRenewalId { core, when };
 		let record = PotentialRenewalRecord {
-			price: 1u32.into(),
+			price: 1_000_000u32.into(),
 			completion: CompletionStatus::Complete(new_schedule()),
 		};
 		PotentialRenewals::<T>::insert(id, record);
@@ -732,23 +733,27 @@ mod benches {
 		let caller: T::AccountId = whitelisted_caller();
 		T::Currency::set_balance(
 			&caller.clone(),
-			T::Currency::minimum_balance().saturating_add(30u32.into()),
+			T::Currency::minimum_balance().saturating_add(30_000_000u32.into()),
+		);
+		T::Currency::set_balance(
+			&Broker::<T>::account_id(),
+			T::Currency::minimum_balance().saturating_add(90_000_000u32.into()),
 		);
-		T::Currency::set_balance(&Broker::<T>::account_id(), T::Currency::minimum_balance());
 
 		let timeslice_period: u32 = T::TimeslicePeriod::get().try_into().ok().unwrap();
 		let multiplicator = 5;
-		<T::Coretime as CoretimeInterface>::ensure_notify_revenue_info(
-			(timeslice_period * multiplicator).into(),
-			10u32.into(),
-		);
+
+		RevenueInbox::<T>::put(OnDemandRevenueRecord {
+			until: (timeslice_period * multiplicator).into(),
+			amount: 10_000_000u32.into(),
+		});
 
 		let timeslice = multiplicator - 1;
 		InstaPoolHistory::<T>::insert(
 			timeslice,
 			InstaPoolHistoryRecord {
-				private_contributions: 1u32.into(),
-				system_contributions: 9u32.into(),
+				private_contributions: 4u32.into(),
+				system_contributions: 6u32.into(),
 				maybe_payout: None,
 			},
 		);
@@ -761,8 +766,8 @@ mod benches {
 		assert_last_event::<T>(
 			Event::ClaimsReady {
 				when: timeslice.into(),
-				system_payout: 9u32.into(),
-				private_payout: 1u32.into(),
+				system_payout: 6_000_000u32.into(),
+				private_payout: 4_000_000u32.into(),
 			}
 			.into(),
 		);
@@ -776,7 +781,7 @@ mod benches {
 		let config = new_config_record::<T>();
 
 		let now = frame_system::Pallet::<T>::block_number();
-		let end_price = 10u32.into();
+		let end_price = 10_000_000u32.into();
 		let commit_timeslice = Broker::<T>::latest_timeslice_ready_to_commit(&config);
 		let sale = SaleInfoRecordOf::<T> {
 			sale_start: now,
@@ -815,8 +820,8 @@ mod benches {
 			Event::SaleInitialized {
 				sale_start: 2u32.into(),
 				leadin_length: 1u32.into(),
-				start_price: 1000u32.into(),
-				end_price: 10u32.into(),
+				start_price: 1_000_000_000u32.into(),
+				end_price: 10_000_000u32.into(),
 				region_begin: sale.region_begin + config.region_length,
 				region_end: sale.region_end + config.region_length,
 				ideal_cores_sold: 0,
@@ -889,6 +894,7 @@ mod benches {
 			T::Coretime::request_revenue_info_at(rc_block);
 		}
 	}
+
 	#[benchmark]
 	fn notify_core_count() -> Result<(), BenchmarkError> {
 		let admin_origin =
@@ -901,6 +907,21 @@ mod benches {
 		Ok(())
 	}
 
+	#[benchmark]
+	fn notify_revenue() -> Result<(), BenchmarkError> {
+		let admin_origin =
+			T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+
+		#[extrinsic_call]
+		_(
+			admin_origin as T::RuntimeOrigin,
+			OnDemandRevenueRecord { until: 100u32.into(), amount: 100_000_000u32.into() },
+		);
+
+		assert!(RevenueInbox::<T>::take().is_some());
+		Ok(())
+	}
+
 	#[benchmark]
 	fn do_tick_base() -> Result<(), BenchmarkError> {
 		setup_and_start_sale::<T>()?;
@@ -939,6 +960,31 @@ mod benches {
 		Ok(())
 	}
 
+	#[benchmark]
+	fn on_new_timeslice() -> Result<(), BenchmarkError> {
+		setup_and_start_sale::<T>()?;
+
+		advance_to::<T>(2);
+
+		let caller: T::AccountId = whitelisted_caller();
+		T::Currency::set_balance(
+			&caller.clone(),
+			T::Currency::minimum_balance().saturating_add(u32::MAX.into()),
+		);
+
+		let _region = Broker::<T>::do_purchase(caller.clone(), (u32::MAX / 2).into())
+			.map_err(|_| BenchmarkError::Weightless)?;
+
+		let timeslice = Broker::<T>::current_timeslice();
+
+		#[block]
+		{
+			T::Coretime::on_new_timeslice(timeslice);
+		}
+
+		Ok(())
+	}
+
 	// Implements a test for each benchmark. Execute with:
 	// `cargo test -p pallet-broker --features runtime-benchmarks`.
 	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
diff --git a/substrate/frame/broker/src/coretime_interface.rs b/substrate/frame/broker/src/coretime_interface.rs
index 58efa7fa92bb0fa6c29a45375593f2246f5eaa8a..f92f8b22091ac992180fd3f44d93cffddd59061d 100644
--- a/substrate/frame/broker/src/coretime_interface.rs
+++ b/substrate/frame/broker/src/coretime_interface.rs
@@ -23,7 +23,9 @@ use scale_info::TypeInfo;
 use sp_arithmetic::traits::AtLeast32BitUnsigned;
 use sp_core::RuntimeDebug;
 use sp_runtime::traits::BlockNumberProvider;
-use sp_std::vec::Vec;
+use sp_std::{fmt::Debug, vec::Vec};
+
+use crate::Timeslice;
 
 /// Index of a Polkadot Core.
 pub type CoreIndex = u16;
@@ -62,7 +64,7 @@ pub trait CoretimeInterface {
 	type AccountId: Parameter;
 
 	/// A (Relay-chain-side) balance.
-	type Balance: AtLeast32BitUnsigned;
+	type Balance: AtLeast32BitUnsigned + Encode + Decode + MaxEncodedLen + TypeInfo + Debug;
 
 	/// A provider for the relay chain block number.
 	type RelayChainBlockNumberProvider: BlockNumberProvider;
@@ -107,22 +109,10 @@ pub trait CoretimeInterface {
 		end_hint: Option<RCBlockNumberOf<Self>>,
 	);
 
-	/// Provide the amount of revenue accumulated from Instantaneous Coretime Sales from Relay-chain
-	/// block number `last_until` to `until`, not including `until` itself. `last_until` is defined
-	/// as being the `until` argument of the last `notify_revenue` message sent, or zero for the
-	/// first call. If `revenue` is `None`, this indicates that the information is no longer
-	/// available.
-	///
-	/// This explicitly disregards the possibility of multiple parachains requesting and being
-	/// notified of revenue information. The Relay-chain must be configured to ensure that only a
-	/// single revenue information destination exists.
-	fn check_notify_revenue_info() -> Option<(RCBlockNumberOf<Self>, Self::Balance)>;
-
-	/// Ensure that revenue information is updated to the provided value.
-	///
-	/// This is only used for benchmarking.
-	#[cfg(feature = "runtime-benchmarks")]
-	fn ensure_notify_revenue_info(when: RCBlockNumberOf<Self>, revenue: Self::Balance);
+	/// A hook supposed to be called right after a new timeslice has begun. Likely to be used for
+	/// batching different matters happened during the timeslice that may benifit from batched
+	/// processing.
+	fn on_new_timeslice(_timeslice: Timeslice) {}
 }
 
 impl CoretimeInterface for () {
@@ -140,9 +130,4 @@ impl CoretimeInterface for () {
 		_end_hint: Option<RCBlockNumberOf<Self>>,
 	) {
 	}
-	fn check_notify_revenue_info() -> Option<(RCBlockNumberOf<Self>, Self::Balance)> {
-		None
-	}
-	#[cfg(feature = "runtime-benchmarks")]
-	fn ensure_notify_revenue_info(_when: RCBlockNumberOf<Self>, _revenue: Self::Balance) {}
 }
diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs
index 79c1a1f79796330a7377f06ef5f1a62045eb2848..9e7a56e52812e578d12c709a4dafb85dcc0d041a 100644
--- a/substrate/frame/broker/src/dispatchable_impls.rs
+++ b/substrate/frame/broker/src/dispatchable_impls.rs
@@ -16,6 +16,7 @@
 // limitations under the License.
 
 use super::*;
+use coretime_interface::CoretimeInterface;
 use frame_support::{
 	pallet_prelude::{DispatchResult, *},
 	traits::{fungible::Mutate, tokens::Preservation::Expendable, DefensiveResult},
@@ -458,6 +459,11 @@ impl<T: Config> Pallet<T> {
 		Ok(())
 	}
 
+	pub(crate) fn do_notify_revenue(revenue: OnDemandRevenueRecordOf<T>) -> DispatchResult {
+		RevenueInbox::<T>::put(revenue);
+		Ok(())
+	}
+
 	pub(crate) fn do_swap_leases(id: TaskId, other: TaskId) -> DispatchResult {
 		let mut id_leases_count = 0;
 		let mut other_leases_count = 0;
@@ -472,7 +478,6 @@ impl<T: Config> Pallet<T> {
 				}
 			})
 		});
-
 		Ok(())
 	}
 
diff --git a/substrate/frame/broker/src/lib.rs b/substrate/frame/broker/src/lib.rs
index 0774c02e1cf10e7360c89dfc6c1dc11f28b563ac..4cb380bae91d87e1ec32a96d88cfaa1b5fcd97a4 100644
--- a/substrate/frame/broker/src/lib.rs
+++ b/substrate/frame/broker/src/lib.rs
@@ -57,7 +57,7 @@ pub mod pallet {
 		pallet_prelude::{DispatchResult, DispatchResultWithPostInfo, *},
 		traits::{
 			fungible::{Balanced, Credit, Mutate},
-			EnsureOrigin, OnUnbalanced,
+			BuildGenesisConfig, EnsureOrigin, OnUnbalanced,
 		},
 		PalletId,
 	};
@@ -65,7 +65,7 @@ pub mod pallet {
 	use sp_runtime::traits::{Convert, ConvertBack};
 	use sp_std::vec::Vec;
 
-	const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(3);
 
 	#[pallet::pallet]
 	#[pallet::storage_version(STORAGE_VERSION)]
@@ -174,6 +174,10 @@ pub mod pallet {
 	#[pallet::storage]
 	pub type CoreCountInbox<T> = StorageValue<_, CoreIndex, OptionQuery>;
 
+	/// Received revenue info from the relay chain.
+	#[pallet::storage]
+	pub type RevenueInbox<T> = StorageValue<_, OnDemandRevenueRecordOf<T>, OptionQuery>;
+
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
@@ -488,6 +492,20 @@ pub mod pallet {
 		NoClaimTimeslices,
 	}
 
+	#[derive(frame_support::DefaultNoBound)]
+	#[pallet::genesis_config]
+	pub struct GenesisConfig<T: Config> {
+		#[serde(skip)]
+		pub _config: sp_std::marker::PhantomData<T>,
+	}
+
+	#[pallet::genesis_build]
+	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
+		fn build(&self) {
+			frame_system::Pallet::<T>::inc_providers(&Pallet::<T>::account_id());
+		}
+	}
+
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
 		fn on_initialize(_now: BlockNumberFor<T>) -> Weight {
@@ -804,6 +822,17 @@ pub mod pallet {
 			Ok(())
 		}
 
+		#[pallet::call_index(20)]
+		#[pallet::weight(T::WeightInfo::notify_revenue())]
+		pub fn notify_revenue(
+			origin: OriginFor<T>,
+			revenue: OnDemandRevenueRecordOf<T>,
+		) -> DispatchResult {
+			T::AdminOrigin::ensure_origin_or_root(origin)?;
+			Self::do_notify_revenue(revenue)?;
+			Ok(())
+		}
+
 		#[pallet::call_index(99)]
 		#[pallet::weight(T::WeightInfo::swap_leases())]
 		pub fn swap_leases(origin: OriginFor<T>, id: TaskId, other: TaskId) -> DispatchResult {
diff --git a/substrate/frame/broker/src/migration.rs b/substrate/frame/broker/src/migration.rs
index f354e447fe84eba4df56d02e82c69519ba67cf7d..917f44a134cc17bb61ce6dfed0206a505a0f2d21 100644
--- a/substrate/frame/broker/src/migration.rs
+++ b/substrate/frame/broker/src/migration.rs
@@ -128,6 +128,36 @@ mod v2 {
 	}
 }
 
+mod v3 {
+	use super::*;
+	use frame_system::Pallet as System;
+
+	pub struct MigrateToV3Impl<T>(PhantomData<T>);
+
+	impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV3Impl<T> {
+		fn on_runtime_upgrade() -> frame_support::weights::Weight {
+			let acc = Pallet::<T>::account_id();
+			System::<T>::inc_providers(&acc);
+			// calculate and return migration weights
+			T::DbWeight::get().writes(1)
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
+			Ok(System::<T>::providers(&Pallet::<T>::account_id()).encode())
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
+			let old_providers = u32::decode(&mut &state[..]).expect("Known good");
+			let new_providers = System::<T>::providers(&Pallet::<T>::account_id()) as u32;
+
+			ensure!(new_providers == old_providers + 1, "Providers count should increase by one");
+			Ok(())
+		}
+	}
+}
+
 /// Migrate the pallet storage from `0` to `1`.
 pub type MigrateV0ToV1<T> = frame_support::migrations::VersionedMigration<
 	0,
@@ -144,3 +174,11 @@ pub type MigrateV1ToV2<T> = frame_support::migrations::VersionedMigration<
 	Pallet<T>,
 	<T as frame_system::Config>::DbWeight,
 >;
+
+pub type MigrateV2ToV3<T> = frame_support::migrations::VersionedMigration<
+	2,
+	3,
+	v3::MigrateToV3Impl<T>,
+	Pallet<T>,
+	<T as frame_system::Config>::DbWeight,
+>;
diff --git a/substrate/frame/broker/src/mock.rs b/substrate/frame/broker/src/mock.rs
index 6fff6aa10080c5a888ba35b4c3aeb1d180f9361b..f29651abff7b814791c446c29994e7617c619da1 100644
--- a/substrate/frame/broker/src/mock.rs
+++ b/substrate/frame/broker/src/mock.rs
@@ -70,7 +70,6 @@ parameter_types! {
 	pub static CoretimeWorkplan: BTreeMap<(u32, CoreIndex), Vec<(CoreAssignment, PartsOf57600)>> = Default::default();
 	pub static CoretimeUsage: BTreeMap<CoreIndex, Vec<(CoreAssignment, PartsOf57600)>> = Default::default();
 	pub static CoretimeInPool: CoreMaskBitCount = 0;
-	pub static NotifyRevenueInfo: Vec<(u32, u64)> = Default::default();
 }
 
 pub struct TestCoretimeProvider;
@@ -90,11 +89,10 @@ impl CoretimeInterface for TestCoretimeProvider {
 			);
 		}
 
-		let when = when as u32;
 		let mut total = 0;
 		CoretimeSpending::mutate(|s| {
 			s.retain(|(n, a)| {
-				if *n < when {
+				if *n < when as u32 {
 					total += a;
 					false
 				} else {
@@ -102,7 +100,8 @@ impl CoretimeInterface for TestCoretimeProvider {
 				}
 			})
 		});
-		NotifyRevenueInfo::mutate(|s| s.insert(0, (when, total)));
+		mint_to_pot(total);
+		RevenueInbox::<Test>::put(OnDemandRevenueRecord { until: when, amount: total });
 	}
 	fn credit_account(who: Self::AccountId, amount: Self::Balance) {
 		CoretimeCredit::mutate(|c| c.entry(who).or_default().saturating_accrue(amount));
@@ -125,19 +124,13 @@ impl CoretimeInterface for TestCoretimeProvider {
 		);
 		CoretimeTrace::mutate(|v| v.push(item));
 	}
-	fn check_notify_revenue_info() -> Option<(RCBlockNumberOf<Self>, Self::Balance)> {
-		NotifyRevenueInfo::mutate(|s| s.pop()).map(|v| (v.0 as _, v.1))
-	}
-	#[cfg(feature = "runtime-benchmarks")]
-	fn ensure_notify_revenue_info(when: RCBlockNumberOf<Self>, revenue: Self::Balance) {
-		NotifyRevenueInfo::mutate(|s| s.push((when as u32, revenue)));
-	}
 }
+
 impl TestCoretimeProvider {
-	pub fn spend_instantaneous(who: u64, price: u64) -> Result<(), ()> {
-		let mut c = CoretimeCredit::get();
+	pub fn spend_instantaneous(_who: u64, price: u64) -> Result<(), ()> {
+		let c = CoretimeCredit::get();
 		ensure!(CoretimeInPool::get() > 0, ());
-		c.insert(who, c.get(&who).ok_or(())?.checked_sub(price).ok_or(())?);
+		// c.insert(who, c.get(&who).ok_or(())?.checked_sub(price).ok_or(())?);
 		CoretimeCredit::set(c);
 		CoretimeSpending::mutate(|v| {
 			v.push((RCBlockNumberProviderOf::<Self>::current_block_number() as u32, price))
@@ -223,6 +216,11 @@ pub fn pot() -> u64 {
 	balance(Broker::account_id())
 }
 
+pub fn mint_to_pot(amount: u64) {
+	let imb = <Test as crate::Config>::Currency::issue(amount);
+	let _ = <Test as crate::Config>::Currency::resolve(&Broker::account_id(), imb);
+}
+
 pub fn revenue() -> u64 {
 	balance(0)
 }
diff --git a/substrate/frame/broker/src/tests.rs b/substrate/frame/broker/src/tests.rs
index e953afd6dc3c8818338d810d0c9d9d37c0b742af..2a8ea24b447ada3660ee9e5852dcf3c9e469f0db 100644
--- a/substrate/frame/broker/src/tests.rs
+++ b/substrate/frame/broker/src/tests.rs
@@ -451,6 +451,8 @@ fn renewals_affect_price() {
 
 #[test]
 fn instapool_payouts_work() {
+	// Commented out code is from the reference test implementation and should be uncommented as
+	// soon as we have the credit system implemented
 	TestExt::new().endow(1, 1000).execute_with(|| {
 		let item = ScheduleItem { assignment: Pool, mask: CoreMask::complete() };
 		assert_ok!(Broker::do_reserve(Schedule::truncate_from(vec![item])));
@@ -458,11 +460,13 @@ fn instapool_payouts_work() {
 		advance_to(2);
 		let region = Broker::do_purchase(1, u64::max_value()).unwrap();
 		assert_ok!(Broker::do_pool(region, None, 2, Final));
-		assert_ok!(Broker::do_purchase_credit(1, 20, 1));
+		// assert_ok!(Broker::do_purchase_credit(1, 20, 1));
 		advance_to(8);
 		assert_ok!(TestCoretimeProvider::spend_instantaneous(1, 10));
 		advance_to(11);
-		assert_eq!(pot(), 14);
+		// Should get revenue amount 10 from RC, from which 6 is system payout (goes to account0
+		// instantly) and the rest is private (kept in the pot until claimed)
+		assert_eq!(pot(), 4);
 		assert_eq!(revenue(), 106);
 
 		// Cannot claim for 0 timeslices.
@@ -470,13 +474,15 @@ fn instapool_payouts_work() {
 
 		// Revenue can be claimed.
 		assert_ok!(Broker::do_claim_revenue(region, 100));
-		assert_eq!(pot(), 10);
+		assert_eq!(pot(), 0);
 		assert_eq!(balance(2), 4);
 	});
 }
 
 #[test]
 fn instapool_partial_core_payouts_work() {
+	// Commented out code is from the reference test implementation and should be uncommented as
+	// soon as we have the credit system implemented
 	TestExt::new().endow(1, 1000).execute_with(|| {
 		let item = ScheduleItem { assignment: Pool, mask: CoreMask::complete() };
 		assert_ok!(Broker::do_reserve(Schedule::truncate_from(vec![item])));
@@ -487,7 +493,7 @@ fn instapool_partial_core_payouts_work() {
 			Broker::do_interlace(region, None, CoreMask::from_chunk(0, 20)).unwrap();
 		assert_ok!(Broker::do_pool(region1, None, 2, Final));
 		assert_ok!(Broker::do_pool(region2, None, 3, Final));
-		assert_ok!(Broker::do_purchase_credit(1, 40, 1));
+		// assert_ok!(Broker::do_purchase_credit(1, 40, 1));
 		advance_to(8);
 		assert_ok!(TestCoretimeProvider::spend_instantaneous(1, 40));
 		advance_to(11);
@@ -502,6 +508,8 @@ fn instapool_partial_core_payouts_work() {
 
 #[test]
 fn instapool_core_payouts_work_with_partitioned_region() {
+	// Commented out code is from the reference test implementation and should be uncommented as
+	// soon as we have the credit system implemented
 	TestExt::new().endow(1, 1000).execute_with(|| {
 		assert_ok!(Broker::do_start_sales(100, 1));
 		advance_to(2);
@@ -514,14 +522,14 @@ fn instapool_core_payouts_work_with_partitioned_region() {
 		// coretime will be purchased from `region2`.
 		assert_ok!(Broker::do_pool(region1, None, 2, Final));
 		assert_ok!(Broker::do_pool(region2, None, 3, Final));
-		assert_ok!(Broker::do_purchase_credit(1, 20, 1));
+		// assert_ok!(Broker::do_purchase_credit(1, 20, 1));
 		advance_to(8);
 		assert_ok!(TestCoretimeProvider::spend_instantaneous(1, 10));
 		advance_to(11);
-		assert_eq!(pot(), 20);
+		assert_eq!(pot(), 10);
 		assert_eq!(revenue(), 100);
 		assert_ok!(Broker::do_claim_revenue(region1, 100));
-		assert_eq!(pot(), 10);
+		assert_eq!(pot(), 0);
 		assert_eq!(balance(2), 10);
 		advance_to(12);
 		assert_ok!(TestCoretimeProvider::spend_instantaneous(1, 10));
diff --git a/substrate/frame/broker/src/tick_impls.rs b/substrate/frame/broker/src/tick_impls.rs
index 20637cf7b903cf73fb5d9bfe08e70013303bcb1a..3292faa4eb7e398bd603de6fa1108a1e5470f588 100644
--- a/substrate/frame/broker/src/tick_impls.rs
+++ b/substrate/frame/broker/src/tick_impls.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 use super::*;
-use frame_support::{pallet_prelude::*, weights::WeightMeter};
+use frame_support::{pallet_prelude::*, traits::defensive_prelude::*, weights::WeightMeter};
 use sp_arithmetic::traits::{One, SaturatedConversion, Saturating, Zero};
 use sp_runtime::traits::ConvertBack;
 use sp_std::{vec, vec::Vec};
@@ -76,6 +76,8 @@ impl<T: Config> Pallet<T> {
 			let rc_block = T::TimeslicePeriod::get() * status.last_timeslice.into();
 			T::Coretime::request_revenue_info_at(rc_block);
 			meter.consume(T::WeightInfo::request_revenue_info_at());
+			T::Coretime::on_new_timeslice(status.last_timeslice);
+			meter.consume(T::WeightInfo::on_new_timeslice());
 		}
 
 		Status::<T>::put(&status);
@@ -93,15 +95,23 @@ impl<T: Config> Pallet<T> {
 	}
 
 	pub(crate) fn process_revenue() -> bool {
-		let Some((until, amount)) = T::Coretime::check_notify_revenue_info() else { return false };
+		let Some(OnDemandRevenueRecord { until, amount }) = RevenueInbox::<T>::take() else {
+			return false
+		};
 		let when: Timeslice =
 			(until / T::TimeslicePeriod::get()).saturating_sub(One::one()).saturated_into();
-		let mut revenue = T::ConvertBalance::convert_back(amount);
+		let mut revenue = T::ConvertBalance::convert_back(amount.clone());
 		if revenue.is_zero() {
 			Self::deposit_event(Event::<T>::HistoryDropped { when, revenue });
 			InstaPoolHistory::<T>::remove(when);
 			return true
 		}
+
+		log::debug!(
+			target: "pallet_broker::process_revenue",
+			"Received {amount:?} from RC, converted into {revenue:?} revenue",
+		);
+
 		let mut r = InstaPoolHistory::<T>::get(when).unwrap_or_default();
 		if r.maybe_payout.is_some() {
 			Self::deposit_event(Event::<T>::HistoryIgnored { when, revenue });
@@ -112,7 +122,7 @@ impl<T: Config> Pallet<T> {
 		let system_payout = if !total_contrib.is_zero() {
 			let system_payout =
 				revenue.saturating_mul(r.system_contributions.into()) / total_contrib.into();
-			let _ = Self::charge(&Self::account_id(), system_payout);
+			Self::charge(&Self::account_id(), system_payout).defensive_ok();
 			revenue.saturating_reduce(system_payout);
 
 			system_payout
@@ -120,6 +130,11 @@ impl<T: Config> Pallet<T> {
 			Zero::zero()
 		};
 
+		log::debug!(
+			target: "pallet_broker::process_revenue",
+			"Charged {system_payout:?} for system payouts, {revenue:?} remaining for private contributions",
+		);
+
 		if !revenue.is_zero() && r.private_contributions > 0 {
 			r.maybe_payout = Some(revenue);
 			InstaPoolHistory::<T>::insert(when, &r);
diff --git a/substrate/frame/broker/src/types.rs b/substrate/frame/broker/src/types.rs
index 885cac9a5c23d47add53ce4e2eff02da49d3cdc9..dcfa9a77e4f3a4f8f9d21375e860a537b76f9218 100644
--- a/substrate/frame/broker/src/types.rs
+++ b/substrate/frame/broker/src/types.rs
@@ -255,6 +255,21 @@ pub struct LeaseRecordItem {
 pub type LeasesRecord<Max> = BoundedVec<LeaseRecordItem, Max>;
 pub type LeasesRecordOf<T> = LeasesRecord<<T as Config>::MaxLeasedCores>;
 
+/// Record for On demand core sales.
+///
+/// The blocknumber is the relay chain block height `until` which the original request
+/// for revenue was made.
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+pub struct OnDemandRevenueRecord<RelayBlockNumber, RelayBalance> {
+	/// The height of the Relay-chain at the time the revenue request was made.
+	pub until: RelayBlockNumber,
+	/// The accumulated balance of on demand sales made on the relay chain.
+	pub amount: RelayBalance,
+}
+
+pub type OnDemandRevenueRecordOf<T> =
+	OnDemandRevenueRecord<RelayBlockNumberOf<T>, RelayBalanceOf<T>>;
+
 /// Configuration of this pallet.
 #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
 pub struct ConfigRecord<BlockNumber, RelayBlockNumber> {
diff --git a/substrate/frame/broker/src/weights.rs b/substrate/frame/broker/src/weights.rs
index d9d9d348e47e9db76731b41fd65086c689fc86f0..4889c2577ddd80d9eac3652dd239271978416beb 100644
--- a/substrate/frame/broker/src/weights.rs
+++ b/substrate/frame/broker/src/weights.rs
@@ -18,9 +18,9 @@
 //! Autogenerated weights for `pallet_broker`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-05-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-06-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-vicqj8em-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-x5tnzzy-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
 
 // Executed Command:
@@ -75,8 +75,10 @@ pub trait WeightInfo {
 	fn process_core_schedule() -> Weight;
 	fn request_revenue_info_at() -> Weight;
 	fn notify_core_count() -> Weight;
+	fn notify_revenue() -> Weight;
 	fn do_tick_base() -> Weight;
 	fn swap_leases() -> Weight;
+	fn on_new_timeslice() -> Weight;
 }
 
 /// Weights for `pallet_broker` using the Substrate node and recommended hardware.
@@ -88,8 +90,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_945_000 picoseconds.
-		Weight::from_parts(2_142_000, 0)
+		// Minimum execution time: 1_977_000 picoseconds.
+		Weight::from_parts(2_114_000, 0)
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Reservations` (r:1 w:1)
@@ -98,8 +100,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `5016`
 		//  Estimated: `7496`
-		// Minimum execution time: 16_274_000 picoseconds.
-		Weight::from_parts(16_828_000, 7496)
+		// Minimum execution time: 16_880_000 picoseconds.
+		Weight::from_parts(17_506_000, 7496)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -109,8 +111,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `6218`
 		//  Estimated: `7496`
-		// Minimum execution time: 15_080_000 picoseconds.
-		Weight::from_parts(15_874_000, 7496)
+		// Minimum execution time: 15_569_000 picoseconds.
+		Weight::from_parts(16_123_000, 7496)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -120,8 +122,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `239`
 		//  Estimated: `1526`
-		// Minimum execution time: 8_761_000 picoseconds.
-		Weight::from_parts(9_203_000, 1526)
+		// Minimum execution time: 8_962_000 picoseconds.
+		Weight::from_parts(9_389_000, 1526)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -144,10 +146,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `6330`
 		//  Estimated: `8499`
-		// Minimum execution time: 26_057_000 picoseconds.
-		Weight::from_parts(46_673_357, 8499)
-			// Standard Error: 456
-			.saturating_add(Weight::from_parts(2_677, 0).saturating_mul(n.into()))
+		// Minimum execution time: 27_119_000 picoseconds.
+		Weight::from_parts(47_930_900, 8499)
+			// Standard Error: 464
+			.saturating_add(Weight::from_parts(2_940, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(6_u64))
 			.saturating_add(T::DbWeight::get().writes(15_u64))
 	}
@@ -165,8 +167,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `651`
 		//  Estimated: `2136`
-		// Minimum execution time: 40_907_000 picoseconds.
-		Weight::from_parts(42_566_000, 2136)
+		// Minimum execution time: 42_429_000 picoseconds.
+		Weight::from_parts(43_538_000, 2136)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -188,8 +190,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `769`
 		//  Estimated: `4698`
-		// Minimum execution time: 65_209_000 picoseconds.
-		Weight::from_parts(68_604_000, 4698)
+		// Minimum execution time: 62_957_000 picoseconds.
+		Weight::from_parts(66_821_000, 4698)
 			.saturating_add(T::DbWeight::get().reads(6_u64))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
 	}
@@ -199,8 +201,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `496`
 		//  Estimated: `3551`
-		// Minimum execution time: 15_860_000 picoseconds.
-		Weight::from_parts(16_393_000, 3551)
+		// Minimum execution time: 16_146_000 picoseconds.
+		Weight::from_parts(16_775_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -210,8 +212,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `496`
 		//  Estimated: `3551`
-		// Minimum execution time: 17_651_000 picoseconds.
-		Weight::from_parts(18_088_000, 3551)
+		// Minimum execution time: 17_720_000 picoseconds.
+		Weight::from_parts(18_916_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -221,8 +223,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `496`
 		//  Estimated: `3551`
-		// Minimum execution time: 18_576_000 picoseconds.
-		Weight::from_parts(19_810_000, 3551)
+		// Minimum execution time: 19_088_000 picoseconds.
+		Weight::from_parts(19_732_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
 	}
@@ -238,8 +240,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `741`
 		//  Estimated: `4681`
-		// Minimum execution time: 31_015_000 picoseconds.
-		Weight::from_parts(31_932_000, 4681)
+		// Minimum execution time: 30_522_000 picoseconds.
+		Weight::from_parts(31_573_000, 4681)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -257,8 +259,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `776`
 		//  Estimated: `5996`
-		// Minimum execution time: 36_473_000 picoseconds.
-		Weight::from_parts(37_382_000, 5996)
+		// Minimum execution time: 35_833_000 picoseconds.
+		Weight::from_parts(36_830_000, 5996)
 			.saturating_add(T::DbWeight::get().reads(5_u64))
 			.saturating_add(T::DbWeight::get().writes(5_u64))
 	}
@@ -273,10 +275,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `859`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 64_957_000 picoseconds.
-		Weight::from_parts(66_024_232, 6196)
-			// Standard Error: 50_170
-			.saturating_add(Weight::from_parts(1_290_632, 0).saturating_mul(m.into()))
+		// Minimum execution time: 65_882_000 picoseconds.
+		Weight::from_parts(67_506_904, 6196)
+			// Standard Error: 49_386
+			.saturating_add(Weight::from_parts(1_197_959, 0).saturating_mul(m.into()))
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(T::DbWeight::get().writes(5_u64))
@@ -288,8 +290,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `103`
 		//  Estimated: `3593`
-		// Minimum execution time: 39_939_000 picoseconds.
-		Weight::from_parts(40_788_000, 3593)
+		// Minimum execution time: 41_860_000 picoseconds.
+		Weight::from_parts(42_478_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -301,8 +303,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `604`
 		//  Estimated: `3551`
-		// Minimum execution time: 31_709_000 picoseconds.
-		Weight::from_parts(37_559_000, 3551)
+		// Minimum execution time: 32_593_000 picoseconds.
+		Weight::from_parts(35_399_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -316,8 +318,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `601`
 		//  Estimated: `3533`
-		// Minimum execution time: 42_895_000 picoseconds.
-		Weight::from_parts(53_945_000, 3533)
+		// Minimum execution time: 41_934_000 picoseconds.
+		Weight::from_parts(50_480_000, 3533)
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -333,8 +335,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `995`
 		//  Estimated: `3593`
-		// Minimum execution time: 50_770_000 picoseconds.
-		Weight::from_parts(63_117_000, 3593)
+		// Minimum execution time: 47_167_000 picoseconds.
+		Weight::from_parts(54_289_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -346,18 +348,20 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `661`
 		//  Estimated: `4698`
-		// Minimum execution time: 33_396_000 picoseconds.
-		Weight::from_parts(36_247_000, 4698)
+		// Minimum execution time: 29_755_000 picoseconds.
+		Weight::from_parts(32_857_000, 4698)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 3_625_000 picoseconds.
-		Weight::from_parts(4_011_396, 0)
+		// Minimum execution time: 3_793_000 picoseconds.
+		Weight::from_parts(4_086_907, 0)
+			// Standard Error: 14
+			.saturating_add(Weight::from_parts(60, 0).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -366,13 +370,13 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `404`
 		//  Estimated: `1487`
-		// Minimum execution time: 6_217_000 picoseconds.
-		Weight::from_parts(6_608_394, 1487)
+		// Minimum execution time: 6_262_000 picoseconds.
+		Weight::from_parts(6_734_896, 1487)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::InstaPoolHistory` (r:1 w:1)
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
 	/// Storage: `System::Account` (r:1 w:1)
@@ -383,10 +387,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `972`
-		//  Estimated: `4437`
-		// Minimum execution time: 46_853_000 picoseconds.
-		Weight::from_parts(47_740_000, 4437)
+		//  Measured:  `829`
+		//  Estimated: `3593`
+		// Minimum execution time: 39_812_000 picoseconds.
+		Weight::from_parts(41_227_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(5_u64))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
 	}
@@ -405,8 +409,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `6281`
 		//  Estimated: `8499`
-		// Minimum execution time: 34_240_000 picoseconds.
-		Weight::from_parts(35_910_175, 8499)
+		// Minimum execution time: 34_576_000 picoseconds.
+		Weight::from_parts(36_303_629, 8499)
 			.saturating_add(T::DbWeight::get().reads(5_u64))
 			.saturating_add(T::DbWeight::get().writes(15_u64))
 	}
@@ -418,8 +422,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `180`
 		//  Estimated: `3493`
-		// Minimum execution time: 7_083_000 picoseconds.
-		Weight::from_parts(7_336_000, 3493)
+		// Minimum execution time: 6_978_000 picoseconds.
+		Weight::from_parts(7_206_000, 3493)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -431,8 +435,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `1423`
 		//  Estimated: `4681`
-		// Minimum execution time: 15_029_000 picoseconds.
-		Weight::from_parts(15_567_000, 4681)
+		// Minimum execution time: 15_063_000 picoseconds.
+		Weight::from_parts(15_463_000, 4681)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -440,8 +444,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 123_000 picoseconds.
-		Weight::from_parts(136_000, 0)
+		// Minimum execution time: 126_000 picoseconds.
+		Weight::from_parts(157_000, 0)
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:0 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -449,8 +453,18 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_775_000 picoseconds.
-		Weight::from_parts(1_911_000, 0)
+		// Minimum execution time: 1_803_000 picoseconds.
+		Weight::from_parts(1_965_000, 0)
+			.saturating_add(T::DbWeight::get().writes(1_u64))
+	}
+	/// Storage: `Broker::RevenueInbox` (r:0 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
+	fn notify_revenue() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 1_902_000 picoseconds.
+		Weight::from_parts(2_116_000, 0)
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Status` (r:1 w:1)
@@ -459,16 +473,16 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:0)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:0)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `603`
-		//  Estimated: `4068`
-		// Minimum execution time: 11_859_000 picoseconds.
-		Weight::from_parts(12_214_000, 4068)
+		//  Measured:  `441`
+		//  Estimated: `1516`
+		// Minimum execution time: 9_313_000 picoseconds.
+		Weight::from_parts(9_699_000, 1516)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
-			.saturating_add(T::DbWeight::get().writes(2_u64))
+			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Leases` (r:1 w:1)
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
@@ -476,11 +490,18 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `239`
 		//  Estimated: `1526`
-		// Minimum execution time: 5_864_000 picoseconds.
-		Weight::from_parts(6_231_000, 1526)
+		// Minimum execution time: 5_984_000 picoseconds.
+		Weight::from_parts(6_296_000, 1526)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
+	fn on_new_timeslice() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 229_000 picoseconds.
+		Weight::from_parts(268_000, 0)
+	}
 }
 
 // For backwards compatibility and tests.
@@ -491,8 +512,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_945_000 picoseconds.
-		Weight::from_parts(2_142_000, 0)
+		// Minimum execution time: 1_977_000 picoseconds.
+		Weight::from_parts(2_114_000, 0)
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Reservations` (r:1 w:1)
@@ -501,8 +522,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `5016`
 		//  Estimated: `7496`
-		// Minimum execution time: 16_274_000 picoseconds.
-		Weight::from_parts(16_828_000, 7496)
+		// Minimum execution time: 16_880_000 picoseconds.
+		Weight::from_parts(17_506_000, 7496)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -512,8 +533,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `6218`
 		//  Estimated: `7496`
-		// Minimum execution time: 15_080_000 picoseconds.
-		Weight::from_parts(15_874_000, 7496)
+		// Minimum execution time: 15_569_000 picoseconds.
+		Weight::from_parts(16_123_000, 7496)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -523,8 +544,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `239`
 		//  Estimated: `1526`
-		// Minimum execution time: 8_761_000 picoseconds.
-		Weight::from_parts(9_203_000, 1526)
+		// Minimum execution time: 8_962_000 picoseconds.
+		Weight::from_parts(9_389_000, 1526)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -547,10 +568,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `6330`
 		//  Estimated: `8499`
-		// Minimum execution time: 26_057_000 picoseconds.
-		Weight::from_parts(46_673_357, 8499)
-			// Standard Error: 456
-			.saturating_add(Weight::from_parts(2_677, 0).saturating_mul(n.into()))
+		// Minimum execution time: 27_119_000 picoseconds.
+		Weight::from_parts(47_930_900, 8499)
+			// Standard Error: 464
+			.saturating_add(Weight::from_parts(2_940, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(6_u64))
 			.saturating_add(RocksDbWeight::get().writes(15_u64))
 	}
@@ -568,8 +589,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `651`
 		//  Estimated: `2136`
-		// Minimum execution time: 40_907_000 picoseconds.
-		Weight::from_parts(42_566_000, 2136)
+		// Minimum execution time: 42_429_000 picoseconds.
+		Weight::from_parts(43_538_000, 2136)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -591,8 +612,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `769`
 		//  Estimated: `4698`
-		// Minimum execution time: 65_209_000 picoseconds.
-		Weight::from_parts(68_604_000, 4698)
+		// Minimum execution time: 62_957_000 picoseconds.
+		Weight::from_parts(66_821_000, 4698)
 			.saturating_add(RocksDbWeight::get().reads(6_u64))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
 	}
@@ -602,8 +623,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `496`
 		//  Estimated: `3551`
-		// Minimum execution time: 15_860_000 picoseconds.
-		Weight::from_parts(16_393_000, 3551)
+		// Minimum execution time: 16_146_000 picoseconds.
+		Weight::from_parts(16_775_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -613,8 +634,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `496`
 		//  Estimated: `3551`
-		// Minimum execution time: 17_651_000 picoseconds.
-		Weight::from_parts(18_088_000, 3551)
+		// Minimum execution time: 17_720_000 picoseconds.
+		Weight::from_parts(18_916_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -624,8 +645,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `496`
 		//  Estimated: `3551`
-		// Minimum execution time: 18_576_000 picoseconds.
-		Weight::from_parts(19_810_000, 3551)
+		// Minimum execution time: 19_088_000 picoseconds.
+		Weight::from_parts(19_732_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
 	}
@@ -641,8 +662,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `741`
 		//  Estimated: `4681`
-		// Minimum execution time: 31_015_000 picoseconds.
-		Weight::from_parts(31_932_000, 4681)
+		// Minimum execution time: 30_522_000 picoseconds.
+		Weight::from_parts(31_573_000, 4681)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -660,8 +681,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `776`
 		//  Estimated: `5996`
-		// Minimum execution time: 36_473_000 picoseconds.
-		Weight::from_parts(37_382_000, 5996)
+		// Minimum execution time: 35_833_000 picoseconds.
+		Weight::from_parts(36_830_000, 5996)
 			.saturating_add(RocksDbWeight::get().reads(5_u64))
 			.saturating_add(RocksDbWeight::get().writes(5_u64))
 	}
@@ -676,10 +697,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `859`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 64_957_000 picoseconds.
-		Weight::from_parts(66_024_232, 6196)
-			// Standard Error: 50_170
-			.saturating_add(Weight::from_parts(1_290_632, 0).saturating_mul(m.into()))
+		// Minimum execution time: 65_882_000 picoseconds.
+		Weight::from_parts(67_506_904, 6196)
+			// Standard Error: 49_386
+			.saturating_add(Weight::from_parts(1_197_959, 0).saturating_mul(m.into()))
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(RocksDbWeight::get().writes(5_u64))
@@ -691,8 +712,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `103`
 		//  Estimated: `3593`
-		// Minimum execution time: 39_939_000 picoseconds.
-		Weight::from_parts(40_788_000, 3593)
+		// Minimum execution time: 41_860_000 picoseconds.
+		Weight::from_parts(42_478_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -704,8 +725,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `604`
 		//  Estimated: `3551`
-		// Minimum execution time: 31_709_000 picoseconds.
-		Weight::from_parts(37_559_000, 3551)
+		// Minimum execution time: 32_593_000 picoseconds.
+		Weight::from_parts(35_399_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -719,8 +740,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `601`
 		//  Estimated: `3533`
-		// Minimum execution time: 42_895_000 picoseconds.
-		Weight::from_parts(53_945_000, 3533)
+		// Minimum execution time: 41_934_000 picoseconds.
+		Weight::from_parts(50_480_000, 3533)
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -736,8 +757,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `995`
 		//  Estimated: `3593`
-		// Minimum execution time: 50_770_000 picoseconds.
-		Weight::from_parts(63_117_000, 3593)
+		// Minimum execution time: 47_167_000 picoseconds.
+		Weight::from_parts(54_289_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -749,18 +770,20 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `661`
 		//  Estimated: `4698`
-		// Minimum execution time: 33_396_000 picoseconds.
-		Weight::from_parts(36_247_000, 4698)
+		// Minimum execution time: 29_755_000 picoseconds.
+		Weight::from_parts(32_857_000, 4698)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 3_625_000 picoseconds.
-		Weight::from_parts(4_011_396, 0)
+		// Minimum execution time: 3_793_000 picoseconds.
+		Weight::from_parts(4_086_907, 0)
+			// Standard Error: 14
+			.saturating_add(Weight::from_parts(60, 0).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -769,13 +792,13 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `404`
 		//  Estimated: `1487`
-		// Minimum execution time: 6_217_000 picoseconds.
-		Weight::from_parts(6_608_394, 1487)
+		// Minimum execution time: 6_262_000 picoseconds.
+		Weight::from_parts(6_734_896, 1487)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::InstaPoolHistory` (r:1 w:1)
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
 	/// Storage: `System::Account` (r:1 w:1)
@@ -786,10 +809,10 @@ impl WeightInfo for () {
 	/// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `972`
-		//  Estimated: `4437`
-		// Minimum execution time: 46_853_000 picoseconds.
-		Weight::from_parts(47_740_000, 4437)
+		//  Measured:  `829`
+		//  Estimated: `3593`
+		// Minimum execution time: 39_812_000 picoseconds.
+		Weight::from_parts(41_227_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(5_u64))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
 	}
@@ -808,8 +831,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `6281`
 		//  Estimated: `8499`
-		// Minimum execution time: 34_240_000 picoseconds.
-		Weight::from_parts(35_910_175, 8499)
+		// Minimum execution time: 34_576_000 picoseconds.
+		Weight::from_parts(36_303_629, 8499)
 			.saturating_add(RocksDbWeight::get().reads(5_u64))
 			.saturating_add(RocksDbWeight::get().writes(15_u64))
 	}
@@ -821,8 +844,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `180`
 		//  Estimated: `3493`
-		// Minimum execution time: 7_083_000 picoseconds.
-		Weight::from_parts(7_336_000, 3493)
+		// Minimum execution time: 6_978_000 picoseconds.
+		Weight::from_parts(7_206_000, 3493)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -834,8 +857,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `1423`
 		//  Estimated: `4681`
-		// Minimum execution time: 15_029_000 picoseconds.
-		Weight::from_parts(15_567_000, 4681)
+		// Minimum execution time: 15_063_000 picoseconds.
+		Weight::from_parts(15_463_000, 4681)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -843,8 +866,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 123_000 picoseconds.
-		Weight::from_parts(136_000, 0)
+		// Minimum execution time: 126_000 picoseconds.
+		Weight::from_parts(157_000, 0)
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:0 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -852,8 +875,18 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 1_775_000 picoseconds.
-		Weight::from_parts(1_911_000, 0)
+		// Minimum execution time: 1_803_000 picoseconds.
+		Weight::from_parts(1_965_000, 0)
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: `Broker::RevenueInbox` (r:0 w:1)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
+	fn notify_revenue() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 1_902_000 picoseconds.
+		Weight::from_parts(2_116_000, 0)
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Status` (r:1 w:1)
@@ -862,16 +895,16 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:0)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
-	/// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
-	/// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1)
+	/// Storage: `Broker::RevenueInbox` (r:1 w:0)
+	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `603`
-		//  Estimated: `4068`
-		// Minimum execution time: 11_859_000 picoseconds.
-		Weight::from_parts(12_214_000, 4068)
+		//  Measured:  `441`
+		//  Estimated: `1516`
+		// Minimum execution time: 9_313_000 picoseconds.
+		Weight::from_parts(9_699_000, 1516)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
-			.saturating_add(RocksDbWeight::get().writes(2_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Leases` (r:1 w:1)
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
@@ -879,9 +912,16 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `239`
 		//  Estimated: `1526`
-		// Minimum execution time: 5_864_000 picoseconds.
-		Weight::from_parts(6_231_000, 1526)
+		// Minimum execution time: 5_984_000 picoseconds.
+		Weight::from_parts(6_296_000, 1526)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
+	fn on_new_timeslice() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 229_000 picoseconds.
+		Weight::from_parts(268_000, 0)
+	}
 }