difftreelog
Merge pull request #144 from usetech-llc/feature/NFTPAR-413_inflation
in: master
Feature/nftpar 413 inflation
11 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "Inflector"
version = "0.11.4"
@@ -3606,6 +3608,7 @@
"pallet-contracts-primitives",
"pallet-contracts-rpc-runtime-api",
"pallet-grandpa",
+ "pallet-inflation",
"pallet-nft",
"pallet-randomness-collective-flip",
"pallet-sudo",
@@ -3920,6 +3923,24 @@
]
[[package]]
+name = "pallet-inflation"
+version = "3.0.0"
+dependencies = [
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "pallet-balances",
+ "pallet-randomness-collective-flip",
+ "pallet-timestamp",
+ "parity-scale-codec",
+ "serde",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
name = "pallet-nft"
version = "3.0.0"
dependencies = [
pallets/inflation/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/pallets/inflation/Cargo.toml
@@ -0,0 +1,48 @@
+[package]
+authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
+description = 'Unqiue pallet inflation'
+edition = '2018'
+homepage = 'https://substrate.io'
+license = 'Unlicense'
+name = 'pallet-inflation'
+repository = 'https://github.com/usetech-llc/nft_private/'
+version = '3.0.0'
+
+[package.metadata.docs.rs]
+targets = ['x86_64-unknown-linux-gnu']
+
+# alias "parity-scale-code" to "codec"
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.0.0'
+
+[dependencies]
+serde = { version = "1.0.119" }
+frame-support = { default-features = false, version = '3.0.0' }
+frame-system = { default-features = false, version = '3.0.0' }
+pallet-balances = { default-features = false, version = '3.0.0' }
+pallet-timestamp = { default-features = false, version = '3.0.0' }
+pallet-randomness-collective-flip = { default-features = false, version = '3.0.0' }
+sp-std = { default-features = false, version = '3.0.0' }
+frame-benchmarking = { default-features = false, version = "3.0.0", optional = true }
+sp-core = { default-features = false, version = '3.0.0' }
+sp-io = { default-features = false, version = '3.0.0' }
+sp-runtime = { default-features = false, version = '3.0.0' }
+
+[features]
+default = ['std']
+std = [
+ 'codec/std',
+ 'serde/std',
+ 'frame-support/std',
+ 'frame-system/std',
+ 'pallet-balances/std',
+ 'pallet-timestamp/std',
+ 'pallet-randomness-collective-flip/std',
+ 'sp-std/std',
+ 'sp-runtime/std',
+ 'frame-benchmarking/std',
+]
+runtime-benchmarks = ["frame-benchmarking"]
pallets/inflation/src/benchmarking.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/inflation/src/benchmarking.rs
@@ -0,0 +1,19 @@
+#![cfg(feature = "runtime-benchmarks")]
+
+use super::*;
+use crate::Module as Inflation;
+
+use sp_std::prelude::*;
+use frame_system::RawOrigin;
+use frame_benchmarking::{benchmarks};
+use frame_support::traits::OnInitialize;
+
+benchmarks! {
+
+ on_initialize {
+ let block1: T::BlockNumber = T::BlockNumber::from(1u32);
+ let block2: T::BlockNumber = T::BlockNumber::from(2u32);
+ Inflation::<T>::on_initialize(block1); // Create Treasury account
+ }: { Inflation::<T>::on_initialize(block2); } // Benchmark deposit_into_existing path
+
+}
pallets/inflation/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/inflation/src/lib.rs
@@ -0,0 +1,130 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+#![recursion_limit = "1024"]
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[cfg(feature = "std")]
+pub use std::*;
+
+#[cfg(feature = "std")]
+pub use serde::*;
+
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+
+#[cfg(test)]
+mod tests;
+
+pub use frame_support::{
+ construct_runtime, decl_module, decl_storage,
+ ensure,
+ traits::{
+ Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,
+ Randomness, IsSubType, WithdrawReasons,
+ },
+ weights::{
+ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
+ DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
+ WeightToFeePolynomial, DispatchClass,
+ },
+ StorageValue,
+ transactional,
+};
+
+// #[cfg(feature = "runtime-benchmarks")]
+pub use frame_support::dispatch::DispatchResult;
+
+use sp_runtime::{
+ Perbill,
+ traits::{Zero}
+};
+use sp_std::convert::TryInto;
+
+use frame_system::{self as system};
+
+/// The balance type of this module.
+pub type BalanceOf<T> =
+ <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+
+pub const YEAR: u32 = 5_259_600;
+pub const TOTAL_YEARS_UNTIL_FLAT: u32 = 9;
+pub const START_INFLATION_PERCENT: u32 = 10;
+pub const END_INFLATION_PERCENT: u32 = 4;
+
+pub trait Config: system::Config {
+ type Currency: Currency<Self::AccountId>;
+ type TreasuryAccountId: Get<Self::AccountId>;
+ type InflationBlockInterval: Get<Self::BlockNumber>;
+}
+
+decl_storage! {
+ trait Store for Module<T: Config> as Inflation {
+ /// starting year total issuance
+ pub StartingYearTotalIssuance get(fn starting_year_total_issuance): BalanceOf<T>;
+
+ /// Current block inflation
+ pub BlockInflation get(fn block_inflation): BalanceOf<T>;
+ }
+}
+
+decl_module! {
+ pub struct Module<T: Config> for enum Call
+ where
+ origin: T::Origin,
+ {
+ const InflationBlockInterval: T::BlockNumber = T::InflationBlockInterval::get();
+
+ fn on_initialize(now: T::BlockNumber) -> Weight
+ {
+ let mut consumed_weight = 0;
+ let mut add_weight = |reads, writes, weight| {
+ consumed_weight += T::DbWeight::get().reads_writes(reads, writes);
+ consumed_weight += weight;
+ };
+
+ let block_interval: u32 = T::InflationBlockInterval::get().try_into().unwrap_or(0);
+
+ // Recalculate inflation on the first block of the year (or if it is not initialized yet)
+ if (now % T::BlockNumber::from(YEAR)).is_zero() || <BlockInflation<T>>::get().is_zero() {
+ let current_year: u32 = (now / T::BlockNumber::from(YEAR)).try_into().unwrap_or(0);
+
+ let one_percent = Perbill::from_percent(1);
+
+ if current_year <= TOTAL_YEARS_UNTIL_FLAT {
+ let amount: BalanceOf<T> = Perbill::from_rational_approximation(
+ block_interval * (START_INFLATION_PERCENT * TOTAL_YEARS_UNTIL_FLAT - current_year * (START_INFLATION_PERCENT - END_INFLATION_PERCENT)),
+ YEAR * TOTAL_YEARS_UNTIL_FLAT
+ ) * ( one_percent * T::Currency::total_issuance() );
+ <BlockInflation<T>>::put(amount);
+ }
+ else {
+ let amount: BalanceOf<T> = Perbill::from_rational_approximation(
+ block_interval * END_INFLATION_PERCENT,
+ YEAR
+ ) * (one_percent * T::Currency::total_issuance());
+ <BlockInflation<T>>::put(amount);
+ }
+ <StartingYearTotalIssuance<T>>::set(T::Currency::total_issuance());
+
+ // First time deposit
+ T::Currency::deposit_creating(&T::TreasuryAccountId::get(), <BlockInflation<T>>::get());
+
+ add_weight(7, 6, 28_300_000);
+ }
+
+ // Apply inflation every InflationBlockInterval blocks and in the 1st block to initialize Treasury account
+ else if (now % T::BlockNumber::from(block_interval)).is_zero() {
+ T::Currency::deposit_into_existing(&T::TreasuryAccountId::get(), <BlockInflation<T>>::get()).ok();
+
+ add_weight(3, 2, 12_900_000);
+ }
+
+ consumed_weight
+ }
+
+ }
+}
pallets/inflation/src/tests.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/inflation/src/tests.rs
@@ -0,0 +1,241 @@
+#[cfg(test)]
+mod tests {
+ use crate as pallet_inflation;
+
+ use frame_system;
+ use frame_support::{traits::{Currency}, parameter_types};
+ use frame_support::{traits::OnInitialize};
+ use sp_core::H256;
+ use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::Header};
+
+ type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
+ type Block = frame_system::mocking::MockBlock<Test>;
+
+ const YEAR: u64 = 5_259_600;
+
+ parameter_types! {
+ pub const ExistentialDeposit: u64 = 1;
+ pub const MaxLocks: u32 = 50;
+ }
+
+ impl pallet_balances::Config for Test {
+ type AccountStore = System;
+ type Balance = u64;
+ type DustRemoval = ();
+ type Event = ();
+ type ExistentialDeposit = ExistentialDeposit;
+ type WeightInfo = ();
+ type MaxLocks = MaxLocks;
+ }
+
+ frame_support::construct_runtime!(
+ pub enum Test where
+ Block = Block,
+ NodeBlock = Block,
+ UncheckedExtrinsic = UncheckedExtrinsic,
+ {
+ Balances: pallet_balances::{Module, Call, Storage},
+ System: frame_system::{Module, Call, Config, Storage, Event<T>},
+ Inflation: pallet_inflation::{Module, Call, Storage},
+ }
+ );
+
+ parameter_types! {
+ pub const BlockHashCount: u64 = 250;
+ pub BlockWeights: frame_system::limits::BlockWeights =
+ frame_system::limits::BlockWeights::simple_max(1024);
+ pub const SS58Prefix: u8 = 42;
+ }
+
+ impl frame_system::Config for Test {
+ type BaseCallFilter = ();
+ type BlockWeights = ();
+ type BlockLength = ();
+ type DbWeight = ();
+ type Origin = Origin;
+ type Call = Call;
+ type Index = u64;
+ type BlockNumber = u64;
+ type Hash = H256;
+ type Hashing = BlakeTwo256;
+ type AccountId = u64;
+ type Lookup = IdentityLookup<Self::AccountId>;
+ type Header = Header;
+ type Event = ();
+ type BlockHashCount = BlockHashCount;
+ type Version = ();
+ type PalletInfo = PalletInfo;
+ type AccountData = pallet_balances::AccountData<u64>;
+ type OnNewAccount = ();
+ type OnKilledAccount = ();
+ type SystemWeightInfo = ();
+ type SS58Prefix = SS58Prefix;
+ }
+
+ parameter_types! {
+ pub TreasuryAccountId: u64 = 1234;
+ pub const InflationBlockInterval: u32 = 100; // every time per how many blocks inflation is applied
+ }
+
+ impl pallet_inflation::Config for Test {
+ type Currency = Balances;
+ type TreasuryAccountId = TreasuryAccountId;
+ type InflationBlockInterval = InflationBlockInterval;
+ }
+
+ // Build genesis storage according to the mock runtime.
+ pub fn new_test_ext() -> sp_io::TestExternalities {
+ frame_system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
+ }
+
+ #[test]
+ fn inflation_works() {
+ new_test_ext().execute_with(|| {
+ // Total issuance = 1_000_000_000
+ let initial_issuance: u64 = 1_000_000_000;
+ let _ = <Balances as Currency<_>>::deposit_creating(&1234, initial_issuance);
+ assert_eq!(Balances::free_balance(1234), initial_issuance);
+
+ // BlockInflation should be set after 1st block and
+ // first inflation deposit should be equal to BlockInflation
+ Inflation::on_initialize(1);
+ assert!(Inflation::block_inflation() > 0);
+ assert_eq!(Balances::free_balance(1234) - initial_issuance, Inflation::block_inflation());
+ });
+ }
+
+ #[test]
+ fn inflation_second_deposit() {
+ new_test_ext().execute_with(|| {
+ // Total issuance = 1_000_000_000
+ let initial_issuance: u64 = 1_000_000_000;
+ let _ = <Balances as Currency<_>>::deposit_creating(&1234, initial_issuance);
+ assert_eq!(Balances::free_balance(1234), initial_issuance);
+ Inflation::on_initialize(1);
+
+ // Next inflation deposit happens when block is multiple of InflationBlockInterval
+ let mut block: u32 = 2;
+ let balance_before: u64 = Balances::free_balance(1234);
+ while block % InflationBlockInterval::get() != 0 {
+ Inflation::on_initialize(block as u64);
+ block += 1;
+ }
+ let balance_just_before: u64 = Balances::free_balance(1234);
+ assert_eq!(balance_before, balance_just_before);
+
+ // The block with inflation
+ Inflation::on_initialize(block as u64);
+ let balance_after: u64 = Balances::free_balance(1234);
+ assert_eq!(balance_after - balance_just_before, Inflation::block_inflation());
+ });
+ }
+
+ #[test]
+ fn inflation_in_1_year() {
+ new_test_ext().execute_with(|| {
+ // Total issuance = 1_000_000_000
+ let initial_issuance: u64 = 1_000_000_000;
+ let _ = <Balances as Currency<_>>::deposit_creating(&1234, initial_issuance);
+ assert_eq!(Balances::free_balance(1234), initial_issuance);
+ Inflation::on_initialize(1);
+ let block_inflation_year_0 = Inflation::block_inflation();
+
+ Inflation::on_initialize(YEAR);
+ let block_inflation_year_1 = Inflation::block_inflation();
+
+ // Assert that year 1 inflation is less than year 0
+ assert!(block_inflation_year_0 > block_inflation_year_1);
+ });
+ }
+
+ #[test]
+ fn inflation_in_1_to_9_years() {
+ new_test_ext().execute_with(|| {
+ // Total issuance = 1_000_000_000
+ let initial_issuance: u64 = 1_000_000_000;
+ let _ = <Balances as Currency<_>>::deposit_creating(&1234, initial_issuance);
+ assert_eq!(Balances::free_balance(1234), initial_issuance);
+ Inflation::on_initialize(1);
+
+ for year in 1..=9 {
+ let block_inflation_year_before = Inflation::block_inflation();
+ Inflation::on_initialize(YEAR * year);
+ let block_inflation_year_after = Inflation::block_inflation();
+
+ // Assert that next year inflation is less than previous year inflation
+ assert!(block_inflation_year_before > block_inflation_year_after);
+ }
+
+ });
+ }
+
+ #[test]
+ fn inflation_after_year_10_is_flat() {
+ new_test_ext().execute_with(|| {
+ // Total issuance = 1_000_000_000
+ let initial_issuance: u64 = 1_000_000_000;
+ let _ = <Balances as Currency<_>>::deposit_creating(&1234, initial_issuance);
+ assert_eq!(Balances::free_balance(1234), initial_issuance);
+ Inflation::on_initialize(YEAR * 9);
+
+ for year in 10..=20 {
+ let block_inflation_year_before = Inflation::block_inflation();
+ Inflation::on_initialize(YEAR * year);
+ let block_inflation_year_after = Inflation::block_inflation();
+
+ // Assert that next year inflation is equal to previous year inflation
+ assert_eq!(block_inflation_year_before, block_inflation_year_after);
+ }
+ });
+ }
+
+ #[test]
+ fn inflation_rate_by_year() {
+ new_test_ext().execute_with(|| {
+ let payouts: u64 = YEAR / InflationBlockInterval::get() as u64;
+
+ // Inflation starts at 10% and does down by 2/3% every year until year 9 (included),
+ // then it is flat.
+ let payout_by_year: [u64; 11] = [
+ 1000,
+ 933,
+ 867,
+ 800,
+ 733,
+ 667,
+ 600,
+ 533,
+ 467,
+ 400,
+ 400
+ ];
+
+ // For accuracy total issuance = payout0 * payouts * 10;
+ let initial_issuance: u64 = payout_by_year[0] * payouts * 10;
+ let _ = <Balances as Currency<_>>::deposit_creating(&1234, initial_issuance);
+ assert_eq!(Balances::free_balance(1234), initial_issuance);
+
+ for year in 0..=10 {
+ // Year first block
+ Inflation::on_initialize(year*YEAR);
+ let mut actual_payout = Inflation::block_inflation();
+ assert_eq!(actual_payout, payout_by_year[year as usize]);
+
+ // Year second block
+ Inflation::on_initialize(year*YEAR+1);
+ actual_payout = Inflation::block_inflation();
+ assert_eq!(actual_payout, payout_by_year[year as usize]);
+
+ // Year middle block
+ Inflation::on_initialize(year*YEAR + YEAR/2);
+ actual_payout = Inflation::block_inflation();
+ assert_eq!(actual_payout, payout_by_year[year as usize]);
+
+ // Year last block
+ Inflation::on_initialize((year + 1)*YEAR-1);
+ actual_payout = Inflation::block_inflation();
+ assert_eq!(actual_payout, payout_by_year[year as usize]);
+ }
+ });
+ }
+}
pallets/nft/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nft/src/benchmarking.rs
+++ b/pallets/nft/src/benchmarking.rs
@@ -1,420 +1,419 @@
-#[cfg(feature = "runtime-benchmarks")]
-// mod benchmarking {
- use super::*;
- use sp_std::prelude::*;
- use frame_system::RawOrigin;
- // use frame_support::{ensure, traits::OnFinalize};
- use frame_benchmarking::{benchmarks, account, whitelisted_caller}; // , TrackedStorageKey,
- use crate::Module as Nft;
+#![cfg(feature = "runtime-benchmarks")]
- const SEED: u32 = 1;
+use super::*;
+use crate::Module as Nft;
- fn default_nft_data() -> CreateItemData {
- CreateItemData::NFT(CreateNftData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] })
- }
-
- fn default_fungible_data () -> CreateItemData {
- CreateItemData::Fungible(CreateFungibleData { })
- }
-
- fn default_re_fungible_data () -> CreateItemData {
- CreateItemData::ReFungible(CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] })
- }
+use sp_std::prelude::*;
+use frame_system::RawOrigin;
+use frame_benchmarking::{benchmarks, account, whitelisted_caller}; // , TrackedStorageKey,
+const SEED: u32 = 1;
+/*
+fn default_nft_data() -> CreateItemData {
+ CreateItemData::NFT(CreateNftData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] })
+}
- benchmarks! {
+fn default_fungible_data () -> CreateItemData {
+ CreateItemData::Fungible(CreateFungibleData { })
+}
- _ {}
+fn default_re_fungible_data () -> CreateItemData {
+ CreateItemData::ReFungible(CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] })
+}
+*/
- create_collection {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = account("caller", 0, SEED);
- }: create_collection(RawOrigin::Signed(caller.clone()), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode)
- verify {
- assert_eq!(Nft::<T>::collection(2).owner, caller);
- }
+benchmarks! {
- destroy_collection {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: destroy_collection(RawOrigin::Signed(caller.clone()), 2)
+ create_collection {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = account("caller", 0, SEED);
+ }: _(RawOrigin::Signed(caller.clone()), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode)
+/*
+ verify {
+ assert_eq!(Nft::<T>::collection_id(2).owner, caller);
+ }
+ destroy_collection {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: _(RawOrigin::Signed(caller.clone()), 2)
- add_to_white_list {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- let whitelist_account: T::AccountId = account("admin", 0, SEED);
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: add_to_white_list(RawOrigin::Signed(caller.clone()), 2, whitelist_account)
+ add_to_white_list {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ let whitelist_account: T::AccountId = account("admin", 0, SEED);
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: add_to_white_list(RawOrigin::Signed(caller.clone()), 2, whitelist_account)
- remove_from_white_list {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- let whitelist_account: T::AccountId = account("admin", 0, SEED);
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- Nft::<T>::add_to_white_list(RawOrigin::Signed(caller.clone()).into(), 2, whitelist_account.clone())?;
- }: remove_from_white_list(RawOrigin::Signed(caller.clone()), 2, whitelist_account)
+ remove_from_white_list {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ let whitelist_account: T::AccountId = account("admin", 0, SEED);
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ Nft::<T>::add_to_white_list(RawOrigin::Signed(caller.clone()).into(), 2, whitelist_account.clone())?;
+ }: remove_from_white_list(RawOrigin::Signed(caller.clone()), 2, whitelist_account)
- set_public_access_mode {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: set_public_access_mode(RawOrigin::Signed(caller.clone()), 2, AccessMode::WhiteList)
+ set_public_access_mode {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: set_public_access_mode(RawOrigin::Signed(caller.clone()), 2, AccessMode::WhiteList)
- set_mint_permission {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: set_mint_permission(RawOrigin::Signed(caller.clone()), 2, true)
+ set_mint_permission {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: set_mint_permission(RawOrigin::Signed(caller.clone()), 2, true)
- change_collection_owner {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let new_owner: T::AccountId = account("admin", 0, SEED);
- }: change_collection_owner(RawOrigin::Signed(caller.clone()), 2, new_owner)
+ change_collection_owner {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let new_owner: T::AccountId = account("admin", 0, SEED);
+ }: change_collection_owner(RawOrigin::Signed(caller.clone()), 2, new_owner)
- add_collection_admin {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let new_admin: T::AccountId = account("admin", 0, SEED);
- }: add_collection_admin(RawOrigin::Signed(caller.clone()), 2, new_admin)
+ add_collection_admin {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let new_admin: T::AccountId = account("admin", 0, SEED);
+ }: add_collection_admin(RawOrigin::Signed(caller.clone()), 2, new_admin)
- remove_collection_admin {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let new_admin: T::AccountId = account("admin", 0, SEED);
- Nft::<T>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), 2, new_admin.clone())?;
- }: remove_collection_admin(RawOrigin::Signed(caller.clone()), 2, new_admin)
+ remove_collection_admin {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let new_admin: T::AccountId = account("admin", 0, SEED);
+ Nft::<T>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), 2, new_admin.clone())?;
+ }: remove_collection_admin(RawOrigin::Signed(caller.clone()), 2, new_admin)
- set_collection_sponsor {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: set_collection_sponsor(RawOrigin::Signed(caller.clone()), 2, caller.clone())
+ set_collection_sponsor {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: set_collection_sponsor(RawOrigin::Signed(caller.clone()), 2, caller.clone())
- confirm_sponsorship {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- Nft::<T>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
- }: confirm_sponsorship(RawOrigin::Signed(caller.clone()), 2)
+ confirm_sponsorship {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ Nft::<T>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
+ }: confirm_sponsorship(RawOrigin::Signed(caller.clone()), 2)
- remove_collection_sponsor {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- Nft::<T>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
- Nft::<T>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), 2)?;
- }: remove_collection_sponsor(RawOrigin::Signed(caller.clone()), 2)
+ remove_collection_sponsor {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ Nft::<T>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
+ Nft::<T>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), 2)?;
+ }: remove_collection_sponsor(RawOrigin::Signed(caller.clone()), 2)
- // nft item
- create_item_nft {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_nft_data();
-
- }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+ // nft item
+ create_item_nft {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_nft_data();
+
+ }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
- #[extra]
- create_item_nft_large {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- let mut nft_data = CreateNftData {
- const_data: vec![],
- variable_data: vec![]
- };
- for i in 0..1998 {
- nft_data.const_data.push(10);
- nft_data.variable_data.push(10);
- }
- let data = CreateItemData::NFT(nft_data);
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ #[extra]
+ create_item_nft_large {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ let mut nft_data = CreateNftData {
+ const_data: vec![],
+ variable_data: vec![]
+ };
+ for i in 0..1998 {
+ nft_data.const_data.push(10);
+ nft_data.variable_data.push(10);
+ }
+ let data = CreateItemData::NFT(nft_data);
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+ }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
- // fungible item
- create_item_fungible {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::Fungible(3);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_fungible_data();
+ // fungible item
+ create_item_fungible {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::Fungible(3);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_fungible_data();
- }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+ }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
- // refungible item
- create_item_refungible {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::ReFungible(3);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_re_fungible_data();
+ // refungible item
+ create_item_refungible {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(3);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_re_fungible_data();
- }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+ }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
- burn_item {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_nft_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ burn_item {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_nft_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- }: burn_item(RawOrigin::Signed(caller.clone()), 2, 1)
+ }: burn_item(RawOrigin::Signed(caller.clone()), 2, 1)
- transfer_nft {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let recipient: T::AccountId = account("recipient", 0, SEED);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_nft_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ transfer_nft {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let recipient: T::AccountId = account("recipient", 0, SEED);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_nft_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- }: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
-
- transfer_fungible {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::Fungible(3);
- let recipient: T::AccountId = account("recipient", 0, SEED);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_fungible_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ }: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
+
+ transfer_fungible {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::Fungible(3);
+ let recipient: T::AccountId = account("recipient", 0, SEED);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_fungible_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- }: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
+ }: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
- transfer_refungible {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::ReFungible(3);
- let recipient: T::AccountId = account("recipient", 0, SEED);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_re_fungible_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ transfer_refungible {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(3);
+ let recipient: T::AccountId = account("recipient", 0, SEED);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_re_fungible_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- }: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
+ }: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
- approve {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::ReFungible(3);
- let recipient: T::AccountId = account("recipient", 0, SEED);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_re_fungible_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ approve {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(3);
+ let recipient: T::AccountId = account("recipient", 0, SEED);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_re_fungible_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- }: approve(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1)
+ }: approve(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1)
- // Nft
- transfer_from_nft {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let recipient: T::AccountId = account("recipient", 0, SEED);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_nft_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
+ // Nft
+ transfer_from_nft {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let recipient: T::AccountId = account("recipient", 0, SEED);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_nft_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
- }: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
+ }: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
- // Fungible
- transfer_from_fungible {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::Fungible(3);
- let recipient: T::AccountId = account("recipient", 0, SEED);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_fungible_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
+ // Fungible
+ transfer_from_fungible {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::Fungible(3);
+ let recipient: T::AccountId = account("recipient", 0, SEED);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_fungible_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
- }: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
+ }: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
- // ReFungible
- transfer_from_refungible {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::ReFungible(3);
- let recipient: T::AccountId = account("recipient", 0, SEED);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_re_fungible_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
+ // ReFungible
+ transfer_from_refungible {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(3);
+ let recipient: T::AccountId = account("recipient", 0, SEED);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_re_fungible_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
- }: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
+ }: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
- enable_contract_sponsoring {
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ enable_contract_sponsoring {
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- }: enable_contract_sponsoring(RawOrigin::Signed(caller.clone()), caller.clone(), true)
+ }: enable_contract_sponsoring(RawOrigin::Signed(caller.clone()), caller.clone(), true)
- set_offchain_schema {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::ReFungible(3);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ set_offchain_schema {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(3);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: set_offchain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
+ }: set_offchain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
- set_const_on_chain_schema {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::ReFungible(3);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: set_const_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
-
- set_variable_on_chain_schema {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::ReFungible(3);
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
+ set_const_on_chain_schema {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(3);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: set_const_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
+
+ set_variable_on_chain_schema {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(3);
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
- set_variable_meta_data {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let data = default_nft_data();
- Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+ set_variable_meta_data {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let data = default_nft_data();
+ Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
- }: set_variable_meta_data(RawOrigin::Signed(caller.clone()), 2, 1, [1, 2, 3].to_vec())
+ }: set_variable_meta_data(RawOrigin::Signed(caller.clone()), 2, 1, [1, 2, 3].to_vec())
- set_schema_version {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- }: set_schema_version(RawOrigin::Signed(caller.clone()), 2, SchemaVersion::Unique)
+ set_schema_version {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ }: set_schema_version(RawOrigin::Signed(caller.clone()), 2, SchemaVersion::Unique)
- set_chain_limits {
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- let limits = ChainLimits {
- collection_numbers_limit: 0,
- account_token_ownership_limit: 0,
- collections_admins_limit: 0,
- custom_data_limit: 0,
- nft_sponsor_transfer_timeout: 0,
- fungible_sponsor_transfer_timeout: 0,
- refungible_sponsor_transfer_timeout: 0
- };
- }: set_chain_limits(RawOrigin::Signed(caller.clone()), limits)
+ set_chain_limits {
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ let limits = ChainLimits {
+ collection_numbers_limit: 0,
+ account_token_ownership_limit: 0,
+ collections_admins_limit: 0,
+ custom_data_limit: 0,
+ nft_sponsor_transfer_timeout: 0,
+ fungible_sponsor_transfer_timeout: 0,
+ refungible_sponsor_transfer_timeout: 0
+ };
+ }: set_chain_limits(RawOrigin::Signed(caller.clone()), limits)
- set_contract_sponsoring_rate_limit {
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
- let block_number: T::BlockNumber = 0.into();
- }: set_contract_sponsoring_rate_limit(RawOrigin::Signed(caller.clone()), caller.clone(), block_number)
+ set_contract_sponsoring_rate_limit {
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+ let block_number: T::BlockNumber = 0.into();
+ }: set_contract_sponsoring_rate_limit(RawOrigin::Signed(caller.clone()), caller.clone(), block_number)
- set_collection_limits{
- let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
- let mode: CollectionMode = CollectionMode::NFT;
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
-
- let cl = CollectionLimits {
- account_token_ownership_limit: 0,
- sponsored_data_size: 0,
- token_limit: 0,
- sponsor_transfer_timeout: 0
- };
+ set_collection_limits{
+ let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT;
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+
+ let cl = CollectionLimits {
+ account_token_ownership_limit: 0,
+ sponsored_data_size: 0,
+ token_limit: 0,
+ sponsor_transfer_timeout: 0
+ };
- }: set_collection_limits(RawOrigin::Signed(caller.clone()), 2, cl)
+ }: set_collection_limits(RawOrigin::Signed(caller.clone()), 2, cl)
- add_to_contract_white_list{
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- }: add_to_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), caller.clone())
+ add_to_contract_white_list{
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ }: add_to_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), caller.clone())
- remove_from_contract_white_list{
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- Nft::<T>::add_to_contract_white_list(RawOrigin::Signed(caller.clone()).into(), caller.clone(), caller.clone())?;
- }: remove_from_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), caller.clone())
+ remove_from_contract_white_list{
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ Nft::<T>::add_to_contract_white_list(RawOrigin::Signed(caller.clone()).into(), caller.clone(), caller.clone())?;
+ }: remove_from_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), caller.clone())
- toggle_contract_white_list{
- let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- }: toggle_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), true)
-}
\ No newline at end of file
+ toggle_contract_white_list{
+ let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+ }: toggle_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), true)
+*/
+}
runtime/Cargo.tomldiffbeforeafterboth--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -26,6 +26,7 @@
# local dependencies
pallet-nft = { path = '../pallets/nft', default-features = false, version = '3.0.0' }
+pallet-inflation = { path = '../pallets/inflation', default-features = false, version = '3.0.0' }
# Substrate dependencies
frame-benchmarking = { default-features = false, optional = true, version = '3.0.0' }
@@ -72,6 +73,7 @@
'pallet-balances/runtime-benchmarks',
'pallet-timestamp/runtime-benchmarks',
'pallet-nft/runtime-benchmarks',
+ 'pallet-inflation/runtime-benchmarks',
'sp-runtime/runtime-benchmarks',
]
std = [
@@ -95,6 +97,7 @@
'pallet-treasury/std',
'pallet-vesting/std',
+ 'pallet-inflation/std',
'pallet-nft/std',
'sp-api/std',
'sp-block-builder/std',
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, AccountIdConversion,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}522523parameter_types! {524 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();525 pub const CollectionCreationPrice: Balance = 100 * UNIQUE;526}527528/// Used for the module nft in `./nft.rs`529impl pallet_nft::Config for Runtime {530 type Event = Event;531 type WeightInfo = nft_weights::WeightInfo;532 type Currency = Balances;533 type CollectionCreationPrice = CollectionCreationPrice;534 type TreasuryAccountId = TreasuryAccountId;535}536537construct_runtime!(538 pub enum Runtime where539 Block = Block,540 NodeBlock = opaque::Block,541 UncheckedExtrinsic = UncheckedExtrinsic542 {543 System: system::{Module, Call, Config, Storage, Event<T>},544 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},545 Contracts: pallet_contracts::{Module, Call, Config<T>, Storage, Event<T>},546 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},547 Aura: pallet_aura::{Module, Config<T> },548 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},549 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},550 TransactionPayment: pallet_transaction_payment::{Module, Storage},551 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},552 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},553 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},554 Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},555 }556);557558/// The address format for describing accounts.559pub type Address = AccountId;560/// Block header type as expected by this runtime.561pub type Header = generic::Header<BlockNumber, BlakeTwo256>;562/// Block type as expected by this runtime.563pub type Block = generic::Block<Header, UncheckedExtrinsic>;564/// A Block signed with a Justification565pub type SignedBlock = generic::SignedBlock<Block>;566/// BlockId type as expected by this runtime.567pub type BlockId = generic::BlockId<Block>;568/// The SignedExtension to the basic transaction logic.569pub type SignedExtra = (570 system::CheckSpecVersion<Runtime>,571 system::CheckTxVersion<Runtime>,572 system::CheckGenesis<Runtime>,573 system::CheckEra<Runtime>,574 system::CheckNonce<Runtime>,575 system::CheckWeight<Runtime>,576 pallet_nft::ChargeTransactionPayment<Runtime>,577);578/// Unchecked extrinsic type as expected by this runtime.579pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;580/// Extrinsic type that has already been checked.581pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;582/// Executive: handles dispatch to the various modules.583pub type Executive =584 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;585586impl_runtime_apis! {587588 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>589 for Runtime590 {591 fn call(592 origin: AccountId,593 dest: AccountId,594 value: Balance,595 gas_limit: u64,596 input_data: Vec<u8>,597 ) -> pallet_contracts_primitives::ContractExecResult {598 Contracts::bare_call(origin, dest, value, gas_limit, input_data)599 }600601 fn get_storage(602 address: AccountId,603 key: [u8; 32],604 ) -> pallet_contracts_primitives::GetStorageResult {605 Contracts::get_storage(address, key)606 }607608 fn rent_projection(609 address: AccountId,610 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {611 Contracts::rent_projection(address)612 }613 }614615 impl sp_api::Core<Block> for Runtime {616 fn version() -> RuntimeVersion {617 VERSION618 }619620 fn execute_block(block: Block) {621 Executive::execute_block(block)622 }623624 fn initialize_block(header: &<Block as BlockT>::Header) {625 Executive::initialize_block(header)626 }627 }628629 impl sp_api::Metadata<Block> for Runtime {630 fn metadata() -> OpaqueMetadata {631 Runtime::metadata().into()632 }633 }634635 impl sp_block_builder::BlockBuilder<Block> for Runtime {636 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {637 Executive::apply_extrinsic(extrinsic)638 }639640 fn finalize_block() -> <Block as BlockT>::Header {641 Executive::finalize_block()642 }643644 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {645 data.create_extrinsics()646 }647648 fn check_inherents(649 block: Block,650 data: sp_inherents::InherentData,651 ) -> sp_inherents::CheckInherentsResult {652 data.check_extrinsics(&block)653 }654655 fn random_seed() -> <Block as BlockT>::Hash {656 RandomnessCollectiveFlip::random_seed()657 }658 }659660 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {661 fn validate_transaction(662 source: TransactionSource,663 tx: <Block as BlockT>::Extrinsic,664 ) -> TransactionValidity {665 Executive::validate_transaction(source, tx)666 }667 }668669 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {670 fn offchain_worker(header: &<Block as BlockT>::Header) {671 Executive::offchain_worker(header)672 }673 }674675 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {676 fn slot_duration() -> u64 {677 Aura::slot_duration()678 }679680 fn authorities() -> Vec<AuraId> {681 Aura::authorities()682 }683 }684685 impl sp_session::SessionKeys<Block> for Runtime {686 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {687 opaque::SessionKeys::generate(seed)688 }689690 fn decode_session_keys(691 encoded: Vec<u8>,692 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {693 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)694 }695 }696697 impl fg_primitives::GrandpaApi<Block> for Runtime {698 fn grandpa_authorities() -> GrandpaAuthorityList {699 Grandpa::grandpa_authorities()700 }701702 fn submit_report_equivocation_unsigned_extrinsic(703 _equivocation_proof: fg_primitives::EquivocationProof<704 <Block as BlockT>::Hash,705 NumberFor<Block>,706 >,707 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,708 ) -> Option<()> {709 None710 }711712 fn generate_key_ownership_proof(713 _set_id: fg_primitives::SetId,714 _authority_id: GrandpaId,715 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {716 // NOTE: this is the only implementation possible since we've717 // defined our key owner proof type as a bottom type (i.e. a type718 // with no values).719 None720 }721 }722 723 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {724 fn account_nonce(account: AccountId) -> Index {725 System::account_nonce(account)726 }727 }728729 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {730 fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {731 TransactionPayment::query_info(uxt, len)732 }733 fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {734 TransactionPayment::query_fee_details(uxt, len)735 }736 }737738 #[cfg(feature = "runtime-benchmarks")]739 impl frame_benchmarking::Benchmark<Block> for Runtime {740 fn dispatch_benchmark(741 config: frame_benchmarking::BenchmarkConfig742 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {743 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};744745 let whitelist: Vec<TrackedStorageKey> = vec![746 // Alice account747 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),748 // // Total Issuance749 // hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),750 // // Execution Phase751 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),752 // // Event Count753 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),754 // // System Events755 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),756 ];757758 let mut batches = Vec::<BenchmarkBatch>::new();759 let params = (&config, &whitelist);760761 add_benchmark!(params, batches, pallet_nft, Nft);762763 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }764 Ok(batches)765 }766 }767}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, AccountIdConversion,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}522523parameter_types! {524 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();525 pub const CollectionCreationPrice: Balance = 100 * UNIQUE;526}527528/// Used for the pallet nft in `./nft.rs`529impl pallet_nft::Config for Runtime {530 type Event = Event;531 type WeightInfo = nft_weights::WeightInfo;532 type Currency = Balances;533 type CollectionCreationPrice = CollectionCreationPrice;534 type TreasuryAccountId = TreasuryAccountId;535}536537/// Reimport pallet inflation538extern crate pallet_inflation;539pub use pallet_inflation::*;540541parameter_types! {542 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied543}544545/// Used for the pallet inflation546impl pallet_inflation::Config for Runtime {547 type Currency = Balances;548 type TreasuryAccountId = TreasuryAccountId;549 type InflationBlockInterval = InflationBlockInterval;550}551552construct_runtime!(553 pub enum Runtime where554 Block = Block,555 NodeBlock = opaque::Block,556 UncheckedExtrinsic = UncheckedExtrinsic557 {558 System: system::{Module, Call, Config, Storage, Event<T>},559 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},560 Contracts: pallet_contracts::{Module, Call, Config<T>, Storage, Event<T>},561 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},562 Aura: pallet_aura::{Module, Config<T> },563 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},564 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},565 TransactionPayment: pallet_transaction_payment::{Module, Storage},566 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},567 Inflation: pallet_inflation::{Module, Call, Storage},568 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},569 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},570 Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},571 }572);573574/// The address format for describing accounts.575pub type Address = AccountId;576/// Block header type as expected by this runtime.577pub type Header = generic::Header<BlockNumber, BlakeTwo256>;578/// Block type as expected by this runtime.579pub type Block = generic::Block<Header, UncheckedExtrinsic>;580/// A Block signed with a Justification581pub type SignedBlock = generic::SignedBlock<Block>;582/// BlockId type as expected by this runtime.583pub type BlockId = generic::BlockId<Block>;584/// The SignedExtension to the basic transaction logic.585pub type SignedExtra = (586 system::CheckSpecVersion<Runtime>,587 system::CheckTxVersion<Runtime>,588 system::CheckGenesis<Runtime>,589 system::CheckEra<Runtime>,590 system::CheckNonce<Runtime>,591 system::CheckWeight<Runtime>,592 pallet_nft::ChargeTransactionPayment<Runtime>,593);594/// Unchecked extrinsic type as expected by this runtime.595pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;596/// Extrinsic type that has already been checked.597pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;598/// Executive: handles dispatch to the various modules.599pub type Executive =600 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;601602impl_runtime_apis! {603604 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>605 for Runtime606 {607 fn call(608 origin: AccountId,609 dest: AccountId,610 value: Balance,611 gas_limit: u64,612 input_data: Vec<u8>,613 ) -> pallet_contracts_primitives::ContractExecResult {614 Contracts::bare_call(origin, dest, value, gas_limit, input_data)615 }616617 fn get_storage(618 address: AccountId,619 key: [u8; 32],620 ) -> pallet_contracts_primitives::GetStorageResult {621 Contracts::get_storage(address, key)622 }623624 fn rent_projection(625 address: AccountId,626 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {627 Contracts::rent_projection(address)628 }629 }630631 impl sp_api::Core<Block> for Runtime {632 fn version() -> RuntimeVersion {633 VERSION634 }635636 fn execute_block(block: Block) {637 Executive::execute_block(block)638 }639640 fn initialize_block(header: &<Block as BlockT>::Header) {641 Executive::initialize_block(header)642 }643 }644645 impl sp_api::Metadata<Block> for Runtime {646 fn metadata() -> OpaqueMetadata {647 Runtime::metadata().into()648 }649 }650651 impl sp_block_builder::BlockBuilder<Block> for Runtime {652 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {653 Executive::apply_extrinsic(extrinsic)654 }655656 fn finalize_block() -> <Block as BlockT>::Header {657 Executive::finalize_block()658 }659660 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {661 data.create_extrinsics()662 }663664 fn check_inherents(665 block: Block,666 data: sp_inherents::InherentData,667 ) -> sp_inherents::CheckInherentsResult {668 data.check_extrinsics(&block)669 }670671 fn random_seed() -> <Block as BlockT>::Hash {672 RandomnessCollectiveFlip::random_seed()673 }674 }675676 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {677 fn validate_transaction(678 source: TransactionSource,679 tx: <Block as BlockT>::Extrinsic,680 ) -> TransactionValidity {681 Executive::validate_transaction(source, tx)682 }683 }684685 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {686 fn offchain_worker(header: &<Block as BlockT>::Header) {687 Executive::offchain_worker(header)688 }689 }690691 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {692 fn slot_duration() -> u64 {693 Aura::slot_duration()694 }695696 fn authorities() -> Vec<AuraId> {697 Aura::authorities()698 }699 }700701 impl sp_session::SessionKeys<Block> for Runtime {702 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {703 opaque::SessionKeys::generate(seed)704 }705706 fn decode_session_keys(707 encoded: Vec<u8>,708 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {709 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)710 }711 }712713 impl fg_primitives::GrandpaApi<Block> for Runtime {714 fn grandpa_authorities() -> GrandpaAuthorityList {715 Grandpa::grandpa_authorities()716 }717718 fn submit_report_equivocation_unsigned_extrinsic(719 _equivocation_proof: fg_primitives::EquivocationProof<720 <Block as BlockT>::Hash,721 NumberFor<Block>,722 >,723 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,724 ) -> Option<()> {725 None726 }727728 fn generate_key_ownership_proof(729 _set_id: fg_primitives::SetId,730 _authority_id: GrandpaId,731 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {732 // NOTE: this is the only implementation possible since we've733 // defined our key owner proof type as a bottom type (i.e. a type734 // with no values).735 None736 }737 }738 739 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {740 fn account_nonce(account: AccountId) -> Index {741 System::account_nonce(account)742 }743 }744745 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {746 fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {747 TransactionPayment::query_info(uxt, len)748 }749 fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {750 TransactionPayment::query_fee_details(uxt, len)751 }752 }753754 #[cfg(feature = "runtime-benchmarks")]755 impl frame_benchmarking::Benchmark<Block> for Runtime {756 fn dispatch_benchmark(757 config: frame_benchmarking::BenchmarkConfig758 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {759 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};760761 let whitelist: Vec<TrackedStorageKey> = vec![762 // Alice account763 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),764 // // Total Issuance765 // hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),766 // // Execution Phase767 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),768 // // Event Count769 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),770 // // System Events771 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),772 ];773774 let mut batches = Vec::<BenchmarkBatch>::new();775 let params = (&config, &whitelist);776777 add_benchmark!(params, batches, pallet_nft, Nft);778 add_benchmark!(params, batches, pallet_inflation, Inflation);779780 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }781 Ok(batches)782 }783 }784}tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -50,7 +50,8 @@
"testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts",
"testSetOffchainSchema": "mocha --timeout 9999999 -r ts-node/register ./**/setOffchainSchema.test.ts",
"testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",
- "testSetVariableMetadataSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetadataSponsoringRateLimit.test.ts"
+ "testSetVariableMetadataSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetadataSponsoringRateLimit.test.ts",
+ "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts"
},
"author": "",
"license": "SEE LICENSE IN ../LICENSE",
tests/src/creditFeesToTreasury.test.tsdiffbeforeafterboth--- a/tests/src/creditFeesToTreasury.test.ts
+++ b/tests/src/creditFeesToTreasury.test.ts
@@ -18,6 +18,7 @@
} from './util/helpers';
import { default as waitNewBlocks } from './substrate/wait-new-blocks';
+import { ApiPromise } from '@polkadot/api';
chai.use(chaiAsPromised);
const expect = chai.expect;
@@ -30,6 +31,25 @@
let alice: IKeyringPair;
let bob: IKeyringPair;
+// Skip the inflation block pauses if the block is close to inflation block
+// until the inflation happens
+function skipInflationBlock(api: ApiPromise): Promise<void> {
+ const promise = new Promise<void>(async (resolve, reject) => {
+ const blockInterval = parseInt((await api.consts.inflation.inflationBlockInterval).toString());
+ const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => {
+ const currentBlock = parseInt(head.number.toString());
+ if (currentBlock % blockInterval < blockInterval - 10) {
+ unsubscribe();
+ resolve();
+ } else {
+ console.log(`Skipping inflation block, current block: ${currentBlock}`);
+ }
+ });
+ });
+
+ return promise;
+}
+
describe('integration test: Fees must be credited to Treasury:', () => {
before(async () => {
await usingApi(async (api) => {
@@ -40,6 +60,7 @@
it('Total issuance does not change', async () => {
await usingApi(async (api) => {
+ await skipInflationBlock(api);
await waitNewBlocks(api, 1);
const totalBefore = new BigNumber((await api.query.balances.totalIssuance()).toString());
@@ -59,6 +80,7 @@
it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {
await usingApi(async (api) => {
+ await skipInflationBlock(api);
await waitNewBlocks(api, 1);
const alicePrivateKey = privateKey('//Alice');
@@ -81,6 +103,7 @@
it('Treasury balance increased by failed tx fee', async () => {
await usingApi(async (api) => {
+ await skipInflationBlock(api);
await waitNewBlocks(api, 1);
const bobPrivateKey = privateKey('//Bob');
@@ -101,6 +124,7 @@
it('NFT Transactions also send fees to Treasury', async () => {
await usingApi(async (api) => {
+ await skipInflationBlock(api);
await waitNewBlocks(api, 1);
const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
@@ -119,6 +143,7 @@
it('Fees are sane', async () => {
await usingApi(async (api) => {
+ await skipInflationBlock(api);
await waitNewBlocks(api, 1);
const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
@@ -135,6 +160,7 @@
it('NFT Transfer fee is close to 0.1 Unique', async () => {
await usingApi(async (api) => {
+ await skipInflationBlock(api);
await waitNewBlocks(api, 1);
const collectionId = await createCollectionExpectSuccess();
@@ -147,7 +173,7 @@
// console.log(fee.toString());
const expectedTransferFee = 0.1;
- const tolerance = 0.00001;
+ const tolerance = 0.001;
expect(fee.dividedBy(1e15).minus(expectedTransferFee).abs().toNumber()).to.be.lessThan(tolerance);
});
});
tests/src/inflation.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/inflation.test.ts
@@ -0,0 +1,43 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { default as usingApi } from "./substrate/substrate-api";
+import privateKey from "./substrate/privateKey";
+import { BigNumber } from 'bignumber.js';
+import { IKeyringPair } from '@polkadot/types/types';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let alice: IKeyringPair;
+let bob: IKeyringPair;
+
+describe('integration test: Inflation', () => {
+ before(async () => {
+ await usingApi(async (api) => {
+ alice = privateKey('//Alice');
+ bob = privateKey('//Bob');
+ });
+ });
+
+ it('First year inflation is 10%', async () => {
+ await usingApi(async (api) => {
+
+ const blockInterval = parseInt((await api.consts.inflation.inflationBlockInterval).toString());
+ const totalIssuanceStart = new BigNumber((await api.query.inflation.startingYearTotalIssuance()).toString());
+ const blockInflation = new BigNumber((await api.query.inflation.blockInflation()).toString());
+
+ const YEAR = 5259600; // Blocks in one year
+ const totalExpectedInflation = totalIssuanceStart.multipliedBy(0.1);
+ const totalActualInflation = blockInflation.multipliedBy(YEAR / blockInterval);
+
+ const tolerance = 0.00001; // Relative difference per year between theoretical and actual inflation
+ expect(totalExpectedInflation.dividedBy(totalActualInflation).minus(1).abs().toNumber()).to.be.lessThan(tolerance);
+ });
+ });
+
+});