difftreelog
feat custom collection creation price
in: master
3 files changed
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -434,6 +434,8 @@
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
+
+ type CollectionCreationPrice: Get<BalanceOf<Self>>;
}
#[cfg(feature = "runtime-benchmarks")]
@@ -2535,14 +2537,10 @@
> {
let tip = self.0;
- // Set fee based on call type. Creating collection costs 1 Unique.
- // All other transactions have traditional fees so far
- // let fee = match call.is_sub_type() {
- // Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),
- // _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes
- // // _ => <BalanceOf<T>>::from(100)
- // };
- let fee = Self::traditional_fee(len, info, tip);
+ let fee = match call.is_sub_type() {
+ Some(Call::create_collection(..)) => T::CollectionCreationPrice::get(),
+ _ => Self::traditional_fee(len, info, tip),
+ };
// Only mess with balances if fee is not zero.
if fee.is_zero() {
pallets/nft/src/mock.rsdiffbeforeafterboth--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -133,9 +133,14 @@
type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
}
+parameter_types! {
+ pub const CollectionCreationPrice: u64 = 1_000_000_000_000;
+}
+
impl pallet_template::Config for Test {
type Event = ();
type WeightInfo = ();
+ type CollectionCreationPrice = CollectionCreationPrice;
}
// Build genesis storage according to the mock runtime.
runtime/src/lib.rsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.78#![cfg_attr(not(feature = "std"), no_std)]9// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.10#![recursion_limit = "256"]1112// Make the WASM binary available.13#[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};36// A few exports that help ease life for downstream crates.37pub 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;55// #[cfg(any(feature = "std", test))]56use 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 };6970/// Struct that handles the conversion of Balance -> `u64`. This is used for71/// staking's election calculation.72pub 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}9192/// Re-export a nft pallet93/// TODO: Check this re-export. Is this safe and good style?94extern crate pallet_nft;95pub use pallet_nft::*;9697/// An index to a block.98pub type BlockNumber = u32;99100/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.101pub type Signature = MultiSignature;102103/// Some way of identifying an account on the chain. We intentionally make it equivalent104/// to the public key of our transaction signing scheme.105pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;106107/// The type for looking up accounts. We don't expect more than 4 billion of them, but you108/// never know...109pub type AccountIndex = u32;110111/// Balance of an account.112pub type Balance = u128;113114/// Index of a transaction in the chain.115pub type Index = u32;116117/// A hash of some data used by the chain.118pub type Hash = sp_core::H256;119120/// Digest item type.121pub type DigestItem = generic::DigestItem<Hash>;122123mod nft_weights;124125/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know126/// the specifics of the runtime. They can then be made to be agnostic over specific formats127/// of data like extrinsics, allowing for them to continue syncing the network through upgrades128/// to even the core data structures.129pub mod opaque {130 use super::*;131132 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;133134 /// Opaque block header type.135 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;136 /// Opaque block type.137 pub type Block = generic::Block<Header, UncheckedExtrinsic>;138 /// Opaque block identifier type.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}148149/// This runtime version.150pub 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;163164// These time units are defined in number of blocks.165pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);166pub const HOURS: BlockNumber = MINUTES * 60;167pub const DAYS: BlockNumber = HOURS * 24;168169/// The version information used to identify this runtime when compiled natively.170#[cfg(feature = "std")]171pub fn native_version() -> NativeVersion {172 NativeVersion {173 runtime_version: VERSION,174 can_author_with: Default::default(),175 }176}177178/// Provides a membership set with only the configured aura users179pub 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 // for fees, 100% to treasury222 let mut split = fees.ration(100, 0);223 if let Some(tips) = fees_then_tips.next() {224 // for tips, if any, 100% to treasury225 tips.ration_merge_into(100, 0, &mut split);226 }227 Treasury::on_unbalanced(split.0);228 // Author::on_unbalanced(split.1);229 }230 }231}232233// impl OnUnbalanced<NegativeImbalance> for DealWithFees {234// fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item=NegativeImbalance>) {235// if let Some(fees) = fees_then_tips.next() {236// // for fees, 100% to treasury237// let mut split = fees.ration(100, 0);238// if let Some(tips) = fees_then_tips.next() {239// // for tips, if any, 100% to treasury240// tips.ration_merge_into(100, 0, &mut split);241// }242// Treasury::on_unbalanced(split.0);243// // Author::on_unbalanced(split.1);244// }245// }246// }247248/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.249/// This is used to limit the maximal weight of a single extrinsic.250const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);251/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used252/// by Operational extrinsics.253const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);254/// We allow for 2 seconds of compute with a 6 second average block time.255const 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 // Operational transactions have some extra reserved space, so that they274 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.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 /// The basic call filter to use in dispatchable.287 type BaseCallFilter = ();288 /// The identifier used to distinguish between accounts.289 type AccountId = AccountId;290 /// The aggregated dispatch type that is available for extrinsics.291 type Call = Call;292 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.293 type Lookup = IdentityLookup<AccountId>;294 /// The index type for storing how many extrinsics an account has signed.295 type Index = Index;296 /// The index type for blocks.297 type BlockNumber = BlockNumber;298 /// The type for hashing blocks and tries.299 type Hash = Hash;300 /// The hashing algorithm used.301 type Hashing = BlakeTwo256;302 /// The header type.303 type Header = generic::Header<BlockNumber, BlakeTwo256>;304 /// The ubiquitous event type.305 type Event = Event;306 /// The ubiquitous origin type.307 type Origin = Origin;308 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).309 type BlockHashCount = BlockHashCount;310 /// The weight of database operations that the runtime can invoke.311 type DbWeight = RocksDbWeight;312 /// The weight of the overhead invoked on the block import process, independent of the313 /// extrinsics included in that block.314 type BlockWeights = RuntimeBlockWeights;315 /// Version of the runtime.316 type Version = Version;317 /// This type is being generated by `construct_runtime!`.318 type PalletInfo = PalletInfo;319 /// What to do if a new account is created.320 type OnNewAccount = ();321 /// What to do if an account is fully reaped from the system.322 type OnKilledAccount = ();323 /// The data to be stored in an account.324 type AccountData = pallet_balances::AccountData<Balance>;325 /// Weight information for the extrinsics of this pallet.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 /// A timestamp: milliseconds since the unix epoch.361 type Moment = u64;362 type OnTimestampSet = Aura;363 type MinimumPeriod = MinimumPeriod;364 type WeightInfo = ();365}366367parameter_types! {368 // pub const ExistentialDeposit: u128 = 500;369 pub const ExistentialDeposit: u128 = 0;370 pub const MaxLocks: u32 = 50;371}372373impl pallet_balances::Config for Runtime {374 type MaxLocks = MaxLocks;375 /// The type for recording an account's balance.376 type Balance = Balance;377 /// The ubiquitous event type.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; // 25 Mb 408 // The lazy deletion runs inside on_initialize.409 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *410 RuntimeBlockWeights::get().max_block;411 // The weight needed for decoding the queue should be less or equal than a fifth412 // of the overall weight dedicated to the lazy deletion.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; // Targeting 0.1 Unique per NFT transfer 445}446447/// Linear implementor of `WeightToFeePolynomial` 448pub 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(), // Targeting 0.1 Unique per NFT transfer458 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}522523/// Used for the module nft in `./nft.rs`524impl 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);549550/// The address format for describing accounts.551pub type Address = AccountId;552/// Block header type as expected by this runtime.553pub type Header = generic::Header<BlockNumber, BlakeTwo256>;554/// Block type as expected by this runtime.555pub type Block = generic::Block<Header, UncheckedExtrinsic>;556/// A Block signed with a Justification557pub type SignedBlock = generic::SignedBlock<Block>;558/// BlockId type as expected by this runtime.559pub type BlockId = generic::BlockId<Block>;560/// The SignedExtension to the basic transaction logic.561pub 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);570/// Unchecked extrinsic type as expected by this runtime.571pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;572/// Extrinsic type that has already been checked.573pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;574/// Executive: handles dispatch to the various modules.575pub 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 // NOTE: this is the only implementation possible since we've709 // defined our key owner proof type as a bottom type (i.e. a type710 // with no values).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 // Alice account739 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),740 // // Total Issuance741 // hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),742 // // Execution Phase743 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),744 // // Event Count745 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),746 // // System Events747 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),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}1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.78#![cfg_attr(not(feature = "std"), no_std)]9// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.10#![recursion_limit = "256"]1112// Make the WASM binary available.13#[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};36// A few exports that help ease life for downstream crates.37pub 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;55// #[cfg(any(feature = "std", test))]56use 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 };6970/// Struct that handles the conversion of Balance -> `u64`. This is used for71/// staking's election calculation.72pub 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}9192/// Re-export a nft pallet93/// TODO: Check this re-export. Is this safe and good style?94extern crate pallet_nft;95pub use pallet_nft::*;9697/// An index to a block.98pub type BlockNumber = u32;99100/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.101pub type Signature = MultiSignature;102103/// Some way of identifying an account on the chain. We intentionally make it equivalent104/// to the public key of our transaction signing scheme.105pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;106107/// The type for looking up accounts. We don't expect more than 4 billion of them, but you108/// never know...109pub type AccountIndex = u32;110111/// Balance of an account.112pub type Balance = u128;113114/// Index of a transaction in the chain.115pub type Index = u32;116117/// A hash of some data used by the chain.118pub type Hash = sp_core::H256;119120/// Digest item type.121pub type DigestItem = generic::DigestItem<Hash>;122123mod nft_weights;124125/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know126/// the specifics of the runtime. They can then be made to be agnostic over specific formats127/// of data like extrinsics, allowing for them to continue syncing the network through upgrades128/// to even the core data structures.129pub mod opaque {130 use super::*;131132 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;133134 /// Opaque block header type.135 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;136 /// Opaque block type.137 pub type Block = generic::Block<Header, UncheckedExtrinsic>;138 /// Opaque block identifier type.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}148149/// This runtime version.150pub 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;163164// These time units are defined in number of blocks.165pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);166pub const HOURS: BlockNumber = MINUTES * 60;167pub const DAYS: BlockNumber = HOURS * 24;168169/// The version information used to identify this runtime when compiled natively.170#[cfg(feature = "std")]171pub fn native_version() -> NativeVersion {172 NativeVersion {173 runtime_version: VERSION,174 can_author_with: Default::default(),175 }176}177178/// Provides a membership set with only the configured aura users179pub 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 // for fees, 100% to treasury222 let mut split = fees.ration(100, 0);223 if let Some(tips) = fees_then_tips.next() {224 // for tips, if any, 100% to treasury225 tips.ration_merge_into(100, 0, &mut split);226 }227 Treasury::on_unbalanced(split.0);228 // Author::on_unbalanced(split.1);229 }230 }231}232233// impl OnUnbalanced<NegativeImbalance> for DealWithFees {234// fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item=NegativeImbalance>) {235// if let Some(fees) = fees_then_tips.next() {236// // for fees, 100% to treasury237// let mut split = fees.ration(100, 0);238// if let Some(tips) = fees_then_tips.next() {239// // for tips, if any, 100% to treasury240// tips.ration_merge_into(100, 0, &mut split);241// }242// Treasury::on_unbalanced(split.0);243// // Author::on_unbalanced(split.1);244// }245// }246// }247248/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.249/// This is used to limit the maximal weight of a single extrinsic.250const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);251/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used252/// by Operational extrinsics.253const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);254/// We allow for 2 seconds of compute with a 6 second average block time.255const 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 // Operational transactions have some extra reserved space, so that they274 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.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 /// The basic call filter to use in dispatchable.287 type BaseCallFilter = ();288 /// The identifier used to distinguish between accounts.289 type AccountId = AccountId;290 /// The aggregated dispatch type that is available for extrinsics.291 type Call = Call;292 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.293 type Lookup = IdentityLookup<AccountId>;294 /// The index type for storing how many extrinsics an account has signed.295 type Index = Index;296 /// The index type for blocks.297 type BlockNumber = BlockNumber;298 /// The type for hashing blocks and tries.299 type Hash = Hash;300 /// The hashing algorithm used.301 type Hashing = BlakeTwo256;302 /// The header type.303 type Header = generic::Header<BlockNumber, BlakeTwo256>;304 /// The ubiquitous event type.305 type Event = Event;306 /// The ubiquitous origin type.307 type Origin = Origin;308 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).309 type BlockHashCount = BlockHashCount;310 /// The weight of database operations that the runtime can invoke.311 type DbWeight = RocksDbWeight;312 /// The weight of the overhead invoked on the block import process, independent of the313 /// extrinsics included in that block.314 type BlockWeights = RuntimeBlockWeights;315 /// Version of the runtime.316 type Version = Version;317 /// This type is being generated by `construct_runtime!`.318 type PalletInfo = PalletInfo;319 /// What to do if a new account is created.320 type OnNewAccount = ();321 /// What to do if an account is fully reaped from the system.322 type OnKilledAccount = ();323 /// The data to be stored in an account.324 type AccountData = pallet_balances::AccountData<Balance>;325 /// Weight information for the extrinsics of this pallet.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 /// A timestamp: milliseconds since the unix epoch.361 type Moment = u64;362 type OnTimestampSet = Aura;363 type MinimumPeriod = MinimumPeriod;364 type WeightInfo = ();365}366367parameter_types! {368 // pub const ExistentialDeposit: u128 = 500;369 pub const ExistentialDeposit: u128 = 0;370 pub const MaxLocks: u32 = 50;371}372373impl pallet_balances::Config for Runtime {374 type MaxLocks = MaxLocks;375 /// The type for recording an account's balance.376 type Balance = Balance;377 /// The ubiquitous event type.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; // 25 Mb 408 // The lazy deletion runs inside on_initialize.409 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *410 RuntimeBlockWeights::get().max_block;411 // The weight needed for decoding the queue should be less or equal than a fifth412 // of the overall weight dedicated to the lazy deletion.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; // Targeting 0.1 Unique per NFT transfer 445}446447/// Linear implementor of `WeightToFeePolynomial` 448pub 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(), // Targeting 0.1 Unique per NFT transfer458 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 pub const CollectionCreationPrice: Balance = 100 * UNIQUE;514}515516impl pallet_vesting::Config for Runtime {517 type Event = Event;518 type Currency = Balances;519 type BlockNumberToBalance = ConvertInto;520 type MinVestedTransfer = MinVestedTransfer;521 type WeightInfo = ();522}523524/// Used for the module nft in `./nft.rs`525impl pallet_nft::Config for Runtime {526 type Event = Event;527 type WeightInfo = nft_weights::WeightInfo;528 type CollectionCreationPrice = CollectionCreationPrice;529}530531construct_runtime!(532 pub enum Runtime where533 Block = Block,534 NodeBlock = opaque::Block,535 UncheckedExtrinsic = UncheckedExtrinsic536 {537 System: system::{Module, Call, Config, Storage, Event<T>},538 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},539 Contracts: pallet_contracts::{Module, Call, Config<T>, Storage, Event<T>},540 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},541 Aura: pallet_aura::{Module, Config<T> },542 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},543 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},544 TransactionPayment: pallet_transaction_payment::{Module, Storage},545 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},546 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},547 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},548 Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},549 }550);551552/// The address format for describing accounts.553pub type Address = AccountId;554/// Block header type as expected by this runtime.555pub type Header = generic::Header<BlockNumber, BlakeTwo256>;556/// Block type as expected by this runtime.557pub type Block = generic::Block<Header, UncheckedExtrinsic>;558/// A Block signed with a Justification559pub type SignedBlock = generic::SignedBlock<Block>;560/// BlockId type as expected by this runtime.561pub type BlockId = generic::BlockId<Block>;562/// The SignedExtension to the basic transaction logic.563pub type SignedExtra = (564 system::CheckSpecVersion<Runtime>,565 system::CheckTxVersion<Runtime>,566 system::CheckGenesis<Runtime>,567 system::CheckEra<Runtime>,568 system::CheckNonce<Runtime>,569 system::CheckWeight<Runtime>,570 pallet_nft::ChargeTransactionPayment<Runtime>,571);572/// Unchecked extrinsic type as expected by this runtime.573pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;574/// Extrinsic type that has already been checked.575pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;576/// Executive: handles dispatch to the various modules.577pub type Executive =578 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;579580impl_runtime_apis! {581582 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>583 for Runtime584 {585 fn call(586 origin: AccountId,587 dest: AccountId,588 value: Balance,589 gas_limit: u64,590 input_data: Vec<u8>,591 ) -> pallet_contracts_primitives::ContractExecResult {592 Contracts::bare_call(origin, dest, value, gas_limit, input_data)593 }594595 fn get_storage(596 address: AccountId,597 key: [u8; 32],598 ) -> pallet_contracts_primitives::GetStorageResult {599 Contracts::get_storage(address, key)600 }601602 fn rent_projection(603 address: AccountId,604 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {605 Contracts::rent_projection(address)606 }607 }608609 impl sp_api::Core<Block> for Runtime {610 fn version() -> RuntimeVersion {611 VERSION612 }613614 fn execute_block(block: Block) {615 Executive::execute_block(block)616 }617618 fn initialize_block(header: &<Block as BlockT>::Header) {619 Executive::initialize_block(header)620 }621 }622623 impl sp_api::Metadata<Block> for Runtime {624 fn metadata() -> OpaqueMetadata {625 Runtime::metadata().into()626 }627 }628629 impl sp_block_builder::BlockBuilder<Block> for Runtime {630 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {631 Executive::apply_extrinsic(extrinsic)632 }633634 fn finalize_block() -> <Block as BlockT>::Header {635 Executive::finalize_block()636 }637638 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {639 data.create_extrinsics()640 }641642 fn check_inherents(643 block: Block,644 data: sp_inherents::InherentData,645 ) -> sp_inherents::CheckInherentsResult {646 data.check_extrinsics(&block)647 }648649 fn random_seed() -> <Block as BlockT>::Hash {650 RandomnessCollectiveFlip::random_seed()651 }652 }653654 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {655 fn validate_transaction(656 source: TransactionSource,657 tx: <Block as BlockT>::Extrinsic,658 ) -> TransactionValidity {659 Executive::validate_transaction(source, tx)660 }661 }662663 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {664 fn offchain_worker(header: &<Block as BlockT>::Header) {665 Executive::offchain_worker(header)666 }667 }668669 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {670 fn slot_duration() -> u64 {671 Aura::slot_duration()672 }673674 fn authorities() -> Vec<AuraId> {675 Aura::authorities()676 }677 }678679 impl sp_session::SessionKeys<Block> for Runtime {680 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {681 opaque::SessionKeys::generate(seed)682 }683684 fn decode_session_keys(685 encoded: Vec<u8>,686 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {687 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)688 }689 }690691 impl fg_primitives::GrandpaApi<Block> for Runtime {692 fn grandpa_authorities() -> GrandpaAuthorityList {693 Grandpa::grandpa_authorities()694 }695696 fn submit_report_equivocation_unsigned_extrinsic(697 _equivocation_proof: fg_primitives::EquivocationProof<698 <Block as BlockT>::Hash,699 NumberFor<Block>,700 >,701 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,702 ) -> Option<()> {703 None704 }705706 fn generate_key_ownership_proof(707 _set_id: fg_primitives::SetId,708 _authority_id: GrandpaId,709 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {710 // NOTE: this is the only implementation possible since we've711 // defined our key owner proof type as a bottom type (i.e. a type712 // with no values).713 None714 }715 }716 717 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {718 fn account_nonce(account: AccountId) -> Index {719 System::account_nonce(account)720 }721 }722723 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {724 fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {725 TransactionPayment::query_info(uxt, len)726 }727 fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {728 TransactionPayment::query_fee_details(uxt, len)729 }730 }731732 #[cfg(feature = "runtime-benchmarks")]733 impl frame_benchmarking::Benchmark<Block> for Runtime {734 fn dispatch_benchmark(735 config: frame_benchmarking::BenchmarkConfig736 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {737 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};738739 let whitelist: Vec<TrackedStorageKey> = vec![740 // Alice account741 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),742 // // Total Issuance743 // hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),744 // // Execution Phase745 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),746 // // Event Count747 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),748 // // System Events749 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),750 ];751752 let mut batches = Vec::<BenchmarkBatch>::new();753 let params = (&config, &whitelist);754755 add_benchmark!(params, batches, pallet_nft, Nft);756757 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }758 Ok(batches)759 }760 }761}