difftreelog
Merge pull request #66 from usetech-llc/feature/NFTPAR-280
in: master
Feature/nftpar 280
3 files changed
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -419,6 +419,7 @@
pub AddressTokens get(fn address_tokens): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => Vec<TokenId>;
/// Tokens transfer baskets
+ pub CreateItemBasket get(fn create_item_basket): map hasher(twox_64_concat) (CollectionId, T::AccountId) => T::BlockNumber;
pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;
pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => T::BlockNumber;
pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;
@@ -2297,9 +2298,26 @@
let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {
Some(Call::create_item(collection_id, _owner, _properties)) => {
+ // sponsor timeout
+ let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
+
+ let limit = <Collection<T>>::get(collection_id).limits.sponsor_transfer_timeout;
+ let mut sponsored = true;
+ if <CreateItemBasket<T>>::contains_key((collection_id, &who)) {
+ let last_tx_block = <CreateItemBasket<T>>::get((collection_id, &who));
+ let limit_time = last_tx_block + limit.into();
+ if block_number <= limit_time {
+ sponsored = false;
+ }
+ }
+ if sponsored {
+ <CreateItemBasket<T>>::insert((collection_id, who.clone()), block_number);
+ }
+
// check free create limit
if (<Collection<T>>::get(collection_id).limits.sponsored_data_size >= (_properties.len() as u32)) &&
- (<Collection<T>>::get(collection_id).sponsor_confirmed)
+ (<Collection<T>>::get(collection_id).sponsor_confirmed) &&
+ (sponsored)
{
<Collection<T>>::get(collection_id).sponsor
} else {
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_contracts_rpc_runtime_api::ContractExecResult;17use pallet_grandpa::fg_primitives;18use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};19use sp_api::impl_runtime_apis;20use sp_consensus_aura::sr25519::AuthorityId as AuraId;21use sp_core::{ crypto::KeyTypeId, crypto::Public, OpaqueMetadata };22use sp_runtime::{23 create_runtime_str, generic, impl_opaque_keys,24 traits::{25 Convert, ConvertInto, BlakeTwo256, Block as BlockT, IdentifyAccount, 26 IdentityLookup, NumberFor, Saturating, Verify,27 },28 transaction_validity::{TransactionSource, TransactionValidity},29 ApplyExtrinsicResult, MultiSignature,30};31use sp_std::prelude::*;32#[cfg(feature = "std")]33use sp_version::NativeVersion;34use sp_version::RuntimeVersion;3536// 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 traits::{44 Currency, ExistenceRequirement, Get, KeyOwnerProofSystem, OnUnbalanced, Randomness,45 WithdrawReason, LockIdentifier,46 },47 weights::{48 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},49 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,50 WeightToFeePolynomial,51 },52 StorageValue,53};54#[cfg(any(feature = "std", test))]55pub use sp_runtime::BuildStorage;56use sp_runtime:: { Perbill, Permill, Percent, ModuleId };57use frame_system::{self as system, EnsureRoot };58use sp_std::{marker::PhantomData};5960pub use pallet_timestamp::Call as TimestampCall;6162/// Struct that handles the conversion of Balance -> `u64`. This is used for63/// staking's election calculation.64pub struct CurrencyToVoteHandler;6566impl CurrencyToVoteHandler {67 fn factor() -> Balance {68 (Balances::total_issuance() / u64::max_value() as Balance).max(1)69 }70}7172impl Convert<Balance, u64> for CurrencyToVoteHandler {73 fn convert(x: Balance) -> u64 {74 (x / Self::factor()) as u6475 }76}7778impl Convert<u128, Balance> for CurrencyToVoteHandler {79 fn convert(x: u128) -> Balance {80 x * Self::factor()81 }82}8384/// Re-export a nft pallet85/// TODO: Check this re-export. Is this safe and good style?86extern crate pallet_nft;87pub use pallet_nft::*;8889/// An index to a block.90pub type BlockNumber = u32;9192/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.93pub type Signature = MultiSignature;9495/// Some way of identifying an account on the chain. We intentionally make it equivalent96/// to the public key of our transaction signing scheme.97pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;9899/// The type for looking up accounts. We don't expect more than 4 billion of them, but you100/// never know...101pub type AccountIndex = u32;102103/// Balance of an account.104pub type Balance = u128;105106/// Index of a transaction in the chain.107pub type Index = u32;108109/// A hash of some data used by the chain.110pub type Hash = sp_core::H256;111112/// Digest item type.113pub type DigestItem = generic::DigestItem<Hash>;114115mod nft_weights;116117/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know118/// the specifics of the runtime. They can then be made to be agnostic over specific formats119/// of data like extrinsics, allowing for them to continue syncing the network through upgrades120/// to even the core data structures.121pub mod opaque {122 use super::*;123124 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;125126 /// Opaque block header type.127 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;128 /// Opaque block type.129 pub type Block = generic::Block<Header, UncheckedExtrinsic>;130 /// Opaque block identifier type.131 pub type BlockId = generic::BlockId<Block>;132133 impl_opaque_keys! {134 pub struct SessionKeys {135 pub aura: Aura,136 pub grandpa: Grandpa,137 }138 }139}140141/// This runtime version.142pub const VERSION: RuntimeVersion = RuntimeVersion {143 spec_name: create_runtime_str!("nft"),144 impl_name: create_runtime_str!("nft"),145 authoring_version: 1,146 spec_version: 2,147 impl_version: 1,148 apis: RUNTIME_API_VERSIONS,149 transaction_version: 1,150};151152pub const MILLISECS_PER_BLOCK: u64 = 6000;153154pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;155156// These time units are defined in number of blocks.157pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);158pub const HOURS: BlockNumber = MINUTES * 60;159pub const DAYS: BlockNumber = HOURS * 24;160161/// The version information used to identify this runtime when compiled natively.162#[cfg(feature = "std")]163pub fn native_version() -> NativeVersion {164 NativeVersion {165 runtime_version: VERSION,166 can_author_with: Default::default(),167 }168}169170/// Provides a membership set with only the configured aura users171pub struct ValiudatorsOnly<Runtime: pallet_aura::Trait>(PhantomData<Runtime>);172impl frame_support::traits::Contains<AccountId> for ValiudatorsOnly<Runtime> {173 fn contains(t: &AccountId) -> bool {174 let arr: [u8; 32] = *t.as_ref();175 let raw_key: Vec<u8> = Vec::from(arr);176177 match pallet_aura::Module::<Runtime>::authorities().iter().find(|auth| auth.to_raw_vec() == raw_key) {178 Some(_) => true,179 None => false,180 } 181 }182 fn sorted_members() -> Vec<AccountId> {183 let mut members: Vec<AccountId> = Vec::new();184 for auth in pallet_aura::Module::<Runtime>::authorities() {185 let mut arr: [u8; 32] = Default::default(); 186 let bor_arr = auth.clone().to_raw_vec();187 let slice = bor_arr.as_slice();188 arr.copy_from_slice(slice);189 members.push(AccountId::from(arr));190 }191 members 192 }193 fn count() -> usize {194 pallet_aura::Module::<Runtime>::authorities().len()195 }196}197198impl frame_support::traits::ContainsLengthBound for ValiudatorsOnly<Runtime> {199 fn min_len() -> usize {200 1201 }202 fn max_len() -> usize {203 100204 }205}206207parameter_types! {208 pub const BlockHashCount: BlockNumber = 2400;209 /// We allow for 2 seconds of compute with a 6 second average block time.210 pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND;211 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);212 /// Assume 10% of weight for average on_initialize calls.213 pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()214 .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();215 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;216 pub const Version: RuntimeVersion = VERSION;217}218219impl system::Trait for Runtime {220 /// The basic call filter to use in dispatchable.221 type BaseCallFilter = ();222 /// The identifier used to distinguish between accounts.223 type AccountId = AccountId;224 /// The aggregated dispatch type that is available for extrinsics.225 type Call = Call;226 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.227 type Lookup = IdentityLookup<AccountId>;228 /// The index type for storing how many extrinsics an account has signed.229 type Index = Index;230 /// The index type for blocks.231 type BlockNumber = BlockNumber;232 /// The type for hashing blocks and tries.233 type Hash = Hash;234 /// The hashing algorithm used.235 type Hashing = BlakeTwo256;236 /// The header type.237 type Header = generic::Header<BlockNumber, BlakeTwo256>;238 /// The ubiquitous event type.239 type Event = Event;240 /// The ubiquitous origin type.241 type Origin = Origin;242 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).243 type BlockHashCount = BlockHashCount;244 /// Maximum weight of each block.245 type MaximumBlockWeight = MaximumBlockWeight;246 /// The weight of database operations that the runtime can invoke.247 type DbWeight = RocksDbWeight;248 /// The weight of the overhead invoked on the block import process, independent of the249 /// extrinsics included in that block.250 type BlockExecutionWeight = BlockExecutionWeight;251 /// The base weight of any extrinsic processed by the runtime, independent of the252 /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...)253 type ExtrinsicBaseWeight = ExtrinsicBaseWeight;254 /// The maximum weight that a single extrinsic of `Normal` dispatch class can have,255 /// idependent of the logic of that extrinsics. (Roughly max block weight - average on256 /// initialize cost).257 type MaximumExtrinsicWeight = MaximumExtrinsicWeight;258 /// Maximum size of all encoded transactions (in bytes) that are allowed in one block.259 type MaximumBlockLength = MaximumBlockLength;260 /// Portion of the block weight that is available to all normal transactions.261 type AvailableBlockRatio = AvailableBlockRatio;262 /// Version of the runtime.263 type Version = Version;264 /// This type is being generated by `construct_runtime!`.265 type PalletInfo = PalletInfo;266 /// What to do if a new account is created.267 type OnNewAccount = ();268 /// What to do if an account is fully reaped from the system.269 type OnKilledAccount = ();270 /// The data to be stored in an account.271 type AccountData = pallet_balances::AccountData<Balance>;272 /// Weight information for the extrinsics of this pallet.273 type SystemWeightInfo = ();274}275276impl pallet_aura::Trait for Runtime {277 type AuthorityId = AuraId;278}279280impl pallet_grandpa::Trait for Runtime {281 type Event = Event;282 type Call = Call;283284 type KeyOwnerProofSystem = ();285286 type KeyOwnerProof =287 <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;288289 type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(290 KeyTypeId,291 GrandpaId,292 )>>::IdentificationTuple;293294 type HandleEquivocation = ();295296 type WeightInfo = ();297}298299parameter_types! {300 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;301}302303impl pallet_timestamp::Trait for Runtime {304 /// A timestamp: milliseconds since the unix epoch.305 type Moment = u64;306 type OnTimestampSet = Aura;307 type MinimumPeriod = MinimumPeriod;308 type WeightInfo = ();309}310311parameter_types! {312 // pub const ExistentialDeposit: u128 = 500;313 pub const ExistentialDeposit: u128 = 0;314 pub const MaxLocks: u32 = 50;315}316317impl pallet_balances::Trait for Runtime {318 type MaxLocks = MaxLocks;319 /// The type for recording an account's balance.320 type Balance = Balance;321 /// The ubiquitous event type.322 type Event = Event;323 type DustRemoval = Treasury;324 type ExistentialDeposit = ExistentialDeposit;325 type AccountStore = System;326 type WeightInfo = ();327}328329pub const MILLICENTS: Balance = 1_000_000_000;330pub const CENTS: Balance = 1_000 * MILLICENTS;331pub const DOLLARS: Balance = 100 * CENTS;332333parameter_types! {334 pub const TombstoneDeposit: Balance = 0;335 pub const RentByteFee: Balance = 4 * MILLICENTS;336 pub const RentDepositOffset: Balance = 1000 * MILLICENTS;337 pub const SurchargeReward: Balance = 150 * MILLICENTS;338}339340impl pallet_contracts::Trait for Runtime {341 type Time = Timestamp;342 type Randomness = RandomnessCollectiveFlip;343 type Currency = Balances;344 type Event = Event;345 type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer<Runtime>;346 type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter<Runtime>;347 type RentPayment = ();348 type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;349 type TombstoneDeposit = TombstoneDeposit;350 type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;351 type RentByteFee = RentByteFee;352 type RentDepositOffset = RentDepositOffset;353 type SurchargeReward = SurchargeReward;354 type MaxDepth = pallet_contracts::DefaultMaxDepth;355 type MaxValueSize = pallet_contracts::DefaultMaxValueSize;356 type WeightPrice = pallet_transaction_payment::Module<Self>;357}358359parameter_types! {360 pub const TransactionByteFee: Balance = 10 * MILLICENTS;361}362363impl pallet_transaction_payment::Trait for Runtime {364 type Currency = pallet_balances::Module<Runtime>;365 type OnTransactionPayment = Treasury;366 type TransactionByteFee = TransactionByteFee;367 type WeightToFee = IdentityFee<Balance>;368 type FeeMultiplierUpdate = ();369}370371parameter_types! {372 pub const ProposalBond: Permill = Permill::from_percent(5);373 pub const ProposalBondMinimum: Balance = 1 * DOLLARS;374 pub const SpendPeriod: BlockNumber = 5 * MINUTES;375 pub const Burn: Permill = Permill::from_percent(0);376 pub const TipCountdown: BlockNumber = 1 * DAYS;377 pub const TipFindersFee: Percent = Percent::from_percent(20);378 pub const TipReportDepositBase: Balance = 1 * DOLLARS;379 pub const DataDepositPerByte: Balance = 1 * CENTS;380 pub const BountyDepositBase: Balance = 1 * DOLLARS;381 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;382 pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry");383 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;384 pub const MaximumReasonLength: u32 = 16384;385 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);386 pub const BountyValueMinimum: Balance = 5 * DOLLARS;387}388389impl pallet_treasury::Trait for Runtime {390 type ModuleId = TreasuryModuleId;391 type Currency = Balances;392 type ApproveOrigin = EnsureRoot<AccountId>;393 type RejectOrigin = EnsureRoot<AccountId>;394 type Tippers = ValiudatorsOnly<Self>;395 type TipCountdown = TipCountdown;396 type TipFindersFee = TipFindersFee;397 type TipReportDepositBase = TipReportDepositBase;398 type DataDepositPerByte = DataDepositPerByte;399 type Event = Event;400 type OnSlash = ();401 type ProposalBond = ProposalBond;402 type ProposalBondMinimum = ProposalBondMinimum;403 type SpendPeriod = SpendPeriod;404 type Burn = Burn;405 type BountyDepositBase = BountyDepositBase;406 type BountyDepositPayoutDelay = BountyDepositPayoutDelay;407 type BountyUpdatePeriod = BountyUpdatePeriod;408 type BountyCuratorDeposit = BountyCuratorDeposit;409 type BountyValueMinimum = BountyValueMinimum;410 type MaximumReasonLength = MaximumReasonLength;411 type BurnDestination = ();412 type WeightInfo = ();413}414415impl pallet_sudo::Trait for Runtime {416 type Event = Event;417 type Call = Call;418}419420parameter_types! {421 pub const MinVestedTransfer: Balance = 100 * DOLLARS;422}423424impl pallet_vesting::Trait for Runtime {425 type Event = Event;426 type Currency = Balances;427 type BlockNumberToBalance = ConvertInto;428 type MinVestedTransfer = MinVestedTransfer;429 type WeightInfo = ();430}431432/// Used for the module nft in `./nft.rs`433impl pallet_nft::Trait for Runtime {434 type Event = Event;435 type WeightInfo = nft_weights::WeightInfo;436}437438construct_runtime!(439 pub enum Runtime where440 Block = Block,441 NodeBlock = opaque::Block,442 UncheckedExtrinsic = UncheckedExtrinsic443 {444 System: system::{Module, Call, Config, Storage, Event<T>},445 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},446 Contracts: pallet_contracts::{Module, Call, Config, Storage, Event<T>},447 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},448 Aura: pallet_aura::{Module, Config<T>, Inherent},449 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},450 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},451 TransactionPayment: pallet_transaction_payment::{Module, Storage},452 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},453 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},454 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},455 Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},456 }457);458459/// The address format for describing accounts.460pub type Address = AccountId;461/// Block header type as expected by this runtime.462pub type Header = generic::Header<BlockNumber, BlakeTwo256>;463/// Block type as expected by this runtime.464pub type Block = generic::Block<Header, UncheckedExtrinsic>;465/// A Block signed with a Justification466pub type SignedBlock = generic::SignedBlock<Block>;467/// BlockId type as expected by this runtime.468pub type BlockId = generic::BlockId<Block>;469/// The SignedExtension to the basic transaction logic.470pub type SignedExtra = (471 system::CheckSpecVersion<Runtime>,472 system::CheckTxVersion<Runtime>,473 system::CheckGenesis<Runtime>,474 system::CheckEra<Runtime>,475 system::CheckNonce<Runtime>,476 system::CheckWeight<Runtime>,477 pallet_nft::ChargeTransactionPayment<Runtime>,478);479/// Unchecked extrinsic type as expected by this runtime.480pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;481/// Extrinsic type that has already been checked.482pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;483/// Executive: handles dispatch to the various modules.484pub type Executive =485 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;486487impl_runtime_apis! {488489 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>490 for Runtime491 {492 fn call(493 origin: AccountId,494 dest: AccountId,495 value: Balance,496 gas_limit: u64,497 input_data: Vec<u8>,498 ) -> ContractExecResult {499 let (exec_result, gas_consumed) =500 Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);501 match exec_result {502 Ok(v) => ContractExecResult::Success {503 flags: v.flags.bits(),504 data: v.data,505 gas_consumed: gas_consumed,506 },507 Err(_) => ContractExecResult::Error,508 }509 }510511 fn get_storage(512 address: AccountId,513 key: [u8; 32],514 ) -> pallet_contracts_primitives::GetStorageResult {515 Contracts::get_storage(address, key)516 }517518 fn rent_projection(519 address: AccountId,520 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {521 Contracts::rent_projection(address)522 }523 }524525 impl sp_api::Core<Block> for Runtime {526 fn version() -> RuntimeVersion {527 VERSION528 }529530 fn execute_block(block: Block) {531 Executive::execute_block(block)532 }533534 fn initialize_block(header: &<Block as BlockT>::Header) {535 Executive::initialize_block(header)536 }537 }538539 impl sp_api::Metadata<Block> for Runtime {540 fn metadata() -> OpaqueMetadata {541 Runtime::metadata().into()542 }543 }544545 impl sp_block_builder::BlockBuilder<Block> for Runtime {546 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {547 Executive::apply_extrinsic(extrinsic)548 }549550 fn finalize_block() -> <Block as BlockT>::Header {551 Executive::finalize_block()552 }553554 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {555 data.create_extrinsics()556 }557558 fn check_inherents(559 block: Block,560 data: sp_inherents::InherentData,561 ) -> sp_inherents::CheckInherentsResult {562 data.check_extrinsics(&block)563 }564565 fn random_seed() -> <Block as BlockT>::Hash {566 RandomnessCollectiveFlip::random_seed()567 }568 }569570 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {571 fn validate_transaction(572 source: TransactionSource,573 tx: <Block as BlockT>::Extrinsic,574 ) -> TransactionValidity {575 Executive::validate_transaction(source, tx)576 }577 }578579 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {580 fn offchain_worker(header: &<Block as BlockT>::Header) {581 Executive::offchain_worker(header)582 }583 }584585 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {586 fn slot_duration() -> u64 {587 Aura::slot_duration()588 }589590 fn authorities() -> Vec<AuraId> {591 Aura::authorities()592 }593 }594595 impl sp_session::SessionKeys<Block> for Runtime {596 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {597 opaque::SessionKeys::generate(seed)598 }599600 fn decode_session_keys(601 encoded: Vec<u8>,602 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {603 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)604 }605 }606607 impl fg_primitives::GrandpaApi<Block> for Runtime {608 fn grandpa_authorities() -> GrandpaAuthorityList {609 Grandpa::grandpa_authorities()610 }611612 fn submit_report_equivocation_unsigned_extrinsic(613 _equivocation_proof: fg_primitives::EquivocationProof<614 <Block as BlockT>::Hash,615 NumberFor<Block>,616 >,617 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,618 ) -> Option<()> {619 None620 }621622 fn generate_key_ownership_proof(623 _set_id: fg_primitives::SetId,624 _authority_id: GrandpaId,625 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {626 // NOTE: this is the only implementation possible since we've627 // defined our key owner proof type as a bottom type (i.e. a type628 // with no values).629 None630 }631 }632 633 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {634 fn account_nonce(account: AccountId) -> Index {635 System::account_nonce(account)636 }637 }638639 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {640 fn query_info(641 uxt: <Block as BlockT>::Extrinsic,642 len: u32,643 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {644 TransactionPayment::query_info(uxt, len)645 }646 }647648 #[cfg(feature = "runtime-benchmarks")]649 impl frame_benchmarking::Benchmark<Block> for Runtime {650 fn dispatch_benchmark(651 config: frame_benchmarking::BenchmarkConfig652 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {653 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};654655 let whitelist: Vec<TrackedStorageKey> = vec![656 // Alice account657 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),658 // // Total Issuance659 // hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),660 // // Execution Phase661 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),662 // // Event Count663 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),664 // // System Events665 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),666 ];667668 let mut batches = Vec::<BenchmarkBatch>::new();669 let params = (&config, &whitelist);670671 add_benchmark!(params, batches, pallet_nft, Nft);672673 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }674 Ok(batches)675 }676 }677}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_contracts_rpc_runtime_api::ContractExecResult;17use pallet_grandpa::fg_primitives;18use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};19use sp_api::impl_runtime_apis;20use sp_consensus_aura::sr25519::AuthorityId as AuraId;21use sp_core::{ crypto::KeyTypeId, crypto::Public, OpaqueMetadata };22use sp_runtime::{23 create_runtime_str, generic, impl_opaque_keys,24 traits::{25 Convert, ConvertInto, BlakeTwo256, Block as BlockT, IdentifyAccount, 26 IdentityLookup, NumberFor, Saturating, Verify,27 },28 transaction_validity::{TransactionSource, TransactionValidity},29 ApplyExtrinsicResult, MultiSignature,30};31use sp_std::prelude::*;32#[cfg(feature = "std")]33use sp_version::NativeVersion;34use sp_version::RuntimeVersion;3536// 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 traits::{44 Currency, ExistenceRequirement, Get, KeyOwnerProofSystem, OnUnbalanced, Randomness,45 WithdrawReason, LockIdentifier,46 },47 weights::{48 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},49 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,50 WeightToFeePolynomial,51 },52 StorageValue,53};54#[cfg(any(feature = "std", test))]55pub use sp_runtime::BuildStorage;56use sp_runtime:: { Perbill, Permill, Percent, ModuleId };57use frame_system::{self as system, EnsureRoot };58use sp_std::{marker::PhantomData};5960pub use pallet_timestamp::Call as TimestampCall;6162/// Struct that handles the conversion of Balance -> `u64`. This is used for63/// staking's election calculation.64pub struct CurrencyToVoteHandler;6566impl CurrencyToVoteHandler {67 fn factor() -> Balance {68 (Balances::total_issuance() / u64::max_value() as Balance).max(1)69 }70}7172impl Convert<Balance, u64> for CurrencyToVoteHandler {73 fn convert(x: Balance) -> u64 {74 (x / Self::factor()) as u6475 }76}7778impl Convert<u128, Balance> for CurrencyToVoteHandler {79 fn convert(x: u128) -> Balance {80 x * Self::factor()81 }82}8384/// Re-export a nft pallet85/// TODO: Check this re-export. Is this safe and good style?86extern crate pallet_nft;87pub use pallet_nft::*;8889/// An index to a block.90pub type BlockNumber = u32;9192/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.93pub type Signature = MultiSignature;9495/// Some way of identifying an account on the chain. We intentionally make it equivalent96/// to the public key of our transaction signing scheme.97pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;9899/// The type for looking up accounts. We don't expect more than 4 billion of them, but you100/// never know...101pub type AccountIndex = u32;102103/// Balance of an account.104pub type Balance = u128;105106/// Index of a transaction in the chain.107pub type Index = u32;108109/// A hash of some data used by the chain.110pub type Hash = sp_core::H256;111112/// Digest item type.113pub type DigestItem = generic::DigestItem<Hash>;114115mod nft_weights;116117/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know118/// the specifics of the runtime. They can then be made to be agnostic over specific formats119/// of data like extrinsics, allowing for them to continue syncing the network through upgrades120/// to even the core data structures.121pub mod opaque {122 use super::*;123124 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;125126 /// Opaque block header type.127 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;128 /// Opaque block type.129 pub type Block = generic::Block<Header, UncheckedExtrinsic>;130 /// Opaque block identifier type.131 pub type BlockId = generic::BlockId<Block>;132133 impl_opaque_keys! {134 pub struct SessionKeys {135 pub aura: Aura,136 pub grandpa: Grandpa,137 }138 }139}140141/// This runtime version.142pub const VERSION: RuntimeVersion = RuntimeVersion {143 spec_name: create_runtime_str!("nft"),144 impl_name: create_runtime_str!("nft"),145 authoring_version: 1,146 spec_version: 3,147 impl_version: 1,148 apis: RUNTIME_API_VERSIONS,149 transaction_version: 1,150};151152pub const MILLISECS_PER_BLOCK: u64 = 6000;153154pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;155156// These time units are defined in number of blocks.157pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);158pub const HOURS: BlockNumber = MINUTES * 60;159pub const DAYS: BlockNumber = HOURS * 24;160161/// The version information used to identify this runtime when compiled natively.162#[cfg(feature = "std")]163pub fn native_version() -> NativeVersion {164 NativeVersion {165 runtime_version: VERSION,166 can_author_with: Default::default(),167 }168}169170/// Provides a membership set with only the configured aura users171pub struct ValiudatorsOnly<Runtime: pallet_aura::Trait>(PhantomData<Runtime>);172impl frame_support::traits::Contains<AccountId> for ValiudatorsOnly<Runtime> {173 fn contains(t: &AccountId) -> bool {174 let arr: [u8; 32] = *t.as_ref();175 let raw_key: Vec<u8> = Vec::from(arr);176177 match pallet_aura::Module::<Runtime>::authorities().iter().find(|auth| auth.to_raw_vec() == raw_key) {178 Some(_) => true,179 None => false,180 } 181 }182 fn sorted_members() -> Vec<AccountId> {183 let mut members: Vec<AccountId> = Vec::new();184 for auth in pallet_aura::Module::<Runtime>::authorities() {185 let mut arr: [u8; 32] = Default::default(); 186 let bor_arr = auth.clone().to_raw_vec();187 let slice = bor_arr.as_slice();188 arr.copy_from_slice(slice);189 members.push(AccountId::from(arr));190 }191 members 192 }193 fn count() -> usize {194 pallet_aura::Module::<Runtime>::authorities().len()195 }196}197198impl frame_support::traits::ContainsLengthBound for ValiudatorsOnly<Runtime> {199 fn min_len() -> usize {200 1201 }202 fn max_len() -> usize {203 100204 }205}206207parameter_types! {208 pub const BlockHashCount: BlockNumber = 2400;209 /// We allow for 2 seconds of compute with a 6 second average block time.210 pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND;211 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);212 /// Assume 10% of weight for average on_initialize calls.213 pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()214 .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();215 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;216 pub const Version: RuntimeVersion = VERSION;217}218219impl system::Trait for Runtime {220 /// The basic call filter to use in dispatchable.221 type BaseCallFilter = ();222 /// The identifier used to distinguish between accounts.223 type AccountId = AccountId;224 /// The aggregated dispatch type that is available for extrinsics.225 type Call = Call;226 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.227 type Lookup = IdentityLookup<AccountId>;228 /// The index type for storing how many extrinsics an account has signed.229 type Index = Index;230 /// The index type for blocks.231 type BlockNumber = BlockNumber;232 /// The type for hashing blocks and tries.233 type Hash = Hash;234 /// The hashing algorithm used.235 type Hashing = BlakeTwo256;236 /// The header type.237 type Header = generic::Header<BlockNumber, BlakeTwo256>;238 /// The ubiquitous event type.239 type Event = Event;240 /// The ubiquitous origin type.241 type Origin = Origin;242 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).243 type BlockHashCount = BlockHashCount;244 /// Maximum weight of each block.245 type MaximumBlockWeight = MaximumBlockWeight;246 /// The weight of database operations that the runtime can invoke.247 type DbWeight = RocksDbWeight;248 /// The weight of the overhead invoked on the block import process, independent of the249 /// extrinsics included in that block.250 type BlockExecutionWeight = BlockExecutionWeight;251 /// The base weight of any extrinsic processed by the runtime, independent of the252 /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...)253 type ExtrinsicBaseWeight = ExtrinsicBaseWeight;254 /// The maximum weight that a single extrinsic of `Normal` dispatch class can have,255 /// idependent of the logic of that extrinsics. (Roughly max block weight - average on256 /// initialize cost).257 type MaximumExtrinsicWeight = MaximumExtrinsicWeight;258 /// Maximum size of all encoded transactions (in bytes) that are allowed in one block.259 type MaximumBlockLength = MaximumBlockLength;260 /// Portion of the block weight that is available to all normal transactions.261 type AvailableBlockRatio = AvailableBlockRatio;262 /// Version of the runtime.263 type Version = Version;264 /// This type is being generated by `construct_runtime!`.265 type PalletInfo = PalletInfo;266 /// What to do if a new account is created.267 type OnNewAccount = ();268 /// What to do if an account is fully reaped from the system.269 type OnKilledAccount = ();270 /// The data to be stored in an account.271 type AccountData = pallet_balances::AccountData<Balance>;272 /// Weight information for the extrinsics of this pallet.273 type SystemWeightInfo = ();274}275276impl pallet_aura::Trait for Runtime {277 type AuthorityId = AuraId;278}279280impl pallet_grandpa::Trait for Runtime {281 type Event = Event;282 type Call = Call;283284 type KeyOwnerProofSystem = ();285286 type KeyOwnerProof =287 <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;288289 type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(290 KeyTypeId,291 GrandpaId,292 )>>::IdentificationTuple;293294 type HandleEquivocation = ();295296 type WeightInfo = ();297}298299parameter_types! {300 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;301}302303impl pallet_timestamp::Trait for Runtime {304 /// A timestamp: milliseconds since the unix epoch.305 type Moment = u64;306 type OnTimestampSet = Aura;307 type MinimumPeriod = MinimumPeriod;308 type WeightInfo = ();309}310311parameter_types! {312 // pub const ExistentialDeposit: u128 = 500;313 pub const ExistentialDeposit: u128 = 0;314 pub const MaxLocks: u32 = 50;315}316317impl pallet_balances::Trait for Runtime {318 type MaxLocks = MaxLocks;319 /// The type for recording an account's balance.320 type Balance = Balance;321 /// The ubiquitous event type.322 type Event = Event;323 type DustRemoval = Treasury;324 type ExistentialDeposit = ExistentialDeposit;325 type AccountStore = System;326 type WeightInfo = ();327}328329pub const MILLICENTS: Balance = 1_000_000_000;330pub const CENTS: Balance = 1_000 * MILLICENTS;331pub const DOLLARS: Balance = 100 * CENTS;332333parameter_types! {334 pub const TombstoneDeposit: Balance = 0;335 pub const RentByteFee: Balance = 4 * MILLICENTS;336 pub const RentDepositOffset: Balance = 1000 * MILLICENTS;337 pub const SurchargeReward: Balance = 150 * MILLICENTS;338}339340impl pallet_contracts::Trait for Runtime {341 type Time = Timestamp;342 type Randomness = RandomnessCollectiveFlip;343 type Currency = Balances;344 type Event = Event;345 type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer<Runtime>;346 type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter<Runtime>;347 type RentPayment = ();348 type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;349 type TombstoneDeposit = TombstoneDeposit;350 type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;351 type RentByteFee = RentByteFee;352 type RentDepositOffset = RentDepositOffset;353 type SurchargeReward = SurchargeReward;354 type MaxDepth = pallet_contracts::DefaultMaxDepth;355 type MaxValueSize = pallet_contracts::DefaultMaxValueSize;356 type WeightPrice = pallet_transaction_payment::Module<Self>;357}358359parameter_types! {360 pub const TransactionByteFee: Balance = 10 * MILLICENTS;361}362363impl pallet_transaction_payment::Trait for Runtime {364 type Currency = pallet_balances::Module<Runtime>;365 type OnTransactionPayment = Treasury;366 type TransactionByteFee = TransactionByteFee;367 type WeightToFee = IdentityFee<Balance>;368 type FeeMultiplierUpdate = ();369}370371parameter_types! {372 pub const ProposalBond: Permill = Permill::from_percent(5);373 pub const ProposalBondMinimum: Balance = 1 * DOLLARS;374 pub const SpendPeriod: BlockNumber = 5 * MINUTES;375 pub const Burn: Permill = Permill::from_percent(0);376 pub const TipCountdown: BlockNumber = 1 * DAYS;377 pub const TipFindersFee: Percent = Percent::from_percent(20);378 pub const TipReportDepositBase: Balance = 1 * DOLLARS;379 pub const DataDepositPerByte: Balance = 1 * CENTS;380 pub const BountyDepositBase: Balance = 1 * DOLLARS;381 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;382 pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry");383 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;384 pub const MaximumReasonLength: u32 = 16384;385 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);386 pub const BountyValueMinimum: Balance = 5 * DOLLARS;387}388389impl pallet_treasury::Trait for Runtime {390 type ModuleId = TreasuryModuleId;391 type Currency = Balances;392 type ApproveOrigin = EnsureRoot<AccountId>;393 type RejectOrigin = EnsureRoot<AccountId>;394 type Tippers = ValiudatorsOnly<Self>;395 type TipCountdown = TipCountdown;396 type TipFindersFee = TipFindersFee;397 type TipReportDepositBase = TipReportDepositBase;398 type DataDepositPerByte = DataDepositPerByte;399 type Event = Event;400 type OnSlash = ();401 type ProposalBond = ProposalBond;402 type ProposalBondMinimum = ProposalBondMinimum;403 type SpendPeriod = SpendPeriod;404 type Burn = Burn;405 type BountyDepositBase = BountyDepositBase;406 type BountyDepositPayoutDelay = BountyDepositPayoutDelay;407 type BountyUpdatePeriod = BountyUpdatePeriod;408 type BountyCuratorDeposit = BountyCuratorDeposit;409 type BountyValueMinimum = BountyValueMinimum;410 type MaximumReasonLength = MaximumReasonLength;411 type BurnDestination = ();412 type WeightInfo = ();413}414415impl pallet_sudo::Trait for Runtime {416 type Event = Event;417 type Call = Call;418}419420parameter_types! {421 pub const MinVestedTransfer: Balance = 100 * DOLLARS;422}423424impl pallet_vesting::Trait for Runtime {425 type Event = Event;426 type Currency = Balances;427 type BlockNumberToBalance = ConvertInto;428 type MinVestedTransfer = MinVestedTransfer;429 type WeightInfo = ();430}431432/// Used for the module nft in `./nft.rs`433impl pallet_nft::Trait for Runtime {434 type Event = Event;435 type WeightInfo = nft_weights::WeightInfo;436}437438construct_runtime!(439 pub enum Runtime where440 Block = Block,441 NodeBlock = opaque::Block,442 UncheckedExtrinsic = UncheckedExtrinsic443 {444 System: system::{Module, Call, Config, Storage, Event<T>},445 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},446 Contracts: pallet_contracts::{Module, Call, Config, Storage, Event<T>},447 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},448 Aura: pallet_aura::{Module, Config<T>, Inherent},449 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},450 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},451 TransactionPayment: pallet_transaction_payment::{Module, Storage},452 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},453 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},454 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},455 Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},456 }457);458459/// The address format for describing accounts.460pub type Address = AccountId;461/// Block header type as expected by this runtime.462pub type Header = generic::Header<BlockNumber, BlakeTwo256>;463/// Block type as expected by this runtime.464pub type Block = generic::Block<Header, UncheckedExtrinsic>;465/// A Block signed with a Justification466pub type SignedBlock = generic::SignedBlock<Block>;467/// BlockId type as expected by this runtime.468pub type BlockId = generic::BlockId<Block>;469/// The SignedExtension to the basic transaction logic.470pub type SignedExtra = (471 system::CheckSpecVersion<Runtime>,472 system::CheckTxVersion<Runtime>,473 system::CheckGenesis<Runtime>,474 system::CheckEra<Runtime>,475 system::CheckNonce<Runtime>,476 system::CheckWeight<Runtime>,477 pallet_nft::ChargeTransactionPayment<Runtime>,478);479/// Unchecked extrinsic type as expected by this runtime.480pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;481/// Extrinsic type that has already been checked.482pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;483/// Executive: handles dispatch to the various modules.484pub type Executive =485 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;486487impl_runtime_apis! {488489 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>490 for Runtime491 {492 fn call(493 origin: AccountId,494 dest: AccountId,495 value: Balance,496 gas_limit: u64,497 input_data: Vec<u8>,498 ) -> ContractExecResult {499 let (exec_result, gas_consumed) =500 Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);501 match exec_result {502 Ok(v) => ContractExecResult::Success {503 flags: v.flags.bits(),504 data: v.data,505 gas_consumed: gas_consumed,506 },507 Err(_) => ContractExecResult::Error,508 }509 }510511 fn get_storage(512 address: AccountId,513 key: [u8; 32],514 ) -> pallet_contracts_primitives::GetStorageResult {515 Contracts::get_storage(address, key)516 }517518 fn rent_projection(519 address: AccountId,520 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {521 Contracts::rent_projection(address)522 }523 }524525 impl sp_api::Core<Block> for Runtime {526 fn version() -> RuntimeVersion {527 VERSION528 }529530 fn execute_block(block: Block) {531 Executive::execute_block(block)532 }533534 fn initialize_block(header: &<Block as BlockT>::Header) {535 Executive::initialize_block(header)536 }537 }538539 impl sp_api::Metadata<Block> for Runtime {540 fn metadata() -> OpaqueMetadata {541 Runtime::metadata().into()542 }543 }544545 impl sp_block_builder::BlockBuilder<Block> for Runtime {546 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {547 Executive::apply_extrinsic(extrinsic)548 }549550 fn finalize_block() -> <Block as BlockT>::Header {551 Executive::finalize_block()552 }553554 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {555 data.create_extrinsics()556 }557558 fn check_inherents(559 block: Block,560 data: sp_inherents::InherentData,561 ) -> sp_inherents::CheckInherentsResult {562 data.check_extrinsics(&block)563 }564565 fn random_seed() -> <Block as BlockT>::Hash {566 RandomnessCollectiveFlip::random_seed()567 }568 }569570 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {571 fn validate_transaction(572 source: TransactionSource,573 tx: <Block as BlockT>::Extrinsic,574 ) -> TransactionValidity {575 Executive::validate_transaction(source, tx)576 }577 }578579 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {580 fn offchain_worker(header: &<Block as BlockT>::Header) {581 Executive::offchain_worker(header)582 }583 }584585 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {586 fn slot_duration() -> u64 {587 Aura::slot_duration()588 }589590 fn authorities() -> Vec<AuraId> {591 Aura::authorities()592 }593 }594595 impl sp_session::SessionKeys<Block> for Runtime {596 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {597 opaque::SessionKeys::generate(seed)598 }599600 fn decode_session_keys(601 encoded: Vec<u8>,602 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {603 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)604 }605 }606607 impl fg_primitives::GrandpaApi<Block> for Runtime {608 fn grandpa_authorities() -> GrandpaAuthorityList {609 Grandpa::grandpa_authorities()610 }611612 fn submit_report_equivocation_unsigned_extrinsic(613 _equivocation_proof: fg_primitives::EquivocationProof<614 <Block as BlockT>::Hash,615 NumberFor<Block>,616 >,617 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,618 ) -> Option<()> {619 None620 }621622 fn generate_key_ownership_proof(623 _set_id: fg_primitives::SetId,624 _authority_id: GrandpaId,625 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {626 // NOTE: this is the only implementation possible since we've627 // defined our key owner proof type as a bottom type (i.e. a type628 // with no values).629 None630 }631 }632 633 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {634 fn account_nonce(account: AccountId) -> Index {635 System::account_nonce(account)636 }637 }638639 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {640 fn query_info(641 uxt: <Block as BlockT>::Extrinsic,642 len: u32,643 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {644 TransactionPayment::query_info(uxt, len)645 }646 }647648 #[cfg(feature = "runtime-benchmarks")]649 impl frame_benchmarking::Benchmark<Block> for Runtime {650 fn dispatch_benchmark(651 config: frame_benchmarking::BenchmarkConfig652 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {653 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};654655 let whitelist: Vec<TrackedStorageKey> = vec![656 // Alice account657 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),658 // // Total Issuance659 // hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),660 // // Execution Phase661 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),662 // // Event Count663 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),664 // // System Events665 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),666 ];667668 let mut batches = Vec::<BenchmarkBatch>::new();669 let params = (&config, &whitelist);670671 add_benchmark!(params, batches, pallet_nft, Nft);672673 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }674 Ok(batches)675 }676 }677}tests/src/confirmSponsorship.test.tsdiffbeforeafterboth--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -170,7 +170,7 @@
});
});
- it('NFT: Sponsoring is rate limited', async () => {
+ it('NFT: Sponsoring of transfers is rate limited', async () => {
const collectionId = await createCollectionExpectSuccess();
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
@@ -285,6 +285,51 @@
});
});
+ it('NFT: Sponsoring of createItem is rate limited', async () => {
+ const collectionId = await createCollectionExpectSuccess();
+ await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+ // Enable collection white list
+ await enableWhiteListExpectSuccess(alice, collectionId);
+
+ // Enable public minting
+ await enablePublicMintingExpectSuccess(alice, collectionId);
+
+ await usingApi(async (api) => {
+ // Find unused address
+ const zeroBalance = await findUnusedAddress(api);
+
+ // Add zeroBalance address to white list
+ await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);
+
+ // Mint token using unused address as signer - gets sponsored
+ await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);
+
+ // Second mint should fail
+ const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+ const consoleError = console.error;
+ const consoleLog = console.log;
+ console.error = () => {};
+ console.log = () => {};
+ const badTransaction = async function () {
+ await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);
+ };
+ await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");
+ console.error = consoleError;
+ console.log = consoleLog;
+ const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+ // Try again after Zero gets some balance - now it should succeed
+ const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);
+ await submitTransactionAsync(alice, balancetx);
+ await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);
+
+ expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;
+ });
+ });
+
});
describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {