12345678#![cfg_attr(not(feature = "std"), no_std)]910#![recursion_limit = "256"]111213#[cfg(feature = "std")]14include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));1516use pallet_grandpa::fg_primitives;17use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};18use sp_api::impl_runtime_apis;19use sp_consensus_aura::sr25519::AuthorityId as AuraId;20use sp_core::{ crypto::KeyTypeId, crypto::Public, OpaqueMetadata };21use sp_runtime::{22 Permill, Perbill, Percent,23 ModuleId,24 create_runtime_str, generic, impl_opaque_keys,25 traits::{26 Convert, ConvertInto, BlakeTwo256, Block as BlockT, IdentifyAccount, 27 IdentityLookup, NumberFor, Verify,28 },29 transaction_validity::{TransactionSource, TransactionValidity},30 ApplyExtrinsicResult, MultiSignature,31};32#[cfg(feature = "std")]33use sp_version::NativeVersion;34use sp_version::RuntimeVersion;35pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment, CurrencyAdapter, FeeDetails, RuntimeDispatchInfo};3637pub use pallet_balances::Call as BalancesCall;38pub use pallet_contracts::{Schedule as ContractsSchedule };39pub use frame_support::{40 construct_runtime,41 dispatch::DispatchResult,42 parameter_types,43 StorageValue,44 traits::{45 Currency, ExistenceRequirement, Get, KeyOwnerProofSystem, OnUnbalanced, Randomness,46 LockIdentifier,47 },48 weights::{49 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},50 DispatchClass, DispatchInfo, GetDispatchInfo, Pays, PostDispatchInfo, Weight,51 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients52 },53};54use pallet_contracts::weights::WeightInfo;5556use frame_system::{57 self as system,58 EnsureRoot, 59 limits::{BlockWeights, BlockLength},60};61use sp_std::{prelude::*, marker::PhantomData};62use sp_arithmetic::{traits::{BaseArithmetic, Unsigned}};63use smallvec::smallvec;6465pub use pallet_timestamp::Call as TimestampCall;6667mod chain_extension;68use crate::chain_extension::{ NFTExtension, Imbalance };69707172pub struct CurrencyToVoteHandler;7374impl CurrencyToVoteHandler {75 fn factor() -> Balance {76 (Balances::total_issuance() / u64::max_value() as Balance).max(1)77 }78}7980impl Convert<Balance, u64> for CurrencyToVoteHandler {81 fn convert(x: Balance) -> u64 {82 (x / Self::factor()) as u6483 }84}8586impl Convert<u128, Balance> for CurrencyToVoteHandler {87 fn convert(x: u128) -> Balance {88 x * Self::factor()89 }90}91929394extern crate pallet_nft;95pub use pallet_nft::*;969798pub type BlockNumber = u32;99100101pub type Signature = MultiSignature;102103104105pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;106107108109pub type AccountIndex = u32;110111112pub type Balance = u128;113114115pub type Index = u32;116117118pub type Hash = sp_core::H256;119120121pub type DigestItem = generic::DigestItem<Hash>;122123mod nft_weights;124125126127128129pub mod opaque {130 use super::*;131132 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;133134 135 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;136 137 pub type Block = generic::Block<Header, UncheckedExtrinsic>;138 139 pub type BlockId = generic::BlockId<Block>;140141 impl_opaque_keys! {142 pub struct SessionKeys {143 pub aura: Aura,144 pub grandpa: Grandpa,145 }146 }147}148149150pub const VERSION: RuntimeVersion = RuntimeVersion {151 spec_name: create_runtime_str!("nft"),152 impl_name: create_runtime_str!("nft"),153 authoring_version: 1,154 spec_version: 3,155 impl_version: 1,156 apis: RUNTIME_API_VERSIONS,157 transaction_version: 1,158};159160pub const MILLISECS_PER_BLOCK: u64 = 6000;161162pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;163164165pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);166pub const HOURS: BlockNumber = MINUTES * 60;167pub const DAYS: BlockNumber = HOURS * 24;168169170#[cfg(feature = "std")]171pub fn native_version() -> NativeVersion {172 NativeVersion {173 runtime_version: VERSION,174 can_author_with: Default::default(),175 }176}177178179pub struct ValiudatorsOnly<Runtime: pallet_aura::Config>(PhantomData<Runtime>);180impl frame_support::traits::Contains<AccountId> for ValiudatorsOnly<Runtime> {181 fn contains(t: &AccountId) -> bool {182 let arr: [u8; 32] = *t.as_ref();183 let raw_key: Vec<u8> = Vec::from(arr);184185 match pallet_aura::Module::<Runtime>::authorities().iter().find(|auth| auth.to_raw_vec() == raw_key) {186 Some(_) => true,187 None => false,188 } 189 }190 fn sorted_members() -> Vec<AccountId> {191 let mut members: Vec<AccountId> = Vec::new();192 for auth in pallet_aura::Module::<Runtime>::authorities() {193 let mut arr: [u8; 32] = Default::default(); 194 let bor_arr = auth.clone().to_raw_vec();195 let slice = bor_arr.as_slice();196 arr.copy_from_slice(slice);197 members.push(AccountId::from(arr));198 }199 members 200 }201 fn count() -> usize {202 pallet_aura::Module::<Runtime>::authorities().len()203 }204}205206impl frame_support::traits::ContainsLengthBound for ValiudatorsOnly<Runtime> {207 fn min_len() -> usize {208 1209 }210 fn max_len() -> usize {211 100212 }213}214215type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;216217pub struct DealWithFees;218impl OnUnbalanced<NegativeImbalance> for DealWithFees {219 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item=NegativeImbalance>) {220 if let Some(fees) = fees_then_tips.next() {221 222 let mut split = fees.ration(100, 0);223 if let Some(tips) = fees_then_tips.next() {224 225 tips.ration_merge_into(100, 0, &mut split);226 }227 Treasury::on_unbalanced(split.0);228 229 }230 }231}232233234235236237238239240241242243244245246247248249250const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);251252253const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);254255const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND;256257parameter_types! {258 pub const BlockHashCount: BlockNumber = 2400;259 pub RuntimeBlockLength: BlockLength =260 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);261 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);262 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;263 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()264 .base_block(BlockExecutionWeight::get())265 .for_class(DispatchClass::all(), |weights| {266 weights.base_extrinsic = ExtrinsicBaseWeight::get();267 })268 .for_class(DispatchClass::Normal, |weights| {269 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);270 })271 .for_class(DispatchClass::Operational, |weights| {272 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);273 274 275 weights.reserved = Some(276 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT277 );278 })279 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)280 .build_or_panic();281 pub const Version: RuntimeVersion = VERSION;282 pub const SS58Prefix: u8 = 42;283}284285impl system::Config for Runtime {286 287 type BaseCallFilter = ();288 289 type AccountId = AccountId;290 291 type Call = Call;292 293 type Lookup = IdentityLookup<AccountId>;294 295 type Index = Index;296 297 type BlockNumber = BlockNumber;298 299 type Hash = Hash;300 301 type Hashing = BlakeTwo256;302 303 type Header = generic::Header<BlockNumber, BlakeTwo256>;304 305 type Event = Event;306 307 type Origin = Origin;308 309 type BlockHashCount = BlockHashCount;310 311 type DbWeight = RocksDbWeight;312 313 314 type BlockWeights = RuntimeBlockWeights;315 316 type Version = Version;317 318 type PalletInfo = PalletInfo;319 320 type OnNewAccount = ();321 322 type OnKilledAccount = ();323 324 type AccountData = pallet_balances::AccountData<Balance>;325 326 type SystemWeightInfo = system::weights::SubstrateWeight<Runtime>;327 328 type BlockLength = RuntimeBlockLength;329 type SS58Prefix = SS58Prefix;330}331332impl pallet_aura::Config for Runtime {333 type AuthorityId = AuraId;334}335336impl pallet_grandpa::Config for Runtime {337 type Event = Event;338 type Call = Call;339340 type KeyOwnerProofSystem = ();341342 type KeyOwnerProof =343 <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;344345 type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(346 KeyTypeId,347 GrandpaId,348 )>>::IdentificationTuple;349350 type HandleEquivocation = ();351352 type WeightInfo = ();353}354355parameter_types! {356 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;357}358359impl pallet_timestamp::Config for Runtime {360 361 type Moment = u64;362 type OnTimestampSet = Aura;363 type MinimumPeriod = MinimumPeriod;364 type WeightInfo = ();365}366367parameter_types! {368 369 pub const ExistentialDeposit: u128 = 0;370 pub const MaxLocks: u32 = 50;371}372373impl pallet_balances::Config for Runtime {374 type MaxLocks = MaxLocks;375 376 type Balance = Balance;377 378 type Event = Event;379 type DustRemoval = Treasury;380 type ExistentialDeposit = ExistentialDeposit;381 type AccountStore = System;382 type WeightInfo = ();383}384385pub const MICROUNIQUE: Balance = 1_000_000_000;386pub const MILLIUNIQUE: Balance = 1_000 * MICROUNIQUE;387pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE;388pub const UNIQUE: Balance = 100 * CENTIUNIQUE;389390pub const fn deposit(items: u32, bytes: u32) -> Balance {391 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE392}393394parameter_types! {395 pub const TombstoneDeposit: Balance = deposit(396 0,397 sp_std::mem::size_of::<pallet_contracts::ContractInfo<Runtime>>() as u32398 );399 pub const DepositPerContract: Balance = TombstoneDeposit::get();400 pub const DepositPerStorageByte: Balance = deposit(0, 1);401 pub const DepositPerStorageItem: Balance = deposit(1, 0);402 pub RentFraction: Perbill = Perbill::from_rational_approximation(1u32, 30 * DAYS);403 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;404 pub const SignedClaimHandicap: u32 = 2;405 pub const MaxDepth: u32 = 32;406 pub const MaxValueSize: u32 = 16 * 1024;407 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; 408 409 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *410 RuntimeBlockWeights::get().max_block;411 412 413 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (414 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -415 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)416 )) / 5) as u32;417}418419420impl pallet_contracts::Config for Runtime {421 type Time = Timestamp;422 type Randomness = RandomnessCollectiveFlip;423 type Currency = Balances;424 type Event = Event;425 type RentPayment = ();426 type SignedClaimHandicap = SignedClaimHandicap;427 type TombstoneDeposit = TombstoneDeposit;428 type DepositPerContract = DepositPerContract;429 type DepositPerStorageByte = DepositPerStorageByte;430 type DepositPerStorageItem = DepositPerStorageItem;431 type RentFraction = RentFraction;432 type SurchargeReward = SurchargeReward;433 type MaxDepth = MaxDepth;434 type MaxValueSize = MaxValueSize;435 type WeightPrice = pallet_transaction_payment::Module<Self>;436 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;437 type ChainExtension = NFTExtension;438 type DeletionQueueDepth = DeletionQueueDepth;439 type DeletionWeightLimit = DeletionWeightLimit;440 type MaxCodeSize = MaxCodeSize;441}442443parameter_types! {444 pub const TransactionByteFee: Balance = 501 * MICROUNIQUE; 445}446447448pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);449450impl<T> WeightToFeePolynomial for LinearFee<T> where451 T: BaseArithmetic + From<u32> + Copy + Unsigned452{453 type Balance = T;454455 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {456 smallvec!(WeightToFeeCoefficient {457 coeff_integer: 146_700u32.into(), 458 coeff_frac: Perbill::zero(),459 negative: false,460 degree: 1,461 })462 }463}464465impl pallet_transaction_payment::Config for Runtime {466 type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;467 type TransactionByteFee = TransactionByteFee;468 type WeightToFee = LinearFee<Balance>;469 type FeeMultiplierUpdate = ();470}471472parameter_types! {473 pub const ProposalBond: Permill = Permill::from_percent(5);474 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;475 pub const SpendPeriod: BlockNumber = 5 * MINUTES;476 pub const Burn: Permill = Permill::from_percent(0);477 pub const TipCountdown: BlockNumber = 1 * DAYS;478 pub const TipFindersFee: Percent = Percent::from_percent(20);479 pub const TipReportDepositBase: Balance = 1 * UNIQUE;480 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;481 pub const BountyDepositBase: Balance = 1 * UNIQUE;482 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;483 pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry");484 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;485 pub const MaximumReasonLength: u32 = 16384;486 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);487 pub const BountyValueMinimum: Balance = 5 * UNIQUE;488}489490impl pallet_treasury::Config for Runtime {491 type ModuleId = TreasuryModuleId;492 type Currency = Balances;493 type ApproveOrigin = EnsureRoot<AccountId>;494 type RejectOrigin = EnsureRoot<AccountId>;495 type Event = Event;496 type OnSlash = ();497 type ProposalBond = ProposalBond;498 type ProposalBondMinimum = ProposalBondMinimum;499 type SpendPeriod = SpendPeriod;500 type Burn = Burn;501 type BurnDestination = ();502 type SpendFunds = ();503 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Runtime>;504}505506impl pallet_sudo::Config for Runtime {507 type Event = Event;508 type Call = Call;509}510511parameter_types! {512 pub const MinVestedTransfer: Balance = 10 * UNIQUE;513}514515impl pallet_vesting::Config for Runtime {516 type Event = Event;517 type Currency = Balances;518 type BlockNumberToBalance = ConvertInto;519 type MinVestedTransfer = MinVestedTransfer;520 type WeightInfo = ();521}522523524impl pallet_nft::Config for Runtime {525 type Event = Event;526 type WeightInfo = nft_weights::WeightInfo;527}528529construct_runtime!(530 pub enum Runtime where531 Block = Block,532 NodeBlock = opaque::Block,533 UncheckedExtrinsic = UncheckedExtrinsic534 {535 System: system::{Module, Call, Config, Storage, Event<T>},536 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},537 Contracts: pallet_contracts::{Module, Call, Config<T>, Storage, Event<T>},538 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},539 Aura: pallet_aura::{Module, Config<T> },540 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},541 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},542 TransactionPayment: pallet_transaction_payment::{Module, Storage},543 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},544 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},545 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},546 Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},547 }548);549550551pub type Address = AccountId;552553pub type Header = generic::Header<BlockNumber, BlakeTwo256>;554555pub type Block = generic::Block<Header, UncheckedExtrinsic>;556557pub type SignedBlock = generic::SignedBlock<Block>;558559pub type BlockId = generic::BlockId<Block>;560561pub type SignedExtra = (562 system::CheckSpecVersion<Runtime>,563 system::CheckTxVersion<Runtime>,564 system::CheckGenesis<Runtime>,565 system::CheckEra<Runtime>,566 system::CheckNonce<Runtime>,567 system::CheckWeight<Runtime>,568 pallet_nft::ChargeTransactionPayment<Runtime>,569);570571pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;572573pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;574575pub type Executive =576 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;577578impl_runtime_apis! {579580 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>581 for Runtime582 {583 fn call(584 origin: AccountId,585 dest: AccountId,586 value: Balance,587 gas_limit: u64,588 input_data: Vec<u8>,589 ) -> pallet_contracts_primitives::ContractExecResult {590 Contracts::bare_call(origin, dest, value, gas_limit, input_data)591 }592593 fn get_storage(594 address: AccountId,595 key: [u8; 32],596 ) -> pallet_contracts_primitives::GetStorageResult {597 Contracts::get_storage(address, key)598 }599600 fn rent_projection(601 address: AccountId,602 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {603 Contracts::rent_projection(address)604 }605 }606607 impl sp_api::Core<Block> for Runtime {608 fn version() -> RuntimeVersion {609 VERSION610 }611612 fn execute_block(block: Block) {613 Executive::execute_block(block)614 }615616 fn initialize_block(header: &<Block as BlockT>::Header) {617 Executive::initialize_block(header)618 }619 }620621 impl sp_api::Metadata<Block> for Runtime {622 fn metadata() -> OpaqueMetadata {623 Runtime::metadata().into()624 }625 }626627 impl sp_block_builder::BlockBuilder<Block> for Runtime {628 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {629 Executive::apply_extrinsic(extrinsic)630 }631632 fn finalize_block() -> <Block as BlockT>::Header {633 Executive::finalize_block()634 }635636 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {637 data.create_extrinsics()638 }639640 fn check_inherents(641 block: Block,642 data: sp_inherents::InherentData,643 ) -> sp_inherents::CheckInherentsResult {644 data.check_extrinsics(&block)645 }646647 fn random_seed() -> <Block as BlockT>::Hash {648 RandomnessCollectiveFlip::random_seed()649 }650 }651652 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {653 fn validate_transaction(654 source: TransactionSource,655 tx: <Block as BlockT>::Extrinsic,656 ) -> TransactionValidity {657 Executive::validate_transaction(source, tx)658 }659 }660661 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {662 fn offchain_worker(header: &<Block as BlockT>::Header) {663 Executive::offchain_worker(header)664 }665 }666667 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {668 fn slot_duration() -> u64 {669 Aura::slot_duration()670 }671672 fn authorities() -> Vec<AuraId> {673 Aura::authorities()674 }675 }676677 impl sp_session::SessionKeys<Block> for Runtime {678 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {679 opaque::SessionKeys::generate(seed)680 }681682 fn decode_session_keys(683 encoded: Vec<u8>,684 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {685 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)686 }687 }688689 impl fg_primitives::GrandpaApi<Block> for Runtime {690 fn grandpa_authorities() -> GrandpaAuthorityList {691 Grandpa::grandpa_authorities()692 }693694 fn submit_report_equivocation_unsigned_extrinsic(695 _equivocation_proof: fg_primitives::EquivocationProof<696 <Block as BlockT>::Hash,697 NumberFor<Block>,698 >,699 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,700 ) -> Option<()> {701 None702 }703704 fn generate_key_ownership_proof(705 _set_id: fg_primitives::SetId,706 _authority_id: GrandpaId,707 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {708 709 710 711 None712 }713 }714 715 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {716 fn account_nonce(account: AccountId) -> Index {717 System::account_nonce(account)718 }719 }720721 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {722 fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {723 TransactionPayment::query_info(uxt, len)724 }725 fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {726 TransactionPayment::query_fee_details(uxt, len)727 }728 }729730 #[cfg(feature = "runtime-benchmarks")]731 impl frame_benchmarking::Benchmark<Block> for Runtime {732 fn dispatch_benchmark(733 config: frame_benchmarking::BenchmarkConfig734 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {735 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};736737 let whitelist: Vec<TrackedStorageKey> = vec![738 739 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),740 741 742 743 744 745 746 747 748 ];749750 let mut batches = Vec::<BenchmarkBatch>::new();751 let params = (&config, &whitelist);752753 add_benchmark!(params, batches, pallet_nft, Nft);754755 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }756 Ok(batches)757 }758 }759}