Skip to content
lib.rs 86.7 KiB
Newer Older
			Ok(pallet_mmr::NumberOfLeaves::<Runtime>::get())
			block_numbers: Vec<BlockNumber>,
			best_known_block_number: Option<BlockNumber>,
		) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
			Mmr::generate_proof(block_numbers, best_known_block_number).map(
				|(leaves, proof)| {
					(
						leaves
							.into_iter()
							.map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf))
							.collect(),
						proof,
					)
				},
			)
		fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
			-> Result<(), mmr::Error>
		{
			let leaves = leaves.into_iter().map(|leaf|
				leaf.into_opaque_leaf()
				.try_decode()
				.ok_or(mmr::Error::Verify)).collect::<Result<Vec<mmr::Leaf>, mmr::Error>>()?;
			Mmr::verify_leaves(leaves, proof)
			root: mmr::Hash,
			leaves: Vec<mmr::EncodableOpaqueLeaf>,
			proof: mmr::Proof<mmr::Hash>
		) -> Result<(), mmr::Error> {
			let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
			pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
		}
	}

	impl pallet_beefy_mmr::BeefyMmrApi<Block, Hash> for RuntimeApi {
		fn authority_set_proof() -> beefy_primitives::mmr::BeefyAuthoritySet<Hash> {
			BeefyMmrLeaf::authority_set_proof()
		}
		fn next_authority_set_proof() -> beefy_primitives::mmr::BeefyNextAuthoritySet<Hash> {
			BeefyMmrLeaf::next_authority_set_proof()
ddorgan's avatar
ddorgan committed

	impl fg_primitives::GrandpaApi<Block> for Runtime {
		fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
			Grandpa::grandpa_authorities()
		}
		fn current_set_id() -> fg_primitives::SetId {
			Grandpa::current_set_id()
		}

		fn submit_report_equivocation_unsigned_extrinsic(
			equivocation_proof: fg_primitives::EquivocationProof<
				<Block as BlockT>::Hash,
				sp_runtime::traits::NumberFor<Block>,
			>,
			key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
		) -> Option<()> {
			let key_owner_proof = key_owner_proof.decode()?;

			Grandpa::submit_unsigned_equivocation_report(
				equivocation_proof,
				key_owner_proof,
			)
		}

		fn generate_key_ownership_proof(
			_set_id: fg_primitives::SetId,
			authority_id: fg_primitives::AuthorityId,
		) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {
			use parity_scale_codec::Encode;

			Historical::prove((fg_primitives::KEY_TYPE, authority_id))
				.map(|p| p.encode())
				.map(fg_primitives::OpaqueKeyOwnershipProof::new)
		}
ddorgan's avatar
ddorgan committed
	}

	impl babe_primitives::BabeApi<Block> for Runtime {
		fn configuration() -> babe_primitives::BabeConfiguration {
			let epoch_config = Babe::epoch_config().unwrap_or(BABE_GENESIS_EPOCH_CONFIG);
			babe_primitives::BabeConfiguration {
ddorgan's avatar
ddorgan committed
				slot_duration: Babe::slot_duration(),
				epoch_length: EpochDuration::get(),
				c: epoch_config.c,
				authorities: Babe::authorities().to_vec(),
ddorgan's avatar
ddorgan committed
				randomness: Babe::randomness(),
				allowed_slots: epoch_config.allowed_slots,
		fn current_epoch_start() -> babe_primitives::Slot {
ddorgan's avatar
ddorgan committed
			Babe::current_epoch_start()
		}
		fn current_epoch() -> babe_primitives::Epoch {
			Babe::current_epoch()
		}

		fn next_epoch() -> babe_primitives::Epoch {
			Babe::next_epoch()
		}

		fn generate_key_ownership_proof(
			_slot: babe_primitives::Slot,
			authority_id: babe_primitives::AuthorityId,
		) -> Option<babe_primitives::OpaqueKeyOwnershipProof> {
			use parity_scale_codec::Encode;

			Historical::prove((babe_primitives::KEY_TYPE, authority_id))
				.map(|p| p.encode())
				.map(babe_primitives::OpaqueKeyOwnershipProof::new)
		}

		fn submit_report_equivocation_unsigned_extrinsic(
			equivocation_proof: babe_primitives::EquivocationProof<<Block as BlockT>::Header>,
			key_owner_proof: babe_primitives::OpaqueKeyOwnershipProof,
		) -> Option<()> {
			let key_owner_proof = key_owner_proof.decode()?;

			Babe::submit_unsigned_equivocation_report(
				equivocation_proof,
				key_owner_proof,
			)
		}
ddorgan's avatar
ddorgan committed
	}

	impl authority_discovery_primitives::AuthorityDiscoveryApi<Block> for Runtime {
		fn authorities() -> Vec<AuthorityDiscoveryId> {
			parachains_runtime_api_impl::relevant_authority_ids::<Runtime>()
ddorgan's avatar
ddorgan committed
		}
	}

	impl sp_session::SessionKeys<Block> for Runtime {
		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
			SessionKeys::generate(seed)
		}

		fn decode_session_keys(
			encoded: Vec<u8>,
		) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
			SessionKeys::decode_into_raw_public_keys(&encoded)
		}
	}

	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
ddorgan's avatar
ddorgan committed
		fn account_nonce(account: AccountId) -> Nonce {
			System::account_nonce(account)
		}
	}

	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
