From c66b5029763a9a0b213e616627917cabb0754906 Mon Sep 17 00:00:00 2001 From: Dusan Morhac <55763425+dudo50@users.noreply.github.com> Date: Sun, 3 Nov 2024 00:13:22 +0100 Subject: [PATCH] Add basic unit tests --- Cargo.lock | 11 + templates/parachain/pallets/xcnft/Cargo.toml | 23 + templates/parachain/pallets/xcnft/src/lib.rs | 63 +- templates/parachain/pallets/xcnft/src/mock.rs | 174 ++++ .../parachain/pallets/xcnft/src/mock/mod.rs | 106 -- .../pallets/xcnft/src/mock/parachain.rs | 410 -------- .../pallets/xcnft/src/mock/relaychain.rs | 738 -------------- .../parachain/pallets/xcnft/src/tests.rs | 922 ++++++++++++++++++ .../parachain_two/pallets/xcnft/Cargo.toml | 1 + .../parachain_two/pallets/xcnft/src/lib.rs | 58 +- .../parachain_two/pallets/xcnft/src/mock.rs | 165 ++++ .../pallets/xcnft/src/mock/mod.rs | 106 -- .../pallets/xcnft/src/mock/parachain.rs | 410 -------- .../pallets/xcnft/src/mock/relaychain.rs | 738 -------------- .../parachain_two/pallets/xcnft/src/tests.rs | 764 +++++++++++++++ 15 files changed, 2120 insertions(+), 2569 deletions(-) create mode 100644 templates/parachain/pallets/xcnft/src/mock.rs delete mode 100644 templates/parachain/pallets/xcnft/src/mock/mod.rs delete mode 100644 templates/parachain/pallets/xcnft/src/mock/parachain.rs delete mode 100644 templates/parachain/pallets/xcnft/src/mock/relaychain.rs create mode 100644 templates/parachain_two/pallets/xcnft/src/mock.rs delete mode 100644 templates/parachain_two/pallets/xcnft/src/mock/mod.rs delete mode 100644 templates/parachain_two/pallets/xcnft/src/mock/parachain.rs delete mode 100644 templates/parachain_two/pallets/xcnft/src/mock/relaychain.rs diff --git a/Cargo.lock b/Cargo.lock index 2e93b27db325..cba8f5564c3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12329,17 +12329,27 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "pallet-balances", + "pallet-message-queue", "pallet-nfts", + "pallet-xcm", "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-runtime-parachains", "scale-info", "serde", "sp-core 28.0.0", "sp-io 30.0.0", "sp-runtime 31.0.1", "sp-std 14.0.0", + "sp-tracing 16.0.0", "staging-parachain-info", "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "xcm-simulator", ] [[package]] @@ -12363,6 +12373,7 @@ dependencies = [ "sp-std 14.0.0", "staging-parachain-info", "staging-xcm", + "staging-xcm-builder", ] [[package]] diff --git a/templates/parachain/pallets/xcnft/Cargo.toml b/templates/parachain/pallets/xcnft/Cargo.toml index 19ee04e76dbb..accfa52cca94 100644 --- a/templates/parachain/pallets/xcnft/Cargo.toml +++ b/templates/parachain/pallets/xcnft/Cargo.toml @@ -18,6 +18,7 @@ codec = { features = [ scale-info = { features = [ "derive", ], workspace = true } +log = { workspace = true } # Substrate @@ -27,11 +28,21 @@ frame-system = { workspace = true } #XCM xcm = { workspace = true} +xcm-simulator = { workspace = true, default-features = true } +xcm-executor = { workspace = true, default-features = true } +xcm-builder = { workspace = true, default-features = true } +pallet-xcm = { workspace = true, default-features = true } +polkadot-core-primitives = { workspace = true, default-features = true } +polkadot-runtime-parachains = { workspace = true, default-features = true } +polkadot-parachain-primitives = { workspace = true, default-features = true } cumulus-primitives-core = { workspace = true } cumulus-pallet-xcm = { workspace = true } parachain-info = { workspace = true } +pallet-message-queue = { workspace = true, default-features = true } +sp-tracing = { workspace = true, default-features = true } + sp-runtime = { workspace = true } sp-std = {workspace = true} @@ -47,6 +58,9 @@ sp-io = { workspace = true, default-features = true } pallet-balances = { workspace = true, default-features = true } + + + [features] default = [ "std" ] runtime-benchmarks = [ @@ -54,6 +68,15 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-parachains/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "pallet-nfts/runtime-benchmarks", ] std = [ "codec/std", diff --git a/templates/parachain/pallets/xcnft/src/lib.rs b/templates/parachain/pallets/xcnft/src/lib.rs index 73e26d51d5a7..740b7ea7a4f1 100644 --- a/templates/parachain/pallets/xcnft/src/lib.rs +++ b/templates/parachain/pallets/xcnft/src/lib.rs @@ -60,10 +60,9 @@ pub use pallet::*; #[cfg(test)] -mod mock; - +pub mod mock; #[cfg(test)] -mod tests; +pub mod tests; pub mod weights; @@ -121,9 +120,9 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] #[scale_info(skip_type_params(T, I))] pub struct GeneralizedDestroyWitness { - item_meta: u32, - item_configs: u32, - attributes: u32, + pub item_meta: u32, + pub item_configs: u32, + pub attributes: u32, } /// Enum for voting, either Aye or Nay option. @@ -139,8 +138,8 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] #[scale_info(skip_type_params(T, I))] pub struct Votes, I: 'static = ()> { - aye: BoundedVec, - nay: BoundedVec, + pub aye: BoundedVec, + pub nay: BoundedVec, } /// Structure of proposal, contains proposal id, collection id, proposed collection owner, @@ -149,15 +148,15 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] #[scale_info(skip_type_params(T, I))] pub struct Proposal, I: 'static = ()> { - proposal_id: u64, - collection_id: T::CollectionId, - proposed_collection_owner: T::AccountId, - proposed_destination_para: ParaId, - proposed_dest_collection_id: Option, - proposed_destination_config: Option>, - owners: BoundedVec, - number_of_votes: Votes, - end_time: BlockNumberFor, + pub proposal_id: u64, + pub collection_id: T::CollectionId, + pub proposed_collection_owner: T::AccountId, + pub proposed_destination_para: ParaId, + pub proposed_dest_collection_id: Option, + pub proposed_destination_config: Option>, + pub owners: BoundedVec, + pub number_of_votes: Votes, + pub end_time: BlockNumberFor, } /// Structure of sent assets, contains origin parachain id, origin collection id, origin asset @@ -165,11 +164,11 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct SentStruct, I: 'static = ()> { - origin_para_id: ParaId, - origin_collection_id: T::CollectionId, - origin_asset_id: T::ItemId, - destination_collection_id: T::CollectionId, - destination_asset_id: T::ItemId, + pub origin_para_id: ParaId, + pub origin_collection_id: T::CollectionId, + pub origin_asset_id: T::ItemId, + pub destination_collection_id: T::CollectionId, + pub destination_asset_id: T::ItemId, } /// Structure of received assets, contains origin parachain id, origin collection id, origin @@ -177,11 +176,11 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct ReceivedStruct, I: 'static = ()> { - origin_para_id: ParaId, - origin_collection_id: T::CollectionId, - origin_asset_id: T::ItemId, - received_collection_id: T::CollectionId, - received_asset_id: T::ItemId, + pub origin_para_id: ParaId, + pub origin_collection_id: T::CollectionId, + pub origin_asset_id: T::ItemId, + pub received_collection_id: T::CollectionId, + pub received_asset_id: T::ItemId, } /// Structure of received collections, contains origin parachain id, origin collection id, and @@ -189,9 +188,9 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct ReceivedCols, I: 'static = ()> { - origin_para_id: ParaId, - origin_collection_id: T::CollectionId, - received_collection_id: T::CollectionId, + pub origin_para_id: ParaId, + pub origin_collection_id: T::CollectionId, + pub received_collection_id: T::CollectionId, } /// Storage for sent assets, contains origin collection id and origin asset id as tuple key and @@ -922,7 +921,7 @@ pub mod pallet { // storage and emit event. if unwrapped_proposal.number_of_votes.aye.len() < number_of_votes / 2 || unwrapped_proposal.number_of_votes.aye.len() == 0 && - unwrapped_proposal.number_of_votes.nay.len() == 0 + unwrapped_proposal.number_of_votes.nay.len() == 0 || unwrapped_proposal.number_of_votes.aye.len() == 0 && unwrapped_proposal.number_of_votes.nay.len() == 1 { CrossChainProposals::::remove(proposal_id); @@ -1041,7 +1040,7 @@ pub mod pallet { if proposal.number_of_votes.aye.len() < number_of_votes / 2 || proposal.number_of_votes.aye.len() == 0 && - proposal.number_of_votes.nay.len() == 0 + proposal.number_of_votes.nay.len() == 0 || proposal.number_of_votes.aye.len() == 0 && proposal.number_of_votes.nay.len() == 1 { Self::deposit_event(Event::ProposalDidNotPass { proposal_id }); diff --git a/templates/parachain/pallets/xcnft/src/mock.rs b/templates/parachain/pallets/xcnft/src/mock.rs new file mode 100644 index 000000000000..bc113d442218 --- /dev/null +++ b/templates/parachain/pallets/xcnft/src/mock.rs @@ -0,0 +1,174 @@ +use frame_support::weights::constants::RocksDbWeight; +use frame_system::{mocking::MockBlock, GenesisConfig}; +use sp_runtime::{traits::ConstU64, BuildStorage}; +use frame_support::parameter_types; +use pallet_balances::AccountData; +use xcm_builder::WithUniqueTopic; +use sp_runtime::MultiSignature; +use sp_runtime::traits::Verify; +use frame_system::EnsureRoot; +use frame_system::EnsureSigned; +use sp_core::ConstU32; +use frame_support::traits::VariantCountOf; +use sp_runtime::AccountId32 as AccountId; + +pub type XcmRouter = WithUniqueTopic<( + (), +)>; + +// Configure a mock runtime to test the pallet. +#[frame_support::runtime] +mod test_runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Test; + + #[runtime::pallet_index(0)] + pub type System = frame_system; + + #[runtime::pallet_index(1)] + pub type XcNFT = crate; + + #[runtime::pallet_index(2)] + pub type Balances = pallet_balances; + + #[runtime::pallet_index(3)] + pub type NFTs = pallet_nfts; + + #[runtime::pallet_index(4)] + pub type ParachainInfo = parachain_info; +} + +/// Balance of an account. +pub type Balance = u128; + +impl frame_system::Config for Test { + type RuntimeEvent = RuntimeEvent; + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Hash = sp_core::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = sp_runtime::traits::IdentityLookup; + type Nonce = u64; + type Block = MockBlock; + type BlockHashCount = ConstU64<250>; + type DbWeight = RocksDbWeight; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type ExtensionsWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); +} + +impl parachain_info::Config for Test {} + +impl crate::Config for Test { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + type XcmSender = XcmRouter; + type RuntimeCall = RuntimeCall; + type ProposalTimeInBlocks = proposal_time_in_blocks_parameter; + type MaxOwners = max_owners_parameter; +} + +pub const UNIT: Balance = 1; + +impl pallet_balances::Config for Test { + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = VariantCountOf; + type DoneSlashHandler = (); +} + +parameter_types! { + pub const SS58Prefix: u16 = 42; + pub const ExistentialDeposit: u128 = 500; + pub const CollectionDeposit: Balance = 0 * UNIT; // 1 UNIT deposit to create asset collection + pub const ItemDeposit: Balance = 0 * UNIT; // 1/100 UNIT deposit to create asset item + pub const KeyLimit: u32 = 32; + pub const ValueLimit: u32 = 64; + pub const UniquesMetadataDepositBase: Balance = 0 * UNIT; + pub const AttributeDepositBase: Balance = 0 * UNIT; + pub const DepositPerByte: Balance = 0 * UNIT; + pub const UniquesStringLimit: u32 = 32; + pub const ApprovalsLimit: u32 = 1; + pub const ItemAttributesApprovalsLimit: u32 = 1; + pub const MaxTips: u32 = 1; + pub const MaxDeadlineDuration: u32 = 1; + pub const MaxAttributesPerCall: u32 = 10; + pub NftFeatures: pallet_nfts::PalletFeatures = pallet_nfts::PalletFeatures::all_enabled(); + pub const proposal_time_in_blocks_parameter: u32 = 10; + pub const max_owners_parameter: u32 = 1000000; + pub const max_votes: u32 = 1000000; +} + +pub type AccountPublic = ::Signer; + +impl pallet_nfts::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CollectionId = u32; + type ItemId = u32; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type CreateOrigin = EnsureSigned; + type CollectionDeposit = CollectionDeposit; + type Locker = (); + type ItemDeposit = ItemDeposit; + type MetadataDepositBase = UniquesMetadataDepositBase; + type AttributeDepositBase = AttributeDepositBase; + type DepositPerByte = DepositPerByte; + type StringLimit = UniquesStringLimit; + type KeyLimit = KeyLimit; + type ValueLimit = ValueLimit; + type ApprovalsLimit = ApprovalsLimit; + type ItemAttributesApprovalsLimit = ItemAttributesApprovalsLimit; + type MaxTips = MaxTips; + type MaxDeadlineDuration = MaxDeadlineDuration; + type MaxAttributesPerCall = MaxAttributesPerCall; + type Features = NftFeatures; + type OffchainSignature = MultiSignature; + type OffchainPublic = AccountPublic; + type WeightInfo = (); +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + GenesisConfig::::default().build_storage().unwrap().into() +} diff --git a/templates/parachain/pallets/xcnft/src/mock/mod.rs b/templates/parachain/pallets/xcnft/src/mock/mod.rs deleted file mode 100644 index e25e77b394e1..000000000000 --- a/templates/parachain/pallets/xcnft/src/mock/mod.rs +++ /dev/null @@ -1,106 +0,0 @@ -#![cfg(test)] - -use super::*; -use sp_io::TestExternalities; -use sp_runtime::AccountId32; -mod parachain; -mod relaychain; -use crate as xnft; -use sp_runtime::BuildStorage; -use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; - -pub const ALICE: AccountId32 = AccountId32::new([0u8; 32]); -pub const BOB: AccountId32 = AccountId32::new([1u8; 32]); -pub const CHARLIE: AccountId32 = AccountId32::new([1u8; 32]); - -pub const INITIAL_BALANCE: u64 = 1_000_000_000; - -pub type Balance = u128; -pub type Amount = i128; - -decl_test_parachain! { - pub struct Para1 { - Runtime = parachain::Test, - XcmpMessageHandler = parachain::XcmpQueue, - DmpMessageHandler = parachain::DmpQueue, - new_ext = para_ext(4), - } -} - -decl_test_parachain! { - pub struct Para2 { - Runtime = parachain::Test, - XcmpMessageHandler = parachain::XcmpQueue, - DmpMessageHandler = parachain::DmpQueue, - new_ext = para_ext(4), - } -} - -decl_test_relay_chain! { - pub struct Relay { - Runtime = relaychain::Test, - RuntimeCall = relaychain::RuntimeCall, - RuntimeEvent = relaychain::RuntimeEvent, - XcmConfig = relaychain::XcmConfig, - MessageQueue = relaychain::MessageQueue, - System = relaychain::System, - new_ext = relay_ext(), - } -} - -decl_test_network! { - pub struct TestNet { - relay_chain = Relay, - parachains = vec![ - (2000, Para1), - (2001, Para2), - ], - } -} -pub type RelayBalances = pallet_balances::Pallet; -pub type ParaChain1 = xnft::Pallet; -pub type NFT = pallet_nfts::Pallet; -pub fn para_ext(para_id: u32) -> TestExternalities { - use parachain::{System, Test}; - - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - let parachain_info_config = parachain_info::GenesisConfig:: { - _config: Default::default(), - parachain_id: para_id.into(), - }; - parachain_info_config.assimilate_storage(&mut t).unwrap(); - - let mut ext = TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -pub fn para_teleport_ext(para_id: u32) -> TestExternalities { - use parachain::{System, Test}; - - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - let parachain_info_config = parachain_info::GenesisConfig:: { - _config: Default::default(), - parachain_id: para_id.into(), - }; - parachain_info_config.assimilate_storage(&mut t).unwrap(); - let mut ext = TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -pub fn relay_ext() -> sp_io::TestExternalities { - use relaychain::{System, Test}; - - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - pallet_balances::GenesisConfig:: { balances: vec![(ALICE, 1_000)] } - .assimilate_storage(&mut t) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} diff --git a/templates/parachain/pallets/xcnft/src/mock/parachain.rs b/templates/parachain/pallets/xcnft/src/mock/parachain.rs deleted file mode 100644 index 92cf0c836157..000000000000 --- a/templates/parachain/pallets/xcnft/src/mock/parachain.rs +++ /dev/null @@ -1,410 +0,0 @@ -#![cfg(test)] -use crate::{self as pallet_parachain_xcnft}; - -use crate::test::*; -use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; -use frame_support::{ - construct_runtime, match_types, - pallet_prelude::{DispatchResult, Get}, - parameter_types, - traits::{ - AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, ConstU64, Currency, Everything, - Nothing, - }, - weights::constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, -}; -use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned}; - -use sp_runtime::{generic, BoundedVec}; -pub use sp_runtime::{ - testing::Header, - traits::{AccountIdLookup, BlakeTwo256, IdentityLookup}, - DispatchError, MultiSignature, -}; - -use crate::test::parachain::currency::DOLLARS; -use sp_core::{H256, U256}; -use sp_runtime::BuildStorage; - -pub type CollectionId = u64; -type Origin = ::RuntimeOrigin; -use crate::Config; -type Balance = u128; -use cumulus_primitives_core::{ChannelStatus, GetChannelInfo, ParaId}; -use pallet_nfts::PalletFeatures; -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use xcm::v3::{prelude::*, Weight}; -use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, - NativeAsset, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, -}; -use xcm_executor::XcmExecutor; - -pub mod currency { - use node_primitives::Balance; - - pub const MILLICENTS: Balance = 1_000_000_000; - pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. - pub const DOLLARS: Balance = 100 * CENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS - } -} -pub fn root_user() -> Origin { - RuntimeOrigin::root() -} -pub fn who(who: AccountId) -> Origin { - RuntimeOrigin::signed(who) -} - -pub type Signature = MultiSignature; -pub type AccountPublic = ::Signer; -pub type AccountId = ::AccountId; -pub type BlockNumber = u32; -pub type Index = u32; -pub type Address = sp_runtime::MultiAddress; -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, -); - -type UncheckedExtrinsics = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsics, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances, - ParachainInfo: parachain_info, - XcmpQueue: cumulus_pallet_xcmp_queue, - DmpQueue: cumulus_pallet_dmp_queue, - CumulusXcm: cumulus_pallet_xcm, - PolkadotXcm: pallet_xcm, - Xnft: pallet_xnft, - ParachainSystem: cumulus_pallet_parachain_system, - NFT:pallet_nfts::{Pallet, Call, Storage, Event}, - } -); - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type Block = Block; - type Nonce = u64; - type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Lookup = IdentityLookup; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = (); - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = ConstU32<16>; -} - -impl cumulus_pallet_parachain_system::Config for Test { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; - type OutboundXcmpMessageSource = XcmpQueue; - type DmpMessageHandler = DmpQueue; - type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; - type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; -} - -parameter_types! { - pub const CollectionDeposit: Balance = 100 * DOLLARS; - pub const ItemDeposit: Balance = 1 * DOLLARS; - pub const KeyLimit: u32 = 32; - pub const ValueLimit: u32 = 256; - pub const ApprovalsLimit: u32 = 20; - pub const ItemAttributesApprovalsLimit: u32 = 20; - pub const MaxTips: u32 = 10; - -} - -parameter_types! { - pub Features: PalletFeatures = PalletFeatures::all_enabled(); - pub const MaxAttributesPerCall: u32 = 10; -} - -parameter_types! { - pub const AssetDeposit: Balance = 100 * DOLLARS; - pub const ApprovalDeposit: Balance = 1 * DOLLARS; - pub const StringLimit: u32 = 50; - pub const MetadataDepositBase: Balance = 10 * DOLLARS; - pub const MetadataDepositPerByte: Balance = 1 * DOLLARS; -} - -impl pallet_nfts::Config for Test { - type RuntimeEvent = RuntimeEvent; - type CollectionId = u32; - type ItemId = u32; - type Currency = Balances; - type CreateOrigin = AsEnsureOriginWithArg>; - type ForceOrigin = frame_system::EnsureRoot; - type Locker = (); - type CollectionDeposit = ConstU64<2>; - type ItemDeposit = ConstU64<1>; - type MetadataDepositBase = ConstU64<1>; - type AttributeDepositBase = ConstU64<1>; - type DepositPerByte = ConstU64<1>; - type StringLimit = ConstU32<50>; - type KeyLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; - type ApprovalsLimit = ConstU32<10>; - type ItemAttributesApprovalsLimit = ConstU32<2>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = (); - type MaxAttributesPerCall = ConstU32<2>; - type Features = Features; - type OffchainSignature = Signature; - type OffchainPublic = ::Signer; - type WeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxLocks: u32 = 10; -} - -impl pallet_balances::Config for Test { - type MaxLocks = MaxLocks; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type MaxHolds = (); - type RuntimeHoldReason = RuntimeHoldReason; -} - -parameter_types! { - pub const ReservedXcmpWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4), 0); - pub const ReservedDmpWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4), 0); -} - -impl parachain_info::Config for Test {} - -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: Option = None; - pub const AnyNetwork: Option = None; - pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); -} - -pub type LocationToAccountId = ( - ParentIsPreset, - SiblingParachainConvertsVia, - AccountId32Aliases, -); - -pub type XcmOriginToCallOrigin = ( - SovereignSignedViaLocation, - RelayChainAsNative, - SiblingParachainAsNative, - SignedAccountId32AsNative, - XcmPassthrough, -); - -pub type XcmRouter = ( - // Two routers - use UMP to communicate with the relay chain: - cumulus_primitives_utility::ParentAsUmp, - // ..and XCMP to communicate with the sibling chains. - XcmpQueue, -); -pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom); - -parameter_types! { - pub const UnitWeightCost: Weight = Weight::from_parts(10, 10); - pub const BaseXcmWeight: Weight = Weight::from_parts(100_000_000, 100_000_000); - pub const MaxInstructions: u32 = 100; - pub const MaxAssetsIntoHolding: u32 = 64; -} - -parameter_types! { - pub const Roc: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(RelayLocation::get()) }); - pub const Para: MultiLocation = Parachain(2000).into_location(); - pub const Para2: MultiLocation = Parachain(2001).into_location(); - pub const OurchainPara: (MultiAssetFilter, MultiLocation) = (Roc::get(), Para::get()); - pub const OurchainPara2: (MultiAssetFilter, MultiLocation) = (Roc::get(), Para2::get()); - -} - -pub type TrustedTeleporters = (xcm_builder::Case, xcm_builder::Case); - -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; - type AssetTransactor = (); - type OriginConverter = (); - type IsReserve = NativeAsset; - type IsTeleporter = TrustedTeleporters; - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = (); - type ResponseHandler = (); - type AssetTrap = (); - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = (); - type SubscriptionService = (); - type PalletInstancesInfo = (); - type FeeManager = (); - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type MessageExporter = (); - type UniversalAliases = Everything; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = (); -} - -pub struct ChannelInfo; -impl GetChannelInfo for ChannelInfo { - fn get_channel_status(_id: ParaId) -> ChannelStatus { - ChannelStatus::Ready(10, 10) - } - fn get_channel_max(_id: ParaId) -> Option { - Some(usize::max_value()) - } -} - -impl cumulus_pallet_xcmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ChannelInfo = ChannelInfo; - type VersionWrapper = (); - type ExecuteOverweightOrigin = EnsureRoot; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = (); - type WeightInfo = (); - type PriceForSiblingDelivery = (); -} - -impl cumulus_pallet_dmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; -} - -impl cumulus_pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; -} - -pub type LocalOriginToLocation = SignedToAccountId32; - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); -} - -impl pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = (); - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; -} - -parameter_types! { - pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); - // pub const MaxAssetsForTransfer: usize = 3; -} - -match_types! { - pub type ParentOrParachains: impl Contains = { - MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X1(Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X1(Parachain(2000)) } | - MultiLocation { parents: 1, interior: X1(Parachain(2001)) } | - MultiLocation { parents: 1, interior: X2(Parachain(2000), Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X2(Parachain(2001), Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X2(Parachain(100), Junction::AccountId32 { .. }) } - }; -} - -parameter_types! { - pub const MaxAssetsForTransfer: usize = 2; -} - -impl pallet_xnft::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmSender = XcmRouter; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); -} -pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::::default().build_storage().unwrap().into() -} -pub struct ExtBuilder; - -impl Default for ExtBuilder { - fn default() -> Self { - ExtBuilder - } -} - -impl ExtBuilder { - pub fn build(self) -> sp_io::TestExternalities { - let storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - storage.into() - } -} diff --git a/templates/parachain/pallets/xcnft/src/mock/relaychain.rs b/templates/parachain/pallets/xcnft/src/mock/relaychain.rs deleted file mode 100644 index 24f70dace738..000000000000 --- a/templates/parachain/pallets/xcnft/src/mock/relaychain.rs +++ /dev/null @@ -1,738 +0,0 @@ -#![cfg(test)] -use crate::{ - self as pallet_parachain_xcnft, - test::{ - relay::currency::{CENTS, MILLICENTS}, - *, - }, -}; -use cumulus_primitives_core::relay_chain::CandidateHash; -use frame_support::{ - assert_ok, construct_runtime, - dispatch::DispatchClass, - pallet_prelude::{DispatchResult, Get}, - parameter_types, - traits::{ - AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, ConstU64, Currency, Everything, - GenesisBuild, KeyOwnerProofSystem, Nothing, ProcessMessage, ProcessMessageError, - }, - weights::{constants::RocksDbWeight, IdentityFee, Weight, WeightMeter}, -}; -use polkadot_parachain::primitives::ValidationCode; -use polkadot_runtime_common::{ - paras_sudo_wrapper, - xcm_sender::{ChildParachainRouter, ExponentialPrice}, -}; -use sp_runtime::{traits::AccountIdConversion, BuildStorage}; - -use crate::test::relay::currency::DOLLARS; -use cumulus_primitives_core::{ - relay_chain::{AuthorityDiscoveryId, SessionIndex, ValidatorIndex}, - ChannelStatus, GetChannelInfo, ParaId, -}; -use frame_support::traits::ValidatorSetWithIdentification; -use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned}; -use polkadot_runtime_parachains::disputes::SlashingHandler; -use sp_runtime::{transaction_validity::TransactionPriority, Permill}; -use std::{cell::RefCell, collections::HashMap}; -pub mod currency { - use node_primitives::Balance; - - pub const MILLICENTS: Balance = 1_000_000_000; - pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. - pub const DOLLARS: Balance = 100 * CENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS - } -} -use sp_runtime::{ - generic, - testing::Header, - traits::{AccountIdLookup, BlakeTwo256, IdentityLookup}, - BoundedVec, DispatchError, MultiSignature, -}; -pub type Signature = MultiSignature; -pub type AccountPublic = ::Signer; -pub type AccountId = ::AccountId; -use crate::test::para::ParachainInfo; -use frame_support::traits::ValidatorSet; -use sp_core::H256; -use xcm_builder::{EnsureXcmOrigin, NativeAsset}; -//pub type AccountId = u64; -use pallet_nfts::PalletFeatures; - -pub use polkadot_runtime_parachains::{ - assigner, assigner_on_demand, assigner_parachains, configuration, disputes, - disputes::slashing as parachains_slashing, - dmp as parachains_dmp, hrmp, inclusion, - inclusion::{AggregateMessageOrigin, UmpQueueId}, - origin, paras, - paras::ParaGenesisArgs, - schedule_para_initialize, scheduler, session_info, shared, -}; -use primitives::ValidatorId; -pub type BlockNumber = u64; -pub type Index = u32; -use sp_runtime::KeyTypeId; -use xcm::v3::prelude::*; -use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, - ChildParachainConvertsVia, CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, - IsConcrete, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, - TakeWeightCredit, UsingComponents, -}; -use xcm_executor::XcmExecutor; -type Origin = ::RuntimeOrigin; -use crate::Config; - -type Balance = u128; - -pub fn root_user() -> Origin { - RuntimeOrigin::root() -} -pub fn who(who: AccountId) -> Origin { - RuntimeOrigin::signed(who) -} - -pub type Address = sp_runtime::MultiAddress; -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, -); - -type UncheckedExtrinsics = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsics, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances, - ParasOrigin: origin, - MessageQueue: pallet_message_queue, - XcmPallet: pallet_xcm, - ParaInclusion: inclusion, - Paras: paras, - Xnft: pallet_xnft, - Disputes: disputes, - Scheduler: scheduler, - Configuration: configuration, - ParasShared: shared, - ParasSudoWrapperCall:paras_sudo_wrapper, - Dmp: parachains_dmp, - NFT:pallet_nfts, - CumulusXcm: cumulus_pallet_xcm, - DmpQueue: cumulus_pallet_dmp_queue, - XcmpQueue: cumulus_pallet_xcmp_queue, - Hrmp: hrmp, - Assigner: assigner, - ParachainsAssigner: assigner_parachains, - OnDemandAssigner: assigner_on_demand, - //ParasSlashing: parachains_slashing, - Offences: pallet_offences, - } - -); -impl frame_system::offchain::SendTransactionTypes for Test -where - RuntimeCall: From, -{ - type Extrinsic = UncheckedExtrinsics; - type OverarchingCall = RuntimeCall; -} -impl paras_sudo_wrapper::Config for Test {} -impl assigner_on_demand::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type TrafficDefaultValue = (); - type WeightInfo = assigner_on_demand::TestWeightInfo; -} - -pub struct ChannelInfo; -impl GetChannelInfo for ChannelInfo { - fn get_channel_status(_id: ParaId) -> ChannelStatus { - ChannelStatus::Ready(10, 10) - } - fn get_channel_max(_id: ParaId) -> Option { - Some(usize::max_value()) - } -} -impl assigner_parachains::Config for Test {} -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Nonce = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = (); - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; -} - -parameter_types! { - pub const CollectionDeposit: Balance = 100 * DOLLARS; - pub const ItemDeposit: Balance = 1 * DOLLARS; - pub const KeyLimit: u32 = 32; - pub const ValueLimit: u32 = 256; - pub const ApprovalsLimit: u32 = 20; - pub const ItemAttributesApprovalsLimit: u32 = 20; - pub const MaxTips: u32 = 10; - -} -impl pallet_offences::Config for Test { - type RuntimeEvent = RuntimeEvent; - type IdentificationTuple = (); - type OnOffenceHandler = (); -} -parameter_types! { - pub Features: PalletFeatures = PalletFeatures::all_enabled(); - pub const MaxAttributesPerCall: u32 = 10; -} - -impl pallet_nfts::Config for Test { - type RuntimeEvent = RuntimeEvent; - type CollectionId = u32; - type ItemId = u32; - type Currency = Balances; - type CreateOrigin = AsEnsureOriginWithArg>; - type ForceOrigin = frame_system::EnsureRoot; - type Locker = (); - type CollectionDeposit = ConstU64<2>; - type ItemDeposit = ConstU64<1>; - type MetadataDepositBase = ConstU64<1>; - type AttributeDepositBase = ConstU64<1>; - type DepositPerByte = ConstU64<1>; - type StringLimit = ConstU32<50>; - type KeyLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; - type ApprovalsLimit = ConstU32<10>; - type ItemAttributesApprovalsLimit = ConstU32<2>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = (); - type MaxAttributesPerCall = ConstU32<2>; - type Features = Features; - type OffchainSignature = Signature; - type OffchainPublic = ::Signer; - type WeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxLocks: u32 = 10; -} - -impl pallet_balances::Config for Test { - type MaxLocks = MaxLocks; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type MaxHolds = (); - type RuntimeHoldReason = RuntimeHoldReason; -} -parameter_types! { - pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); -} - -pub struct TestNextSessionRotation; - -impl frame_support::traits::EstimateNextSessionRotation for TestNextSessionRotation { - fn average_session_length() -> u32 { - 10 - } - - fn estimate_current_session_progress(_now: u32) -> (Option, Weight) { - (None, Weight::zero()) - } - - fn estimate_next_session_rotation(_now: u32) -> (Option, Weight) { - (None, Weight::zero()) - } -} - -impl paras::Config for Test { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = polkadot_runtime_parachains::paras::TestWeightInfo; - type UnsignedPriority = ParasUnsignedPriority; - type QueueFootprinter = ParaInclusion; - type NextSessionRotation = (); - type OnNewHead = (); -} - -thread_local! { - pub static BACKING_REWARDS: RefCell> - = RefCell::new(HashMap::new()); - - pub static AVAILABILITY_REWARDS: RefCell> - = RefCell::new(HashMap::new()); -} - -pub struct TestRewardValidators; - -impl inclusion::RewardValidators for TestRewardValidators { - fn reward_backing(v: impl IntoIterator) { - BACKING_REWARDS.with(|r| { - let mut r = r.borrow_mut(); - for i in v { - *r.entry(i).or_insert(0) += 1; - } - }) - } - fn reward_bitfields(v: impl IntoIterator) { - AVAILABILITY_REWARDS.with(|r| { - let mut r = r.borrow_mut(); - for i in v { - *r.entry(i).or_insert(0) += 1; - } - }) - } -} - -impl inclusion::Config for Test { - type WeightInfo = (); - type RuntimeEvent = RuntimeEvent; - type DisputesHandler = Disputes; - type RewardValidators = TestRewardValidators; - type MessageQueue = MessageQueue; -} - -pub struct ValidatorIdOf; -impl sp_runtime::traits::Convert> for ValidatorIdOf { - fn convert(a: AccountId) -> Option { - Some(a) - } -} - -pub struct MockValidatorSet; - -impl ValidatorSet for MockValidatorSet { - type ValidatorId = AccountId; - type ValidatorIdOf = ValidatorIdOf; - fn session_index() -> SessionIndex { - 0 - } - fn validators() -> Vec { - Vec::new() - } -} - -pub struct FoolIdentificationOf; -impl sp_runtime::traits::Convert> for FoolIdentificationOf { - fn convert(_: AccountId) -> Option<()> { - Some(()) - } -} - -impl ValidatorSetWithIdentification for MockValidatorSet { - type Identification = (); - type IdentificationOf = FoolIdentificationOf; -} -impl assigner::Config for Test { - type ParachainsAssignmentProvider = ParachainsAssigner; - type OnDemandAssignmentProvider = OnDemandAssigner; -} -impl scheduler::Config for Test { - type AssignmentProvider = Assigner; -} - -impl SlashingHandler for Test { - fn punish_for_invalid( - session: SessionIndex, - _: CandidateHash, - losers: impl IntoIterator, - backers: impl IntoIterator, - ) { - PUNISH_VALIDATORS_FOR - .with(|r| r.borrow_mut().push((session, losers.into_iter().collect()))); - PUNISH_BACKERS_FOR.with(|r| r.borrow_mut().push((session, backers.into_iter().collect()))); - } - - fn punish_against_valid( - session: SessionIndex, - _: CandidateHash, - losers: impl IntoIterator, - _backers: impl IntoIterator, - ) { - PUNISH_VALIDATORS_AGAINST - .with(|r| r.borrow_mut().push((session, losers.into_iter().collect()))) - } - - fn initializer_initialize(_now: BlockNumber) -> Weight { - Weight::zero() - } - - fn initializer_finalize() {} - - fn initializer_on_new_session(_: SessionIndex) {} -} - -impl disputes::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RewardValidators = Self; - type SlashingHandler = Self; - type WeightInfo = disputes::TestWeightInfo; -} -// impl parachains_slashing::Config for Test { -// type KeyOwnerProofSystem = (); -// type KeyOwnerProof = -// >::Proof; -// type KeyOwnerIdentification = >::IdentificationTuple; -// type HandleReports = parachains_slashing::SlashingReportHandler< -// Self::KeyOwnerIdentification, -// Offences, -// ReportLongevity, -// >; -// type WeightInfo = parachains_slashing::TestWeightInfo; -// type BenchmarkingConfig = parachains_slashing::BenchConfig<200>; -// } - -thread_local! { - pub static REWARD_VALIDATORS: RefCell)>> = RefCell::new(Vec::new()); - pub static PUNISH_VALIDATORS_FOR: RefCell)>> = RefCell::new(Vec::new()); - pub static PUNISH_VALIDATORS_AGAINST: RefCell)>> = RefCell::new(Vec::new()); - pub static PUNISH_BACKERS_FOR: RefCell)>> = RefCell::new(Vec::new()); -} - -impl disputes::RewardValidators for Test { - fn reward_dispute_statement( - session: SessionIndex, - validators: impl IntoIterator, - ) { - REWARD_VALIDATORS.with(|r| r.borrow_mut().push((session, validators.into_iter().collect()))) - } -} - -thread_local! { - pub static DISCOVERY_AUTHORITIES: RefCell> = RefCell::new(Vec::new()); -} - -pub fn discovery_authorities() -> Vec { - DISCOVERY_AUTHORITIES.with(|r| r.borrow().clone()) -} - -impl session_info::AuthorityDiscoveryConfig for Test { - fn authorities() -> Vec { - discovery_authorities() - } -} - -impl session_info::Config for Test { - type ValidatorSet = MockValidatorSet; -} - -impl hrmp::Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type RuntimeEvent = RuntimeEvent; - type Currency = pallet_balances::Pallet; - type WeightInfo = hrmp::TestWeightInfo; - type ChannelManager = EnsureRoot; -} - -impl shared::Config for Test {} - -impl configuration::Config for Test { - type WeightInfo = configuration::TestWeightInfo; -} - -impl cumulus_pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; -} - -impl cumulus_pallet_xcmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ChannelInfo = ChannelInfo; - type VersionWrapper = (); - type ExecuteOverweightOrigin = EnsureRoot; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = (); - type WeightInfo = (); - type PriceForSiblingDelivery = (); -} -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: Option = None; - pub const AnyNetwork: Option = None; - pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); -} - -pub type SovereignAccountOf = (ChildParachainConvertsVia,); -parameter_types! { - pub const MaxAssetsForTransfer: usize = 2; - pub const BaseXcmWeight: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); -} - -parameter_types! { - /// The amount of weight an XCM operation takes. This is a safe overestimate. - /// The asset ID for the asset that we use to pay for message delivery fees. - pub FeeAssetId: AssetId = Concrete(RelayLocation::get()); - /// The base fee for the message delivery fees. - pub const BaseDeliveryFee: u128 = CENTS.saturating_mul(3); -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10 * MILLICENTS; - /// This value increases the priority of `Operational` transactions by adding - /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`. - pub const OperationalFeeMultiplier: u8 = 5; -} - -pub type XcmRouter = ( - // Only one router so far - use DMP to communicate with child parachains. - ChildParachainRouter< - Test, - XcmPallet, - ExponentialPrice, - >, -); - -pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom); - -parameter_types! { - pub const UnitWeightCost: Weight = Weight::from_parts(10, 10); - pub const MaxInstructions: u32 = 100; - pub const MaxAssetsIntoHolding: u32 = 64; -} -impl cumulus_pallet_dmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; -} - -impl parachains_dmp::Config for Test {} - -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; - type OriginConverter = (); - type IsReserve = NativeAsset; - type IsTeleporter = (); - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type ResponseHandler = (); - type AssetTrap = (); - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = (); - type SubscriptionService = (); - type PalletInstancesInfo = (); - type AssetTransactor = (); - type Trader = (); - type FeeManager = (); - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = (); -} - -pub type LocalOriginToLocation = SignedToAccountId32; - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); -} - -impl pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Nothing; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = (); - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; -} - -impl origin::Config for Test {} - -parameter_types! { - pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); - pub const MessageQueueHeapSize: u32 = 65_536; - pub const MessageQueueMaxStale: u32 = 16; -} - -pub struct MessageProcessor; -impl ProcessMessage for MessageProcessor { - type Origin = AggregateMessageOrigin; - - fn process_message( - message: &[u8], - origin: Self::Origin, - meter: &mut WeightMeter, - id: &mut [u8; 32], - ) -> Result { - let para = match origin { - AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para, - }; - xcm_builder::ProcessXcmMessage::, RuntimeCall>::process_message( - message, - Junction::Parachain(para.into()), - meter, - id, - ) - } -} - -impl pallet_message_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Size = u32; - type HeapSize = MessageQueueHeapSize; - type MaxStale = MessageQueueMaxStale; - type ServiceWeight = MessageQueueServiceWeight; - type MessageProcessor = MessageProcessor; - type QueueChangeHandler = (); - type QueuePausedQuery = (); - type WeightInfo = (); -} - -impl pallet_xnft::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmSender = XcmRouter; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); -} - -pub fn new_test_ext(state: MockGenesisConfig) -> sp_io::TestExternalities { - use sp_keystore::{testing::MemoryKeystore, KeystoreExt, KeystorePtr}; - use sp_std::sync::Arc; - - sp_tracing::try_init_simple(); - - BACKING_REWARDS.with(|r| r.borrow_mut().clear()); - AVAILABILITY_REWARDS.with(|r| r.borrow_mut().clear()); - - let mut t = state.system.build_storage().unwrap(); - state.configuration.assimilate_storage(&mut t).unwrap(); - state.paras.assimilate_storage(&mut t).unwrap(); - - let mut ext: sp_io::TestExternalities = t.into(); - ext.register_extension(KeystoreExt(Arc::new(MemoryKeystore::new()) as KeystorePtr)); - - ext -} -pub struct ExtBuilder; - -impl Default for ExtBuilder { - fn default() -> Self { - ExtBuilder - } -} - -impl ExtBuilder { - pub fn build(self) -> sp_io::TestExternalities { - let storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - storage.into() - } -} - -pub fn assert_last_events(generic_events: E) -where - E: DoubleEndedIterator + ExactSizeIterator, -{ - for (i, (got, want)) in frame_system::Pallet::::events() - .into_iter() - .rev() - .map(|e| e.event) - .zip(generic_events.rev().map(::RuntimeEvent::from)) - .rev() - .enumerate() - { - assert_eq!((i, got), (i, want)); - } -} - -#[derive(Default)] -pub struct MockGenesisConfig { - pub system: frame_system::GenesisConfig, - pub configuration: configuration::GenesisConfig, - pub paras: paras::GenesisConfig, -} - -pub fn sudo_establish_hrmp_channel( - sender: ParaId, - recipient: ParaId, - max_capacity: u32, - max_message_size: u32, -) -> DispatchResult { - Hrmp::init_open_channel(sender, recipient, max_capacity, max_message_size); - Hrmp::accept_open_channel(recipient, sender); - Ok(()) -} - -pub(crate) fn register_parachain_with_balance(id: ParaId, balance: Balance) { - let validation_code: ValidationCode = vec![1].into(); - assert_ok!(schedule_para_initialize::( - id, - paras::ParaGenesisArgs { - para_kind: paras::ParaKind::Parachain, - genesis_head: vec![1].into(), - validation_code: validation_code.clone(), - }, - )); - - assert_ok!(Paras::add_trusted_validation_code(RuntimeOrigin::root(), validation_code)); - ::Currency::make_free_balance_be( - &id.into_account_truncating(), - balance.try_into().unwrap(), - ); -} diff --git a/templates/parachain/pallets/xcnft/src/tests.rs b/templates/parachain/pallets/xcnft/src/tests.rs index 8b137891791f..699caa5cf3c2 100644 --- a/templates/parachain/pallets/xcnft/src/tests.rs +++ b/templates/parachain/pallets/xcnft/src/tests.rs @@ -1 +1,923 @@ +use crate::{mock::*, Error, Event, GeneralizedDestroyWitness, Proposal, ReceivedAssets, ReceivedCollections, ReceivedCols, ReceivedStruct, SentAssets, SentStruct}; +use frame_support::assert_noop; +use pallet_nfts::{CollectionConfigFor, CollectionSettings, MintSettings}; +use sp_runtime::{AccountId32, BoundedVec}; +use pallet_nfts::Event::Destroyed; +pub const ALICE: AccountId32 = AccountId32::new([0u8; 32]); +pub const BOB: AccountId32 = AccountId32::new([1u8; 32]); + + +#[test] +fn try_sending_collection_that_doesnt_exist() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + assert_noop!( + XcNFT::collection_x_transfer(RuntimeOrigin::signed(ALICE), COLLECTION_ID, Some(COLLECTION_ID), 2000.into(), None), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_sending_collection_that_user_doesnt_own() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + assert_noop!( + XcNFT::collection_x_transfer(RuntimeOrigin::signed(BOB), 0, Some(COLLECTION_ID), 2000.into(), None), + Error::::NotCollectionOwner + ); + }); +} + +#[test] +fn try_voting_on_non_existing_proposal() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + + assert_noop!( + XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 0, crate::Vote::Aye), + Error::::ProposalDoesNotExist + ); + }); +} + +#[test] +fn try_voting_on_proposal_when_no_owner() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: BoundedVec::new(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: BoundedVec::new(), + }, + end_time: 20u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + assert_noop!( + XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(BOB), 1, crate::Vote::Aye), + Error::::NotNFTOwner + ); + }); + +} + +#[test] +fn try_voting_on_proposal_expired(){ + + new_test_ext().execute_with(|| { + System::set_block_number(3); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: owners.clone(), + nay: BoundedVec::new(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + System::assert_last_event(RuntimeEvent::XcNFT(Event::ProposalExpired { + proposal_id: 1, + })); + }); +} + +#[test] +fn try_voting_on_proposal_did_not_pass() { + new_test_ext().execute_with(|| { + System::set_block_number(3); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + System::assert_last_event(RuntimeEvent::XcNFT(Event::ProposalDidNotPass { + proposal_id: 1, + })); + }); +} + +#[test] +fn try_voting_on_proposal_again_same_vote() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 3u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + assert_noop!( + XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye), + Error::::AlreadyVotedThis + ); + + }); +} + +#[test] +fn vote_on_proposal_successfuly() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 2u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + System::assert_last_event(RuntimeEvent::XcNFT(Event::CrossChainPropoposalVoteRegistered { proposal_id: 1, voter: ALICE, vote: crate::Vote::Aye })); + }); +} + +#[test] +fn try_initiating_proposal_doesnt_exist() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + + assert_noop!( + XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1), + Error::::ProposalDoesNotExist + ); + }); +} + +#[test] +fn try_initiating_proposal_collection_doesnt_exist() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 2u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + assert_noop!( + XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_initiating_proposal_no_collection_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(BOB), ALICE, def_config); + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(BOB).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: 0, + proposed_collection_owner: BOB, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + assert_noop!( + XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1), + Error::::NotCollectionOwner + ); + }); +} + + +#[test] +fn try_initiating_proposal_that_did_not_pass() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: 0, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + let _ = XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1); + + System::assert_has_event(RuntimeEvent::XcNFT(Event::ProposalDidNotPass { proposal_id: 1, })); + }); +} + +#[test] +fn try_sending_nft_no_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + assert_noop!( + XcNFT::nft_x_transfer(RuntimeOrigin::signed(ALICE), 1, 0, 1000.into(), 1, 1), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_sending_nft_no_nft() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + assert_noop!( + XcNFT::nft_x_transfer(RuntimeOrigin::signed(ALICE), 0, 0, 1000.into(), 1, 1), + Error::::NFTDoesNotExist + ); + }); +} + +#[test] +fn try_sending_nft_not_nft_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE, None); + + assert_noop!( + XcNFT::nft_x_transfer(RuntimeOrigin::signed(BOB), 0, 0, 1000.into(), 1, 1), + Error::::NotNFTOwner + ); + }); +} + +#[test] +fn try_claiming_nft_no_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 1u32, 0u32, 100u32.into(), 1u32, 1u32), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_claiming_nft_no_collection_origin() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 1u32, 0u32, 100u32.into(), 1u32, 1u32), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_claiming_nft_wrong_origin_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 10, + received_collection_id: 20, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 0u32, 0u32, 100u32.into(), 0u32, 1u32), + Error::::WrongOriginCollectionAtOrigin + ); + }); +} + +#[test] +fn try_claiming_nft_wrong_nft() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + received_collection_id: 0, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 0u32, 0u32, 100u32.into(), 0u32, 0u32), + Error::::NFTNotReceived + ); + }); +} + +#[test] +fn try_claiming_nft_not_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0u32, 0u32, ALICE, None); + + System::set_block_number(3); + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 1u32, 0u32, ALICE, None); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + received_collection_id: 0, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + let nfts: ReceivedStruct:: = ReceivedStruct:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + origin_asset_id: 0, + received_collection_id: 1, + received_asset_id: 0, + }; + + let _ = ReceivedAssets::::insert((1, 0), nfts); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(BOB), 0u32, 0u32, 0u32, 1u32, 0u32), + Error::::NotNFTOwner + ); + }); +} + +#[test] +fn try_claiming_nft_success() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0u32, 0u32, ALICE, None); + + System::set_block_number(3); + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 1u32, 0u32, ALICE, None); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + received_collection_id: 0, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + let nfts: ReceivedStruct:: = ReceivedStruct:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + origin_asset_id: 0, + received_collection_id: 1, + received_asset_id: 0, + }; + + let _ = ReceivedAssets::::insert((1, 0), nfts); + System::set_block_number(3); + + let _ = XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 0u32, 0u32, 0u32, 1u32, 0u32); + + System::assert_has_event(RuntimeEvent::XcNFT(Event::NFTClaimed { collection_claimed_from: 1, asset_removed: 0, collection_claimed_to: 0, asset_claimed: 0 })); + + }); +} + +#[test] +fn try_collection_parse_empty_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = XcNFT::parse_collection_empty(RuntimeOrigin::signed(ALICE), 1, None, BoundedVec::new(), None); + + System::assert_has_event(RuntimeEvent::XcNFT(Event::CollectionReceived { origin_collection_id: 1, received_collection_id: 1, to_address: ALICE })); + }); +} + +#[test] +fn try_parse_collection_burn_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let destroy_witness = GeneralizedDestroyWitness { + item_meta: 0, + item_configs: 0, + attributes: 0, + }; + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let _ = XcNFT::parse_collection_burn(RuntimeOrigin::signed(ALICE), 0, destroy_witness); + + System::assert_has_event(RuntimeEvent::NFTs(pallet_nfts::Event::Destroyed { collection: 0 })); + }); +} + +#[test] +fn try_parse_collection_metadata_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let _ = XcNFT::parse_collection_metadata(RuntimeOrigin::signed(ALICE), 0, BoundedVec::new()); + + System::assert_has_event(RuntimeEvent::NFTs(pallet_nfts::Event::CollectionMetadataSet { collection: 0, data: BoundedVec::new() })); + }); +} + +#[test] +fn try_parse_collection_owner_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + pallet_nfts::OwnershipAcceptance::::insert(BOB, 0); + + let _ = XcNFT::parse_collection_owner(RuntimeOrigin::signed(ALICE), BOB, 0); + + System::assert_has_event(RuntimeEvent::NFTs(pallet_nfts::Event::OwnerChanged { collection: 0, new_owner: BOB })); + }); +} + +#[test] +fn try_parse_nft_burn_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE, None); + + let _ = XcNFT::parse_nft_burn(RuntimeOrigin::signed(ALICE), 0, 0); + + System::assert_has_event(RuntimeEvent::NFTs(pallet_nfts::Event::Burned { collection: 0, item: 0, owner: ALICE })); + }); +} + +#[test] +fn try_parse_nft_metadata_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE, None); + + let _ = XcNFT::parse_nft_metadata(RuntimeOrigin::signed(ALICE), 0, 0, BoundedVec::new()); + + System::assert_has_event(RuntimeEvent::NFTs(pallet_nfts::Event::ItemMetadataSet { collection: 0, item: 0, data: BoundedVec::new() })); + }); +} + +#[test] +fn try_parse_nft_owner_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE, None); + + let _ = XcNFT::parse_nft_owner(RuntimeOrigin::signed(ALICE), BOB ,0, 0); + + System::assert_has_event(RuntimeEvent::NFTs(pallet_nfts::Event::Transferred { collection: 0, item: 0, from: ALICE, to: BOB })); + }); +} + +#[test] +fn try_parse_nft_transfer_no_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()), Error::::CollectionDoesNotExist); + }); +} + + +#[test] +fn try_parse_nft_transfer_already_received() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE, None); + + let nfts: ReceivedStruct:: = ReceivedStruct:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + origin_asset_id: 0, + received_collection_id: 0, + received_asset_id: 0, + }; + + let _ = ReceivedAssets::::insert((0, 0), nfts); + + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()), Error::::NFTAlreadyReceived); + }); +} + +#[test] +fn try_parse_nft_transfer_not_collection_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE, None); + + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(BOB),0,0,BoundedVec::new(),0,0,1000.into()), Error::::NotCollectionOwner); + }); +} + +#[test] +fn try_parse_nft_transfer_not_existing_nft() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + let _ = NFTs::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE, None); + + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()), Error::::NFTExists); + }); +} + +#[test] +fn try_parse_nft_transfer_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + let _ = XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()); + System::assert_has_event(RuntimeEvent::XcNFT(Event::NFTReceived { origin_collection_id: 0, origin_asset_id: 0, received_collection_id: 0, received_asset_id: 0, to_address: ALICE})); +}); +} + +#[test] +fn try_parse_nft_transfer_return_to_origin(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let _ = NFTs::create(RuntimeOrigin::signed(ALICE), ALICE, def_config); + + let sent = SentStruct:: { + + origin_para_id: ParachainInfo::parachain_id(), + origin_collection_id: 0, + origin_asset_id: 0, + destination_collection_id: 0, + destination_asset_id: 0, + }; + + let _ = SentAssets::::insert((0, 0), sent); + + //Set parachain id to 1000 + ParachainInfo::parachain_id(); + + let _ = XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,ParachainInfo::parachain_id()); + System::assert_has_event(RuntimeEvent::XcNFT(Event::NFTReturnedToOrigin { returned_from_collection_id: 0, returned_from_asset_id: 0, to_address: ALICE })); + + }); +} + +#[test] +fn parse_collection_same_owner_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let mut nfts: Vec<(u32, BoundedVec)> = Vec::new(); + nfts.push((1, BoundedVec::new())); + + let _ = XcNFT::parse_collection_same_owner(RuntimeOrigin::signed(ALICE), Some(def_config), BoundedVec::new(), nfts.clone(), 1000.into(), 0, None); + System::assert_has_event(RuntimeEvent::XcNFT(Event::CollectionWithNftsReceived { collection_id: 0, items: nfts.clone() })); + }); +} + +#[test] +fn parse_collection_diff_nft_owners_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let def_config: CollectionConfigFor = CollectionConfigFor:: { + settings: CollectionSettings::all_enabled(), // Default settings (all enabled) + max_supply: None, /* No maximum supply defined + * initially */ + mint_settings: MintSettings::default(), // Use default mint settings + }; + + let mut nfts: Vec<(u32, AccountId32, BoundedVec)> = Vec::new(); + nfts.push((1, BOB, BoundedVec::new())); + + let _ = XcNFT::parse_collection_diff_owners(RuntimeOrigin::signed(ALICE), Some(def_config), BoundedVec::new(), nfts.clone(), 1000.into(), 0, None); + System::assert_has_event(RuntimeEvent::XcNFT(Event::CollectionWithNftsDiffOwnersReceived { collection_id: 0, items: nfts.clone() })); + }); +} \ No newline at end of file diff --git a/templates/parachain_two/pallets/xcnft/Cargo.toml b/templates/parachain_two/pallets/xcnft/Cargo.toml index b80df228fca3..5890c34c1d25 100644 --- a/templates/parachain_two/pallets/xcnft/Cargo.toml +++ b/templates/parachain_two/pallets/xcnft/Cargo.toml @@ -28,6 +28,7 @@ enumflags2 = { workspace = true } #XCM xcm = { workspace = true} +xcm-builder = { workspace = true, default-features = true } cumulus-primitives-core = { workspace = true } cumulus-pallet-xcm = { workspace = true } diff --git a/templates/parachain_two/pallets/xcnft/src/lib.rs b/templates/parachain_two/pallets/xcnft/src/lib.rs index bf40f8ad1b1d..2e7565034299 100644 --- a/templates/parachain_two/pallets/xcnft/src/lib.rs +++ b/templates/parachain_two/pallets/xcnft/src/lib.rs @@ -131,9 +131,9 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] #[scale_info(skip_type_params(T, I))] pub struct GeneralizedDestroyWitness { - item_meta: u32, - item_configs: u32, - attributes: u32, + pub item_meta: u32, + pub item_configs: u32, + pub attributes: u32, } /// Following struct is abstracted from pallet_nfts and is meant to replicate CollectionConfig @@ -270,8 +270,8 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] #[scale_info(skip_type_params(T, I))] pub struct Votes, I: 'static = ()> { - aye: BoundedVec, - nay: BoundedVec, + pub aye: BoundedVec, + pub nay: BoundedVec, } /// Structure of proposal, contains proposal id, collection id, proposed collection owner, @@ -280,15 +280,15 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] #[scale_info(skip_type_params(T, I))] pub struct Proposal, I: 'static = ()> { - proposal_id: u64, - collection_id: T::CollectionId, - proposed_collection_owner: T::AccountId, - proposed_destination_para: ParaId, - proposed_dest_collection_id: Option, - proposed_destination_config: Option>, - owners: BoundedVec, - number_of_votes: Votes, - end_time: BlockNumberFor, + pub proposal_id: u64, + pub collection_id: T::CollectionId, + pub proposed_collection_owner: T::AccountId, + pub proposed_destination_para: ParaId, + pub proposed_dest_collection_id: Option, + pub proposed_destination_config: Option>, + pub owners: BoundedVec, + pub number_of_votes: Votes, + pub end_time: BlockNumberFor, } /// Structure of sent assets, contains origin parachain id, origin collection id, origin asset @@ -296,11 +296,11 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct SentStruct, I: 'static = ()> { - origin_para_id: ParaId, - origin_collection_id: T::CollectionId, - origin_asset_id: T::ItemId, - destination_collection_id: T::CollectionId, - destination_asset_id: T::ItemId, + pub origin_para_id: ParaId, + pub origin_collection_id: T::CollectionId, + pub origin_asset_id: T::ItemId, + pub destination_collection_id: T::CollectionId, + pub destination_asset_id: T::ItemId, } /// Structure of received assets, contains origin parachain id, origin collection id, origin @@ -308,11 +308,11 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct ReceivedStruct, I: 'static = ()> { - origin_para_id: ParaId, - origin_collection_id: T::CollectionId, - origin_asset_id: T::ItemId, - received_collection_id: T::CollectionId, - received_asset_id: T::ItemId, + pub origin_para_id: ParaId, + pub origin_collection_id: T::CollectionId, + pub origin_asset_id: T::ItemId, + pub received_collection_id: T::CollectionId, + pub received_asset_id: T::ItemId, } /// Structure of received collections, contains origin parachain id, origin collection id, and @@ -320,9 +320,9 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct ReceivedCols, I: 'static = ()> { - origin_para_id: ParaId, - origin_collection_id: T::CollectionId, - received_collection_id: T::CollectionId, + pub origin_para_id: ParaId, + pub origin_collection_id: T::CollectionId, + pub received_collection_id: T::CollectionId, } /// Storage for sent assets, contains origin collection id and origin asset id as tuple key and @@ -1071,7 +1071,7 @@ pub mod pallet { // storage and emit event. if unwrapped_proposal.number_of_votes.aye.len() < number_of_votes / 2 || unwrapped_proposal.number_of_votes.aye.len() == 0 && - unwrapped_proposal.number_of_votes.nay.len() == 0 + unwrapped_proposal.number_of_votes.nay.len() == 0 || unwrapped_proposal.number_of_votes.aye.len() == 0 && unwrapped_proposal.number_of_votes.nay.len() == 1 { CrossChainProposals::::remove(proposal_id); @@ -1190,7 +1190,7 @@ pub mod pallet { if proposal.number_of_votes.aye.len() < number_of_votes / 2 || proposal.number_of_votes.aye.len() == 0 && - proposal.number_of_votes.nay.len() == 0 + proposal.number_of_votes.nay.len() == 0 || proposal.number_of_votes.aye.len() == 0 && proposal.number_of_votes.nay.len() == 1 { Self::deposit_event(Event::ProposalDidNotPass { proposal_id }); diff --git a/templates/parachain_two/pallets/xcnft/src/mock.rs b/templates/parachain_two/pallets/xcnft/src/mock.rs new file mode 100644 index 000000000000..2f46dcb0f9b8 --- /dev/null +++ b/templates/parachain_two/pallets/xcnft/src/mock.rs @@ -0,0 +1,165 @@ +use frame_support::weights::constants::RocksDbWeight; +use frame_system::{mocking::MockBlock, GenesisConfig}; +use sp_runtime::{traits::ConstU64, BuildStorage}; +use frame_support::parameter_types; +use pallet_balances::AccountData; +use xcm_builder::WithUniqueTopic; +use sp_runtime::MultiSignature; +use sp_runtime::traits::Verify; +use frame_system::EnsureRoot; +use frame_system::EnsureSigned; +use sp_core::ConstU32; +use frame_support::traits::VariantCountOf; +use sp_runtime::AccountId32 as AccountId; + +pub type XcmRouter = WithUniqueTopic<( + (), +)>; + +// Configure a mock runtime to test the pallet. +#[frame_support::runtime] +mod test_runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Test; + + #[runtime::pallet_index(0)] + pub type System = frame_system; + + #[runtime::pallet_index(1)] + pub type XcNFT = crate; + + #[runtime::pallet_index(2)] + pub type Balances = pallet_balances; + + #[runtime::pallet_index(3)] + pub type Uniques = pallet_uniques; + + #[runtime::pallet_index(4)] + pub type ParachainInfo = parachain_info; +} + +/// Balance of an account. +pub type Balance = u128; + +impl frame_system::Config for Test { + type RuntimeEvent = RuntimeEvent; + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Hash = sp_core::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = sp_runtime::traits::IdentityLookup; + type Nonce = u64; + type Block = MockBlock; + type BlockHashCount = ConstU64<250>; + type DbWeight = RocksDbWeight; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type ExtensionsWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); +} + +impl parachain_info::Config for Test {} + +impl crate::Config for Test { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + type XcmSender = XcmRouter; + type RuntimeCall = RuntimeCall; + type ProposalTimeInBlocks = proposal_time_in_blocks_parameter; + type MaxOwners = max_owners_parameter; +} + +pub const UNIT: Balance = 1; + +impl pallet_balances::Config for Test { + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = VariantCountOf; + type DoneSlashHandler = (); +} + +parameter_types! { + pub const SS58Prefix: u16 = 42; + pub const ExistentialDeposit: u128 = 500; + pub const CollectionDeposit: Balance = 0 * UNIT; // 1 UNIT deposit to create asset collection + pub const ItemDeposit: Balance = 0 * UNIT; // 1/100 UNIT deposit to create asset item + pub const KeyLimit: u32 = 32; + pub const ValueLimit: u32 = 64; + pub const UniquesMetadataDepositBase: Balance = 0 * UNIT; + pub const AttributeDepositBase: Balance = 0 * UNIT; + pub const DepositPerByte: Balance = 0 * UNIT; + pub const UniquesStringLimit: u32 = 32; + pub const ApprovalsLimit: u32 = 1; + pub const ItemAttributesApprovalsLimit: u32 = 1; + pub const MaxTips: u32 = 1; + pub const MaxDeadlineDuration: u32 = 1; + pub const MaxAttributesPerCall: u32 = 10; + pub const proposal_time_in_blocks_parameter: u32 = 10; + pub const max_owners_parameter: u32 = 1000000; + pub const max_votes: u32 = 1000000; +} + +pub type AccountPublic = ::Signer; + +impl pallet_uniques::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CollectionId = u32; + type ItemId = u32; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type CreateOrigin = EnsureSigned; + type Locker = (); + type CollectionDeposit = CollectionDeposit; + type ItemDeposit = ItemDeposit; + type MetadataDepositBase = UniquesMetadataDepositBase; + type AttributeDepositBase = AttributeDepositBase; + type DepositPerByte = DepositPerByte; + type StringLimit = UniquesStringLimit; + type KeyLimit = KeyLimit; + type ValueLimit = ValueLimit; + type WeightInfo = (); +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + GenesisConfig::::default().build_storage().unwrap().into() +} diff --git a/templates/parachain_two/pallets/xcnft/src/mock/mod.rs b/templates/parachain_two/pallets/xcnft/src/mock/mod.rs deleted file mode 100644 index e25e77b394e1..000000000000 --- a/templates/parachain_two/pallets/xcnft/src/mock/mod.rs +++ /dev/null @@ -1,106 +0,0 @@ -#![cfg(test)] - -use super::*; -use sp_io::TestExternalities; -use sp_runtime::AccountId32; -mod parachain; -mod relaychain; -use crate as xnft; -use sp_runtime::BuildStorage; -use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; - -pub const ALICE: AccountId32 = AccountId32::new([0u8; 32]); -pub const BOB: AccountId32 = AccountId32::new([1u8; 32]); -pub const CHARLIE: AccountId32 = AccountId32::new([1u8; 32]); - -pub const INITIAL_BALANCE: u64 = 1_000_000_000; - -pub type Balance = u128; -pub type Amount = i128; - -decl_test_parachain! { - pub struct Para1 { - Runtime = parachain::Test, - XcmpMessageHandler = parachain::XcmpQueue, - DmpMessageHandler = parachain::DmpQueue, - new_ext = para_ext(4), - } -} - -decl_test_parachain! { - pub struct Para2 { - Runtime = parachain::Test, - XcmpMessageHandler = parachain::XcmpQueue, - DmpMessageHandler = parachain::DmpQueue, - new_ext = para_ext(4), - } -} - -decl_test_relay_chain! { - pub struct Relay { - Runtime = relaychain::Test, - RuntimeCall = relaychain::RuntimeCall, - RuntimeEvent = relaychain::RuntimeEvent, - XcmConfig = relaychain::XcmConfig, - MessageQueue = relaychain::MessageQueue, - System = relaychain::System, - new_ext = relay_ext(), - } -} - -decl_test_network! { - pub struct TestNet { - relay_chain = Relay, - parachains = vec![ - (2000, Para1), - (2001, Para2), - ], - } -} -pub type RelayBalances = pallet_balances::Pallet; -pub type ParaChain1 = xnft::Pallet; -pub type NFT = pallet_nfts::Pallet; -pub fn para_ext(para_id: u32) -> TestExternalities { - use parachain::{System, Test}; - - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - let parachain_info_config = parachain_info::GenesisConfig:: { - _config: Default::default(), - parachain_id: para_id.into(), - }; - parachain_info_config.assimilate_storage(&mut t).unwrap(); - - let mut ext = TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -pub fn para_teleport_ext(para_id: u32) -> TestExternalities { - use parachain::{System, Test}; - - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - let parachain_info_config = parachain_info::GenesisConfig:: { - _config: Default::default(), - parachain_id: para_id.into(), - }; - parachain_info_config.assimilate_storage(&mut t).unwrap(); - let mut ext = TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -pub fn relay_ext() -> sp_io::TestExternalities { - use relaychain::{System, Test}; - - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - pallet_balances::GenesisConfig:: { balances: vec![(ALICE, 1_000)] } - .assimilate_storage(&mut t) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} diff --git a/templates/parachain_two/pallets/xcnft/src/mock/parachain.rs b/templates/parachain_two/pallets/xcnft/src/mock/parachain.rs deleted file mode 100644 index 92cf0c836157..000000000000 --- a/templates/parachain_two/pallets/xcnft/src/mock/parachain.rs +++ /dev/null @@ -1,410 +0,0 @@ -#![cfg(test)] -use crate::{self as pallet_parachain_xcnft}; - -use crate::test::*; -use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; -use frame_support::{ - construct_runtime, match_types, - pallet_prelude::{DispatchResult, Get}, - parameter_types, - traits::{ - AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, ConstU64, Currency, Everything, - Nothing, - }, - weights::constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, -}; -use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned}; - -use sp_runtime::{generic, BoundedVec}; -pub use sp_runtime::{ - testing::Header, - traits::{AccountIdLookup, BlakeTwo256, IdentityLookup}, - DispatchError, MultiSignature, -}; - -use crate::test::parachain::currency::DOLLARS; -use sp_core::{H256, U256}; -use sp_runtime::BuildStorage; - -pub type CollectionId = u64; -type Origin = ::RuntimeOrigin; -use crate::Config; -type Balance = u128; -use cumulus_primitives_core::{ChannelStatus, GetChannelInfo, ParaId}; -use pallet_nfts::PalletFeatures; -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use xcm::v3::{prelude::*, Weight}; -use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, - NativeAsset, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, -}; -use xcm_executor::XcmExecutor; - -pub mod currency { - use node_primitives::Balance; - - pub const MILLICENTS: Balance = 1_000_000_000; - pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. - pub const DOLLARS: Balance = 100 * CENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS - } -} -pub fn root_user() -> Origin { - RuntimeOrigin::root() -} -pub fn who(who: AccountId) -> Origin { - RuntimeOrigin::signed(who) -} - -pub type Signature = MultiSignature; -pub type AccountPublic = ::Signer; -pub type AccountId = ::AccountId; -pub type BlockNumber = u32; -pub type Index = u32; -pub type Address = sp_runtime::MultiAddress; -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, -); - -type UncheckedExtrinsics = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsics, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances, - ParachainInfo: parachain_info, - XcmpQueue: cumulus_pallet_xcmp_queue, - DmpQueue: cumulus_pallet_dmp_queue, - CumulusXcm: cumulus_pallet_xcm, - PolkadotXcm: pallet_xcm, - Xnft: pallet_xnft, - ParachainSystem: cumulus_pallet_parachain_system, - NFT:pallet_nfts::{Pallet, Call, Storage, Event}, - } -); - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type Block = Block; - type Nonce = u64; - type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Lookup = IdentityLookup; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = (); - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = ConstU32<16>; -} - -impl cumulus_pallet_parachain_system::Config for Test { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; - type OutboundXcmpMessageSource = XcmpQueue; - type DmpMessageHandler = DmpQueue; - type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; - type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; -} - -parameter_types! { - pub const CollectionDeposit: Balance = 100 * DOLLARS; - pub const ItemDeposit: Balance = 1 * DOLLARS; - pub const KeyLimit: u32 = 32; - pub const ValueLimit: u32 = 256; - pub const ApprovalsLimit: u32 = 20; - pub const ItemAttributesApprovalsLimit: u32 = 20; - pub const MaxTips: u32 = 10; - -} - -parameter_types! { - pub Features: PalletFeatures = PalletFeatures::all_enabled(); - pub const MaxAttributesPerCall: u32 = 10; -} - -parameter_types! { - pub const AssetDeposit: Balance = 100 * DOLLARS; - pub const ApprovalDeposit: Balance = 1 * DOLLARS; - pub const StringLimit: u32 = 50; - pub const MetadataDepositBase: Balance = 10 * DOLLARS; - pub const MetadataDepositPerByte: Balance = 1 * DOLLARS; -} - -impl pallet_nfts::Config for Test { - type RuntimeEvent = RuntimeEvent; - type CollectionId = u32; - type ItemId = u32; - type Currency = Balances; - type CreateOrigin = AsEnsureOriginWithArg>; - type ForceOrigin = frame_system::EnsureRoot; - type Locker = (); - type CollectionDeposit = ConstU64<2>; - type ItemDeposit = ConstU64<1>; - type MetadataDepositBase = ConstU64<1>; - type AttributeDepositBase = ConstU64<1>; - type DepositPerByte = ConstU64<1>; - type StringLimit = ConstU32<50>; - type KeyLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; - type ApprovalsLimit = ConstU32<10>; - type ItemAttributesApprovalsLimit = ConstU32<2>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = (); - type MaxAttributesPerCall = ConstU32<2>; - type Features = Features; - type OffchainSignature = Signature; - type OffchainPublic = ::Signer; - type WeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxLocks: u32 = 10; -} - -impl pallet_balances::Config for Test { - type MaxLocks = MaxLocks; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type MaxHolds = (); - type RuntimeHoldReason = RuntimeHoldReason; -} - -parameter_types! { - pub const ReservedXcmpWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4), 0); - pub const ReservedDmpWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4), 0); -} - -impl parachain_info::Config for Test {} - -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: Option = None; - pub const AnyNetwork: Option = None; - pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); -} - -pub type LocationToAccountId = ( - ParentIsPreset, - SiblingParachainConvertsVia, - AccountId32Aliases, -); - -pub type XcmOriginToCallOrigin = ( - SovereignSignedViaLocation, - RelayChainAsNative, - SiblingParachainAsNative, - SignedAccountId32AsNative, - XcmPassthrough, -); - -pub type XcmRouter = ( - // Two routers - use UMP to communicate with the relay chain: - cumulus_primitives_utility::ParentAsUmp, - // ..and XCMP to communicate with the sibling chains. - XcmpQueue, -); -pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom); - -parameter_types! { - pub const UnitWeightCost: Weight = Weight::from_parts(10, 10); - pub const BaseXcmWeight: Weight = Weight::from_parts(100_000_000, 100_000_000); - pub const MaxInstructions: u32 = 100; - pub const MaxAssetsIntoHolding: u32 = 64; -} - -parameter_types! { - pub const Roc: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(RelayLocation::get()) }); - pub const Para: MultiLocation = Parachain(2000).into_location(); - pub const Para2: MultiLocation = Parachain(2001).into_location(); - pub const OurchainPara: (MultiAssetFilter, MultiLocation) = (Roc::get(), Para::get()); - pub const OurchainPara2: (MultiAssetFilter, MultiLocation) = (Roc::get(), Para2::get()); - -} - -pub type TrustedTeleporters = (xcm_builder::Case, xcm_builder::Case); - -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; - type AssetTransactor = (); - type OriginConverter = (); - type IsReserve = NativeAsset; - type IsTeleporter = TrustedTeleporters; - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = (); - type ResponseHandler = (); - type AssetTrap = (); - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = (); - type SubscriptionService = (); - type PalletInstancesInfo = (); - type FeeManager = (); - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type MessageExporter = (); - type UniversalAliases = Everything; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = (); -} - -pub struct ChannelInfo; -impl GetChannelInfo for ChannelInfo { - fn get_channel_status(_id: ParaId) -> ChannelStatus { - ChannelStatus::Ready(10, 10) - } - fn get_channel_max(_id: ParaId) -> Option { - Some(usize::max_value()) - } -} - -impl cumulus_pallet_xcmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ChannelInfo = ChannelInfo; - type VersionWrapper = (); - type ExecuteOverweightOrigin = EnsureRoot; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = (); - type WeightInfo = (); - type PriceForSiblingDelivery = (); -} - -impl cumulus_pallet_dmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; -} - -impl cumulus_pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; -} - -pub type LocalOriginToLocation = SignedToAccountId32; - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); -} - -impl pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = (); - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; -} - -parameter_types! { - pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); - // pub const MaxAssetsForTransfer: usize = 3; -} - -match_types! { - pub type ParentOrParachains: impl Contains = { - MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X1(Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X1(Parachain(2000)) } | - MultiLocation { parents: 1, interior: X1(Parachain(2001)) } | - MultiLocation { parents: 1, interior: X2(Parachain(2000), Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X2(Parachain(2001), Junction::AccountId32 { .. }) } | - MultiLocation { parents: 1, interior: X2(Parachain(100), Junction::AccountId32 { .. }) } - }; -} - -parameter_types! { - pub const MaxAssetsForTransfer: usize = 2; -} - -impl pallet_xnft::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmSender = XcmRouter; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); -} -pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::::default().build_storage().unwrap().into() -} -pub struct ExtBuilder; - -impl Default for ExtBuilder { - fn default() -> Self { - ExtBuilder - } -} - -impl ExtBuilder { - pub fn build(self) -> sp_io::TestExternalities { - let storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - storage.into() - } -} diff --git a/templates/parachain_two/pallets/xcnft/src/mock/relaychain.rs b/templates/parachain_two/pallets/xcnft/src/mock/relaychain.rs deleted file mode 100644 index 24f70dace738..000000000000 --- a/templates/parachain_two/pallets/xcnft/src/mock/relaychain.rs +++ /dev/null @@ -1,738 +0,0 @@ -#![cfg(test)] -use crate::{ - self as pallet_parachain_xcnft, - test::{ - relay::currency::{CENTS, MILLICENTS}, - *, - }, -}; -use cumulus_primitives_core::relay_chain::CandidateHash; -use frame_support::{ - assert_ok, construct_runtime, - dispatch::DispatchClass, - pallet_prelude::{DispatchResult, Get}, - parameter_types, - traits::{ - AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, ConstU64, Currency, Everything, - GenesisBuild, KeyOwnerProofSystem, Nothing, ProcessMessage, ProcessMessageError, - }, - weights::{constants::RocksDbWeight, IdentityFee, Weight, WeightMeter}, -}; -use polkadot_parachain::primitives::ValidationCode; -use polkadot_runtime_common::{ - paras_sudo_wrapper, - xcm_sender::{ChildParachainRouter, ExponentialPrice}, -}; -use sp_runtime::{traits::AccountIdConversion, BuildStorage}; - -use crate::test::relay::currency::DOLLARS; -use cumulus_primitives_core::{ - relay_chain::{AuthorityDiscoveryId, SessionIndex, ValidatorIndex}, - ChannelStatus, GetChannelInfo, ParaId, -}; -use frame_support::traits::ValidatorSetWithIdentification; -use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned}; -use polkadot_runtime_parachains::disputes::SlashingHandler; -use sp_runtime::{transaction_validity::TransactionPriority, Permill}; -use std::{cell::RefCell, collections::HashMap}; -pub mod currency { - use node_primitives::Balance; - - pub const MILLICENTS: Balance = 1_000_000_000; - pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. - pub const DOLLARS: Balance = 100 * CENTS; - - pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS - } -} -use sp_runtime::{ - generic, - testing::Header, - traits::{AccountIdLookup, BlakeTwo256, IdentityLookup}, - BoundedVec, DispatchError, MultiSignature, -}; -pub type Signature = MultiSignature; -pub type AccountPublic = ::Signer; -pub type AccountId = ::AccountId; -use crate::test::para::ParachainInfo; -use frame_support::traits::ValidatorSet; -use sp_core::H256; -use xcm_builder::{EnsureXcmOrigin, NativeAsset}; -//pub type AccountId = u64; -use pallet_nfts::PalletFeatures; - -pub use polkadot_runtime_parachains::{ - assigner, assigner_on_demand, assigner_parachains, configuration, disputes, - disputes::slashing as parachains_slashing, - dmp as parachains_dmp, hrmp, inclusion, - inclusion::{AggregateMessageOrigin, UmpQueueId}, - origin, paras, - paras::ParaGenesisArgs, - schedule_para_initialize, scheduler, session_info, shared, -}; -use primitives::ValidatorId; -pub type BlockNumber = u64; -pub type Index = u32; -use sp_runtime::KeyTypeId; -use xcm::v3::prelude::*; -use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, - ChildParachainConvertsVia, CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, - IsConcrete, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, - TakeWeightCredit, UsingComponents, -}; -use xcm_executor::XcmExecutor; -type Origin = ::RuntimeOrigin; -use crate::Config; - -type Balance = u128; - -pub fn root_user() -> Origin { - RuntimeOrigin::root() -} -pub fn who(who: AccountId) -> Origin { - RuntimeOrigin::signed(who) -} - -pub type Address = sp_runtime::MultiAddress; -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, -); - -type UncheckedExtrinsics = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsics, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances, - ParasOrigin: origin, - MessageQueue: pallet_message_queue, - XcmPallet: pallet_xcm, - ParaInclusion: inclusion, - Paras: paras, - Xnft: pallet_xnft, - Disputes: disputes, - Scheduler: scheduler, - Configuration: configuration, - ParasShared: shared, - ParasSudoWrapperCall:paras_sudo_wrapper, - Dmp: parachains_dmp, - NFT:pallet_nfts, - CumulusXcm: cumulus_pallet_xcm, - DmpQueue: cumulus_pallet_dmp_queue, - XcmpQueue: cumulus_pallet_xcmp_queue, - Hrmp: hrmp, - Assigner: assigner, - ParachainsAssigner: assigner_parachains, - OnDemandAssigner: assigner_on_demand, - //ParasSlashing: parachains_slashing, - Offences: pallet_offences, - } - -); -impl frame_system::offchain::SendTransactionTypes for Test -where - RuntimeCall: From, -{ - type Extrinsic = UncheckedExtrinsics; - type OverarchingCall = RuntimeCall; -} -impl paras_sudo_wrapper::Config for Test {} -impl assigner_on_demand::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type TrafficDefaultValue = (); - type WeightInfo = assigner_on_demand::TestWeightInfo; -} - -pub struct ChannelInfo; -impl GetChannelInfo for ChannelInfo { - fn get_channel_status(_id: ParaId) -> ChannelStatus { - ChannelStatus::Ready(10, 10) - } - fn get_channel_max(_id: ParaId) -> Option { - Some(usize::max_value()) - } -} -impl assigner_parachains::Config for Test {} -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Nonce = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = (); - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; -} - -parameter_types! { - pub const CollectionDeposit: Balance = 100 * DOLLARS; - pub const ItemDeposit: Balance = 1 * DOLLARS; - pub const KeyLimit: u32 = 32; - pub const ValueLimit: u32 = 256; - pub const ApprovalsLimit: u32 = 20; - pub const ItemAttributesApprovalsLimit: u32 = 20; - pub const MaxTips: u32 = 10; - -} -impl pallet_offences::Config for Test { - type RuntimeEvent = RuntimeEvent; - type IdentificationTuple = (); - type OnOffenceHandler = (); -} -parameter_types! { - pub Features: PalletFeatures = PalletFeatures::all_enabled(); - pub const MaxAttributesPerCall: u32 = 10; -} - -impl pallet_nfts::Config for Test { - type RuntimeEvent = RuntimeEvent; - type CollectionId = u32; - type ItemId = u32; - type Currency = Balances; - type CreateOrigin = AsEnsureOriginWithArg>; - type ForceOrigin = frame_system::EnsureRoot; - type Locker = (); - type CollectionDeposit = ConstU64<2>; - type ItemDeposit = ConstU64<1>; - type MetadataDepositBase = ConstU64<1>; - type AttributeDepositBase = ConstU64<1>; - type DepositPerByte = ConstU64<1>; - type StringLimit = ConstU32<50>; - type KeyLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; - type ApprovalsLimit = ConstU32<10>; - type ItemAttributesApprovalsLimit = ConstU32<2>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = (); - type MaxAttributesPerCall = ConstU32<2>; - type Features = Features; - type OffchainSignature = Signature; - type OffchainPublic = ::Signer; - type WeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxLocks: u32 = 10; -} - -impl pallet_balances::Config for Test { - type MaxLocks = MaxLocks; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type MaxHolds = (); - type RuntimeHoldReason = RuntimeHoldReason; -} -parameter_types! { - pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); -} - -pub struct TestNextSessionRotation; - -impl frame_support::traits::EstimateNextSessionRotation for TestNextSessionRotation { - fn average_session_length() -> u32 { - 10 - } - - fn estimate_current_session_progress(_now: u32) -> (Option, Weight) { - (None, Weight::zero()) - } - - fn estimate_next_session_rotation(_now: u32) -> (Option, Weight) { - (None, Weight::zero()) - } -} - -impl paras::Config for Test { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = polkadot_runtime_parachains::paras::TestWeightInfo; - type UnsignedPriority = ParasUnsignedPriority; - type QueueFootprinter = ParaInclusion; - type NextSessionRotation = (); - type OnNewHead = (); -} - -thread_local! { - pub static BACKING_REWARDS: RefCell> - = RefCell::new(HashMap::new()); - - pub static AVAILABILITY_REWARDS: RefCell> - = RefCell::new(HashMap::new()); -} - -pub struct TestRewardValidators; - -impl inclusion::RewardValidators for TestRewardValidators { - fn reward_backing(v: impl IntoIterator) { - BACKING_REWARDS.with(|r| { - let mut r = r.borrow_mut(); - for i in v { - *r.entry(i).or_insert(0) += 1; - } - }) - } - fn reward_bitfields(v: impl IntoIterator) { - AVAILABILITY_REWARDS.with(|r| { - let mut r = r.borrow_mut(); - for i in v { - *r.entry(i).or_insert(0) += 1; - } - }) - } -} - -impl inclusion::Config for Test { - type WeightInfo = (); - type RuntimeEvent = RuntimeEvent; - type DisputesHandler = Disputes; - type RewardValidators = TestRewardValidators; - type MessageQueue = MessageQueue; -} - -pub struct ValidatorIdOf; -impl sp_runtime::traits::Convert> for ValidatorIdOf { - fn convert(a: AccountId) -> Option { - Some(a) - } -} - -pub struct MockValidatorSet; - -impl ValidatorSet for MockValidatorSet { - type ValidatorId = AccountId; - type ValidatorIdOf = ValidatorIdOf; - fn session_index() -> SessionIndex { - 0 - } - fn validators() -> Vec { - Vec::new() - } -} - -pub struct FoolIdentificationOf; -impl sp_runtime::traits::Convert> for FoolIdentificationOf { - fn convert(_: AccountId) -> Option<()> { - Some(()) - } -} - -impl ValidatorSetWithIdentification for MockValidatorSet { - type Identification = (); - type IdentificationOf = FoolIdentificationOf; -} -impl assigner::Config for Test { - type ParachainsAssignmentProvider = ParachainsAssigner; - type OnDemandAssignmentProvider = OnDemandAssigner; -} -impl scheduler::Config for Test { - type AssignmentProvider = Assigner; -} - -impl SlashingHandler for Test { - fn punish_for_invalid( - session: SessionIndex, - _: CandidateHash, - losers: impl IntoIterator, - backers: impl IntoIterator, - ) { - PUNISH_VALIDATORS_FOR - .with(|r| r.borrow_mut().push((session, losers.into_iter().collect()))); - PUNISH_BACKERS_FOR.with(|r| r.borrow_mut().push((session, backers.into_iter().collect()))); - } - - fn punish_against_valid( - session: SessionIndex, - _: CandidateHash, - losers: impl IntoIterator, - _backers: impl IntoIterator, - ) { - PUNISH_VALIDATORS_AGAINST - .with(|r| r.borrow_mut().push((session, losers.into_iter().collect()))) - } - - fn initializer_initialize(_now: BlockNumber) -> Weight { - Weight::zero() - } - - fn initializer_finalize() {} - - fn initializer_on_new_session(_: SessionIndex) {} -} - -impl disputes::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RewardValidators = Self; - type SlashingHandler = Self; - type WeightInfo = disputes::TestWeightInfo; -} -// impl parachains_slashing::Config for Test { -// type KeyOwnerProofSystem = (); -// type KeyOwnerProof = -// >::Proof; -// type KeyOwnerIdentification = >::IdentificationTuple; -// type HandleReports = parachains_slashing::SlashingReportHandler< -// Self::KeyOwnerIdentification, -// Offences, -// ReportLongevity, -// >; -// type WeightInfo = parachains_slashing::TestWeightInfo; -// type BenchmarkingConfig = parachains_slashing::BenchConfig<200>; -// } - -thread_local! { - pub static REWARD_VALIDATORS: RefCell)>> = RefCell::new(Vec::new()); - pub static PUNISH_VALIDATORS_FOR: RefCell)>> = RefCell::new(Vec::new()); - pub static PUNISH_VALIDATORS_AGAINST: RefCell)>> = RefCell::new(Vec::new()); - pub static PUNISH_BACKERS_FOR: RefCell)>> = RefCell::new(Vec::new()); -} - -impl disputes::RewardValidators for Test { - fn reward_dispute_statement( - session: SessionIndex, - validators: impl IntoIterator, - ) { - REWARD_VALIDATORS.with(|r| r.borrow_mut().push((session, validators.into_iter().collect()))) - } -} - -thread_local! { - pub static DISCOVERY_AUTHORITIES: RefCell> = RefCell::new(Vec::new()); -} - -pub fn discovery_authorities() -> Vec { - DISCOVERY_AUTHORITIES.with(|r| r.borrow().clone()) -} - -impl session_info::AuthorityDiscoveryConfig for Test { - fn authorities() -> Vec { - discovery_authorities() - } -} - -impl session_info::Config for Test { - type ValidatorSet = MockValidatorSet; -} - -impl hrmp::Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type RuntimeEvent = RuntimeEvent; - type Currency = pallet_balances::Pallet; - type WeightInfo = hrmp::TestWeightInfo; - type ChannelManager = EnsureRoot; -} - -impl shared::Config for Test {} - -impl configuration::Config for Test { - type WeightInfo = configuration::TestWeightInfo; -} - -impl cumulus_pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; -} - -impl cumulus_pallet_xcmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ChannelInfo = ChannelInfo; - type VersionWrapper = (); - type ExecuteOverweightOrigin = EnsureRoot; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = (); - type WeightInfo = (); - type PriceForSiblingDelivery = (); -} -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: Option = None; - pub const AnyNetwork: Option = None; - pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); -} - -pub type SovereignAccountOf = (ChildParachainConvertsVia,); -parameter_types! { - pub const MaxAssetsForTransfer: usize = 2; - pub const BaseXcmWeight: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); -} - -parameter_types! { - /// The amount of weight an XCM operation takes. This is a safe overestimate. - /// The asset ID for the asset that we use to pay for message delivery fees. - pub FeeAssetId: AssetId = Concrete(RelayLocation::get()); - /// The base fee for the message delivery fees. - pub const BaseDeliveryFee: u128 = CENTS.saturating_mul(3); -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10 * MILLICENTS; - /// This value increases the priority of `Operational` transactions by adding - /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`. - pub const OperationalFeeMultiplier: u8 = 5; -} - -pub type XcmRouter = ( - // Only one router so far - use DMP to communicate with child parachains. - ChildParachainRouter< - Test, - XcmPallet, - ExponentialPrice, - >, -); - -pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom); - -parameter_types! { - pub const UnitWeightCost: Weight = Weight::from_parts(10, 10); - pub const MaxInstructions: u32 = 100; - pub const MaxAssetsIntoHolding: u32 = 64; -} -impl cumulus_pallet_dmp_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; -} - -impl parachains_dmp::Config for Test {} - -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; - type OriginConverter = (); - type IsReserve = NativeAsset; - type IsTeleporter = (); - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type ResponseHandler = (); - type AssetTrap = (); - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = (); - type SubscriptionService = (); - type PalletInstancesInfo = (); - type AssetTransactor = (); - type Trader = (); - type FeeManager = (); - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = (); -} - -pub type LocalOriginToLocation = SignedToAccountId32; - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); -} - -impl pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Nothing; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = (); - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; -} - -impl origin::Config for Test {} - -parameter_types! { - pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); - pub const MessageQueueHeapSize: u32 = 65_536; - pub const MessageQueueMaxStale: u32 = 16; -} - -pub struct MessageProcessor; -impl ProcessMessage for MessageProcessor { - type Origin = AggregateMessageOrigin; - - fn process_message( - message: &[u8], - origin: Self::Origin, - meter: &mut WeightMeter, - id: &mut [u8; 32], - ) -> Result { - let para = match origin { - AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para, - }; - xcm_builder::ProcessXcmMessage::, RuntimeCall>::process_message( - message, - Junction::Parachain(para.into()), - meter, - id, - ) - } -} - -impl pallet_message_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Size = u32; - type HeapSize = MessageQueueHeapSize; - type MaxStale = MessageQueueMaxStale; - type ServiceWeight = MessageQueueServiceWeight; - type MessageProcessor = MessageProcessor; - type QueueChangeHandler = (); - type QueuePausedQuery = (); - type WeightInfo = (); -} - -impl pallet_xnft::Config for Test { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmSender = XcmRouter; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); -} - -pub fn new_test_ext(state: MockGenesisConfig) -> sp_io::TestExternalities { - use sp_keystore::{testing::MemoryKeystore, KeystoreExt, KeystorePtr}; - use sp_std::sync::Arc; - - sp_tracing::try_init_simple(); - - BACKING_REWARDS.with(|r| r.borrow_mut().clear()); - AVAILABILITY_REWARDS.with(|r| r.borrow_mut().clear()); - - let mut t = state.system.build_storage().unwrap(); - state.configuration.assimilate_storage(&mut t).unwrap(); - state.paras.assimilate_storage(&mut t).unwrap(); - - let mut ext: sp_io::TestExternalities = t.into(); - ext.register_extension(KeystoreExt(Arc::new(MemoryKeystore::new()) as KeystorePtr)); - - ext -} -pub struct ExtBuilder; - -impl Default for ExtBuilder { - fn default() -> Self { - ExtBuilder - } -} - -impl ExtBuilder { - pub fn build(self) -> sp_io::TestExternalities { - let storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - storage.into() - } -} - -pub fn assert_last_events(generic_events: E) -where - E: DoubleEndedIterator + ExactSizeIterator, -{ - for (i, (got, want)) in frame_system::Pallet::::events() - .into_iter() - .rev() - .map(|e| e.event) - .zip(generic_events.rev().map(::RuntimeEvent::from)) - .rev() - .enumerate() - { - assert_eq!((i, got), (i, want)); - } -} - -#[derive(Default)] -pub struct MockGenesisConfig { - pub system: frame_system::GenesisConfig, - pub configuration: configuration::GenesisConfig, - pub paras: paras::GenesisConfig, -} - -pub fn sudo_establish_hrmp_channel( - sender: ParaId, - recipient: ParaId, - max_capacity: u32, - max_message_size: u32, -) -> DispatchResult { - Hrmp::init_open_channel(sender, recipient, max_capacity, max_message_size); - Hrmp::accept_open_channel(recipient, sender); - Ok(()) -} - -pub(crate) fn register_parachain_with_balance(id: ParaId, balance: Balance) { - let validation_code: ValidationCode = vec![1].into(); - assert_ok!(schedule_para_initialize::( - id, - paras::ParaGenesisArgs { - para_kind: paras::ParaKind::Parachain, - genesis_head: vec![1].into(), - validation_code: validation_code.clone(), - }, - )); - - assert_ok!(Paras::add_trusted_validation_code(RuntimeOrigin::root(), validation_code)); - ::Currency::make_free_balance_be( - &id.into_account_truncating(), - balance.try_into().unwrap(), - ); -} diff --git a/templates/parachain_two/pallets/xcnft/src/tests.rs b/templates/parachain_two/pallets/xcnft/src/tests.rs index 8b137891791f..1b60448fcd8e 100644 --- a/templates/parachain_two/pallets/xcnft/src/tests.rs +++ b/templates/parachain_two/pallets/xcnft/src/tests.rs @@ -1 +1,765 @@ +use crate::{mock::*, Error, Event, GeneralizedDestroyWitness, Proposal, ReceivedAssets, ReceivedCollections, ReceivedCols, ReceivedStruct, SentAssets, SentStruct}; +use frame_support::assert_noop; +use sp_runtime::{AccountId32, BoundedVec}; +use pallet_uniques::Event::Destroyed; +pub const ALICE: AccountId32 = AccountId32::new([0u8; 32]); +pub const BOB: AccountId32 = AccountId32::new([1u8; 32]); + + +#[test] +fn try_sending_collection_that_doesnt_exist() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + assert_noop!( + XcNFT::collection_x_transfer(RuntimeOrigin::signed(ALICE), COLLECTION_ID, Some(COLLECTION_ID), 2000.into(), None), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_sending_collection_that_user_doesnt_own() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + assert_noop!( + XcNFT::collection_x_transfer(RuntimeOrigin::signed(BOB), 0, Some(COLLECTION_ID), 2000.into(), None), + Error::::NotCollectionOwner + ); + }); +} + +#[test] +fn try_voting_on_non_existing_proposal() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + + assert_noop!( + XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 0, crate::Vote::Aye), + Error::::ProposalDoesNotExist + ); + }); +} + +#[test] +fn try_voting_on_proposal_when_no_owner() { + + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: BoundedVec::new(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: BoundedVec::new(), + }, + end_time: 20u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + assert_noop!( + XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(BOB), 1, crate::Vote::Aye), + Error::::NotNFTOwner + ); + }); + +} + +#[test] +fn try_voting_on_proposal_expired(){ + + new_test_ext().execute_with(|| { + System::set_block_number(3); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: owners.clone(), + nay: BoundedVec::new(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + System::assert_last_event(RuntimeEvent::XcNFT(Event::ProposalExpired { + proposal_id: 1, + })); + }); +} + +#[test] +fn try_voting_on_proposal_did_not_pass() { + new_test_ext().execute_with(|| { + System::set_block_number(3); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + System::assert_last_event(RuntimeEvent::XcNFT(Event::ProposalDidNotPass { + proposal_id: 1, + })); + }); +} + +#[test] +fn try_voting_on_proposal_again_same_vote() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 3u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + assert_noop!( + XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye), + Error::::AlreadyVotedThis + ); + + }); +} + +#[test] +fn vote_on_proposal_successfuly() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 2u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + let _ = XcNFT::collection_x_transfer_vote(RuntimeOrigin::signed(ALICE), 1, crate::Vote::Aye); + + System::assert_last_event(RuntimeEvent::XcNFT(Event::CrossChainPropoposalVoteRegistered { proposal_id: 1, voter: ALICE, vote: crate::Vote::Aye })); + }); +} + +#[test] +fn try_initiating_proposal_doesnt_exist() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + + assert_noop!( + XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1), + Error::::ProposalDoesNotExist + ); + }); +} + +#[test] +fn try_initiating_proposal_collection_doesnt_exist() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + + const COLLECTION_ID: u32 = 1; + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: COLLECTION_ID, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 2u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + assert_noop!( + XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_initiating_proposal_no_collection_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let _ = Uniques::create(RuntimeOrigin::signed(BOB), 0, ALICE); + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(BOB).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: 0, + proposed_collection_owner: BOB, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + + assert_noop!( + XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1), + Error::::NotCollectionOwner + ); + }); +} + + +#[test] +fn try_initiating_proposal_that_did_not_pass() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + //Create owners vector + let mut owners = BoundedVec::new(); + owners.try_push(ALICE).expect("Failed to push owner"); + + //Create proposal + let proposal = Proposal:: { + proposal_id: 1, + collection_id: 0, + proposed_collection_owner: ALICE, + proposed_destination_para: 2000.into(), + proposed_dest_collection_id: None, + proposed_destination_config: None, + owners: owners.clone(), + number_of_votes: crate::Votes { + aye: BoundedVec::new(), + nay: owners.clone(), + }, + end_time: 1u64.into(), + }; + + let _ = crate::CrossChainProposals::insert(1, proposal); + let _ = XcNFT::collection_x_transfer_initiate(RuntimeOrigin::signed(ALICE), 1); + + System::assert_has_event(RuntimeEvent::XcNFT(Event::ProposalDidNotPass { proposal_id: 1, })); + }); +} + +#[test] +fn try_sending_nft_no_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + assert_noop!( + XcNFT::nft_x_transfer(RuntimeOrigin::signed(ALICE), 1, 0, 1000.into(), 1, 1), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_sending_nft_no_nft() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + assert_noop!( + XcNFT::nft_x_transfer(RuntimeOrigin::signed(ALICE), 0, 0, 1000.into(), 1, 1), + Error::::NFTDoesNotExist + ); + }); +} + +#[test] +fn try_sending_nft_not_nft_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE); + + assert_noop!( + XcNFT::nft_x_transfer(RuntimeOrigin::signed(BOB), 0, 0, 1000.into(), 1, 1), + Error::::NotNFTOwner + ); + }); +} + +#[test] +fn try_claiming_nft_no_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 1u32, 0u32, 100u32.into(), 1u32, 1u32), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_claiming_nft_no_collection_origin() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 1u32, 0u32, 100u32.into(), 1u32, 1u32), + Error::::CollectionDoesNotExist + ); + }); +} + +#[test] +fn try_claiming_nft_wrong_origin_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 10, + received_collection_id: 20, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 0u32, 0u32, 100u32.into(), 0u32, 1u32), + Error::::WrongOriginCollectionAtOrigin + ); + }); +} + +#[test] +fn try_claiming_nft_wrong_nft() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + received_collection_id: 0, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 0u32, 0u32, 100u32.into(), 0u32, 0u32), + Error::::NFTNotReceived + ); + }); +} + +#[test] +fn try_claiming_nft_not_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0u32, 0u32, ALICE); + + System::set_block_number(3); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 1, ALICE); + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 1u32, 0u32, ALICE); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + received_collection_id: 0, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + let nfts: ReceivedStruct:: = ReceivedStruct:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + origin_asset_id: 0, + received_collection_id: 1, + received_asset_id: 0, + }; + + let _ = ReceivedAssets::::insert((1, 0), nfts); + + assert_noop!( + XcNFT::nft_x_claim(RuntimeOrigin::signed(BOB), 0u32, 0u32, 0u32, 1u32, 0u32), + Error::::NotNFTOwner + ); + }); +} + +#[test] +fn try_claiming_nft_success() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0u32, 0u32, ALICE); + + System::set_block_number(3); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 1, ALICE); + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 1u32, 0u32, ALICE); + + let collections: ReceivedCols:: = ReceivedCols:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + received_collection_id: 0, + }; + + let _ = ReceivedCollections::::insert(0, collections); + + let nfts: ReceivedStruct:: = ReceivedStruct:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + origin_asset_id: 0, + received_collection_id: 1, + received_asset_id: 0, + }; + + let _ = ReceivedAssets::::insert((1, 0), nfts); + System::set_block_number(3); + + let _ = XcNFT::nft_x_claim(RuntimeOrigin::signed(ALICE), 0u32, 0u32, 0u32, 1u32, 0u32); + + System::assert_has_event(RuntimeEvent::XcNFT(Event::NFTClaimed { collection_claimed_from: 1, asset_removed: 0, collection_claimed_to: 0, asset_claimed: 0 })); + + }); +} + +#[test] +fn try_collection_parse_empty_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = XcNFT::parse_collection_empty(RuntimeOrigin::signed(ALICE), 1, None, BoundedVec::new(), None); + + System::assert_has_event(RuntimeEvent::XcNFT(Event::CollectionReceived { origin_collection_id: 1, received_collection_id: 1, to_address: ALICE })); + }); +} + +#[test] +fn try_parse_collection_burn_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let destroy_witness = GeneralizedDestroyWitness { + item_meta: 0, + item_configs: 0, + attributes: 0, + }; + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let _ = XcNFT::parse_collection_burn(RuntimeOrigin::signed(ALICE), 0, destroy_witness); + + System::assert_has_event(RuntimeEvent::Uniques(pallet_uniques::Event::Destroyed { collection: 0 })); + }); +} + +#[test] +fn try_parse_collection_metadata_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let _ = XcNFT::parse_collection_metadata(RuntimeOrigin::signed(ALICE), 0, BoundedVec::new()); + + System::assert_has_event(RuntimeEvent::Uniques(pallet_uniques::Event::CollectionMetadataSet { collection: 0, data: BoundedVec::new(), is_frozen: false })); + }); +} + +#[test] +fn try_parse_collection_owner_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + pallet_uniques::OwnershipAcceptance::::insert(BOB, 0); + + let _ = XcNFT::parse_collection_owner(RuntimeOrigin::signed(ALICE), BOB, 0); + + System::assert_has_event(RuntimeEvent::Uniques(pallet_uniques::Event::OwnerChanged { collection: 0, new_owner: BOB })); + }); +} + +#[test] +fn try_parse_nft_burn_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE); + + let _ = XcNFT::parse_nft_burn(RuntimeOrigin::signed(ALICE), 0, 0); + + System::assert_has_event(RuntimeEvent::Uniques(pallet_uniques::Event::Burned { collection: 0, item: 0, owner: ALICE })); + }); +} + +#[test] +fn try_parse_nft_metadata_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE); + + let _ = XcNFT::parse_nft_metadata(RuntimeOrigin::signed(ALICE), 0, 0, BoundedVec::new()); + + System::assert_has_event(RuntimeEvent::Uniques(pallet_uniques::Event::MetadataSet { collection: 0, item: 0, data: BoundedVec::new(), is_frozen: false })); + }); +} + +#[test] +fn try_parse_nft_owner_successful() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE); + + let _ = XcNFT::parse_nft_owner(RuntimeOrigin::signed(ALICE), BOB ,0, 0); + + System::assert_has_event(RuntimeEvent::Uniques(pallet_uniques::Event::Transferred { collection: 0, item: 0, from: ALICE, to: BOB })); + }); +} + +#[test] +fn try_parse_nft_transfer_no_collection() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()), Error::::CollectionDoesNotExist); + }); +} + + +#[test] +fn try_parse_nft_transfer_already_received() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE); + + let nfts: ReceivedStruct:: = ReceivedStruct:: { + origin_para_id: 1000.into(), + origin_collection_id: 0, + origin_asset_id: 0, + received_collection_id: 0, + received_asset_id: 0, + }; + + let _ = ReceivedAssets::::insert((0, 0), nfts); + + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()), Error::::NFTAlreadyReceived); + }); +} + +#[test] +fn try_parse_nft_transfer_not_collection_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE); + + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(BOB),0,0,BoundedVec::new(),0,0,1000.into()), Error::::NotCollectionOwner); + }); +} + +#[test] +fn try_parse_nft_transfer_not_existing_nft() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + let _ = Uniques::mint(RuntimeOrigin::signed(ALICE), 0, 0, ALICE); + + + assert_noop!(XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()), Error::::NFTExists); + }); +} + +#[test] +fn try_parse_nft_transfer_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + let _ = XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,1000.into()); + System::assert_has_event(RuntimeEvent::XcNFT(Event::NFTReceived { origin_collection_id: 0, origin_asset_id: 0, received_collection_id: 0, received_asset_id: 0, to_address: ALICE})); +}); +} + +#[test] +fn try_parse_nft_transfer_return_to_origin(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let _ = Uniques::create(RuntimeOrigin::signed(ALICE), 0, ALICE); + + let sent = SentStruct:: { + + origin_para_id: ParachainInfo::parachain_id(), + origin_collection_id: 0, + origin_asset_id: 0, + destination_collection_id: 0, + destination_asset_id: 0, + }; + + let _ = SentAssets::::insert((0, 0), sent); + + //Set parachain id to 1000 + ParachainInfo::parachain_id(); + + let _ = XcNFT::parse_nft_transfer(RuntimeOrigin::signed(ALICE),0,0,BoundedVec::new(),0,0,ParachainInfo::parachain_id()); + System::assert_has_event(RuntimeEvent::XcNFT(Event::NFTReturnedToOrigin { returned_from_collection_id: 0, returned_from_asset_id: 0, to_address: ALICE })); + + }); +} + +#[test] +fn parse_collection_same_owner_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + + let mut nfts: Vec<(u32, BoundedVec)> = Vec::new(); + nfts.push((1, BoundedVec::new())); + + let _ = XcNFT::parse_collection_same_owner(RuntimeOrigin::signed(ALICE), None, BoundedVec::new(), nfts.clone(), 1000.into(), 0, None); + System::assert_has_event(RuntimeEvent::XcNFT(Event::CollectionWithNftsReceived { collection_id: 0, items: nfts.clone() })); + }); +} + +#[test] +fn parse_collection_diff_nft_owners_successful(){ + new_test_ext().execute_with(|| { + System::set_block_number(2); + + let mut nfts: Vec<(u32, AccountId32, BoundedVec)> = Vec::new(); + nfts.push((1, BOB, BoundedVec::new())); + + let _ = XcNFT::parse_collection_diff_owners(RuntimeOrigin::signed(ALICE), None, BoundedVec::new(), nfts.clone(), 1000.into(), 0, None); + System::assert_has_event(RuntimeEvent::XcNFT(Event::CollectionWithNftsDiffOwnersReceived { collection_id: 0, items: nfts.clone() })); + }); +} \ No newline at end of file