From ee920c930327ced138cf6363b96823241e646350 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Thu, 24 Jun 2021 19:41:03 +0000 Subject: [PATCH] refactor: switch charging logic to sponsoring primitive --- --- a/pallets/nft-charge-transaction/Cargo.toml +++ b/pallets/nft-charge-transaction/Cargo.toml @@ -23,19 +23,14 @@ frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } pallet-balances = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-contracts = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-timestamp = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } pallet-transaction-payment = { default-features = false, version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-randomness-collective-flip = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } frame-benchmarking = { default-features = false, version = "3.0.0", optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-nft = { default-features = false, path="../nft" } pallet-nft-transaction-payment = { default-features = false, path="../nft-transaction-payment" } -nft-data-structs = { default-features = false, path="../../primitives", version = "0.9.0" } [features] default = ['std'] @@ -45,15 +40,10 @@ 'frame-support/std', 'frame-system/std', 'pallet-balances/std', - 'pallet-timestamp/std', - 'pallet-randomness-collective-flip/std', - 'pallet-contracts/std', - 'pallet-nft/std', 'pallet-transaction-payment/std', 'pallet-nft-transaction-payment/std', 'sp-std/std', 'sp-runtime/std', - 'nft-data-structs/std', 'frame-benchmarking/std', ] runtime-benchmarks = ["frame-benchmarking"] --- a/pallets/nft-charge-transaction/src/lib.rs +++ b/pallets/nft-charge-transaction/src/lib.rs @@ -14,16 +14,10 @@ #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -#[cfg(test)] -mod tests; - use codec::{Decode, Encode}; -use frame_support::traits::{ Get}; +use frame_support::traits::Get; use frame_support::{ decl_module, decl_storage, - traits::{ - IsSubType, - }, weights::{ DispatchInfo, PostDispatchInfo, DispatchClass } @@ -37,7 +31,6 @@ }, FixedPointOperand, DispatchResult }; -use pallet_contracts::chain_extension::UncheckedFrom; use pallet_transaction_payment::OnChargeTransaction; use sp_std::prelude::*; @@ -83,10 +76,8 @@ impl ChargeTransactionPayment where - T::Call: Dispatchable + IsSubType> + IsSubType>, + T::Call: Dispatchable, BalanceOf: Send + Sync + From + FixedPointOperand, - T::AccountId: AsRef<[u8]>, - T::AccountId: UncheckedFrom, { fn traditional_fee( len: usize, @@ -134,13 +125,6 @@ .map(|i| (fee, i)); } - // check errors - let _error = >::check_error(who, call); - match _error { - Err(_error) => return Err(_error), - Ok(_error) => {} - }; - // Determine who is paying transaction fee based on ecnomic model // Parse call to extract collection ID and access collection sponsor let sponsor = >::withdraw_type(who, call); @@ -156,9 +140,7 @@ for ChargeTransactionPayment where BalanceOf: Send + Sync + From + FixedPointOperand, - T::Call: Dispatchable + IsSubType> + IsSubType>, - T::AccountId: AsRef<[u8]>, - T::AccountId: UncheckedFrom, + T::Call: Dispatchable, { const IDENTIFIER: &'static str = "ChargeTransactionPayment"; type AccountId = T::AccountId; @@ -209,7 +191,7 @@ _result: &DispatchResult, ) -> Result<(), TransactionValidityError> { let (tip, who, imbalance) = pre; - let actual_fee = pallet_transaction_payment::Module::::compute_actual_fee( + let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( len as u32, info, post_info, --- a/pallets/nft-transaction-payment/Cargo.toml +++ b/pallets/nft-transaction-payment/Cargo.toml @@ -22,19 +22,14 @@ serde = { version = "1.0.119", default-features = false } frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-balances = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-contracts = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-timestamp = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } pallet-transaction-payment = { default-features = false, version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-randomness-collective-flip = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } frame-benchmarking = { default-features = false, version = "3.0.0", optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' } -pallet-nft = { default-features = false, path="../nft" } -nft-data-structs = { default-features = false, path="../../primitives", version = "0.9.0" } +up-sponsorship = { default-features = false, path = "../../primitives/sponsorship", version = "0.1.0" } [features] default = ['std'] @@ -43,15 +38,13 @@ 'serde/std', 'frame-support/std', 'frame-system/std', - 'pallet-balances/std', - 'pallet-timestamp/std', - 'pallet-randomness-collective-flip/std', - 'pallet-contracts/std', - 'pallet-nft/std', + 'sp-core/std', + 'sp-io/std', 'pallet-transaction-payment/std', 'sp-std/std', 'sp-runtime/std', - 'nft-data-structs/std', 'frame-benchmarking/std', + + 'up-sponsorship/std', ] runtime-benchmarks = ["frame-benchmarking"] --- a/pallets/nft-transaction-payment/src/benchmarking.rs +++ b/pallets/nft-transaction-payment/src/benchmarking.rs @@ -1,7 +1,6 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use crate::Module as NftTransactionPayment; use sp_std::prelude::*; use frame_system::RawOrigin; --- a/pallets/nft-transaction-payment/src/lib.rs +++ b/pallets/nft-transaction-payment/src/lib.rs @@ -14,388 +14,32 @@ #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -#[cfg(test)] -mod tests; - -use frame_support::{ - decl_error, decl_module, decl_storage, - traits::{ - IsSubType, - }, - weights::{ - DispatchInfo - } -}; -use sp_runtime::traits::StaticLookup; -use sp_runtime::{ - traits::{ - Hash, Dispatchable, - }, - transaction_validity::{ - InvalidTransaction, TransactionValidityError, - }, -}; -use pallet_contracts::chain_extension::UncheckedFrom; +use frame_support::{decl_module, decl_storage}; use sp_std::prelude::*; -use nft_data_structs::{ - CreateItemData, - CollectionId, CollectionMode, TokenId -}; - -type CodeHash = ::Hash; +use up_sponsorship::SponsorshipHandler; - pub trait Config: frame_system::Config + pallet_contracts::Config + pallet_transaction_payment::Config + pallet_nft::Config { - } - - // Error for non-fungible-token module. - - decl_error! { - /// Error for non-fungible-token module. - pub enum Error for Module { - /// No available class ID - NoAvailableClassId, - /// No available token ID - NoAvailableTokenId, - /// Token(ClassId, TokenId) not found - TokenNotFound, - /// Class not found - CollectionNotFound, - /// The operator is not the owner of the token and has no permission - NoPermission, - /// Arithmetic calculation overflow - NumOverflow, - /// Can not destroy class - /// Total issuance is not 0 - CannotDestroyClass, - } +pub trait Config: frame_system::Config + pallet_transaction_payment::Config { + type SponsorshipHandler: SponsorshipHandler; } - - decl_storage! { - trait Store for Module as NftTransactionPayment{ +decl_storage! { + trait Store for Module as NftTransactionPayment{ } } decl_module! { - pub struct Module for enum Call where origin: T::Origin, { } } - -impl Module -{ - pub fn check_error( - who: &T::AccountId, - call: &T::Call - ) -> Result where - T::Call: Dispatchable, - T::Call: IsSubType>, - T::Call: IsSubType>, - T::AccountId: AsRef<[u8]>, - T::AccountId: UncheckedFrom - { - - match IsSubType::>::is_sub_type(call) { - Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => { - - let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default()); - - let owned_contract = pallet_nft::ContractOwner::::get(called_contract.clone()).as_ref() == Some(who); - let white_list_enabled = pallet_nft::ContractWhiteListEnabled::::contains_key(called_contract.clone()); - - if !owned_contract && white_list_enabled { - if !pallet_nft::ContractWhiteList::::contains_key(called_contract.clone(), who) { - return Err(InvalidTransaction::Call.into()); - } - } - Ok(true) - }, - _ => { Ok(true) }, - } - } - +impl Module { pub fn withdraw_type( who: &T::AccountId, call: &T::Call - ) -> Option where - T::Call: Dispatchable, - T::Call: IsSubType>, - T::Call: IsSubType>, - T::AccountId: AsRef<[u8]>, - T::AccountId: UncheckedFrom - { - - let mut sponsor: Option = match IsSubType::>::is_sub_type(call) { - Some(pallet_nft::Call::create_item(collection_id, _owner, _properties)) => { - - Self::withdraw_create_item(who, collection_id, &_properties) - }, - Some(pallet_nft::Call::transfer(_new_owner, collection_id, item_id, _value)) => { - - Self::withdraw_transfer(who, collection_id, item_id) - }, - Some(pallet_nft::Call::set_variable_meta_data(collection_id, item_id, data)) => { - - Self::withdraw_set_variable_meta_data(collection_id, item_id, &data) - }, - _ => None, - }; - - sponsor = sponsor.or_else(|| match IsSubType::>::is_sub_type(call) { - Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => { - - Self::withdraw_contract_call(who, dest) - }, - Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, _data, salt)) => { - - Self::withdraw_contract_instantiate(&who, code_hash, salt) - }, - Some(pallet_contracts::Call::instantiate_with_code(_endowment, _gas_limit, _code, _data, _salt)) => { - - Self::withdraw_contract_instantiate(&who, &T::Hashing::hash(&_code), _salt) - }, - _ => None, - }); - - sponsor - } - - - - pub fn withdraw_create_item( - who: &T::AccountId, - collection_id: &CollectionId, - _properties: &CreateItemData, ) -> Option { - - let collection = pallet_nft::CollectionById::::get(collection_id)?; - - // sponsor timeout - let block_number = >::block_number() as T::BlockNumber; - - let limit = collection.limits.sponsor_transfer_timeout; - if pallet_nft::CreateItemBasket::::contains_key((collection_id, &who)) { - let last_tx_block = pallet_nft::CreateItemBasket::::get((collection_id, &who)); - let limit_time = last_tx_block + limit.into(); - if block_number <= limit_time { - return None; - } - } - pallet_nft::CreateItemBasket::::insert((collection_id, who.clone()), block_number); - - // check free create limit - if collection.limits.sponsored_data_size >= (_properties.len() as u32) { - collection.sponsorship.sponsor() - .cloned() - } else { - None - } - } - - pub fn withdraw_transfer( - who: &T::AccountId, - collection_id: &CollectionId, - item_id: &TokenId, - ) -> Option { - - let collection = pallet_nft::CollectionById::::get(collection_id)?; - let limits = pallet_nft::ChainLimit::get(); - - let mut sponsor_transfer = false; - if collection.sponsorship.confirmed() { - - let collection_limits = collection.limits.clone(); - let collection_mode = collection.mode.clone(); - - // sponsor timeout - let block_number = >::block_number() as T::BlockNumber; - sponsor_transfer = match collection_mode { - CollectionMode::NFT => { - - // get correct limit - let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { - collection_limits.sponsor_transfer_timeout - } else { - limits.nft_sponsor_transfer_timeout - }; - - let mut sponsored = true; - if pallet_nft::NftTransferBasket::::contains_key(collection_id, item_id) { - let last_tx_block = pallet_nft::NftTransferBasket::::get(collection_id, item_id); - let limit_time = last_tx_block + limit.into(); - if block_number <= limit_time { - sponsored = false; - } - } - if sponsored { - pallet_nft::NftTransferBasket::::insert(collection_id, item_id, block_number); - } - - sponsored - } - CollectionMode::Fungible(_) => { - - // get correct limit - let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { - collection_limits.sponsor_transfer_timeout - } else { - limits.fungible_sponsor_transfer_timeout - }; - - let block_number = >::block_number() as T::BlockNumber; - let mut sponsored = true; - if pallet_nft::FungibleTransferBasket::::contains_key(collection_id, who) { - let last_tx_block = pallet_nft::FungibleTransferBasket::::get(collection_id, who); - let limit_time = last_tx_block + limit.into(); - if block_number <= limit_time { - sponsored = false; - } - } - if sponsored { - pallet_nft::FungibleTransferBasket::::insert(collection_id, who, block_number); - } - - sponsored - } - CollectionMode::ReFungible => { - - // get correct limit - let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { - collection_limits.sponsor_transfer_timeout - } else { - limits.refungible_sponsor_transfer_timeout - }; - - let mut sponsored = true; - if pallet_nft::ReFungibleTransferBasket::::contains_key(collection_id, item_id) { - let last_tx_block = pallet_nft::ReFungibleTransferBasket::::get(collection_id, item_id); - let limit_time = last_tx_block + limit.into(); - if block_number <= limit_time { - sponsored = false; - } - } - if sponsored { - pallet_nft::ReFungibleTransferBasket::::insert(collection_id, item_id, block_number); - } - - sponsored - } - _ => { - false - }, - }; - } - - if !sponsor_transfer { - None - } else { - collection.sponsorship.sponsor() - .cloned() - } - } - - pub fn withdraw_set_variable_meta_data( - collection_id: &CollectionId, - item_id: &TokenId, - data: &Vec, - ) -> Option { - - let mut sponsor_metadata_changes = false; - - let collection = pallet_nft::CollectionById::::get(collection_id)?; - - if - collection.sponsorship.confirmed() && - // Can't sponsor fungible collection, this tx will be rejected - // as invalid - !matches!(collection.mode, CollectionMode::Fungible(_)) && - data.len() <= collection.limits.sponsored_data_size as usize - { - if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit { - let block_number = >::block_number() as T::BlockNumber; - - if pallet_nft::VariableMetaDataBasket::::get(collection_id, item_id) - .map(|last_block| block_number - last_block > rate_limit) - .unwrap_or(true) - { - sponsor_metadata_changes = true; - pallet_nft::VariableMetaDataBasket::::insert(collection_id, item_id, block_number); - } - } - } - - if !sponsor_metadata_changes { - None - } else { - collection.sponsorship.sponsor().cloned() - } - - } - - pub fn withdraw_contract_call( - who: &T::AccountId, - dest: &::Source - ) -> Option { - - let called_contract: T::AccountId = T::Lookup::lookup((dest).clone()).unwrap_or(T::AccountId::default()); - - let owned_contract = pallet_nft::ContractOwner::::get(called_contract.clone()).as_ref() == Some(who); - let white_list_enabled = pallet_nft::ContractWhiteListEnabled::::contains_key(called_contract.clone()); - - // ??? - if !owned_contract && white_list_enabled { - if !pallet_nft::ContractWhiteList::::contains_key(called_contract.clone(), who) { - return Some(who.clone()) - // return Err(InvalidTransaction::Call.into()); - } - } - - let mut sponsor_transfer = false; - if pallet_nft::ContractSponsoringRateLimit::::contains_key(called_contract.clone()) { - let last_tx_block = pallet_nft::ContractSponsorBasket::::get((&called_contract, &who)); - let block_number = >::block_number() as T::BlockNumber; - let rate_limit = pallet_nft::ContractSponsoringRateLimit::::get(&called_contract); - let limit_time = last_tx_block + rate_limit; - - if block_number >= limit_time { - pallet_nft::ContractSponsorBasket::::insert((called_contract.clone(), who.clone()), block_number); - sponsor_transfer = true; - } - } else { - sponsor_transfer = false; - } - - if sponsor_transfer { - if pallet_nft::ContractSelfSponsoring::::contains_key(called_contract.clone()) { - if pallet_nft::ContractSelfSponsoring::::get(called_contract.clone()) { - return Some(called_contract); - } - } - } - - None - } - - pub fn withdraw_contract_instantiate( - who: &T::AccountId, - code_hash: &CodeHash, - salt: &[u8], - ) -> Option where - T::AccountId: AsRef<[u8]>, - T::AccountId: UncheckedFrom - { - - let new_contract_address = >::contract_address( - &who, - code_hash, - salt, - ); - pallet_nft::ContractOwner::::insert(new_contract_address.clone(), who.clone()); - - None + T::SponsorshipHandler::get_sponsor(who, call) } } \ No newline at end of file --- a/pallets/nft-transaction-payment/src/tests.rs +++ /dev/null @@ -1,241 +0,0 @@ -#[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; - type Block = frame_system::mocking::MockBlock; - - 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}, - 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; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - 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::().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 _ = >::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 _ = >::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 _ = >::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 _ = >::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 _ = >::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 _ = >::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]); - } - }); - } -} -- gitstuff