ddorgan's avatar
ddorgan committed
		Block,
		Balance,
	> for Runtime {
		fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {
ddorgan's avatar
ddorgan committed
			TransactionPayment::query_info(uxt, len)
		}
		fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {
			TransactionPayment::query_fee_details(uxt, len)
		}
		fn query_weight_to_fee(weight: Weight) -> Balance {
			TransactionPayment::weight_to_fee(weight)
		}
		fn query_length_to_fee(length: u32) -> Balance {
			TransactionPayment::length_to_fee(length)
		}
	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
		fn query_call_info(call: RuntimeCall, len: u32) -> RuntimeDispatchInfo<Balance> {
			TransactionPayment::query_call_info(call, len)
		}
		fn query_call_fee_details(call: RuntimeCall, len: u32) -> FeeDetails<Balance> {
			TransactionPayment::query_call_fee_details(call, len)
		}
		fn query_weight_to_fee(weight: Weight) -> Balance {
			TransactionPayment::weight_to_fee(weight)
		}
		fn query_length_to_fee(length: u32) -> Balance {
			TransactionPayment::length_to_fee(length)
		}
	impl xcm_fee_payment_runtime_api::XcmPaymentApi<Block> for Runtime {
		fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
			if !matches!(xcm_version, 3 | 4) {
				return Err(XcmPaymentApiError::UnhandledXcmVersion);
			}
			Ok([VersionedAssetId::V4(xcm_config::TokenLocation::get().into())]
				.into_iter()
				.filter_map(|asset| asset.into_version(xcm_version).ok())
				.collect())
		}

		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
			let local_asset = VersionedAssetId::V4(xcm_config::TokenLocation::get().into());
			let asset = asset
				.into_version(4)
				.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

			if  asset != local_asset { return Err(XcmPaymentApiError::AssetNotFound); }

			Ok(WeightToFee::weight_to_fee(&weight))
		}

		fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
			XcmPallet::query_xcm_weight(message)
		}

		fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
			XcmPallet::query_delivery_fees(destination, message)
		}
	}

	impl pallet_nomination_pools_runtime_api::NominationPoolsApi<
		Block,
		AccountId,
		Balance,
	> for Runtime {
		fn pending_rewards(member: AccountId) -> Balance {
			NominationPools::api_pending_rewards(member).unwrap_or_default()
		}

		fn points_to_balance(pool_id: pallet_nomination_pools::PoolId, points: Balance) -> Balance {
			NominationPools::api_points_to_balance(pool_id, points)
		}

		fn balance_to_points(pool_id: pallet_nomination_pools::PoolId, new_funds: Balance) -> Balance {
			NominationPools::api_balance_to_points(pool_id, new_funds)
		}
	}

	impl pallet_staking_runtime_api::StakingApi<Block, Balance, AccountId> for Runtime {
		fn nominations_quota(balance: Balance) -> u32 {
			Staking::api_nominations_quota(balance)

		fn eras_stakers_page_count(era: sp_staking::EraIndex, account: AccountId) -> sp_staking::Page {
			Staking::api_eras_stakers_page_count(era, account)
		}
	#[cfg(feature = "try-runtime")]
	impl frame_try_runtime::TryRuntime<Block> for Runtime {
		fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
			log::info!("try-runtime::on_runtime_upgrade westend.");
			let weight = Executive::try_runtime_upgrade(checks).unwrap();
			(weight, BlockWeights::get().max_block)
		}
		fn execute_block(
			block: Block,
			state_root_check: bool,
			signature_check: bool,
			select: frame_try_runtime::TryStateSelect,
		) -> Weight {
			// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
			// have a backtrace here.
			Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
ddorgan's avatar
ddorgan committed
	#[cfg(feature = "runtime-benchmarks")]
	impl frame_benchmarking::Benchmark<Block> for Runtime {
		fn benchmark_metadata(extra: bool) -> (
			Vec<frame_benchmarking::BenchmarkList>,
			Vec<frame_support::traits::StorageInfo>,
		) {
			use frame_benchmarking::{Benchmarking, BenchmarkList};
			use frame_support::traits::StorageInfoTrait;

			use pallet_session_benchmarking::Pallet as SessionBench;
			use pallet_offences_benchmarking::Pallet as OffencesBench;
			use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench;
			use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
			use frame_system_benchmarking::Pallet as SystemBench;
			use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench;
			type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
			type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;
			let mut list = Vec::<BenchmarkList>::new();
			list_benchmarks!(list, extra);
			let storage_info = AllPalletsWithSystem::storage_info();
			return (list, storage_info)
		}

ddorgan's avatar
ddorgan committed
		fn dispatch_benchmark(
			Vec<frame_benchmarking::BenchmarkBatch>,
			sp_runtime::RuntimeString,
		> {
			use frame_support::traits::WhitelistedStorageKeys;
			use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError};
			use sp_storage::TrackedStorageKey;
			// Trying to add benchmarks directly to some pallets caused cyclic dependency issues.
			// To get around that, we separated the benchmarks into its own crate.
			use pallet_session_benchmarking::Pallet as SessionBench;
			use pallet_offences_benchmarking::Pallet as OffencesBench;
			use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench;
			use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
			use frame_system_benchmarking::Pallet as SystemBench;
			use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench;
			impl pallet_session_benchmarking::Config for Runtime {}
			impl pallet_offences_benchmarking::Config for Runtime {}
			impl pallet_election_provider_support_benchmarking::Config for Runtime {}

			use xcm_config::{AssetHub, TokenLocation};

			parameter_types! {
				pub ExistentialDepositAsset: Option<Asset> = Some((
					TokenLocation::get(),
					ExistentialDeposit::get()
				).into());
				pub AssetHubParaId: ParaId = westend_runtime_constants::system_parachain::ASSET_HUB_ID.into();
				pub const RandomParaId: ParaId = ParaId::new(43211234);
			}

			impl pallet_xcm::benchmarking::Config for Runtime {
				type DeliveryHelper = (
					runtime_common::xcm_sender::ToParachainDeliveryHelper<
						xcm_config::XcmConfig,
						ExistentialDepositAsset,
						xcm_config::PriceForChildParachainDelivery,
						AssetHubParaId,
						(),
					>,
					runtime_common::xcm_sender::ToParachainDeliveryHelper<
						xcm_config::XcmConfig,
						ExistentialDepositAsset,
						xcm_config::PriceForChildParachainDelivery,
						RandomParaId,
						(),
					>
				);

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn reachable_dest() -> Option<Location> {
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
					// Relay/native token can be teleported to/from AH.
					Some((
						Asset { fun: Fungible(ExistentialDeposit::get()), id: AssetId(Here.into()) },
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
					// Relay can reserve transfer native token to some random parachain.
					Some((
Francisco Aguirre's avatar
Francisco Aguirre committed
						Asset {
Francisco Aguirre's avatar
Francisco Aguirre committed
							id: AssetId(Here.into())
						crate::Junction::Parachain(RandomParaId::get().into()).into(),
Francisco Aguirre's avatar
Francisco Aguirre committed
				) -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)> {
					// Relay supports only native token, either reserve transfer it to non-system parachains,
					// or teleport it to system parachain. Use the teleport case for benchmarking as it's
					// slightly heavier.

					// Relay/native token can be teleported to/from AH.
					let native_location = Here.into();
					let dest = crate::xcm_config::AssetHub::get();
					pallet_xcm::benchmarking::helpers::native_teleport_as_asset_transfer::<Runtime>(
						native_location,
						dest
					)
				}

				fn get_asset() -> Asset {
					Asset {
						id: AssetId(Location::here()),
						fun: Fungible(ExistentialDeposit::get()),
					}
				}
			impl frame_system_benchmarking::Config for Runtime {}
			impl pallet_nomination_pools_benchmarking::Config for Runtime {}
			impl runtime_parachains::disputes::slashing::benchmarking::Config for Runtime {}
ddorgan's avatar
ddorgan committed

Francisco Aguirre's avatar
Francisco Aguirre committed
				AssetId, Fungibility::*, InteriorLocation, Junction, Junctions::*,
				Asset, Assets, Location, NetworkId, Response,
			impl pallet_xcm_benchmarks::Config for Runtime {
				type XcmConfig = xcm_config::XcmConfig;
				type AccountIdConverter = xcm_config::LocationConverter;
				type DeliveryHelper = runtime_common::xcm_sender::ToParachainDeliveryHelper<
					xcm_config::XcmConfig,
Francisco Aguirre's avatar
Francisco Aguirre committed
					ExistentialDepositAsset,
					xcm_config::PriceForChildParachainDelivery,
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn valid_destination() -> Result<Location, BenchmarkError> {
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn worst_case_holding(_depositable_count: u32) -> Assets {
					// Westend only knows about WND.
Francisco Aguirre's avatar
Francisco Aguirre committed
					vec![Asset{
						id: AssetId(TokenLocation::get()),
						fun: Fungible(1_000_000 * UNITS),
					}].into()
				}
Francisco Aguirre's avatar
Francisco Aguirre committed
				pub TrustedTeleporter: Option<(Location, Asset)> = Some((
Francisco Aguirre's avatar
Francisco Aguirre committed
					Asset { fun: Fungible(1 * UNITS), id: AssetId(TokenLocation::get()) },
Francisco Aguirre's avatar
Francisco Aguirre committed
				pub const TrustedReserve: Option<(Location, Asset)> = None;
			}

			impl pallet_xcm_benchmarks::fungible::Config for Runtime {
				type TransactAsset = Balances;

Gavin Wood's avatar
Gavin Wood committed
				type CheckedAccount = xcm_config::LocalCheckAccount;
				type TrustedTeleporter = TrustedTeleporter;
				type TrustedReserve = TrustedReserve;
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn get_asset() -> Asset {
					Asset {
						id: AssetId(TokenLocation::get()),
			impl pallet_xcm_benchmarks::generic::Config for Runtime {
				type TransactAsset = Balances;
				type RuntimeCall = RuntimeCall;

				fn worst_case_response() -> (u64, Response) {
					(0u64, Response::Version(Default::default()))
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn worst_case_asset_exchange() -> Result<(Assets, Assets), BenchmarkError> {
Gavin Wood's avatar
Gavin Wood committed
					// Westend doesn't support asset exchanges
					Err(BenchmarkError::Skip)
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
Gavin Wood's avatar
Gavin Wood committed
					// The XCM executor of Westend doesn't have a configured `UniversalAliases`
					Err(BenchmarkError::Skip)
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> {
					Ok((AssetHub::get(), frame_system::Call::remark_with_event { remark: vec![] }.into()))
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn subscribe_origin() -> Result<Location, BenchmarkError> {
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError> {
					let origin = AssetHub::get();
Francisco Aguirre's avatar
Francisco Aguirre committed
					let assets: Assets = (AssetId(TokenLocation::get()), 1_000 * UNITS).into();
					let ticket = Location { parents: 0, interior: Here };
					Ok((origin, ticket, assets))
				}
Gavin Wood's avatar
Gavin Wood committed

				fn fee_asset() -> Result<Asset, BenchmarkError> {
					Ok(Asset {
						id: AssetId(TokenLocation::get()),
						fun: Fungible(1_000_000 * UNITS),
					})
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> {
Gavin Wood's avatar
Gavin Wood committed
					// Westend doesn't support asset locking
					Err(BenchmarkError::Skip)
				}

				fn export_message_origin_and_destination(
Francisco Aguirre's avatar
Francisco Aguirre committed
				) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> {
					// Westend doesn't support exporting messages
					Err(BenchmarkError::Skip)
				}
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
					// The XCM executor of Westend doesn't have a configured `Aliasers`
					Err(BenchmarkError::Skip)
				}
			type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
			type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;
			let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
ddorgan's avatar
ddorgan committed
			let mut batches = Vec::<BenchmarkBatch>::new();
			add_benchmarks!(params, batches);
ddorgan's avatar
ddorgan committed
		}
	}

	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
		fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
			build_state::<RuntimeGenesisConfig>(config)
		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
			get_preset::<RuntimeGenesisConfig>(id, |_| None)
		}

		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
			vec![]
ddorgan's avatar
ddorgan committed
}

#[cfg(all(test, feature = "try-runtime"))]
mod remote_tests {
	use super::*;
	use frame_try_runtime::{runtime_decl_for_try_runtime::TryRuntime, UpgradeCheckSelect};
	use remote_externalities::{
		Builder, Mode, OfflineConfig, OnlineConfig, SnapshotConfig, Transport,
	};
	use std::env::var;

	#[tokio::test]
	async fn run_migrations() {
		if var("RUN_MIGRATION_TESTS").is_err() {
		sp_tracing::try_init_simple();
		let transport: Transport =
			var("WS").unwrap_or("wss://westend-rpc.polkadot.io:443".to_string()).into();
		let maybe_state_snapshot: Option<SnapshotConfig> = var("SNAP").map(|s| s.into()).ok();
		let mut ext = Builder::<Block>::default()
			.mode(if let Some(state_snapshot) = maybe_state_snapshot {
				Mode::OfflineOrElseOnline(
					OfflineConfig { state_snapshot: state_snapshot.clone() },
					OnlineConfig {
						transport,
						state_snapshot: Some(state_snapshot),
						..Default::default()
					},
				)
			} else {
				Mode::Online(OnlineConfig { transport, ..Default::default() })
			})
			.build()
			.await
			.unwrap();
		ext.execute_with(|| Runtime::on_runtime_upgrade(UpgradeCheckSelect::PreAndPost));
mod clean_state_migration {
	use super::Runtime;
Francisco Aguirre's avatar
Francisco Aguirre committed
	#[cfg(feature = "try-runtime")]
	use super::Vec;
	use frame_support::{pallet_prelude::*, storage_alias, traits::OnRuntimeUpgrade};
	use pallet_state_trie_migration::MigrationLimits;

	#[storage_alias]
	type AutoLimits = StorageValue<StateTrieMigration, Option<MigrationLimits>, ValueQuery>;

	// Actual type of value is `MigrationTask<T>`, putting a dummy
	// one to avoid the trait constraint on T.
	// Since we only use `kill` it is fine.
	#[storage_alias]
	type MigrationProcess = StorageValue<StateTrieMigration, u32, ValueQuery>;

	#[storage_alias]
	type SignedMigrationMaxLimits = StorageValue<StateTrieMigration, MigrationLimits, OptionQuery>;

	/// Initialize an automatic migration process.
	pub struct CleanMigrate;

	impl OnRuntimeUpgrade for CleanMigrate {
		#[cfg(feature = "try-runtime")]
		fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
			Ok(Default::default())
		}

		fn on_runtime_upgrade() -> frame_support::weights::Weight {
			MigrationProcess::kill();
			AutoLimits::kill();
			SignedMigrationMaxLimits::kill();
			<Runtime as frame_system::Config>::DbWeight::get().writes(3)
		}

		#[cfg(feature = "try-runtime")]
		fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
			frame_support::ensure!(
				!AutoLimits::exists() && !SignedMigrationMaxLimits::exists(),
				"State migration clean.",