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, Perquintill, Percent,23 24 ModuleId, FixedPointNumber,25 create_runtime_str, generic, impl_opaque_keys,26 traits::{27 Convert, ConvertInto, BlakeTwo256, Block as BlockT, IdentifyAccount, 28 IdentityLookup, NumberFor, Verify,29 },30 transaction_validity::{TransactionSource, TransactionValidity},31 ApplyExtrinsicResult, MultiSignature,32};33use sp_std::prelude::*;34#[cfg(feature = "std")]35use sp_version::NativeVersion;36use sp_version::RuntimeVersion;37pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment, CurrencyAdapter, FeeDetails, RuntimeDispatchInfo};3839pub use pallet_balances::Call as BalancesCall;40pub use pallet_contracts::Schedule as ContractsSchedule;41use pallet_contracts::WeightInfo;42pub use frame_support::{43 construct_runtime,44 dispatch::DispatchResult,45 parameter_types,46 traits::{47 Currency, ExistenceRequirement, Get, KeyOwnerProofSystem, OnUnbalanced, Randomness,48 LockIdentifier,49 },50 weights::{51 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},52 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,53 WeightToFeePolynomial,54 },55 StorageValue,56};5758use frame_system::{59 self as system,60 EnsureRoot, 61 limits::{BlockWeights, BlockLength}};62use sp_std::{marker::PhantomData};6364pub use pallet_timestamp::Call as TimestampCall;6566mod chain_extension;67use crate::chain_extension::NFTExtension;68697071pub struct CurrencyToVoteHandler;7273impl CurrencyToVoteHandler {74 fn factor() -> Balance {75 (Balances::total_issuance() / u64::max_value() as Balance).max(1)76 }77}7879impl Convert<Balance, u64> for CurrencyToVoteHandler {80 fn convert(x: Balance) -> u64 {81 (x / Self::factor()) as u6482 }83}8485impl Convert<u128, Balance> for CurrencyToVoteHandler {86 fn convert(x: u128) -> Balance {87 x * Self::factor()88 }89}90919293extern crate pallet_nft;94pub use pallet_nft::*;959697pub type BlockNumber = u32;9899100pub type Signature = MultiSignature;101102103104pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;105106107108pub type AccountIndex = u32;109110111pub type Balance = u128;112113114pub type Index = u32;115116117pub type Hash = sp_core::H256;118119120pub type DigestItem = generic::DigestItem<Hash>;121122mod nft_weights;123124125126127128pub mod opaque {129 use super::*;130131 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;132133 134 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;135 136 pub type Block = generic::Block<Header, UncheckedExtrinsic>;137 138 pub type BlockId = generic::BlockId<Block>;139140 impl_opaque_keys! {141 pub struct SessionKeys {142 pub aura: Aura,143 pub grandpa: Grandpa,144 }145 }146}147148149pub const VERSION: RuntimeVersion = RuntimeVersion {150 spec_name: create_runtime_str!("nft"),151 impl_name: create_runtime_str!("nft"),152 authoring_version: 1,153 spec_version: 3,154 impl_version: 1,155 apis: RUNTIME_API_VERSIONS,156 transaction_version: 1,157};158159pub const MILLISECS_PER_BLOCK: u64 = 6000;160161pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;162163164pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);165pub const HOURS: BlockNumber = MINUTES * 60;166pub const DAYS: BlockNumber = HOURS * 24;167168169#[cfg(feature = "std")]170pub fn native_version() -> NativeVersion {171 NativeVersion {172 runtime_version: VERSION,173 can_author_with: Default::default(),174 }175}176177178pub struct ValiudatorsOnly<Runtime: pallet_aura::Config>(PhantomData<Runtime>);179impl frame_support::traits::Contains<AccountId> for ValiudatorsOnly<Runtime> {180 fn contains(t: &AccountId) -> bool {181 let arr: [u8; 32] = *t.as_ref();182 let raw_key: Vec<u8> = Vec::from(arr);183184 match pallet_aura::Module::<Runtime>::authorities().iter().find(|auth| auth.to_raw_vec() == raw_key) {185 Some(_) => true,186 None => false,187 } 188 }189 fn sorted_members() -> Vec<AccountId> {190 let mut members: Vec<AccountId> = Vec::new();191 for auth in pallet_aura::Module::<Runtime>::authorities() {192 let mut arr: [u8; 32] = Default::default(); 193 let bor_arr = auth.clone().to_raw_vec();194 let slice = bor_arr.as_slice();195 arr.copy_from_slice(slice);196 members.push(AccountId::from(arr));197 }198 members 199 }200 fn count() -> usize {201 pallet_aura::Module::<Runtime>::authorities().len()202 }203}204205impl frame_support::traits::ContainsLengthBound for ValiudatorsOnly<Runtime> {206 fn min_len() -> usize {207 1208 }209 fn max_len() -> usize {210 100211 }212}213214type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;215216pub struct DealWithFees;217impl OnUnbalanced<NegativeImbalance> for DealWithFees {218 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item=NegativeImbalance>) {219 if let Some(fees) = fees_then_tips.next() {220 221 let mut split = fees.ration(80, 20);222 if let Some(tips) = fees_then_tips.next() {223 224 tips.ration_merge_into(80, 20, &mut split);225 }226 Treasury::on_unbalanced(split.0);227 228 }229 }230}231232233234const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);235236237const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);238239const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND;240241parameter_types! {242 pub const BlockHashCount: BlockNumber = 2400;243 pub RuntimeBlockLength: BlockLength =244 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);245 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);246 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;247 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()248 .base_block(BlockExecutionWeight::get())249 .for_class(DispatchClass::all(), |weights| {250 weights.base_extrinsic = ExtrinsicBaseWeight::get();251 })252 .for_class(DispatchClass::Normal, |weights| {253 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);254 })255 .for_class(DispatchClass::Operational, |weights| {256 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);257 258 259 weights.reserved = Some(260 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT261 );262 })263 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)264 .build_or_panic();265 pub const Version: RuntimeVersion = VERSION;266 pub const SS58Prefix: u8 = 42;267}268269impl system::Config for Runtime {270 271 type BaseCallFilter = ();272 273 type AccountId = AccountId;274 275 type Call = Call;276 277 type Lookup = IdentityLookup<AccountId>;278 279 type Index = Index;280 281 type BlockNumber = BlockNumber;282 283 type Hash = Hash;284 285 type Hashing = BlakeTwo256;286 287 type Header = generic::Header<BlockNumber, BlakeTwo256>;288 289 type Event = Event;290 291 type Origin = Origin;292 293 type BlockHashCount = BlockHashCount;294 295 type DbWeight = RocksDbWeight;296 297 298 type BlockWeights = RuntimeBlockWeights;299 300 type Version = Version;301 302 type PalletInfo = PalletInfo;303 304 type OnNewAccount = ();305 306 type OnKilledAccount = ();307 308 type AccountData = pallet_balances::AccountData<Balance>;309 310 type SystemWeightInfo = system::weights::SubstrateWeight<Runtime>;311 312 type BlockLength = RuntimeBlockLength;313 type SS58Prefix = SS58Prefix;314}315316impl pallet_aura::Config for Runtime {317 type AuthorityId = AuraId;318}319320impl pallet_grandpa::Config for Runtime {321 type Event = Event;322 type Call = Call;323324 type KeyOwnerProofSystem = ();325326 type KeyOwnerProof =327 <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;328329 type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(330 KeyTypeId,331 GrandpaId,332 )>>::IdentificationTuple;333334 type HandleEquivocation = ();335336 type WeightInfo = ();337}338339parameter_types! {340 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;341}342343impl pallet_timestamp::Config for Runtime {344 345 type Moment = u64;346 type OnTimestampSet = Aura;347 type MinimumPeriod = MinimumPeriod;348 type WeightInfo = ();349}350351parameter_types! {352 353 pub const ExistentialDeposit: u128 = 0;354 pub const MaxLocks: u32 = 50;355}356357impl pallet_balances::Config for Runtime {358 type MaxLocks = MaxLocks;359 360 type Balance = Balance;361 362 type Event = Event;363 type DustRemoval = Treasury;364 type ExistentialDeposit = ExistentialDeposit;365 type AccountStore = System;366 type WeightInfo = ();367}368369pub const MILLICENTS: Balance = 1_000_000_000;370pub const CENTS: Balance = 1_000 * MILLICENTS;371pub const DOLLARS: Balance = 100 * CENTS;372373pub const fn deposit(items: u32, bytes: u32) -> Balance {374 items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS375}376377parameter_types! {378 pub const TombstoneDeposit: Balance = deposit(379 0,380 sp_std::mem::size_of::<pallet_contracts::ContractInfo<Runtime>>() as u32381 );382 pub const DepositPerContract: Balance = TombstoneDeposit::get();383 pub const DepositPerStorageByte: Balance = deposit(0, 1);384 pub const DepositPerStorageItem: Balance = deposit(1, 0);385 pub RentFraction: Perbill = Perbill::from_rational_approximation(1u32, 30 * DAYS);386 pub const SurchargeReward: Balance = 150 * MILLICENTS;387 pub const SignedClaimHandicap: u32 = 2;388 pub const MaxDepth: u32 = 32;389 pub const MaxValueSize: u32 = 16 * 1024;390 391 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *392 RuntimeBlockWeights::get().max_block;393 394 395 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (396 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -397 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)398 )) / 5) as u32;399}400401402impl pallet_contracts::Config for Runtime {403 type Time = Timestamp;404 type Randomness = RandomnessCollectiveFlip;405 type Currency = Balances;406 type Event = Event;407 type RentPayment = ();408 type SignedClaimHandicap = SignedClaimHandicap;409 type TombstoneDeposit = TombstoneDeposit;410 type DepositPerContract = DepositPerContract;411 type DepositPerStorageByte = DepositPerStorageByte;412 type DepositPerStorageItem = DepositPerStorageItem;413 type RentFraction = RentFraction;414 type SurchargeReward = SurchargeReward;415 type MaxDepth = MaxDepth;416 type MaxValueSize = MaxValueSize;417 type WeightPrice = pallet_transaction_payment::Module<Self>;418 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;419 type ChainExtension = NFTExtension;420 type DeletionQueueDepth = DeletionQueueDepth;421 type DeletionWeightLimit = DeletionWeightLimit;422}423424parameter_types! {425 pub const TransactionByteFee: Balance = 10 * MILLICENTS;426 pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);427 pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(1, 100_000);428 pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000_000u128);429}430431impl pallet_transaction_payment::Config for Runtime {432 type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;433 type TransactionByteFee = TransactionByteFee;434 type WeightToFee = IdentityFee<Balance>;435 type FeeMultiplierUpdate =436 TargetedFeeAdjustment<Self, TargetBlockFullness, AdjustmentVariable, MinimumMultiplier>;437}438439parameter_types! {440 pub const ProposalBond: Permill = Permill::from_percent(5);441 pub const ProposalBondMinimum: Balance = 1 * DOLLARS;442 pub const SpendPeriod: BlockNumber = 5 * MINUTES;443 pub const Burn: Permill = Permill::from_percent(0);444 pub const TipCountdown: BlockNumber = 1 * DAYS;445 pub const TipFindersFee: Percent = Percent::from_percent(20);446 pub const TipReportDepositBase: Balance = 1 * DOLLARS;447 pub const DataDepositPerByte: Balance = 1 * CENTS;448 pub const BountyDepositBase: Balance = 1 * DOLLARS;449 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;450 pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry");451 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;452 pub const MaximumReasonLength: u32 = 16384;453 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);454 pub const BountyValueMinimum: Balance = 5 * DOLLARS;455}456457impl pallet_treasury::Config for Runtime {458 type ModuleId = TreasuryModuleId;459 type Currency = Balances;460 type ApproveOrigin = EnsureRoot<AccountId>;461 type RejectOrigin = EnsureRoot<AccountId>;462 type Event = Event;463 type OnSlash = ();464 type ProposalBond = ProposalBond;465 type ProposalBondMinimum = ProposalBondMinimum;466 type SpendPeriod = SpendPeriod;467 type Burn = Burn;468 type BurnDestination = ();469 type SpendFunds = ();470 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Runtime>;471}472473impl pallet_sudo::Config for Runtime {474 type Event = Event;475 type Call = Call;476}477478parameter_types! {479 pub const MinVestedTransfer: Balance = 100 * DOLLARS;480}481482impl pallet_vesting::Config for Runtime {483 type Event = Event;484 type Currency = Balances;485 type BlockNumberToBalance = ConvertInto;486 type MinVestedTransfer = MinVestedTransfer;487 type WeightInfo = ();488}489490491impl pallet_nft::Config for Runtime {492 type Event = Event;493 type WeightInfo = nft_weights::WeightInfo;494}495496construct_runtime!(497 pub enum Runtime where498 Block = Block,499 NodeBlock = opaque::Block,500 UncheckedExtrinsic = UncheckedExtrinsic501 {502 System: system::{Module, Call, Config, Storage, Event<T>},503 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},504 Contracts: pallet_contracts::{Module, Call, Config<T>, Storage, Event<T>},505 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},506 Aura: pallet_aura::{Module, Config<T>, Inherent},507 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},508 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},509 TransactionPayment: pallet_transaction_payment::{Module, Storage},510 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},511 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},512 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},513 Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},514 }515);516517518pub type Address = AccountId;519520pub type Header = generic::Header<BlockNumber, BlakeTwo256>;521522pub type Block = generic::Block<Header, UncheckedExtrinsic>;523524pub type SignedBlock = generic::SignedBlock<Block>;525526pub type BlockId = generic::BlockId<Block>;527528pub type SignedExtra = (529 system::CheckSpecVersion<Runtime>,530 system::CheckTxVersion<Runtime>,531 system::CheckGenesis<Runtime>,532 system::CheckEra<Runtime>,533 system::CheckNonce<Runtime>,534 system::CheckWeight<Runtime>,535 pallet_nft::ChargeTransactionPayment<Runtime>,536);537538pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;539540pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;541542pub type Executive =543 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;544545impl_runtime_apis! {546547 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>548 for Runtime549 {550 fn call(551 origin: AccountId,552 dest: AccountId,553 value: Balance,554 gas_limit: u64,555 input_data: Vec<u8>,556 ) -> pallet_contracts_primitives::ContractExecResult {557 Contracts::bare_call(origin, dest, value, gas_limit, input_data)558 }559560 fn get_storage(561 address: AccountId,562 key: [u8; 32],563 ) -> pallet_contracts_primitives::GetStorageResult {564 Contracts::get_storage(address, key)565 }566567 fn rent_projection(568 address: AccountId,569 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {570 Contracts::rent_projection(address)571 }572 }573574 impl sp_api::Core<Block> for Runtime {575 fn version() -> RuntimeVersion {576 VERSION577 }578579 fn execute_block(block: Block) {580 Executive::execute_block(block)581 }582583 fn initialize_block(header: &<Block as BlockT>::Header) {584 Executive::initialize_block(header)585 }586 }587588 impl sp_api::Metadata<Block> for Runtime {589 fn metadata() -> OpaqueMetadata {590 Runtime::metadata().into()591 }592 }593594 impl sp_block_builder::BlockBuilder<Block> for Runtime {595 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {596 Executive::apply_extrinsic(extrinsic)597 }598599 fn finalize_block() -> <Block as BlockT>::Header {600 Executive::finalize_block()601 }602603 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {604 data.create_extrinsics()605 }606607 fn check_inherents(608 block: Block,609 data: sp_inherents::InherentData,610 ) -> sp_inherents::CheckInherentsResult {611 data.check_extrinsics(&block)612 }613614 fn random_seed() -> <Block as BlockT>::Hash {615 RandomnessCollectiveFlip::random_seed()616 }617 }618619 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {620 fn validate_transaction(621 source: TransactionSource,622 tx: <Block as BlockT>::Extrinsic,623 ) -> TransactionValidity {624 Executive::validate_transaction(source, tx)625 }626 }627628 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {629 fn offchain_worker(header: &<Block as BlockT>::Header) {630 Executive::offchain_worker(header)631 }632 }633634 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {635 fn slot_duration() -> u64 {636 Aura::slot_duration()637 }638639 fn authorities() -> Vec<AuraId> {640 Aura::authorities()641 }642 }643644 impl sp_session::SessionKeys<Block> for Runtime {645 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {646 opaque::SessionKeys::generate(seed)647 }648649 fn decode_session_keys(650 encoded: Vec<u8>,651 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {652 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)653 }654 }655656 impl fg_primitives::GrandpaApi<Block> for Runtime {657 fn grandpa_authorities() -> GrandpaAuthorityList {658 Grandpa::grandpa_authorities()659 }660661 fn submit_report_equivocation_unsigned_extrinsic(662 _equivocation_proof: fg_primitives::EquivocationProof<663 <Block as BlockT>::Hash,664 NumberFor<Block>,665 >,666 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,667 ) -> Option<()> {668 None669 }670671 fn generate_key_ownership_proof(672 _set_id: fg_primitives::SetId,673 _authority_id: GrandpaId,674 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {675 676 677 678 None679 }680 }681 682 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {683 fn account_nonce(account: AccountId) -> Index {684 System::account_nonce(account)685 }686 }687688 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {689 fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {690 TransactionPayment::query_info(uxt, len)691 }692 fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {693 TransactionPayment::query_fee_details(uxt, len)694 }695 }696697 #[cfg(feature = "runtime-benchmarks")]698 impl frame_benchmarking::Benchmark<Block> for Runtime {699 fn dispatch_benchmark(700 config: frame_benchmarking::BenchmarkConfig701 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {702 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};703704 let whitelist: Vec<TrackedStorageKey> = vec![705 706 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),707 708 709 710 711 712 713 714 715 ];716717 let mut batches = Vec::<BenchmarkBatch>::new();718 let params = (&config, &whitelist);719720 add_benchmark!(params, batches, pallet_nft, Nft);721722 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }723 Ok(batches)724 }725 }726}