difftreelog
feat merge native erc20 adapter
in: master
78 files changed
Cargo.lockdiffbeforeafterboth5871 "pallet-aura",5871 "pallet-aura",5872 "pallet-authorship",5872 "pallet-authorship",5873 "pallet-balances",5873 "pallet-balances",5874 "pallet-balances-adapter",5874 "pallet-base-fee",5875 "pallet-base-fee",5875 "pallet-collator-selection",5876 "pallet-collator-selection",5876 "pallet-common",5877 "pallet-common",6251 "sp-std",6252 "sp-std",6252]6253]62546255[[package]]6256name = "pallet-balances-adapter"6257version = "0.1.0"6258dependencies = [6259 "evm-coder",6260 "frame-support",6261 "frame-system",6262 "pallet-balances",6263 "pallet-common",6264 "pallet-evm",6265 "pallet-evm-coder-substrate",6266 "pallet-evm-transaction-payment",6267 "pallet-structure",6268 "parity-scale-codec",6269 "scale-info",6270 "sp-core",6271 "sp-runtime",6272 "sp-std",6273 "up-data-structs",6274]625362756254[[package]]6276[[package]]6255name = "pallet-base-fee"6277name = "pallet-base-fee"6947 "frame-benchmarking",6969 "frame-benchmarking",6948 "frame-support",6970 "frame-support",6949 "frame-system",6971 "frame-system",6972 "pallet-balances",6950 "pallet-common",6973 "pallet-common",6951 "pallet-evm",6974 "pallet-evm",6952 "pallet-evm-coder-substrate",6975 "pallet-evm-coder-substrate",7411 "frame-benchmarking",7434 "frame-benchmarking",7412 "frame-support",7435 "frame-support",7413 "frame-system",7436 "frame-system",7437 "pallet-balances-adapter",7414 "pallet-common",7438 "pallet-common",7415 "pallet-evm",7439 "pallet-evm",7416 "pallet-evm-coder-substrate",7440 "pallet-evm-coder-substrate",9350 "pallet-aura",9374 "pallet-aura",9351 "pallet-authorship",9375 "pallet-authorship",9352 "pallet-balances",9376 "pallet-balances",9377 "pallet-balances-adapter",9353 "pallet-base-fee",9378 "pallet-base-fee",9354 "pallet-collator-selection",9379 "pallet-collator-selection",9355 "pallet-common",9380 "pallet-common",12902 "frame-support",12927 "frame-support",12903 "frame-system",12928 "frame-system",12904 "pallet-balances",12929 "pallet-balances",12930 "pallet-balances-adapter",12905 "pallet-common",12931 "pallet-common",12906 "pallet-configuration",12907 "pallet-ethereum",12932 "pallet-ethereum",12908 "pallet-evm",12933 "pallet-evm",12909 "pallet-evm-coder-substrate",12934 "pallet-evm-coder-substrate",12914 "pallet-timestamp",12939 "pallet-timestamp",12915 "pallet-transaction-payment",12940 "pallet-transaction-payment",12916 "pallet-unique",12941 "pallet-unique",12917 "pallet-xcm",12918 "parity-scale-codec",12942 "parity-scale-codec",12919 "scale-info",12943 "scale-info",12920 "sp-core",12944 "sp-core",13767 "pallet-aura",13791 "pallet-aura",13768 "pallet-authorship",13792 "pallet-authorship",13769 "pallet-balances",13793 "pallet-balances",13794 "pallet-balances-adapter",13770 "pallet-base-fee",13795 "pallet-base-fee",13771 "pallet-collator-selection",13796 "pallet-collator-selection",13772 "pallet-common",13797 "pallet-common",Cargo.tomldiffbeforeafterboth19panic = "unwind"19panic = "unwind"202021[profile.production]21[profile.production]22codegen-units = 122inherits = "release"23inherits = "release"23lto = true24lto = true24codegen-units = 125opt-level = 325opt-level = 3262627[workspace.dependencies]27[workspace.dependencies]28# Unique28# Unique29app-promotion-rpc = { path = "primitives/app_promotion_rpc", default-features = false }29app-promotion-rpc = { path = "primitives/app_promotion_rpc", default-features = false }30evm-coder = { git = "https://github.com/uniquenetwork/evm-coder", tag = "v0.3.1", default-features = false }30evm-coder = { git = "https://github.com/uniquenetwork/evm-coder", tag = "v0.3.1", default-features = false }31pallet-app-promotion = { path = "pallets/app-promotion", default-features = false }31pallet-app-promotion = { path = "pallets/app-promotion", default-features = false }32pallet-balances-adapter = { default-features = false, path = "pallets/balances-adapter" }32pallet-charge-transaction = { package = "pallet-template-transaction-payment", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.42" }33pallet-charge-transaction = { package = "pallet-template-transaction-payment", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.42" }33pallet-collator-selection = { default-features = false, path = "pallets/collator-selection" }34pallet-collator-selection = { default-features = false, path = "pallets/collator-selection" }34pallet-common = { default-features = false, path = "pallets/common" }35pallet-common = { default-features = false, path = "pallets/common" }123sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }124sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }124sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }125sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }125sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }126sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }127sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }126sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }128sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }127sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }129sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }128sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }129sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }130sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }130sc-network-sync = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }131sc-network-sync = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }131sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }132sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" }180orml-tokens = { default-features = false , git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }181orml-tokens = { default-features = false, git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }181orml-traits = { default-features = false , git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }182orml-traits = { default-features = false, git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }182orml-vesting = { default-features = false , git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }183orml-vesting = { default-features = false, git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }184orml-xcm-support = { default-features = false, git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }183orml-xtokens = { default-features = false , git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }185orml-xtokens = { default-features = false, git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }184orml-xcm-support = { default-features = false , git = "https://github.com/uniquenetwork/open-runtime-module-library", branch = "polkadot-v0.9.42" }185186186# Other187# Other187derivative = { version = "2.2.0", features = ["use_core"] }188derivative = { version = "2.2.0", features = ["use_core"] }Makefilediffbeforeafterboth6 @echo " bench-evm-migration"6 @echo " bench-evm-migration"7 @echo " bench-unique"7 @echo " bench-unique"89NATIVE_FUNGIBLE_EVM_STUBS=./pallets/balances-adapter/src/stubs10NATIVE_FUNGIBLE_EVM_ABI=./tests/src/eth/abi/nativeFungible.json8119FUNGIBLE_EVM_STUBS=./pallets/fungible/src/stubs12FUNGIBLE_EVM_STUBS=./pallets/fungible/src/stubs10FUNGIBLE_EVM_ABI=./tests/src/eth/abi/fungible.json13FUNGIBLE_EVM_ABI=./tests/src/eth/abi/fungible.json27.PHONY: regenerate_solidity30.PHONY: regenerate_solidity28regenerate_solidity: UniqueFungible.sol UniqueNFT.sol UniqueRefungible.sol UniqueRefungibleToken.sol ContractHelpers.sol CollectionHelpers.sol31regenerate_solidity: UniqueFungible.sol UniqueNFT.sol UniqueRefungible.sol UniqueRefungibleToken.sol ContractHelpers.sol CollectionHelpers.sol293233UniqueNativeFungible.sol:34 PACKAGE=pallet-balances-adapter NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh35 PACKAGE=pallet-balances-adapter NAME=erc::gen_impl OUTPUT=$(NATIVE_FUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh36 30UniqueFungible.sol:37UniqueFungible.sol:31 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh38 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh32 PACKAGE=pallet-fungible NAME=erc::gen_impl OUTPUT=$(FUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh39 PACKAGE=pallet-fungible NAME=erc::gen_impl OUTPUT=$(FUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh51 PACKAGE=pallet-unique NAME=eth::collection_helper_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh58 PACKAGE=pallet-unique NAME=eth::collection_helper_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh52 PACKAGE=pallet-unique NAME=eth::collection_helper_impl OUTPUT=$(COLLECTION_HELPER_STUBS)/$@ ./.maintain/scripts/generate_sol.sh59 PACKAGE=pallet-unique NAME=eth::collection_helper_impl OUTPUT=$(COLLECTION_HELPER_STUBS)/$@ ./.maintain/scripts/generate_sol.sh536061UniqueNativeFungible: UniqueNativeFungible.sol62 INPUT=$(NATIVE_FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NATIVE_FUNGIBLE_EVM_STUBS)/UniqueNativeFungible.raw ./.maintain/scripts/compile_stub.sh63 INPUT=$(NATIVE_FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NATIVE_FUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh64 54UniqueFungible: UniqueFungible.sol65UniqueFungible: UniqueFungible.sol55 INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_STUBS)/UniqueFungible.raw ./.maintain/scripts/compile_stub.sh66 INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_STUBS)/UniqueFungible.raw ./.maintain/scripts/compile_stub.sh56 INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh67 INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.shnode/cli/src/chain_spec.rsdiffbeforeafterboth267pub fn development_config() -> DefaultChainSpec {267pub fn development_config() -> DefaultChainSpec {268 let mut properties = Map::new();268 let mut properties = Map::new();269 properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());269 properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());270 properties.insert("tokenDecimals".into(), 18.into());270 properties.insert("tokenDecimals".into(), default_runtime::DECIMALS.into());271 properties.insert(271 properties.insert(272 "ss58Format".into(),272 "ss58Format".into(),273 default_runtime::SS58Prefix::get().into(),273 default_runtime::SS58Prefix::get().into(),341pub fn local_testnet_config() -> DefaultChainSpec {341pub fn local_testnet_config() -> DefaultChainSpec {342 let mut properties = Map::new();342 let mut properties = Map::new();343 properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());343 properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());344 properties.insert("tokenDecimals".into(), 18.into());344 properties.insert("tokenDecimals".into(), default_runtime::DECIMALS.into());345 properties.insert(345 properties.insert(346 "ss58Format".into(),346 "ss58Format".into(),347 default_runtime::SS58Prefix::get().into(),347 default_runtime::SS58Prefix::get().into(),pallets/balances-adapter/Cargo.tomldiffbeforeafterbothno changes
pallets/balances-adapter/src/common.rsdiffbeforeafterbothno changes
pallets/balances-adapter/src/erc.rsdiffbeforeafterbothno changes
pallets/balances-adapter/src/lib.rsdiffbeforeafterbothno changes
pallets/balances-adapter/src/stubs/UniqueNativeFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/balances-adapter/src/stubs/UniqueNativeFungible.soldiffbeforeafterbothno changes
pallets/common/src/dispatch.rsdiffbeforeafterboth11use sp_runtime::DispatchError;11use sp_runtime::DispatchError;12use up_data_structs::{CollectionId, CreateCollectionData, CollectionFlags};12use up_data_structs::{CollectionId, CreateCollectionData, CollectionFlags};131314use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle};14use crate::{pallet::Config, CommonCollectionOperations};151516// TODO: move to benchmarking16// TODO: move to benchmarking17/// Price of [`dispatch_tx`] call with noop `call` argument17/// Price of [`dispatch_tx`] call with noop `call` argument34 collection: CollectionId,34 collection: CollectionId,35 call: C,35 call: C,36) -> DispatchResultWithPostInfo {36) -> DispatchResultWithPostInfo {37 let handle =37 let dispatched = T::CollectionDispatch::dispatch(collection)38 .and_then(|dispatched| {39 dispatched.check_is_internal()?;40 Ok(dispatched)41 })38 CollectionHandle::try_get(collection).map_err(|error| DispatchErrorWithPostInfo {42 .map_err(|error| DispatchErrorWithPostInfo {39 post_info: PostDispatchInfo {43 post_info: PostDispatchInfo {40 actual_weight: Some(dispatch_weight::<T>()),44 actual_weight: Some(dispatch_weight::<T>()),41 pays_fee: Pays::Yes,45 pays_fee: Pays::Yes,42 },46 },43 error,47 error,44 })?;48 })?;45 handle46 .check_is_internal()47 .map_err(|error| DispatchErrorWithPostInfo {48 post_info: PostDispatchInfo {49 actual_weight: Some(dispatch_weight::<T>()),50 pays_fee: Pays::Yes,51 },52 error,53 })?;54 let dispatched = T::CollectionDispatch::dispatch(handle);55 let mut result = call(dispatched.as_dyn());49 let mut result = call(dispatched.as_dyn());56 match &mut result {50 match &mut result {57 Ok(PostDispatchInfo {51 Ok(PostDispatchInfo {726673/// Interface for working with different collections through the dispatcher.67/// Interface for working with different collections through the dispatcher.74pub trait CollectionDispatch<T: Config> {68pub trait CollectionDispatch<T: Config> {69 /// Check if the collection is internal.70 fn check_is_internal(&self) -> DispatchResult;7175 /// Create a collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).72 /// Create a collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).76 ///73 ///87 ///84 ///88 /// * `sender` - The owner of the collection.85 /// * `sender` - The owner of the collection.89 /// * `handle` - Collection handle.86 /// * `handle` - Collection handle.90 fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;87 fn destroy(sender: T::CrossAccountId, collection_id: CollectionId) -> DispatchResult;918892 /// Get a specialized collection from the handle.89 /// Get a specialized collection from the handle.93 ///90 ///94 /// * `handle` - Collection handle.91 /// * `handle` - Collection handle.95 fn dispatch(handle: CollectionHandle<T>) -> Self;92 fn dispatch(collection_id: CollectionId) -> Result<Self, DispatchError>9693 where97 /// Get the collection handle for the corresponding implementation.94 Self: Sized;98 fn into_inner(self) -> CollectionHandle<T>;9995100 /// Get the implementation of [`CommonCollectionOperations`].96 /// Get the implementation of [`CommonCollectionOperations`].101 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;97 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;pallets/common/src/lib.rsdiffbeforeafterboth72 dispatch::Pays,72 dispatch::Pays,73 transactional, fail,73 transactional, fail,74};74};75use pallet_evm::GasWeightMapping;76use up_data_structs::{75use up_data_structs::{77 AccessMode, COLLECTION_NUMBER_LIMIT, Collection, RpcCollection, CollectionFlags,76 AccessMode, COLLECTION_NUMBER_LIMIT, Collection, RpcCollection, CollectionFlags,78 RpcCollectionFlags, CollectionId, CreateItemData, MAX_TOKEN_PREFIX_LENGTH,77 RpcCollectionFlags, CollectionId, CreateItemData, MAX_TOKEN_PREFIX_LENGTH,105/// Collection handle contains information about collection data and id.104/// Collection handle contains information about collection data and id.106/// Also provides functionality to count consumed gas.105/// Also provides functionality to count consumed gas.107///106///108/// CollectionHandle is used as a generic wrapper for collections of all types.107/// CollectionHandle is used as a generic wrapper for collections of all types (except native fungible).109/// It allows to perform common operations and queries on any collection type,108/// It allows to perform common operations and queries on any collection type,110/// both completely general for all, as well as their respective implementations of [`CommonCollectionOperations`].109/// both completely general for all, as well as their respective implementations of [`CommonCollectionOperations`].111#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]110#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]129impl<T: Config> CollectionHandle<T> {128impl<T: Config> CollectionHandle<T> {130 /// Same as [CollectionHandle::new] but with an explicit gas limit.129 /// Same as [CollectionHandle::new] but with an explicit gas limit.131 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {130 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {132 <CollectionById<T>>::get(id).map(|collection| Self {131 Self::new_with_recorder(id, SubstrateRecorder::new(gas_limit))133 id,134 collection,135 recorder: SubstrateRecorder::new(gas_limit),136 })137 }132 }138133139 /// Same as [CollectionHandle::new] but with an existed [`SubstrateRecorder`].134 /// Same as [CollectionHandle::new] but with an existed [`SubstrateRecorder`].161 &self,156 &self,162 reads: u64,157 reads: u64,163 ) -> pallet_evm_coder_substrate::execution::Result<()> {158 ) -> pallet_evm_coder_substrate::execution::Result<()> {164 self.recorder159 self.recorder().consume_store_reads(reads)165 .consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(166 <T as frame_system::Config>::DbWeight::get()167 .read168 .saturating_mul(reads),169 // TODO: measure proof170 0,171 )))172 }160 }173161174 /// Consume gas for writing.162 /// Consume gas for writing.175 pub fn consume_store_writes(163 pub fn consume_store_writes(176 &self,164 &self,177 writes: u64,165 writes: u64,178 ) -> pallet_evm_coder_substrate::execution::Result<()> {166 ) -> pallet_evm_coder_substrate::execution::Result<()> {179 self.recorder167 self.recorder().consume_store_writes(writes)180 .consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(181 <T as frame_system::Config>::DbWeight::get()182 .write183 .saturating_mul(writes),184 // TODO: measure proof185 0,186 )))187 }168 }188169189 /// Consume gas for reading and writing.170 /// Consume gas for reading and writing.192 reads: u64,173 reads: u64,193 writes: u64,174 writes: u64,194 ) -> pallet_evm_coder_substrate::execution::Result<()> {175 ) -> pallet_evm_coder_substrate::execution::Result<()> {195 let weight = <T as frame_system::Config>::DbWeight::get();196 let reads = weight.read.saturating_mul(reads);197 let writes = weight.read.saturating_mul(writes);198 self.recorder176 self.recorder()199 .consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(177 .consume_store_reads_and_writes(reads, writes)200 reads.saturating_add(writes),201 // TODO: measure proof202 0,203 )))204 }178 }205179206 /// Save collection to storage.180 /// Save collection to storage.469 }443 }470444471 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);445 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);446 /// Collection id for native fungible collction.447 pub const NATIVE_FUNGIBLE_COLLECTION_ID: CollectionId = CollectionId(0);472448473 #[pallet::pallet]449 #[pallet::pallet]474 #[pallet::storage_version(STORAGE_VERSION)]450 #[pallet::storage_version(STORAGE_VERSION)]pallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth37 ExitError, ExitRevert, ExitSucceed, GasWeightMapping, PrecompileFailure, PrecompileOutput,37 ExitError, ExitRevert, ExitSucceed, GasWeightMapping, PrecompileFailure, PrecompileOutput,38 PrecompileResult, PrecompileHandle,38 PrecompileResult, PrecompileHandle,39};39};40use sp_core::H160;40use sp_core::{Get, H160};41// #[cfg(feature = "runtime-benchmarks")]41// #[cfg(feature = "runtime-benchmarks")]42// pub mod benchmarking;42// pub mod benchmarking;43pub mod execution;43pub mod execution;205 })205 })206 }206 }207208 /// Consume gas for reading.209 pub fn consume_store_reads(&self, reads: u64) -> execution::Result<()> {210 self.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(211 <T as frame_system::Config>::DbWeight::get()212 .read213 .saturating_mul(reads),214 // TODO: measure proof215 0,216 )))217 }218219 /// Consume gas for writing.220 pub fn consume_store_writes(&self, writes: u64) -> execution::Result<()> {221 self.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(222 <T as frame_system::Config>::DbWeight::get()223 .write224 .saturating_mul(writes),225 // TODO: measure proof226 0,227 )))228 }229230 /// Consume gas for reading and writing.231 pub fn consume_store_reads_and_writes(&self, reads: u64, writes: u64) -> execution::Result<()> {232 let weight = <T as frame_system::Config>::DbWeight::get();233 let reads = weight.read.saturating_mul(reads);234 let writes = weight.read.saturating_mul(writes);235 self.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(236 reads.saturating_add(writes),237 // TODO: measure proof238 0,239 )))240 }207}241}208242209pub fn dispatch_to_evm<T: Config>(err: DispatchError) -> execution::Error {243pub fn dispatch_to_evm<T: Config>(err: DispatchError) -> execution::Error {pallets/fungible/src/erc.rsdiffbeforeafterboth109 .recorder109 .recorder110 .weight_calls_budget(<StructureWeight<T>>::find_parent());110 .weight_calls_budget(<StructureWeight<T>>::find_parent());111111112 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;112 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget)113 .map_err(|e| dispatch_to_evm::<T>(e.error))?;113 Ok(true)114 Ok(true)114 }115 }115116pallets/nonfungible/Cargo.tomldiffbeforeafterboth12frame-benchmarking = { workspace = true, optional = true }12frame-benchmarking = { workspace = true, optional = true }13frame-support = { workspace = true }13frame-support = { workspace = true }14frame-system = { workspace = true }14frame-system = { workspace = true }15pallet-balances = { workspace = true }15pallet-common = { workspace = true }16pallet-common = { workspace = true }16pallet-evm = { workspace = true }17pallet-evm = { workspace = true }17pallet-evm-coder-substrate = { workspace = true }18pallet-evm-coder-substrate = { workspace = true }pallets/nonfungible/src/lib.rsdiffbeforeafterboth170 + pallet_common::Config171 + pallet_structure::Config172 + pallet_evm::Config173 + pallet_balances::Config170 {174 {171 type WeightInfo: WeightInfo;175 type WeightInfo: WeightInfo;172 }176 }1325 }1329 }132613301327 fn nest(under: (CollectionId, TokenId), to_nest: (CollectionId, TokenId)) {1331 fn nest(under: (CollectionId, TokenId), to_nest: (CollectionId, TokenId)) {1332 if to_nest.0 != pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1328 <TokenChildren<T>>::insert((under.0, under.1, (to_nest.0, to_nest.1)), true);1333 <TokenChildren<T>>::insert((under.0, under.1, to_nest), true);1334 }1329 }1335 }133013361331 fn unnest(under: (CollectionId, TokenId), to_unnest: (CollectionId, TokenId)) {1337 fn unnest(under: (CollectionId, TokenId), to_unnest: (CollectionId, TokenId)) {1338 if to_unnest.0 != pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1332 <TokenChildren<T>>::remove((under.0, under.1, to_unnest));1339 <TokenChildren<T>>::remove((under.0, under.1, to_unnest));1333 }1340 }1341 }133413421335 fn collection_has_tokens(collection_id: CollectionId) -> bool {1343 fn collection_has_tokens(collection_id: CollectionId) -> bool {pallets/structure/src/benchmarking.rsdiffbeforeafterboth42 },42 },43 CollectionFlags::default(),43 CollectionFlags::default(),44 )?;44 )?;45 let dispatch = T::CollectionDispatch::dispatch(CollectionHandle::try_get(CollectionId(1))?);45 let dispatch = T::CollectionDispatch::dispatch(CollectionId(1))?;46 let dispatch = dispatch.as_dyn();46 let dispatch = dispatch.as_dyn();474748 dispatch.create_item(caller_cross.clone(), caller_cross.clone(), CreateItemData::NFT(CreateNftData::default()), &Unlimited)?;48 dispatch.create_item(caller_cross.clone(), caller_cross.clone(), CreateItemData::NFT(CreateNftData::default()), &Unlimited)?;pallets/structure/src/lib.rsdiffbeforeafterboth60use frame_support::dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo};60use frame_support::dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo};61use frame_support::fail;61use frame_support::fail;62pub use pallet::*;62pub use pallet::*;63use pallet_common::{dispatch::CollectionDispatch, CollectionHandle};63use pallet_common::{dispatch::CollectionDispatch};64use up_data_structs::{64use up_data_structs::{65 CollectionId, TokenId, mapping::TokenAddressMapping, budget::Budget, TokenOwnerError,65 CollectionId, TokenId, mapping::TokenAddressMapping, budget::Budget, TokenOwnerError,66};66};155 token: TokenId,155 token: TokenId,156 ) -> Result<Parent<T::CrossAccountId>, DispatchError> {156 ) -> Result<Parent<T::CrossAccountId>, DispatchError> {157 // TODO: Reduce cost by not reading collection config157 // TODO: Reduce cost by not reading collection config158 let handle = match CollectionHandle::try_get(collection) {158 let handle = match T::CollectionDispatch::dispatch(collection) {159 Ok(v) => v,159 Ok(v) => v,160 Err(_) => return Ok(Parent::TokenNotFound),160 Err(_) => return Ok(Parent::TokenNotFound),161 };161 };162 let handle = T::CollectionDispatch::dispatch(handle);163 let handle = handle.as_dyn();162 let handle = handle.as_dyn();164163165 Ok(match handle.token_owner(token) {164 Ok(match handle.token_owner(token) {279 self_budget: &dyn Budget,278 self_budget: &dyn Budget,280 breadth_budget: &dyn Budget,279 breadth_budget: &dyn Budget,281 ) -> DispatchResultWithPostInfo {280 ) -> DispatchResultWithPostInfo {282 let handle = <CollectionHandle<T>>::try_get(collection)?;283 let dispatch = T::CollectionDispatch::dispatch(handle);281 let dispatch = T::CollectionDispatch::dispatch(collection)?;284 let dispatch = dispatch.as_dyn();282 let dispatch = dispatch.as_dyn();285 dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)283 dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)286 }284 }405 return Ok(())403 return Ok(())406 };404 };407408 let handle = <CollectionHandle<T>>::try_get(collection)?;409405410 let dispatch = T::CollectionDispatch::dispatch(handle);406 let dispatch = T::CollectionDispatch::dispatch(collection)?;411 let dispatch = dispatch.as_dyn();407 let dispatch = dispatch.as_dyn();412408413 action(dispatch, token)409 action(dispatch, token)pallets/unique/Cargo.tomldiffbeforeafterboth24 'frame-benchmarking/std',24 'frame-benchmarking/std',25 'frame-support/std',25 'frame-support/std',26 'frame-system/std',26 'frame-system/std',27 'pallet-balances-adapter/std',27 'pallet-common/std',28 'pallet-common/std',28 'pallet-evm-coder-substrate/std',29 'pallet-evm-coder-substrate/std',29 'pallet-evm/std',30 'pallet-evm/std',46frame-benchmarking = { workspace = true, optional = true }47frame-benchmarking = { workspace = true, optional = true }47frame-support = { workspace = true }48frame-support = { workspace = true }48frame-system = { workspace = true }49frame-system = { workspace = true }50pallet-balances-adapter = { workspace = true }49pallet-common = { workspace = true }51pallet-common = { workspace = true }50pallet-evm = { workspace = true }52pallet-evm = { workspace = true }51pallet-evm-coder-substrate = { workspace = true }53pallet-evm-coder-substrate = { workspace = true }pallets/unique/src/lib.rsdiffbeforeafterboth440 collection_id: CollectionId,440 collection_id: CollectionId,441 address: T::CrossAccountId,441 address: T::CrossAccountId,442 ) -> DispatchResult {442 ) -> DispatchResult {443 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {444 fail!(<pallet_common::Error<T>>::UnsupportedOperation);445 }446443 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);447 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);444 let collection = <CollectionHandle<T>>::try_get(collection_id)?;448 let collection = <CollectionHandle<T>>::try_get(collection_id)?;467 collection_id: CollectionId,471 collection_id: CollectionId,468 address: T::CrossAccountId,472 address: T::CrossAccountId,469 ) -> DispatchResult {473 ) -> DispatchResult {474 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {475 fail!(<pallet_common::Error<T>>::UnsupportedOperation);476 }477470 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);478 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);471 let collection = <CollectionHandle<T>>::try_get(collection_id)?;479 let collection = <CollectionHandle<T>>::try_get(collection_id)?;493 collection_id: CollectionId,501 collection_id: CollectionId,494 new_owner: T::AccountId,502 new_owner: T::AccountId,495 ) -> DispatchResult {503 ) -> DispatchResult {504 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {505 fail!(<pallet_common::Error<T>>::UnsupportedOperation);506 }496 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);507 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);497 let new_owner = T::CrossAccountId::from_sub(new_owner);508 let new_owner = T::CrossAccountId::from_sub(new_owner);498 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;509 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;522 collection_id: CollectionId,533 collection_id: CollectionId,523 new_admin_id: T::CrossAccountId,534 new_admin_id: T::CrossAccountId,524 ) -> DispatchResult {535 ) -> DispatchResult {536 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {537 fail!(<pallet_common::Error<T>>::UnsupportedOperation);538 }525 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);539 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);526 let collection = <CollectionHandle<T>>::try_get(collection_id)?;540 let collection = <CollectionHandle<T>>::try_get(collection_id)?;527 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)541 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)548 collection_id: CollectionId,562 collection_id: CollectionId,549 account_id: T::CrossAccountId,563 account_id: T::CrossAccountId,550 ) -> DispatchResult {564 ) -> DispatchResult {565 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {566 fail!(<pallet_common::Error<T>>::UnsupportedOperation);567 }551 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);568 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);552 let collection = <CollectionHandle<T>>::try_get(collection_id)?;569 let collection = <CollectionHandle<T>>::try_get(collection_id)?;553 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)570 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)573 collection_id: CollectionId,590 collection_id: CollectionId,574 new_sponsor: T::AccountId,591 new_sponsor: T::AccountId,575 ) -> DispatchResult {592 ) -> DispatchResult {593 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {594 fail!(<pallet_common::Error<T>>::UnsupportedOperation);595 }576 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);596 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);577 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;597 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;578 target_collection.set_sponsor(&sender, new_sponsor.clone())598 target_collection.set_sponsor(&sender, new_sponsor.clone())597 origin: OriginFor<T>,617 origin: OriginFor<T>,598 collection_id: CollectionId,618 collection_id: CollectionId,599 ) -> DispatchResult {619 ) -> DispatchResult {620 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {621 fail!(<pallet_common::Error<T>>::UnsupportedOperation);622 }600 let sender = ensure_signed(origin)?;623 let sender = ensure_signed(origin)?;601 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;624 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;602 target_collection.confirm_sponsorship(&sender)625 target_collection.confirm_sponsorship(&sender)617 origin: OriginFor<T>,640 origin: OriginFor<T>,618 collection_id: CollectionId,641 collection_id: CollectionId,619 ) -> DispatchResult {642 ) -> DispatchResult {643 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {644 fail!(<pallet_common::Error<T>>::UnsupportedOperation);645 }620 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);646 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);621 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;647 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;622 target_collection.remove_sponsor(&sender)648 target_collection.remove_sponsor(&sender)894 collection_id: CollectionId,920 collection_id: CollectionId,895 value: bool,921 value: bool,896 ) -> DispatchResult {922 ) -> DispatchResult {923 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {924 fail!(<pallet_common::Error<T>>::UnsupportedOperation);925 }897 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);926 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);898 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;927 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;899 target_collection.check_is_internal()?;928 target_collection.check_is_internal()?;1146 collection_id: CollectionId,1175 collection_id: CollectionId,1147 new_limit: CollectionLimits,1176 new_limit: CollectionLimits,1148 ) -> DispatchResult {1177 ) -> DispatchResult {1178 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1179 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1180 }1149 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1181 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1150 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1182 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1151 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)1183 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)1170 collection_id: CollectionId,1202 collection_id: CollectionId,1171 new_permission: CollectionPermissions,1203 new_permission: CollectionPermissions,1172 ) -> DispatchResult {1204 ) -> DispatchResult {1205 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1206 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1207 }1173 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1208 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1174 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1209 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1175 <PalletCommon<T>>::update_permissions(&sender, &mut target_collection, new_permission)1210 <PalletCommon<T>>::update_permissions(&sender, &mut target_collection, new_permission)1238 origin: OriginFor<T>,1273 origin: OriginFor<T>,1239 collection_id: CollectionId,1274 collection_id: CollectionId,1240 ) -> DispatchResult {1275 ) -> DispatchResult {1276 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1277 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1278 }1241 ensure_root(origin)?;1279 ensure_root(origin)?;1242 <PalletCommon<T>>::repair_collection(collection_id)1280 <PalletCommon<T>>::repair_collection(collection_id)1243 }1281 }1296 sender: T::CrossAccountId,1334 sender: T::CrossAccountId,1297 collection_id: CollectionId,1335 collection_id: CollectionId,1298 ) -> DispatchResult {1336 ) -> DispatchResult {1299 let collection = <CollectionHandle<T>>::try_get(collection_id)?;1300 collection.check_is_internal()?;13011302 T::CollectionDispatch::destroy(sender, collection)?;1337 T::CollectionDispatch::destroy(sender, collection_id)?;130313381304 // TODO: basket cleanup should be moved elsewhere1339 // TODO: basket cleanup should be moved elsewhere1305 // Maybe runtime dispatch.rs should perform it?1340 // Maybe runtime dispatch.rs should perform it?runtime/common/config/pallets/mod.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617use alloc::string::{String, ToString};17use frame_support::parameter_types;18use frame_support::parameter_types;18use sp_runtime::traits::AccountIdConversion;19use sp_runtime::traits::AccountIdConversion;19use crate::{20use crate::{23 weights::CommonWeights,24 weights::CommonWeights,24 RelayChainBlockNumberProvider,25 RelayChainBlockNumberProvider,25 },26 },26 Runtime, RuntimeEvent, RuntimeCall, RuntimeOrigin, Balances,27 Runtime, RuntimeEvent, RuntimeCall, RuntimeOrigin, RUNTIME_NAME, TOKEN_SYMBOL, DECIMALS,28 Balances,27};29};28use frame_support::traits::{ConstU32, ConstU64};30use frame_support::traits::{ConstU32, ConstU64, Currency};29use up_common::{31use up_common::{30 types::{AccountId, Balance, BlockNumber},32 types::{AccountId, Balance, BlockNumber},31 constants::*,33 constants::*,51pub mod preimage;53pub mod preimage;525453parameter_types! {55parameter_types! {56 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;54 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();57 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();55 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;56}58}575958impl pallet_common::Config for Runtime {60impl pallet_common::Config for Runtime {84 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;86 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;85}87}8889parameter_types! {90 pub const Decimals: u8 = DECIMALS;91 pub Name: String = RUNTIME_NAME.to_string();92 pub Symbol: String = TOKEN_SYMBOL.to_string();93}94impl pallet_balances_adapter::Config for Runtime {95 type Inspect = Balances;96 type Mutate = Balances;97 type CurrencyBalance = <Balances as Currency<Self::AccountId>>::Balance;98 type Decimals = Decimals;99 type Name = Name;100 type Symbol = Symbol;101 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;102}8610387parameter_types! {104parameter_types! {88 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied105 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is appliedruntime/common/construct_runtime.rsdiffbeforeafterboth106106107 Maintenance: pallet_maintenance = 154,107 Maintenance: pallet_maintenance = 154,108109 BalancesAdapter: pallet_balances_adapter = 155,108110109 #[cfg(feature = "pallet-test-utils")]111 #[cfg(feature = "pallet-test-utils")]110 TestUtils: pallet_test_utils = 255,112 TestUtils: pallet_test_utils = 255,runtime/common/dispatch.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617use frame_support::{dispatch::DispatchResult, ensure};17use frame_support::{dispatch::DispatchResult, ensure, fail};18use pallet_evm::{PrecompileHandle, PrecompileResult};18use pallet_evm::{PrecompileHandle, PrecompileResult};19use sp_core::H160;19use sp_core::H160;20use sp_runtime::DispatchError;20use sp_runtime::DispatchError;25};25};26pub use pallet_common::dispatch::CollectionDispatch;26pub use pallet_common::dispatch::CollectionDispatch;27use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};27use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};28use pallet_balances_adapter::{NativeFungibleHandle};28use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};29use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};29use pallet_refungible::{30use pallet_refungible::{30 Pallet as PalletRefungible, RefungibleHandle, erc_token::RefungibleTokenHandle,31 Pallet as PalletRefungible, RefungibleHandle, erc_token::RefungibleTokenHandle,42 T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config,43 T: pallet_fungible::Config44 + pallet_nonfungible::Config45 + pallet_refungible::Config46 + pallet_balances_adapter::Config,43{47{44 Fungible(FungibleHandle<T>),48 Fungible(FungibleHandle<T>),45 Nonfungible(NonfungibleHandle<T>),49 Nonfungible(NonfungibleHandle<T>),46 Refungible(RefungibleHandle<T>),50 Refungible(RefungibleHandle<T>),51 NativeFungible(NativeFungibleHandle<T>),47}52}5348impl<T> CollectionDispatch<T> for CollectionDispatchT<T>54impl<T> CollectionDispatch<T> for CollectionDispatchT<T>49where55where50 T: pallet_common::Config56 T: pallet_common::Config51 + pallet_unique::Config57 + pallet_unique::Config52 + pallet_fungible::Config58 + pallet_fungible::Config53 + pallet_nonfungible::Config59 + pallet_nonfungible::Config54 + pallet_refungible::Config,60 + pallet_refungible::Config61 + pallet_balances_adapter::Config,55{62{63 fn check_is_internal(&self) -> DispatchResult {64 match self {65 Self::Fungible(h) => h.check_is_internal(),66 Self::Nonfungible(h) => h.check_is_internal(),67 Self::Refungible(h) => h.check_is_internal(),68 Self::NativeFungible(h) => h.check_is_internal(),69 }70 }7156 fn create(72 fn create(57 sender: T::CrossAccountId,73 sender: T::CrossAccountId,83 Ok(id)99 Ok(id)84 }100 }8510186 fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {102 fn destroy(sender: T::CrossAccountId, collection_id: CollectionId) -> DispatchResult {103 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {104 fail!(<pallet_common::Error<T>>::UnsupportedOperation);105 }106107 let collection = <CollectionHandle<T>>::try_get(collection_id)?;10887 match collection.mode {109 match collection.mode {88 CollectionMode::ReFungible => {110 CollectionMode::ReFungible => {98 Ok(())120 Ok(())99 }121 }100122101 fn dispatch(handle: CollectionHandle<T>) -> Self {123 fn dispatch(collection_id: CollectionId) -> Result<Self, DispatchError> {124 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {125 return Ok(Self::NativeFungible(126 NativeFungibleHandle::new_with_gas_limit(u64::MAX),127 ));128 }129130 let handle = <CollectionHandle<T>>::try_get(collection_id)?;102 match handle.mode {131 Ok(match handle.mode {103 CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),132 CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),104 CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),133 CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),105 CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),134 CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),106 }135 })107 }136 }108109 fn into_inner(self) -> CollectionHandle<T> {110 match self {111 Self::Fungible(f) => f.into_inner(),112 Self::Nonfungible(f) => f.into_inner(),113 Self::Refungible(f) => f.into_inner(),114 }115 }116137117 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {138 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {118 match self {139 match self {119 Self::Fungible(h) => h,140 Self::Fungible(h) => h,120 Self::Nonfungible(h) => h,141 Self::Nonfungible(h) => h,121 Self::Refungible(h) => h,142 Self::Refungible(h) => h,143 Self::NativeFungible(h) => h,122 }144 }123 }145 }124}146}130 + pallet_fungible::Config152 + pallet_fungible::Config131 + pallet_nonfungible::Config153 + pallet_nonfungible::Config132 + pallet_refungible::Config,154 + pallet_refungible::Config155 + pallet_balances_adapter::Config,133 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,156 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,134{157{135 fn is_reserved(target: &H160) -> bool {158 fn is_reserved(target: &H160) -> bool {166 }189 }167 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {190 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {168 if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {191 if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {192 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {193 <NativeFungibleHandle<T>>::new_with_gas_limit(handle.remaining_gas()).call(handle)194 } else {169 let collection =195 let collection = <CollectionHandle<T>>::new_with_gas_limit(170 <CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;196 collection_id,171 let dispatched = Self::dispatch(collection);197 handle.remaining_gas(),198 )?;172199173 match dispatched {200 match collection.mode {174 Self::Fungible(h) => h.call(handle),201 CollectionMode::Fungible(_) => FungibleHandle::cast(collection).call(handle),175 Self::Nonfungible(h) => h.call(handle),202 CollectionMode::NFT => NonfungibleHandle::cast(collection).call(handle),176 Self::Refungible(h) => h.call(handle),203 CollectionMode::ReFungible => RefungibleHandle::cast(collection).call(handle),177 }204 }205 }178 } else if let Some((collection_id, token_id)) =206 } else if let Some((collection_id, token_id)) =179 <T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(207 <T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(180 &handle.code_address(),208 &handle.code_address(),runtime/common/runtime_apis.rsdiffbeforeafterboth17#[macro_export]17#[macro_export]18macro_rules! dispatch_unique_runtime {18macro_rules! dispatch_unique_runtime {19 ($collection:ident.$method:ident($($name:ident),*) $($rest:tt)*) => {{19 ($collection:ident.$method:ident($($name:ident),*) $($rest:tt)*) => {{20 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);20 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch($collection)?;21 let dispatch = collection.as_dyn();21 let dispatch = collection.as_dyn();222223 Ok::<_, DispatchError>(dispatch.$method($($name),*) $($rest)*)23 Ok::<_, DispatchError>(dispatch.$method($($name),*) $($rest)*)runtime/common/weights/mod.rsdiffbeforeafterboth18use frame_support::{weights::Weight};18use frame_support::{weights::Weight};19use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight, RefungibleExtensionsWeightInfo};19use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight, RefungibleExtensionsWeightInfo};202021use pallet_balances_adapter::{22 Config as NativeFungibleConfig, common::CommonWeights as NativeFungibleWeights,23};21use pallet_fungible::{Config as FungibleConfig, common::CommonWeights as FungibleWeights};24use pallet_fungible::{Config as FungibleConfig, common::CommonWeights as FungibleWeights};22use pallet_nonfungible::{Config as NonfungibleConfig, common::CommonWeights as NonfungibleWeights};25use pallet_nonfungible::{Config as NonfungibleConfig, common::CommonWeights as NonfungibleWeights};232632macro_rules! max_weight_of {35macro_rules! max_weight_of {33 ($method:ident ( $($args:tt)* )) => {{36 ($method:ident ( $($args:tt)* )) => {{34 let max_weight = <FungibleWeights<T>>::$method($($args)*)37 let max_weight = <FungibleWeights<T>>::$method($($args)*)38 .max(<NativeFungibleWeights<T>>::$method($($args)*))35 .max(<NonfungibleWeights<T>>::$method($($args)*));39 .max(<NonfungibleWeights<T>>::$method($($args)*));364037 #[cfg(feature = "refungible")]41 #[cfg(feature = "refungible")]42}46}434744#[cfg(not(feature = "refungible"))]48#[cfg(not(feature = "refungible"))]45pub trait CommonWeightConfigs: FungibleConfig + NonfungibleConfig {}49pub trait CommonWeightConfigs: FungibleConfig + NativeFungibleConfig + NonfungibleConfig {}465047#[cfg(not(feature = "refungible"))]51#[cfg(not(feature = "refungible"))]48impl<T: FungibleConfig + NonfungibleConfig> CommonWeightConfigs for T {}52impl<T: FungibleConfig + NativeFungibleConfig + NonfungibleConfig> CommonWeightConfigs for T {}495350#[cfg(feature = "refungible")]54#[cfg(feature = "refungible")]51pub trait CommonWeightConfigs: FungibleConfig + NonfungibleConfig + RefungibleConfig {}55pub trait CommonWeightConfigs:56 FungibleConfig + NativeFungibleConfig + NonfungibleConfig + RefungibleConfig57{58}525953#[cfg(feature = "refungible")]60#[cfg(feature = "refungible")]54impl<T: FungibleConfig + NonfungibleConfig + RefungibleConfig> CommonWeightConfigs for T {}61impl<T: FungibleConfig + NativeFungibleConfig + NonfungibleConfig + RefungibleConfig>62 CommonWeightConfigs for T63{64}runtime/opal/Cargo.tomldiffbeforeafterboth18[features]18[features]19default = ['opal-runtime', 'std']19default = ['opal-runtime', 'std']20limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']20limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']21opal-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'preimage', 'pallet-test-utils', 'refungible']21opal-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'pallet-test-utils', 'preimage', 'refungible']22pov-estimate = []22pov-estimate = []23runtime-benchmarks = [23runtime-benchmarks = [24 "pallet-preimage/runtime-benchmarks",24 'cumulus-pallet-parachain-system/runtime-benchmarks',25 'cumulus-pallet-parachain-system/runtime-benchmarks',25 'frame-benchmarking',26 'frame-benchmarking',26 'frame-support/runtime-benchmarks',27 'frame-support/runtime-benchmarks',41 'pallet-inflation/runtime-benchmarks',42 'pallet-inflation/runtime-benchmarks',42 'pallet-maintenance/runtime-benchmarks',43 'pallet-maintenance/runtime-benchmarks',43 'pallet-nonfungible/runtime-benchmarks',44 'pallet-nonfungible/runtime-benchmarks',44 "pallet-preimage/runtime-benchmarks",45 'pallet-refungible/runtime-benchmarks',45 'pallet-refungible/runtime-benchmarks',46 'pallet-structure/runtime-benchmarks',46 'pallet-structure/runtime-benchmarks',47 'pallet-timestamp/runtime-benchmarks',47 'pallet-timestamp/runtime-benchmarks',70 # 'pallet-contracts-primitives/std',70 # 'pallet-contracts-primitives/std',71 # 'pallet-contracts-rpc-runtime-api/std',71 # 'pallet-contracts-rpc-runtime-api/std',72 # 'pallet-contract-helpers/std',72 # 'pallet-contract-helpers/std',73 "pallet-authorship/std",73 "pallet-preimage/std",74 "pallet-preimage/std",74 "pallet-authorship/std",75 "pallet-session/std",75 "pallet-session/std",76 "sp-consensus-aura/std",76 "sp-consensus-aura/std",77 'app-promotion-rpc/std',77 'app-promotion-rpc/std',78 'evm-coder/std',78 'evm-coder/std',79 'fp-rpc/std',79 'fp-rpc/std',80 'fp-self-contained/std',80 'fp-self-contained/std',81 'pallet-app-promotion/std',81 'pallet-app-promotion/std',82 'pallet-balances-adapter/std',82 'pallet-base-fee/std',83 'pallet-base-fee/std',83 'pallet-charge-transaction/std',84 'pallet-charge-transaction/std',84 'pallet-collator-selection/std',85 'pallet-collator-selection/std',128 "orml-tokens/std",129 "orml-tokens/std",129 "orml-traits/std",130 "orml-traits/std",130 "orml-vesting/std",131 "orml-vesting/std",132 "orml-xcm-support/std",131 "orml-xtokens/std",133 "orml-xtokens/std",132 "orml-xcm-support/std",133 "pallet-foreign-assets/std",134 "pallet-foreign-assets/std",134135135 'pallet-maintenance/std',136 'pallet-maintenance/std',139 "pallet-authorship/try-runtime",140 "pallet-authorship/try-runtime",140 "pallet-collator-selection/try-runtime",141 "pallet-collator-selection/try-runtime",141 "pallet-identity/try-runtime",142 "pallet-identity/try-runtime",143 "pallet-preimage/try-runtime",142 "pallet-session/try-runtime",144 "pallet-session/try-runtime",143 "pallet-preimage/try-runtime",144 'cumulus-pallet-aura-ext/try-runtime',145 'cumulus-pallet-aura-ext/try-runtime',145 'cumulus-pallet-dmp-queue/try-runtime',146 'cumulus-pallet-dmp-queue/try-runtime',146 'cumulus-pallet-parachain-system/try-runtime',147 'cumulus-pallet-parachain-system/try-runtime',158 'pallet-app-promotion/try-runtime',159 'pallet-app-promotion/try-runtime',159 'pallet-aura/try-runtime',160 'pallet-aura/try-runtime',160 'pallet-balances/try-runtime',161 'pallet-balances/try-runtime',162 'pallet-balances-adapter/try-runtime',161 'pallet-base-fee/try-runtime',163 'pallet-base-fee/try-runtime',162 'pallet-charge-transaction/try-runtime',164 'pallet-charge-transaction/try-runtime',163 'pallet-common/try-runtime',165 'pallet-common/try-runtime',189app-promotion = []191app-promotion = []190collator-selection = []192collator-selection = []191foreign-assets = []193foreign-assets = []192preimage = []194pallet-test-utils = []193pallet-test-utils = []195preimage = []194refungible = []196refungible = []195scheduler = []197scheduler = []196198216orml-tokens = { workspace = true }218orml-tokens = { workspace = true }217orml-traits = { workspace = true }219orml-traits = { workspace = true }218orml-vesting = { workspace = true }220orml-vesting = { workspace = true }219orml-xtokens = { workspace = true }221orml-xcm-support = { workspace = true }220orml-xcm-support = { workspace = true }222orml-xtokens = { workspace = true }221pallet-aura = { workspace = true }223pallet-aura = { workspace = true }222pallet-authorship = { workspace = true }224pallet-authorship = { workspace = true }223pallet-balances = { features = ["insecure_zero_ed"], workspace = true }225pallet-balances = { features = ["insecure_zero_ed"], workspace = true }258log = { workspace = true }260log = { workspace = true }259num_enum = { workspace = true }261num_enum = { workspace = true }260pallet-app-promotion = { workspace = true }262pallet-app-promotion = { workspace = true }263pallet-balances-adapter = { workspace = true }261pallet-base-fee = { workspace = true }264pallet-base-fee = { workspace = true }262pallet-charge-transaction = { workspace = true }265pallet-charge-transaction = { workspace = true }263pallet-collator-selection = { workspace = true }266pallet-collator-selection = { workspace = true }291################################################################################294################################################################################292# Optional dependencies295# Optional dependencies293296297frame-benchmarking = { workspace = true, optional = true }294frame-system-benchmarking = { workspace = true, optional = true}298frame-system-benchmarking = { workspace = true, optional = true }295frame-benchmarking = { workspace = true, optional = true }296frame-try-runtime = { workspace = true, optional = true }299frame-try-runtime = { workspace = true, optional = true }300hex-literal = { workspace = true, optional = true }297serde = { workspace = true, optional = true }301serde = { workspace = true, optional = true }298hex-literal = { workspace = true, optional = true }299302300################################################################################303################################################################################301# Test dependencies304# Test dependenciesruntime/opal/src/lib.rsdiffbeforeafterboth454546pub const RUNTIME_NAME: &str = "opal";46pub const RUNTIME_NAME: &str = "opal";47pub const TOKEN_SYMBOL: &str = "OPL";47pub const TOKEN_SYMBOL: &str = "OPL";48pub const DECIMALS: u8 = 18;484949/// This runtime version.50/// This runtime version.50pub const VERSION: RuntimeVersion = RuntimeVersion {51pub const VERSION: RuntimeVersion = RuntimeVersion {runtime/quartz/Cargo.tomldiffbeforeafterboth22pov-estimate = []22pov-estimate = []23quartz-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'preimage', 'refungible']23quartz-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'preimage', 'refungible']24runtime-benchmarks = [24runtime-benchmarks = [25 "pallet-preimage/runtime-benchmarks",25 'cumulus-pallet-parachain-system/runtime-benchmarks',26 'cumulus-pallet-parachain-system/runtime-benchmarks',26 'frame-benchmarking',27 'frame-benchmarking',27 'frame-support/runtime-benchmarks',28 'frame-support/runtime-benchmarks',42 'pallet-inflation/runtime-benchmarks',43 'pallet-inflation/runtime-benchmarks',43 'pallet-maintenance/runtime-benchmarks',44 'pallet-maintenance/runtime-benchmarks',44 'pallet-nonfungible/runtime-benchmarks',45 'pallet-nonfungible/runtime-benchmarks',45 "pallet-preimage/runtime-benchmarks",46 'pallet-refungible/runtime-benchmarks',46 'pallet-refungible/runtime-benchmarks',47 'pallet-structure/runtime-benchmarks',47 'pallet-structure/runtime-benchmarks',48 'pallet-timestamp/runtime-benchmarks',48 'pallet-timestamp/runtime-benchmarks',66 'frame-try-runtime/std',66 'frame-try-runtime/std',67 'pallet-aura/std',67 'pallet-aura/std',68 'pallet-balances/std',68 'pallet-balances/std',69 'pallet-balances-adapter/std',69 # 'pallet-contracts/std',70 # 'pallet-contracts/std',70 # 'pallet-contracts-primitives/std',71 # 'pallet-contracts-primitives/std',71 # 'pallet-contracts-rpc-runtime-api/std',72 # 'pallet-contracts-rpc-runtime-api/std',72 # 'pallet-contract-helpers/std',73 # 'pallet-contract-helpers/std',73 "pallet-preimage/std",74 "pallet-authorship/std",74 "pallet-authorship/std",75 "pallet-identity/std",75 "pallet-identity/std",76 "pallet-preimage/std",76 "pallet-session/std",77 "pallet-session/std",77 "sp-consensus-aura/std",78 "sp-consensus-aura/std",78 'app-promotion-rpc/std',79 'app-promotion-rpc/std',127 "orml-tokens/std",128 "orml-tokens/std",128 "orml-traits/std",129 "orml-traits/std",129 "orml-vesting/std",130 "orml-vesting/std",131 "orml-xcm-support/std",130 "orml-xtokens/std",132 "orml-xtokens/std",131 "orml-xcm-support/std",132 "pallet-foreign-assets/std",133 "pallet-foreign-assets/std",133 "pallet-maintenance/std",134 "pallet-maintenance/std",134]135]135try-runtime = [136try-runtime = [136 "pallet-authorship/try-runtime",137 "pallet-authorship/try-runtime",137 "pallet-collator-selection/try-runtime",138 "pallet-collator-selection/try-runtime",138 "pallet-identity/try-runtime",139 "pallet-identity/try-runtime",140 "pallet-preimage/try-runtime",139 "pallet-session/try-runtime",141 "pallet-session/try-runtime",140 "pallet-preimage/try-runtime",141 'cumulus-pallet-aura-ext/try-runtime',142 'cumulus-pallet-aura-ext/try-runtime',142 'cumulus-pallet-dmp-queue/try-runtime',143 'cumulus-pallet-dmp-queue/try-runtime',143 'cumulus-pallet-parachain-system/try-runtime',144 'cumulus-pallet-parachain-system/try-runtime',154 'pallet-app-promotion/try-runtime',155 'pallet-app-promotion/try-runtime',155 'pallet-aura/try-runtime',156 'pallet-aura/try-runtime',156 'pallet-balances/try-runtime',157 'pallet-balances/try-runtime',158 'pallet-balances-adapter/try-runtime',157 'pallet-charge-transaction/try-runtime',159 'pallet-charge-transaction/try-runtime',158 'pallet-common/try-runtime',160 'pallet-common/try-runtime',159 'pallet-configuration/try-runtime',161 'pallet-configuration/try-runtime',208orml-tokens = { workspace = true }210orml-tokens = { workspace = true }209orml-traits = { workspace = true }211orml-traits = { workspace = true }210orml-vesting = { workspace = true }212orml-vesting = { workspace = true }211orml-xtokens = { workspace = true }213orml-xcm-support = { workspace = true }212orml-xcm-support = { workspace = true }214orml-xtokens = { workspace = true }213pallet-aura = { workspace = true }215pallet-aura = { workspace = true }214pallet-authorship = { workspace = true }216pallet-authorship = { workspace = true }215pallet-balances = { features = ["insecure_zero_ed"], workspace = true }217pallet-balances = { features = ["insecure_zero_ed"], workspace = true }246fp-evm = { workspace = true }248fp-evm = { workspace = true }247log = { workspace = true }249log = { workspace = true }248pallet-app-promotion = { workspace = true }250pallet-app-promotion = { workspace = true }251pallet-balances-adapter = { workspace = true }249pallet-collator-selection = { workspace = true }252pallet-collator-selection = { workspace = true }250pallet-common = { workspace = true }253pallet-common = { workspace = true }251pallet-configuration = { workspace = true }254pallet-configuration = { workspace = true }283################################################################################286################################################################################284# Optional dependencies287# Optional dependencies285288289frame-benchmarking = { workspace = true, optional = true }286frame-system-benchmarking = { workspace = true, optional = true }290frame-system-benchmarking = { workspace = true, optional = true }287frame-benchmarking = { workspace = true, optional = true }288frame-try-runtime = { workspace = true, optional = true }291frame-try-runtime = { workspace = true, optional = true }292hex-literal = { workspace = true, optional = true }289serde = { workspace = true, optional = true }293serde = { workspace = true, optional = true }290hex-literal = { workspace = true, optional = true }291294292295293################################################################################296################################################################################runtime/quartz/src/lib.rsdiffbeforeafterboth48#[cfg(not(feature = "become-sapphire"))]48#[cfg(not(feature = "become-sapphire"))]49pub const RUNTIME_NAME: &str = "quartz";49pub const RUNTIME_NAME: &str = "quartz";50pub const TOKEN_SYMBOL: &str = "QTZ";50pub const TOKEN_SYMBOL: &str = "QTZ";51pub const DECIMALS: u8 = 18;515252/// This runtime version.53/// This runtime version.53pub const VERSION: RuntimeVersion = RuntimeVersion {54pub const VERSION: RuntimeVersion = RuntimeVersion {runtime/tests/Cargo.tomldiffbeforeafterboth26pallet-ethereum = { workspace = true }26pallet-ethereum = { workspace = true }27pallet-evm = { workspace = true }27pallet-evm = { workspace = true }282829pallet-balances-adapter = { workspace = true }29pallet-common = { workspace = true }30pallet-common = { workspace = true }30pallet-fungible = { workspace = true }31pallet-fungible = { workspace = true }31pallet-nonfungible = { workspace = true }32pallet-nonfungible = { workspace = true }41evm-coder = { workspace = true }42evm-coder = { workspace = true }42up-sponsorship = { workspace = true }43up-sponsorship = { workspace = true }43xcm = { workspace = true }44xcm = { workspace = true }44pallet-xcm = { workspace = true }45pallet-configuration = { workspace = true }4645runtime/tests/src/lib.rsdiffbeforeafterboth19use sp_core::{H160, H256, U256};19use sp_core::{H160, H256, U256};20use frame_support::{20use frame_support::{21 parameter_types,21 parameter_types,22 traits::{Everything, ConstU32, ConstU64},22 traits::{Everything, ConstU32, ConstU64, Currency},23 weights::IdentityFee,23 weights::IdentityFee,24 pallet_prelude::Weight,24 pallet_prelude::Weight,25};25};266impl pallet_nonfungible::Config for Test {266impl pallet_nonfungible::Config for Test {267 type WeightInfo = ();267 type WeightInfo = ();268}268}269parameter_types! {270 pub const Decimals: u8 = 18;271 pub Name: String = "Test".to_string();272 pub Symbol: String = "TST".to_string();273}274impl pallet_balances_adapter::Config for Test {275 type Currency = Balances;276 type CurrencyBalance = <Balances as Currency<Self::AccountId>>::Balance;277 type Decimals = Decimals;278 type Name = Name;279 type Symbol = Symbol;280 type WeightInfo = ();281}269282270parameter_types! {283parameter_types! {271 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f284 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54fruntime/unique/Cargo.tomldiffbeforeafterboth20limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']20limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']21pov-estimate = []21pov-estimate = []22runtime-benchmarks = [22runtime-benchmarks = [23 "pallet-preimage/runtime-benchmarks",23 'frame-benchmarking',24 'frame-benchmarking',24 'frame-support/runtime-benchmarks',25 'frame-support/runtime-benchmarks',25 'frame-system-benchmarking',26 'frame-system-benchmarking',39 'pallet-inflation/runtime-benchmarks',40 'pallet-inflation/runtime-benchmarks',40 'pallet-maintenance/runtime-benchmarks',41 'pallet-maintenance/runtime-benchmarks',41 'pallet-nonfungible/runtime-benchmarks',42 'pallet-nonfungible/runtime-benchmarks',42 "pallet-preimage/runtime-benchmarks",43 'pallet-refungible/runtime-benchmarks',43 'pallet-refungible/runtime-benchmarks',44 'pallet-structure/runtime-benchmarks',44 'pallet-structure/runtime-benchmarks',45 'pallet-timestamp/runtime-benchmarks',45 'pallet-timestamp/runtime-benchmarks',68 # 'pallet-contracts-primitives/std',68 # 'pallet-contracts-primitives/std',69 # 'pallet-contracts-rpc-runtime-api/std',69 # 'pallet-contracts-rpc-runtime-api/std',70 # 'pallet-contract-helpers/std',70 # 'pallet-contract-helpers/std',71 "pallet-preimage/std",72 "pallet-authorship/std",71 "pallet-authorship/std",73 "pallet-identity/std",72 "pallet-identity/std",73 "pallet-preimage/std",74 "pallet-session/std",74 "pallet-session/std",75 "sp-consensus-aura/std",75 "sp-consensus-aura/std",76 'app-promotion-rpc/std',76 'app-promotion-rpc/std',77 'evm-coder/std',77 'evm-coder/std',78 'fp-rpc/std',78 'fp-rpc/std',79 'fp-self-contained/std',79 'fp-self-contained/std',80 'pallet-app-promotion/std',80 'pallet-app-promotion/std',81 'pallet-balances-adapter/std',81 'pallet-base-fee/std',82 'pallet-base-fee/std',82 'pallet-charge-transaction/std',83 'pallet-charge-transaction/std',83 'pallet-collator-selection/std',84 'pallet-collator-selection/std',124 "orml-tokens/std",125 "orml-tokens/std",125 "orml-traits/std",126 "orml-traits/std",126 "orml-vesting/std",127 "orml-vesting/std",128 "orml-xcm-support/std",127 "orml-xtokens/std",129 "orml-xtokens/std",128 "orml-xcm-support/std",129 "pallet-foreign-assets/std",130 "pallet-foreign-assets/std",130 "pallet-maintenance/std",131 "pallet-maintenance/std",131]132]134 "pallet-authorship/try-runtime",135 "pallet-authorship/try-runtime",135 "pallet-collator-selection/try-runtime",136 "pallet-collator-selection/try-runtime",136 "pallet-identity/try-runtime",137 "pallet-identity/try-runtime",138 "pallet-preimage/try-runtime",137 "pallet-session/try-runtime",139 "pallet-session/try-runtime",138 "pallet-preimage/try-runtime",139 'cumulus-pallet-aura-ext/try-runtime',140 'cumulus-pallet-aura-ext/try-runtime',140 'cumulus-pallet-dmp-queue/try-runtime',141 'cumulus-pallet-dmp-queue/try-runtime',141 'cumulus-pallet-parachain-system/try-runtime',142 'cumulus-pallet-parachain-system/try-runtime',152 'pallet-app-promotion/try-runtime',153 'pallet-app-promotion/try-runtime',153 'pallet-aura/try-runtime',154 'pallet-aura/try-runtime',154 'pallet-balances/try-runtime',155 'pallet-balances/try-runtime',156 'pallet-balances-adapter/try-runtime',155 'pallet-charge-transaction/try-runtime',157 'pallet-charge-transaction/try-runtime',156 'pallet-common/try-runtime',158 'pallet-common/try-runtime',157 'pallet-configuration/try-runtime',159 'pallet-configuration/try-runtime',207orml-tokens = { workspace = true }209orml-tokens = { workspace = true }208orml-traits = { workspace = true }210orml-traits = { workspace = true }209orml-vesting = { workspace = true }211orml-vesting = { workspace = true }210orml-xtokens = { workspace = true }212orml-xcm-support = { workspace = true }211orml-xcm-support = { workspace = true }213orml-xtokens = { workspace = true }212pallet-aura = { workspace = true }214pallet-aura = { workspace = true }213pallet-authorship = { workspace = true }215pallet-authorship = { workspace = true }214pallet-balances = { features = ["insecure_zero_ed"], workspace = true }216pallet-balances = { features = ["insecure_zero_ed"], workspace = true }244derivative = { workspace = true }246derivative = { workspace = true }245log = { workspace = true }247log = { workspace = true }246pallet-app-promotion = { workspace = true }248pallet-app-promotion = { workspace = true }249pallet-balances-adapter = { workspace = true }247pallet-collator-selection = { workspace = true }250pallet-collator-selection = { workspace = true }248pallet-common = { workspace = true }251pallet-common = { workspace = true }249pallet-configuration = { workspace = true }252pallet-configuration = { workspace = true }282################################################################################285################################################################################283# Optional dependencies286# Optional dependencies284287288frame-benchmarking = { workspace = true, optional = true }285frame-system-benchmarking = { workspace = true, optional = true }289frame-system-benchmarking = { workspace = true, optional = true }286frame-benchmarking = { workspace = true, optional = true }287frame-try-runtime = { workspace = true, optional = true }290frame-try-runtime = { workspace = true, optional = true }291hex-literal = { workspace = true, optional = true }288serde = { workspace = true, optional = true }292serde = { workspace = true, optional = true }289hex-literal = { workspace = true, optional = true }290293291################################################################################294################################################################################292# Test dependencies295# Test dependenciesruntime/unique/src/lib.rsdiffbeforeafterboth454546pub const RUNTIME_NAME: &str = "unique";46pub const RUNTIME_NAME: &str = "unique";47pub const TOKEN_SYMBOL: &str = "UNQ";47pub const TOKEN_SYMBOL: &str = "UNQ";48pub const DECIMALS: u8 = 18;484949/// This runtime version.50/// This runtime version.50pub const VERSION: RuntimeVersion = RuntimeVersion {51pub const VERSION: RuntimeVersion = RuntimeVersion {tests/.eslintrc.jsondiffbeforeafterboth86 "array-bracket-spacing": "warn",86 "array-bracket-spacing": "warn",87 "template-curly-spacing": "warn",87 "template-curly-spacing": "warn",88 "space-in-parens": "warn",88 "space-in-parens": "warn",89 "arrow-body-style": ["warn", "as-needed"],90 "no-restricted-syntax": [91 "warn",92 {93 "message": "toHuman results in horrible, hard to debug conversions with no stability guarantees, use Codec/at least .toJson instead",94 "selector": "MemberExpression > Identifier[name=\"toHuman\"]"95 }96 ],89 "@typescript-eslint/naming-convention": [97 "@typescript-eslint/naming-convention": [90 "warn",98 "warn",91 {99 {tests/package.jsondiffbeforeafterboth39 "testParallelFull": "yarn testParallel && yarn testSequential",39 "testParallelFull": "yarn testParallel && yarn testSequential",40 "testParallel": "yarn _testParallel './src/**/*.test.ts'",40 "testParallel": "yarn _testParallel './src/**/*.test.ts'",41 "testSequential": "yarn _test './src/**/*.seqtest.ts'",41 "testSequential": "yarn _test './src/**/*.seqtest.ts'",42 "testStructure": "yarn setup && yarn _test ./**/nesting/*.*test.ts",42 "testStructure": "yarn _test ./**/nesting/*.*test.ts",43 "testEth": "yarn setup && yarn _test './**/eth/**/*.*test.ts'",43 "testEth": "yarn _test './**/eth/**/*.*test.ts'",44 "testEthNesting": "yarn setup && yarn _test './**/eth/nesting/**/*.*test.ts'",44 "testEthNesting": "yarn _test './**/eth/nesting/**/*.*test.ts'",45 "testEthFractionalizer": "yarn setup && yarn _test './**/eth/fractionalizer/**/*.*test.ts'",45 "testEthFractionalizer": "yarn _test './**/eth/fractionalizer/**/*.*test.ts'",46 "testEthMarketplace": "yarn setup && yarn _test './**/eth/marketplace/**/*.*test.ts'",46 "testEthMarketplace": "yarn _test './**/eth/marketplace/**/*.*test.ts'",47 "testSub": "yarn _test './**/sub/**/*.*test.ts'",48 "testSubNesting": "yarn _test './**/sub/nesting/**/*.*test.ts'",47 "testEvent": "yarn setup && yarn _test ./src/check-event/*.*test.ts",49 "testEvent": "yarn _test ./src/check-event/*.*test.ts",48 "testEthPayable": "yarn _test './**/eth/payable.test.ts'",50 "testEthPayable": "yarn _test './**/eth/payable.test.ts'",49 "testEvmCoder": "yarn _test './**/eth/evmCoder.test.ts'",51 "testEvmCoder": "yarn _test './**/eth/evmCoder.test.ts'",50 "testNesting": "yarn _test ./**/nest.test.ts",52 "testNesting": "yarn _test ./**/nest.test.ts",tests/src/addCollectionAdmin.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itSub, usingPlaygrounds, expect} from './util';18import {itSub, usingPlaygrounds, expect} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {21describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {21 let donor: IKeyringPair;22 let donor: IKeyringPair;828383 itSub("Can't add collection admin of not existing collection.", async ({helper}) => {84 itSub("Can't add collection admin of not existing collection.", async ({helper}) => {84 const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);85 const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);85 const collectionId = (1 << 32) - 1;86 const collectionId = NON_EXISTENT_COLLECTION_ID;868787 await expect(helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address})).to.be.rejectedWith(/common\.CollectionNotFound/);88 await expect(helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address})).to.be.rejectedWith(/common\.CollectionNotFound/);8889tests/src/allowLists.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {usingPlaygrounds, expect, itSub} from './util';18import {usingPlaygrounds, expect, itSub} from './util';19import {ICollectionPermissions} from './util/playgrounds/types';19import {ICollectionPermissions, NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';202021describe('Integration Test ext. Allow list tests', () => {21describe('Integration Test ext. Allow list tests', () => {22 let alice: IKeyringPair;22 let alice: IKeyringPair;606061 describe('Negative', () => {61 describe('Negative', () => {62 itSub('Nobody can add address to allow list of non-existing collection', async ({helper}) => {62 itSub('Nobody can add address to allow list of non-existing collection', async ({helper}) => {63 const collectionId = (1<<32) - 1;63 const collectionId = NON_EXISTENT_COLLECTION_ID;64 await expect(helper.nft.addToAllowList(bob, collectionId, {Substrate: charlie.address}))64 await expect(helper.nft.addToAllowList(bob, collectionId, {Substrate: charlie.address}))65 .to.be.rejectedWith(/common\.CollectionNotFound/);65 .to.be.rejectedWith(/common\.CollectionNotFound/);66 });66 });140 });140 });141141142 itSub('Nobody can remove address from allow list of non-existing collection', async ({helper}) => {142 itSub('Nobody can remove address from allow list of non-existing collection', async ({helper}) => {143 const collectionId = (1<<32) - 1;143 const collectionId = NON_EXISTENT_COLLECTION_ID;144 await expect(helper.collection.removeFromAllowList(bob, collectionId, {Substrate: charlie.address}))144 await expect(helper.collection.removeFromAllowList(bob, collectionId, {Substrate: charlie.address}))145 .to.be.rejectedWith(/common\.CollectionNotFound/);145 .to.be.rejectedWith(/common\.CollectionNotFound/);146 });146 });tests/src/benchmarks/utils/common.tsdiffbeforeafterbothno syntactic changes
tests/src/change-collection-owner.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {usingPlaygrounds, expect, itSub} from './util';18import {usingPlaygrounds, expect, itSub} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020describe('Integration Test changeCollectionOwner(collection_id, new_owner):', () => {21describe('Integration Test changeCollectionOwner(collection_id, new_owner):', () => {21 let alice: IKeyringPair;22 let alice: IKeyringPair;127 });128 });128129129 itSub('Can\'t change owner of a non-existing collection.', async ({helper}) => {130 itSub('Can\'t change owner of a non-existing collection.', async ({helper}) => {130 const collectionId = (1 << 32) - 1;131 const collectionId = NON_EXISTENT_COLLECTION_ID;131 const changeOwnerTx = () => helper.collection.changeOwner(bob, collectionId, bob.address);132 const changeOwnerTx = () => helper.collection.changeOwner(bob, collectionId, bob.address);132 await expect(changeOwnerTx()).to.be.rejectedWith(/common\.CollectionNotFound/);133 await expect(changeOwnerTx()).to.be.rejectedWith(/common\.CollectionNotFound/);133 });134 });tests/src/confirmSponsorship.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {usingPlaygrounds, expect, itSub, Pallets} from './util';18import {usingPlaygrounds, expect, itSub, Pallets} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020async function setSponsorHelper(collection: any, signer: IKeyringPair, sponsorAddress: string) {21async function setSponsorHelper(collection: any, signer: IKeyringPair, sponsorAddress: string) {21 await collection.setSponsor(signer, sponsorAddress);22 await collection.setSponsor(signer, sponsorAddress);198 });199 });199200200 itSub('(!negative test!) Confirm sponsorship for a collection that never existed', async ({helper}) => {201 itSub('(!negative test!) Confirm sponsorship for a collection that never existed', async ({helper}) => {201 const collectionId = (1 << 32) - 1;202 const collectionId = NON_EXISTENT_COLLECTION_ID;202 const confirmSponsorshipTx = () => helper.collection.confirmSponsorship(bob, collectionId);203 const confirmSponsorshipTx = () => helper.collection.confirmSponsorship(bob, collectionId);203 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.CollectionNotFound/);204 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.CollectionNotFound/);204 });205 });tests/src/creditFeesToTreasury.seqtest.tsdiffbeforeafterboth88 expect(treasuryIncrease).to.be.equal(fee);88 expect(treasuryIncrease).to.be.equal(fee);89 });89 });909091 itSub.only('Treasury balance increased by failed tx fee', async ({helper}) => {91 itSub('Treasury balance increased by failed tx fee', async ({helper}) => {92 const api = helper.getApi();92 const api = helper.getApi();93 await helper.wait.newBlocks(1);93 await helper.wait.newBlocks(1);9494tests/src/eth/abi/nativeFungible.jsondiffbeforeafterbothno changes
tests/src/eth/api/UniqueNativeFungible.soldiffbeforeafterbothno changes
tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth18import {Pallets, requirePalletsOrSkip, usingPlaygrounds} from '../util/index';18import {Pallets, requirePalletsOrSkip, usingPlaygrounds} from '../util/index';19import {itEth, expect} from './util';19import {itEth, expect} from './util';202021describe.only('evm nft collection sponsoring', () => {21describe('evm nft collection sponsoring', () => {22 let donor: IKeyringPair;22 let donor: IKeyringPair;23 let alice: IKeyringPair;23 let alice: IKeyringPair;24 let nominal: bigint;24 let nominal: bigint;319 });319 });320});320});321321322describe.only('evm RFT collection sponsoring', () => {322describe('evm RFT collection sponsoring', () => {323 let donor: IKeyringPair;323 let donor: IKeyringPair;324 let alice: IKeyringPair;324 let alice: IKeyringPair;325 let nominal: bigint;325 let nominal: bigint;tests/src/eth/createFTCollection.seqtest.tsdiffbeforeafterboth202021const DECIMALS = 18;21const DECIMALS = 18;222223describe.only('Create FT collection from EVM', () => {23describe('Create FT collection from EVM', () => {24 let donor: IKeyringPair;24 let donor: IKeyringPair;252526 before(async function() {26 before(async function() {tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth222223const DECIMALS = 18;23const DECIMALS = 18;242425describe.only('Create FT collection from EVM', () => {25describe('Create FT collection from EVM', () => {26 let donor: IKeyringPair;26 let donor: IKeyringPair;272728 before(async function() {28 before(async function() {129 });129 });130});130});131131132describe.only('(!negative tests!) Create FT collection from EVM', () => {132describe('(!negative tests!) Create FT collection from EVM', () => {133 let donor: IKeyringPair;133 let donor: IKeyringPair;134 let nominal: bigint;134 let nominal: bigint;135135tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth21import {COLLECTION_HELPER} from '../util';21import {COLLECTION_HELPER} from '../util';2222232324describe.only('Create NFT collection from EVM', () => {24describe('Create NFT collection from EVM', () => {25 let donor: IKeyringPair;25 let donor: IKeyringPair;262627 before(async function () {27 before(async function () {143 });143 });144});144});145145146describe.only('(!negative tests!) Create NFT collection from EVM', () => {146describe('(!negative tests!) Create NFT collection from EVM', () => {147 let donor: IKeyringPair;147 let donor: IKeyringPair;148 let nominal: bigint;148 let nominal: bigint;149149tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth21import {CollectionLimitField} from './util/playgrounds/types';21import {CollectionLimitField} from './util/playgrounds/types';2222232324describe.only('Create RFT collection from EVM', () => {24describe('Create RFT collection from EVM', () => {25 let donor: IKeyringPair;25 let donor: IKeyringPair;262627 before(async function() {27 before(async function() {154 });154 });155});155});156156157describe.only('(!negative tests!) Create RFT collection from EVM', () => {157describe('(!negative tests!) Create RFT collection from EVM', () => {158 let donor: IKeyringPair;158 let donor: IKeyringPair;159 let nominal: bigint;159 let nominal: bigint;160160tests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterboth80};80};8181828283describe.only('Fractionalizer contract usage', () => {83describe('Fractionalizer contract usage', () => {84 let donor: IKeyringPair;84 let donor: IKeyringPair;858586 before(async function() {86 before(async function() {tests/src/eth/nativeFungible.test.tsdiffbeforeafterbothno changes
tests/src/eth/nativeRpc/estimateGas.test.tsdiffbeforeafterbothno changes
tests/src/eth/nesting/nest.test.tsdiffbeforeafterboth188 });188 });189 });189 });190191 describe('Fungible', () => {192 async function createFungibleCollection(helper: EthUniqueHelper, owner: string, mode: 'ft' | 'native ft') {193 if (mode === 'ft') {194 const {collectionAddress} = await helper.eth.createFungibleCollection(owner, '', 18, '', '');195 const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner);196 await contract.methods.mint(owner, 100n).send({from: owner});197 return {collectionAddress, contract};198 }199200 // native ft201 const collectionAddress = helper.ethAddress.fromCollectionId(0);202 const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner);203 return {collectionAddress, contract};204 }205206 [207 {mode: 'ft' as const},208 {mode: 'native ft' as const},209 ].map(testCase => {210 itEth(`Allow nest [${testCase.mode}]`, async ({helper}) => {211 const owner = await helper.eth.createAccountWithBalance(donor);212 const {collectionId: targetCollectionId, contract: targetContract} = await createNestingCollection(helper, owner);213 const {contract: ftContract} = await createFungibleCollection(helper, owner, testCase.mode);214215 const mintingTargetTokenIdResult = await targetContract.methods.mint(owner).send({from: owner});216 const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;217 const targetTokenAddress = helper.ethAddress.fromTokenId(targetCollectionId, targetTokenId);218219 await ftContract.methods.transfer(targetTokenAddress, 10n).send({from: owner});220 expect(await ftContract.methods.balanceOf(targetTokenAddress).call({from: owner})).to.be.equal('10');221 });222 });223224 [225 {mode: 'ft' as const},226 {mode: 'native ft' as const},227 ].map(testCase => {228 itEth(`Allow partial/full unnest [${testCase.mode}]`, async ({helper}) => {229 const owner = await helper.eth.createAccountWithBalance(donor);230 const {collectionId: targetCollectionId, contract: targetContract} = await createNestingCollection(helper, owner);231 const {contract: ftContract} = await createFungibleCollection(helper, owner, testCase.mode);232233 const mintingTargetTokenIdResult = await targetContract.methods.mint(owner).send({from: owner});234 const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;235 const targetTokenAddress = helper.ethAddress.fromTokenId(targetCollectionId, targetTokenId);236237 await ftContract.methods.transfer(targetTokenAddress, 10n).send({from: owner});238239 await ftContract.methods.transferFrom(targetTokenAddress, owner, 5n).send({from: owner});240 expect(await ftContract.methods.balanceOf(targetTokenAddress).call({from: owner})).to.be.equal('5');241242 await ftContract.methods.transferFrom(targetTokenAddress, owner, 5n).send({from: owner});243 expect(await ftContract.methods.balanceOf(targetTokenAddress).call({from: owner})).to.be.equal('0');244 });245 });246247 [248 {mode: 'ft' as const},249 {mode: 'native ft' as const},250 ].map(testCase => {251 itEth(`Disallow nest into collection without nesting permission [${testCase.mode}] (except for native fungible collection)`, async ({helper}) => {252 const owner = await helper.eth.createAccountWithBalance(donor);253 const {collectionId: targetCollectionId, contract: targetContract} = await createNestingCollection(helper, owner);254 await targetContract.methods.setCollectionNesting(false).send({from: owner});255256 const {contract: ftContract} = await createFungibleCollection(helper, owner, testCase.mode);257258 const mintingTargetTokenIdResult = await targetContract.methods.mint(owner).send({from: owner});259 const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;260 const targetTokenAddress = helper.ethAddress.fromTokenId(targetCollectionId, targetTokenId);261262 if (testCase.mode === 'ft') {263 await expect(ftContract.methods.transfer(targetTokenAddress, 10n).call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');264 } else {265 await expect(ftContract.methods.transfer(targetTokenAddress, 10n).call({from: owner})).to.be.not.rejected;266 }267 });268 });269 });190});270});191271tests/src/eth/nonFungible.test.tsdiffbeforeafterboth929 });929 });930 });930 });931931932 itEth.only('Returns collection name', async ({helper}) => {932 itEth('Returns collection name', async ({helper}) => {933 // FIXME: should not have balance to use .call()933 // FIXME: should not have balance to use .call()934 const caller = await helper.eth.createAccountWithBalance(donor);934 const caller = await helper.eth.createAccountWithBalance(donor);935 const tokenPropertyPermissions = [{935 const tokenPropertyPermissions = [{tests/src/eth/payable.test.tsdiffbeforeafterboth41 expect(await contract.methods.getCollected().call()).to.be.equal('10000');41 expect(await contract.methods.getCollected().call()).to.be.equal('10000');42 });42 });434344 itEth.only('Evm contract can receive wei from substrate account', async ({helper}) => {44 itEth('Evm contract can receive wei from substrate account', async ({helper}) => {45 const deployer = await helper.eth.createAccountWithBalance(donor);45 const deployer = await helper.eth.createAccountWithBalance(donor);46 const contract = await helper.eth.deployCollectorContract(deployer);46 const contract = await helper.eth.deployCollectorContract(deployer);47 const [alice] = await helper.arrange.createAccounts([40n], donor);47 const [alice] = await helper.arrange.createAccounts([40n], donor);tests/src/eth/reFungible.test.tsdiffbeforeafterboth679 });679 });680 });680 });681681682 itEth.only('Returns collection name', async ({helper}) => {682 itEth('Returns collection name', async ({helper}) => {683 // FIXME: should not have balance to use .call()683 // FIXME: should not have balance to use .call()684 const caller = await helper.eth.createAccountWithBalance(alice);684 const caller = await helper.eth.createAccountWithBalance(alice);685 const tokenPropertyPermissions = [{685 const tokenPropertyPermissions = [{tests/src/eth/tokenProperties.test.tsdiffbeforeafterboth314 expect(result.length).to.equal(0);314 expect(result.length).to.equal(0);315 }));315 }));316316317 itEth.only('Can be read', async({helper}) => {317 itEth('Can be read', async({helper}) => {318 // FIXME: User with no balance should be able to call318 // FIXME: User with no balance should be able to call319 const caller = await helper.eth.createAccountWithBalance(alice);319 const caller = await helper.eth.createAccountWithBalance(alice);320 const collection = await helper.nft.mintCollection(alice, {320 const collection = await helper.nft.mintCollection(alice, {tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth222223// Native contracts ABI23// Native contracts ABI24import collectionHelpersAbi from '../../abi/collectionHelpers.json' assert {type: 'json'};24import collectionHelpersAbi from '../../abi/collectionHelpers.json' assert {type: 'json'};25import nativeFungibleAbi from '../../abi/nativeFungible.json' assert {type: 'json'};25import fungibleAbi from '../../abi/fungible.json' assert {type: 'json'};26import fungibleAbi from '../../abi/fungible.json' assert {type: 'json'};26import fungibleDeprecatedAbi from '../../abi/fungibleDeprecated.json' assert {type: 'json'};27import fungibleDeprecatedAbi from '../../abi/fungibleDeprecated.json' assert {type: 'json'};27import nonFungibleAbi from '../../abi/nonFungible.json' assert {type: 'json'};28import nonFungibleAbi from '../../abi/nonFungible.json' assert {type: 'json'};112 data: object,113 data: object,113 from: signer,114 from: signer,114 gas: gas ?? this.helper.eth.DEFAULT_GAS,115 gas: gas ?? this.helper.eth.DEFAULT_GAS,115 gasPrice: await this.getGasPrice(),116 });116 });117 return await contract.deploy({data: object}).send({from: signer});117 return await contract.deploy({data: object}).send({from: signer});118 }118 }121121122class NativeContractGroup extends EthGroupBase {122class NativeContractGroup extends EthGroupBase {123123124 async contractHelpers(caller: string): Promise<Contract> {124 contractHelpers(caller: string) {125 const web3 = this.helper.getWeb3();125 const web3 = this.helper.getWeb3();126 return new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), {126 return new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), {127 from: caller,127 from: caller,128 gas: this.helper.eth.DEFAULT_GAS,128 gas: this.helper.eth.DEFAULT_GAS,129 gasPrice: await this.getGasPrice(),130 });129 });131 }130 }132131133 async collectionHelpers(caller: string) {132 collectionHelpers(caller: string) {134 const web3 = this.helper.getWeb3();133 const web3 = this.helper.getWeb3();135 return new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), {134 return new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), {136 from: caller,135 from: caller,137 gas: this.helper.eth.DEFAULT_GAS,136 gas: this.helper.eth.DEFAULT_GAS,138 gasPrice: await this.getGasPrice(),139 });137 });140 }138 }141139142 async collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false) {140 collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false) {143 let abi = {141 let abi;142 if (address === this.helper.ethAddress.fromCollectionId(0)) {143 abi = nativeFungibleAbi;144 } else {145 abi ={144 'nft': nonFungibleAbi,146 'nft': nonFungibleAbi,145 'rft': refungibleAbi,147 'rft': refungibleAbi,146 'ft': fungibleAbi,148 'ft': fungibleAbi,147 }[mode];149 }[mode];150 }148 if (mergeDeprecated) {151 if (mergeDeprecated) {149 const deprecated = {152 const deprecated = {150 'nft': nonFungibleDeprecatedAbi,153 'nft': nonFungibleDeprecatedAbi,156 const web3 = this.helper.getWeb3();159 const web3 = this.helper.getWeb3();157 return new web3.eth.Contract(abi as any, address, {160 return new web3.eth.Contract(abi as any, address, {158 gas: this.helper.eth.DEFAULT_GAS,161 gas: this.helper.eth.DEFAULT_GAS,159 gasPrice: await this.getGasPrice(),160 ...(caller ? {from: caller} : {}),162 ...(caller ? {from: caller} : {}),161 });163 });162 }164 }165 return this.collection(this.helper.ethAddress.fromCollectionId(collectionId), mode, caller, mergeDeprecated);167 return this.collection(this.helper.ethAddress.fromCollectionId(collectionId), mode, caller, mergeDeprecated);166 }168 }167169168 async rftToken(address: string, caller?: string, mergeDeprecated = false) {170 rftToken(address: string, caller?: string, mergeDeprecated = false) {169 const web3 = this.helper.getWeb3();171 const web3 = this.helper.getWeb3();170 const abi = mergeDeprecated ? [...refungibleTokenAbi, ...refungibleTokenDeprecatedAbi] : refungibleTokenAbi;172 const abi = mergeDeprecated ? [...refungibleTokenAbi, ...refungibleTokenDeprecatedAbi] : refungibleTokenAbi;171 return new web3.eth.Contract(abi as any, address, {173 return new web3.eth.Contract(abi as any, address, {172 gas: this.helper.eth.DEFAULT_GAS,174 gas: this.helper.eth.DEFAULT_GAS,173 gasPrice: await this.getGasPrice(),174 ...(caller ? {from: caller} : {}),175 ...(caller ? {from: caller} : {}),175 });176 });176 }177 }210 async sendEVM(signer: IKeyringPair, contractAddress: string, abi: string, value: string, gasLimit?: number) {211 async sendEVM(signer: IKeyringPair, contractAddress: string, abi: string, value: string, gasLimit?: number) {211 if (!gasLimit) gasLimit = this.DEFAULT_GAS;212 if (!gasLimit) gasLimit = this.DEFAULT_GAS;212 const web3 = this.helper.getWeb3();213 const web3 = this.helper.getWeb3();214 // FIXME: can't send legacy transaction using tx.evm.call213 const gasPrice = await web3.eth.getGasPrice();215 const gasPrice = await web3.eth.getGasPrice();214 // TODO: check execution status216 // TODO: check execution status215 await this.helper.executeExtrinsic(217 await this.helper.executeExtrinsic(377class EthAddressGroup extends EthGroupBase {379class EthAddressGroup extends EthGroupBase {378 extractCollectionId(address: string): number {380 extractCollectionId(address: string): number {379 if (!(address.length === 42 || address.length === 40)) throw new Error('address wrong format');381 if (!(address.length === 42 || address.length === 40)) throw new Error('address wrong format');380 return parseInt(address.substr(address.length - 8), 16);382 return parseInt(address.slice(address.length - 8), 16);381 }383 }382384383 fromCollectionId(collectionId: number): string {385 fromCollectionId(collectionId: number): string {tests/src/maintenance.seqtest.tsdiffbeforeafterboth325 expect(await helper.preimage.getPreimageInfo(preimageHashes[0])).to.have.property('unrequested');325 expect(await helper.preimage.getPreimageInfo(preimageHashes[0])).to.have.property('unrequested');326 });326 });327327328 itSub.only('Does not allow execution of a preimage that would fail', async ({helper}) => {328 itSub('Does not allow execution of a preimage that would fail', async ({helper}) => {329 const [zeroAccount] = await helper.arrange.createAccounts([0n], superuser);329 const [zeroAccount] = await helper.arrange.createAccounts([0n], superuser);330330331 const preimage = helper.constructApiCall('api.tx.balances.forceTransfer', [331 const preimage = helper.constructApiCall('api.tx.balances.forceTransfer', [tests/src/nativeFungible.test.tsdiffbeforeafterbothno changes
tests/src/nesting/unnest.test.tsdiffbeforeafterboth47 await expect(nestedToken.getOwner()).to.be.rejected;47 await expect(nestedToken.getOwner()).to.be.rejected;48 });48 });4950 itSub('NativeFungible: allows the owner to successfully unnest a token', async ({helper}) => {51 const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});52 const targetToken = await collection.mintToken(alice);5354 const collectionFT = helper.ft.getCollectionObject(0);5556 // Nest57 await collectionFT.transfer(alice, targetToken.nestingAccount(), 10n);58 // Unnest59 await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;6061 expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(1n);62 });496350 itSub('Fungible: allows the owner to successfully unnest a token', async ({helper}) => {64 itSub('Fungible: allows the owner to successfully unnest a token', async ({helper}) => {51 const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});65 const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});tests/src/pallet-presence.test.tsdiffbeforeafterboth19// Pallets that must always be present19// Pallets that must always be present20const requiredPallets = [20const requiredPallets = [21 'balances',21 'balances',22 'balancesadapter',22 'common',23 'common',23 'timestamp',24 'timestamp',24 'transactionpayment',25 'transactionpayment',tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itSub, usingPlaygrounds, expect} from './util';18import {itSub, usingPlaygrounds, expect} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => {21describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => {21 let alice: IKeyringPair;22 let alice: IKeyringPair;68 });69 });697070 itSub('Can\'t remove collection admin from not existing collection', async ({helper}) => {71 itSub('Can\'t remove collection admin from not existing collection', async ({helper}) => {71 const collectionId = (1 << 32) - 1;72 const collectionId = NON_EXISTENT_COLLECTION_ID;727373 await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address}))74 await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address}))74 .to.be.rejectedWith(/common\.CollectionNotFound/);75 .to.be.rejectedWith(/common\.CollectionNotFound/);tests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itSub, usingPlaygrounds, expect} from './util';18import {itSub, usingPlaygrounds, expect} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020describe('integration test: ext. removeCollectionSponsor():', () => {21describe('integration test: ext. removeCollectionSponsor():', () => {21 let donor: IKeyringPair;22 let donor: IKeyringPair;91 });92 });929393 itSub('(!negative test!) Remove sponsor for a collection that never existed', async ({helper}) => {94 itSub('(!negative test!) Remove sponsor for a collection that never existed', async ({helper}) => {94 const collectionId = (1 << 32) - 1;95 const collectionId = NON_EXISTENT_COLLECTION_ID;95 await expect(helper.collection.removeSponsor(alice, collectionId)).to.be.rejectedWith(/common\.CollectionNotFound/);96 await expect(helper.collection.removeSponsor(alice, collectionId)).to.be.rejectedWith(/common\.CollectionNotFound/);96 });97 });9798tests/src/setCollectionLimits.test.tsdiffbeforeafterboth17// https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits17// https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {itSub, usingPlaygrounds, expect} from './util';19import {itSub, usingPlaygrounds, expect} from './util';20import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';202121const accountTokenOwnershipLimit = 0;22const accountTokenOwnershipLimit = 0;22const sponsoredDataSize = 0;23const sponsoredDataSize = 0;110 });111 });111112112 itSub('execute setCollectionLimits for not exists collection', async ({helper}) => {113 itSub('execute setCollectionLimits for not exists collection', async ({helper}) => {113 const nonExistentCollectionId = (1 << 32) - 1;114 const nonExistentCollectionId = NON_EXISTENT_COLLECTION_ID;114 await expect(helper.collection.setLimits(115 await expect(helper.collection.setLimits(115 alice,116 alice,116 nonExistentCollectionId,117 nonExistentCollectionId,tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itSub, usingPlaygrounds, expect, Pallets} from './util';18import {itSub, usingPlaygrounds, expect, Pallets} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020describe('integration test: ext. setCollectionSponsor():', () => {21describe('integration test: ext. setCollectionSponsor():', () => {21 let alice: IKeyringPair;22 let alice: IKeyringPair;105 });106 });106107107 itSub('(!negative test!) Add sponsor to a collection that never existed', async ({helper}) => {108 itSub('(!negative test!) Add sponsor to a collection that never existed', async ({helper}) => {108 const collectionId = (1 << 32) - 1;109 const collectionId = NON_EXISTENT_COLLECTION_ID;109 await expect(helper.collection.setSponsor(alice, collectionId, bob.address))110 await expect(helper.collection.setSponsor(alice, collectionId, bob.address))110 .to.be.rejectedWith(/common\.CollectionNotFound/);111 .to.be.rejectedWith(/common\.CollectionNotFound/);111 });112 });tests/src/setPermissions.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itSub, usingPlaygrounds, expect} from './util';18import {itSub, usingPlaygrounds, expect} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020describe('Integration Test: Set Permissions', () => {21describe('Integration Test: Set Permissions', () => {21 let alice: IKeyringPair;22 let alice: IKeyringPair;85 });86 });868787 itSub('fails on not existing collection', async ({helper}) => {88 itSub('fails on not existing collection', async ({helper}) => {88 const collectionId = (1 << 32) - 1;89 const collectionId = NON_EXISTENT_COLLECTION_ID;89 await expect(helper.collection.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: true}))90 await expect(helper.collection.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: true}))90 .to.be.rejectedWith(/common\.CollectionNotFound/);91 .to.be.rejectedWith(/common\.CollectionNotFound/);91 });92 });tests/src/sub/appPromotion/appPromotion.test.tsdiffbeforeafterboth157 await helper.staking.stake(staker, 1000n * nominal);157 await helper.staking.stake(staker, 1000n * nominal);158 await helper.staking.stake(staker, 199n * nominal);158 await helper.staking.stake(staker, 199n * nominal);159 // check balances159 // check balances160 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'ormlvest', amount: 200n * nominal, reasons: 'All'}, {id: 'appstake', amount: 1199n * nominal, reasons: 'All'}]);160 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'ormlvest', amount: 200n * nominal, reasons: 'All'}]);161 expect(await helper.balance.getFrozen(staker.address)).to.deep.eq([{id: 'appstakeappstake', amount: 1199n * nominal}]);161 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 1199n * nominal});162 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 1199n * nominal});162 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(1199n);163 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(1199n);163 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(1199n * nominal);164 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(1199n * nominal);453 const [_unstake1, unstake2] = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address});454 const [_unstake1, unstake2] = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address});454 await helper.wait.forParachainBlockNumber(unstake2.block);455 await helper.wait.forParachainBlockNumber(unstake2.block);455456456 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([]);457 expect(await helper.balance.getFrozen(staker.address)).to.deep.eq([]);457 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 0n});458 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 0n});458 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(999n);459 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(999n);459 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(0n);460 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(0n);tests/src/sub/nesting/admin.test.tsdiffbeforeafterboth17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {expect, itSub, usingPlaygrounds} from '../../util';18import {expect, itSub, usingPlaygrounds} from '../../util';191920describe('Collection admin', () => {20describe('Nesting by collection admin', () => {21 let alice: IKeyringPair;21 let alice: IKeyringPair;22 let bob: IKeyringPair;22 let bob: IKeyringPair;23 let charlie: IKeyringPair;23 let charlie: IKeyringPair;tests/src/sub/nesting/common.test.tsdiffbeforeafterboth21let alice: IKeyringPair;21let alice: IKeyringPair;22let bob: IKeyringPair;22let bob: IKeyringPair;232324before(async () => {24describe('Common nesting tests', () => {25 await usingPlaygrounds(async (helper, privateKey) => {25 before(async () => {26 const donor = await privateKey({url: import.meta.url});26 await usingPlaygrounds(async (helper, privateKey) => {27 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);27 const donor = await privateKey({url: import.meta.url});28 });28 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);29});29 });3030 });31[3132 {mode: 'nft' as const, restrictedMode: true, requiredPallets: []},32 [33 {mode: 'nft' as const, restrictedMode: false, requiredPallets: []},33 {mode: 'nft' as const, restrictedMode: true, requiredPallets: []},34 {mode: 'rft' as const, restrictedMode: true, requiredPallets: [Pallets.ReFungible]},34 {mode: 'nft' as const, restrictedMode: false, requiredPallets: []},35 {mode: 'rft' as const, restrictedMode: false, requiredPallets: [Pallets.ReFungible]},35 {mode: 'rft' as const, restrictedMode: true, requiredPallets: [Pallets.ReFungible]},36].map(testCase => {36 {mode: 'rft' as const, restrictedMode: false, requiredPallets: [Pallets.ReFungible]},37 itSub.ifWithPallets(`Token owner can nest ${testCase.mode.toUpperCase()} in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, testCase.requiredPallets, async ({helper}) => {37 ].map(testCase => {38 // Only NFT can be target for nesting in38 itSub.ifWithPallets(`Token owner can nest ${testCase.mode.toUpperCase()} in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, testCase.requiredPallets, async ({helper}) => {39 const targetNFTCollection = await helper.nft.mintCollection(alice);39 // Only NFT can be target for nesting in40 const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});40 const targetNFTCollection = await helper.nft.mintCollection(alice);4141 const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});42 const collectionForNesting = await helper[testCase.mode].mintCollection(bob);4243 // permissions should be set:43 const collectionForNesting = await helper[testCase.mode].mintCollection(bob);44 await targetNFTCollection.setPermissions(alice, {44 // permissions should be set:45 nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},45 await targetNFTCollection.setPermissions(alice, {46 });46 nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},4747 });48 // 1. Bob can immediately create nested token:4849 const nestedToken1 = testCase.mode === 'nft'49 // 1. Bob can immediately create nested token:50 ? await (collectionForNesting as UniqueNFTCollection).mintToken(bob, targetTokenBob.nestingAccount())50 const nestedToken1 = testCase.mode === 'nft'51 : await (collectionForNesting as UniqueRFTCollection).mintToken(bob, 10n, targetTokenBob.nestingAccount());51 ? await (collectionForNesting as UniqueNFTCollection).mintToken(bob, targetTokenBob.nestingAccount())52 expect(await nestedToken1.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});52 : await (collectionForNesting as UniqueRFTCollection).mintToken(bob, 10n, targetTokenBob.nestingAccount());53 expect(await nestedToken1.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());53 expect(await nestedToken1.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});5454 expect(await nestedToken1.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());55 // 2. Bob can mint and nest token:5556 const nestedToken2 = await collectionForNesting.mintToken(bob);56 // 2. Bob can mint and nest token:57 await nestedToken2.nest(bob, targetTokenBob);57 const nestedToken2 = await collectionForNesting.mintToken(bob);58 expect(await nestedToken2.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});58 await nestedToken2.nest(bob, targetTokenBob);59 expect(await nestedToken2.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());59 expect(await nestedToken2.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});60 });60 expect(await nestedToken2.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());61});61 });6262 });636364[6465 {restrictedMode: true},65 [66 {restrictedMode: false},66 {restrictedMode: true},67].map(testCase => {67 {restrictedMode: false},68 itSub(`Token owner can nest FT in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {68 ].map(testCase => {69 // Only NFT allows nesting, permissions should be set:69 itSub(`Token owner can nest FT in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {70 const targetNFTCollection = await helper.nft.mintCollection(alice);70 // Only NFT allows nesting, permissions should be set:71 const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});71 const targetNFTCollection = await helper.nft.mintCollection(alice);7272 const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});73 const collectionForNesting = await helper.ft.mintCollection(bob);7374 // permissions should be set:74 const collectionForNesting = await helper.ft.mintCollection(bob);75 await targetNFTCollection.setPermissions(alice, {75 // permissions should be set:76 nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},76 await targetNFTCollection.setPermissions(alice, {77 });77 nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},7878 });79 // 1. Alice can immediately create nested tokens:7980 await collectionForNesting.mint(bob, 100n, targetTokenBob.nestingAccount());80 // 1. Alice can immediately create nested tokens:81 expect(await collectionForNesting.getTop10Owners()).deep.eq([targetTokenBob.nestingAccount().toLowerCase()]);81 await collectionForNesting.mint(bob, 100n, targetTokenBob.nestingAccount());82 expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(100n);82 expect(await collectionForNesting.getTop10Owners()).deep.eq([targetTokenBob.nestingAccount().toLowerCase()]);8383 expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(100n);84 // 2. Alice can mint and nest token:8485 await collectionForNesting.mint(bob, 100n);85 // 2. Alice can mint and nest token:86 await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);86 await collectionForNesting.mint(bob, 100n);87 expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(150n);87 await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);88 });88 expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(150n);89});89 expect(await targetTokenBob.getChildren()).to.be.deep.equal([{collectionId: collectionForNesting.collectionId, tokenId: 0}]);90 });91 });9293 [94 {restrictedMode: true},95 {restrictedMode: false},96 ].map(testCase => {97 itSub(`Token owner can nest Native FT in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {98 // Only NFT allows nesting, permissions should be set:99 const targetNFTCollection = await helper.nft.mintCollection(alice);100 const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});101 expect(await targetTokenBob.getChildren()).to.be.empty;102103 const collectionForNesting = helper.ft.getCollectionObject(0);104 // permissions should be set:105 await targetNFTCollection.setPermissions(alice, {106 nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},107 });108109 // Bob can nest Native FT into their NFT:110 await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);111 expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(50n);112 // Native FT should't be visible in NFT children:113 expect(await targetTokenBob.getChildren()).to.be.deep.equal([]);114 });115 });901169111792itSub.ifWithPallets('Owner can unnest tokens using transferFrom', [Pallets.ReFungible], async ({helper}) => {118 itSub.ifWithPallets('Owner can unnest tokens using transferFrom', [Pallets.ReFungible], async ({helper}) => {98 const nftCollectionToBeNested = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});124 const nftCollectionToBeNested = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});99 const rftCollectionToBeNested = await helper.rft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});125 const rftCollectionToBeNested = await helper.rft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});100 const ftCollectionToBeNested = await helper.ft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});126 const ftCollectionToBeNested = await helper.ft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});127 const nativeFtCollectionToBeNested = helper.ft.getCollectionObject(0);101128102 const nestedNFT = await nftCollectionToBeNested.mintToken(alice, tokenA.nestingAccount());129 const nestedNFT = await nftCollectionToBeNested.mintToken(alice, tokenA.nestingAccount());103 const nestedRFT = await rftCollectionToBeNested.mintToken(alice, 100n, tokenA.nestingAccount());130 const nestedRFT = await rftCollectionToBeNested.mintToken(alice, 100n, tokenA.nestingAccount());104 const _nestedFT = await ftCollectionToBeNested.mint(alice, 100n, tokenA.nestingAccount());131 const _nestedFT = await ftCollectionToBeNested.mint(alice, 100n, tokenA.nestingAccount());132 await nativeFtCollectionToBeNested.transfer(alice, tokenA.nestingAccount(), 100n);105 expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());133 expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());106 expect(await nestedRFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());134 expect(await nestedRFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());107 expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(100n);135 expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(100n);136 expect(await nativeFtCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(100n);137138 expect(await tokenA.getChildren()).to.be.length(3);139 expect(await tokenB.getChildren()).to.be.length(0);108140109 // Transfer the nested token to another token141 // Transfer the nested token to another token110 await nestedNFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount());142 await nestedNFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount());111 await nestedRFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);143 await nestedRFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);112 await ftCollectionToBeNested.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);144 await ftCollectionToBeNested.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);145 await nativeFtCollectionToBeNested.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);113146114 expect(await nestedNFT.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});147 expect(await nestedNFT.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});115 expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenB.nestingAccount().toLowerCase());148 expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenB.nestingAccount().toLowerCase());120 expect(await ftCollectionToBeNested.getBalance(tokenB.nestingAccount())).to.equal(25n);153 expect(await ftCollectionToBeNested.getBalance(tokenB.nestingAccount())).to.equal(25n);121 expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(75n);154 expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(75n);155156 expect(await nativeFtCollectionToBeNested.getBalance(tokenB.nestingAccount())).to.equal(25n);157 expect(await nativeFtCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(75n);158159 // RFT, FT, and without native FT160 expect(await tokenA.getChildren()).to.be.length(2);161 // NFT, RFT, FT, and without native FT162 expect(await tokenB.getChildren()).to.be.length(3);122});163 });164});123165tests/src/sub/nesting/e2e.test.tsdiffbeforeafterboth32 const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});32 const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});33 const collectionB = await helper.ft.mintCollection(alice);33 const collectionB = await helper.ft.mintCollection(alice);34 const collectionC = await helper.rft.mintCollection(alice);34 const collectionC = await helper.rft.mintCollection(alice);35 const collectionNative = helper.ft.getCollectionObject(0);353636 const targetToken = await collectionA.mintToken(alice);37 const targetToken = await collectionA.mintToken(alice);37 expect((await targetToken.getChildren()).length).to.be.equal(0, 'Children length check at creation');38 expect((await targetToken.getChildren()).length).to.be.equal(0, 'Children length check at creation');73 {tokenId: tokenC.tokenId, collectionId: collectionC.collectionId},74 {tokenId: tokenC.tokenId, collectionId: collectionC.collectionId},74 ]).and.has.length(3);75 ]).and.has.length(3);7677 // Nest native fungible token into another collection78 await collectionNative.transfer(alice, targetToken.nestingAccount(), 2n);79 expect(await targetToken.getChildren()).to.have.deep.members([80 {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},81 {tokenId: 0, collectionId: collectionB.collectionId},82 {tokenId: tokenC.tokenId, collectionId: collectionC.collectionId},83 ]).and.has.length(3);758476 // Burn all nested pieces85 // Burn all nested pieces77 await tokenC.burnFrom(alice, targetToken.nestingAccount(), 2n);86 await tokenC.burnFrom(alice, targetToken.nestingAccount(), 2n);tests/src/sub/nesting/nesting.negative.test.tsdiffbeforeafterboth23let bob: IKeyringPair;23let bob: IKeyringPair;24let charlie: IKeyringPair;24let charlie: IKeyringPair;252526describe('Negative Test: Nesting', () => {26before(async () => {27 before(async () => {27 await usingPlaygrounds(async (helper, privateKey) => {28 await usingPlaygrounds(async (helper, privateKey) => {28 const donor = await privateKey({url: import.meta.url});29 const donor = await privateKey({url: import.meta.url});53 });54 });54});55 });555657 [58 {mode: 'ft'},59 {mode: 'nativeFt'},60 ].map(testCase => {56itSub('Owner cannot nest FT if nesting is disabled', async ({helper}) => {61 itSub(`Owner cannot nest [${testCase.mode}] if nesting is disabled (except for native fungible collection)`, async ({helper}) => {57 // Create default collection, permissions are not set:62 // Create default collection, permissions are not set:58 const aliceNFTCollection = await helper.nft.mintCollection(alice);63 const aliceNFTCollection = await helper.nft.mintCollection(alice);59 const targetToken = await aliceNFTCollection.mintToken(alice);64 const targetToken = await aliceNFTCollection.mintToken(alice);606561 const collectionForNesting = await helper.ft.mintCollection(alice);66 const collectionForNesting = testCase.mode === 'ft' ? await helper.ft.mintCollection(alice) : helper.ft.getCollectionObject(0);626763 // 1. Alice cannot create immediately nested tokens:68 // Alice cannot create immediately nested tokens:69 if (testCase.mode === 'ft') {64 await expect(collectionForNesting.mint(alice, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest');70 await expect(collectionForNesting.mint(alice, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest');71 } else {72 await expect(collectionForNesting.transfer(alice, targetToken.nestingAccount(), 100n)).to.be.not.rejected;73 }657466 // 2. Alice can mint and nest token:75 // Alice can't mint and nest tokens:76 if (testCase.mode === 'ft') {67 await collectionForNesting.mint(alice, 100n);77 await collectionForNesting.mint(alice, 100n);78 }7980 if (testCase.mode === 'ft') {68 await expect(collectionForNesting.transfer(alice, targetToken.nestingAccount(), 50n)).to.be.rejectedWith('common.UserIsNotAllowedToNest');81 await expect(collectionForNesting.transfer(alice, targetToken.nestingAccount(), 50n)).to.be.rejectedWith('common.UserIsNotAllowedToNest');82 } else {83 await expect(collectionForNesting.transfer(alice, targetToken.nestingAccount(), 50n)).to.be.not.rejected;84 }69});85 });86 });708771[88 [72 {mode: 'nft' as const},89 {mode: 'nft' as const},73 {mode: 'rft' as const},90 {mode: 'rft' as const},74 {mode: 'ft' as const},91 {mode: 'ft' as const},92 {mode: 'native ft' as const},75].map(testCase => {93 ].map(testCase => {76 itSub(`Non-owner and non-admin cannot nest ${testCase.mode.toUpperCase()} in someone else's tokens`, async ({helper}) => {94 itSub(`Non-owner and non-admin cannot nest ${testCase.mode.toUpperCase()} in someone else's tokens (except for native fungible collection)`, async ({helper}) => {77 const targetCollection = await helper.nft.mintCollection(alice, {permissions:95 const targetCollection = await helper.nft.mintCollection(alice, {permissions:78 {nesting: {tokenOwner: true, collectionAdmin: true}},96 {nesting: {tokenOwner: true, collectionAdmin: true}},79 });97 });80 const targetToken = await targetCollection.mintToken(alice);98 const targetToken = await targetCollection.mintToken(alice);819982 const nestedCollectionBob = await helper[testCase.mode].mintCollection(bob);100 const nestedCollectionBob = await (101 testCase.mode === 'native ft'102 ? helper.ft.getCollectionObject(0)103 : helper[testCase.mode].mintCollection(bob)104 );8310584 let nestedTokenBob: UniqueNFToken | UniqueRFToken;106 let nestedTokenBob: UniqueNFToken | UniqueRFToken;85 switch (testCase.mode) {107 switch (testCase.mode) {86 case 'nft': nestedTokenBob = await (nestedCollectionBob as UniqueNFTCollection).mintToken(bob); break;108 case 'nft': nestedTokenBob = await (nestedCollectionBob as UniqueNFTCollection).mintToken(bob); break;87 case 'rft': nestedTokenBob = await (nestedCollectionBob as UniqueRFTCollection).mintToken(bob, 100n); break;109 case 'rft': nestedTokenBob = await (nestedCollectionBob as UniqueRFTCollection).mintToken(bob, 100n); break;88 case 'ft': await (nestedCollectionBob as UniqueFTCollection).mint(bob, 100n); break;110 case 'ft': await (nestedCollectionBob as UniqueFTCollection).mint(bob, 100n); break;111 case 'native ft': await expect((nestedCollectionBob as UniqueFTCollection).mint(bob, 100n)).to.be.rejectedWith('common.UnsupportedOperation'); break;89 }112 }9011391 // Bob non-owner of targetToken and non admin of targetCollection, so114 // Bob non-owner of targetToken and non admin of targetCollection, so94 case 'nft': await expect((nestedCollectionBob as UniqueNFTCollection).mintToken(bob, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;117 case 'nft': await expect((nestedCollectionBob as UniqueNFTCollection).mintToken(bob, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;95 case 'rft': await expect((nestedCollectionBob as UniqueRFTCollection).mintToken(bob, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;118 case 'rft': await expect((nestedCollectionBob as UniqueRFTCollection).mintToken(bob, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;96 case 'ft': await expect((nestedCollectionBob as UniqueFTCollection).mint(bob, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;119 case 'ft': await expect((nestedCollectionBob as UniqueFTCollection).mint(bob, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;120 case 'native ft': await expect((nestedCollectionBob as UniqueFTCollection).mint(bob, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UnsupportedOperation'); break;97 }121 }9812299 // 2. cannot nest existing token:123 // 2. cannot nest existing token:100 switch (testCase.mode) {124 switch (testCase.mode) {101 case 'nft':125 case 'nft':102 case 'rft': await expect(nestedTokenBob!.transfer(bob, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;126 case 'rft': await expect(nestedTokenBob!.transfer(bob, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;103 case 'ft': await expect((nestedCollectionBob as UniqueFTCollection).transfer(bob, targetToken.nestingAccount(), 100n)).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;127 case 'ft': await expect((nestedCollectionBob as UniqueFTCollection).transfer(bob, targetToken.nestingAccount(), 100n)).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;128 case 'native ft': await expect((nestedCollectionBob as UniqueFTCollection).transfer(bob, targetToken.nestingAccount(), 100n)).to.be.not.rejected; break;104 }129 }105 });130 });106});131 });125 });150 });126});151 });127152128itSub.ifWithPallets('Cannot nest in non existing token', [Pallets.ReFungible], async ({helper}) => {153 itSub.ifWithPallets('Cannot nest in non existing token (except for native fungible collection)', [Pallets.ReFungible], async ({helper}) => {129 const collection = await helper.nft.mintCollection(alice);154 const collection = await helper.nft.mintCollection(alice);130 // To avoid UserIsNotAllowedToNest error155 // To avoid UserIsNotAllowedToNest error131 await helper.collection.setPermissions(alice, collection.collectionId, {nesting: {collectionAdmin: true}});156 await helper.collection.setPermissions(alice, collection.collectionId, {nesting: {collectionAdmin: true}});140 const nftCollectionForNesting = await helper.nft.mintCollection(alice);165 const nftCollectionForNesting = await helper.nft.mintCollection(alice);141 const rftCollectionForNesting = await helper.rft.mintCollection(alice);166 const rftCollectionForNesting = await helper.rft.mintCollection(alice);142 const ftCollectionForNesting = await helper.ft.mintCollection(alice);167 const ftCollectionForNesting = await helper.ft.mintCollection(alice);168 const nativeFtCollectionForNesting = helper.ft.getCollectionObject(0);143169144 const testCases = [170 const testCases = [145 {token: tokenFromNonExistingCollection, error: 'CollectionNotFound'},171 {token: tokenFromNonExistingCollection, error: 'CollectionNotFound'},160 await expect(nft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);186 await expect(nft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);161 await expect(rft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);187 await expect(rft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);162 await expect(ftCollectionForNesting.transfer(alice, testCase.token.nestingAccount(), 50n)).to.be.rejectedWith(testCase.error);188 await expect(ftCollectionForNesting.transfer(alice, testCase.token.nestingAccount(), 50n)).to.be.rejectedWith(testCase.error);189 await expect(nativeFtCollectionForNesting.transfer(alice, testCase.token.nestingAccount(), 50n)).to.be.not.rejected;163 }190 }164});191 });165192180 await expect(nft.transfer(alice, {Ethereum: futureCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');207 await expect(nft.transfer(alice, {Ethereum: futureCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');181});208 });182209183itEth.ifWithPallets('Cannot nest in RFT or FT', [Pallets.ReFungible], async ({helper}) => {210 itEth.ifWithPallets('Cannot nest in RFT or FT (except for native fungible collection)', [Pallets.ReFungible], async ({helper}) => {184 // Create default collection, permissions are not set:211 // Create default collection, permissions are not set:185 const rftCollection = await helper.rft.mintCollection(alice);212 const rftCollection = await helper.rft.mintCollection(alice);186 const ftCollection = await helper.ft.mintCollection(alice);213 const ftCollection = await helper.ft.mintCollection(alice);214 const nativeFtCollection = helper.ft.getCollectionObject(0);187215188 const rftToken = await rftCollection.mintToken(alice);216 const rftToken = await rftCollection.mintToken(alice);189 const _ftToken = await ftCollection.mint(alice, 100n);217 const _ftToken = await ftCollection.mint(alice, 100n);193 // 1. Alice cannot create immediately nested tokens:221 // 1. Alice cannot create immediately nested tokens:194 await expect(collectionForNesting.mintToken(alice, rftToken.nestingAccount())).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');222 await expect(collectionForNesting.mintToken(alice, rftToken.nestingAccount())).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');195 await expect(collectionForNesting.mintToken(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');223 await expect(collectionForNesting.mintToken(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');224 await expect(collectionForNesting.mintToken(alice, {Ethereum: helper.ethAddress.fromTokenId(nativeFtCollection.collectionId, 0)})).to.be.rejectedWith('common.UnsupportedOperation');196225197 // 2. Alice cannot mint and nest token:226 // 2. Alice cannot mint and nest token:198 const nestedToken2 = await collectionForNesting.mintToken(alice);227 const nestedToken2 = await collectionForNesting.mintToken(alice);199 await expect(nestedToken2.nest(alice, rftToken)).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');228 await expect(nestedToken2.nest(alice, rftToken)).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');200 await expect(ftCollection.transfer(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');229 await expect(ftCollection.transfer(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');230 await expect(nativeFtCollection.transfer(alice, {Ethereum: helper.ethAddress.fromTokenId(nativeFtCollection.collectionId, 0)})).to.be.not.rejected;201});231 });202232203itSub('Cannot nest in restricted collection if collection is not in the list', async ({helper}) => {233 itSub('Cannot nest in restricted collection if collection is not in the list (except native fungible collection)', async ({helper}) => {204 const {collectionId: allowedCollectionId} = await helper.nft.mintCollection(alice);234 const {collectionId: allowedCollectionId} = await helper.nft.mintCollection(alice);205 const notAllowedCollectionNFT = await helper.nft.mintCollection(alice);235 const notAllowedCollectionNFT = await helper.nft.mintCollection(alice);206 const notAllowedCollectionRFT = await helper.rft.mintCollection(alice);236 const notAllowedCollectionRFT = await helper.rft.mintCollection(alice);207 const notAllowedCollectionFT = await helper.ft.mintCollection(alice);237 const notAllowedCollectionFT = await helper.ft.mintCollection(alice);238 const allowedCollectionNativeFT = helper.ft.getCollectionObject(0);208239209 // Collection restricted to allowedCollectionId240 // Collection restricted to allowedCollectionId210 const restrictedCollectionA = await helper.nft.mintCollection(alice, {permissions:241 const restrictedCollectionA = await helper.nft.mintCollection(alice, {permissions:229 await expect(notAllowedCollectionRFT.mintToken(alice, 100n, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);260 await expect(notAllowedCollectionRFT.mintToken(alice, 100n, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);230 await expect(notAllowedCollectionFT.mint(alice, 100n, targetTokenA.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);261 await expect(notAllowedCollectionFT.mint(alice, 100n, targetTokenA.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);231 await expect(notAllowedCollectionFT.mint(alice, 100n, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);262 await expect(notAllowedCollectionFT.mint(alice, 100n, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);263 await expect(allowedCollectionNativeFT.transfer(alice, targetTokenA.nestingAccount(), 100n)).to.be.not.rejected;264 await expect(allowedCollectionNativeFT.transfer(alice, targetTokenB.nestingAccount(), 100n)).to.be.not.rejected;232});265 });233266234itSub('Cannot create nesting chains greater than 5', async ({helper}) => {267 itSub('Cannot create nesting chains greater than 5', async ({helper}) => {258 expect(await token.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});291 expect(await token.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});259 expect(await token.getChildren()).to.has.length(0);292 expect(await token.getChildren()).to.has.length(0);260});293 });294});261295tests/src/sub/nesting/refungible.test.tsdiffbeforeafterboth17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {expect, itSub, Pallets, usingPlaygrounds} from '../../util';18import {expect, itSub, Pallets, usingPlaygrounds} from '../../util';191920// ReFungible specific nesting tests20describe('ReFungible-specific nesting tests', () => {21let alice: IKeyringPair;21 let alice: IKeyringPair;222223before(async () => {23 before(async () => {585859 expect(await rft.getTopmostOwner()).deep.equal({Substrate: alice.address});59 expect(await rft.getTopmostOwner()).deep.equal({Substrate: alice.address});60});60 });61});6162tests/src/sub/nesting/unnesting.negative.test.tsdiffbeforeafterboth52 });52 });535354 [54 [55 {restrictedMode: true},55 {mode: 'ft' as const},56 {restrictedMode: false},56 {mode: 'native ft' as const},57 ].map(testCase => {57 ].map(md => [58 {mode: md.mode, restrictedMode: true},59 {mode: md.mode, restrictedMode: false},60 ].map(testCase => {58 itSub(`Fungible: disallows a non-Owner to unnest someone else's token ${testCase.restrictedMode ? '(Restricted nesting)' : ''}`, async ({helper}) => {61 itSub(`Fungible: disallows a non-Owner to unnest someone else's token [${testCase.mode}${testCase.restrictedMode ? ' (Restricted nesting)' : ''}]`, async ({helper}) => {59 const collectionNFT = await helper.nft.mintCollection(alice);62 const collectionNFT = await helper.nft.mintCollection(alice);60 const collectionFT = await helper.ft.mintCollection(alice);63 const collectionFT = await (64 testCase.mode === 'ft'65 ? helper.ft.mintCollection(alice)66 : helper.ft.getCollectionObject(0)67 );61 const targetToken = await collectionNFT.mintToken(alice, {Substrate: bob.address});68 const targetToken = await collectionNFT.mintToken(alice, {Substrate: bob.address});626963 await collectionNFT.setPermissions(alice, {nesting: {70 await collectionNFT.setPermissions(alice, {nesting: {64 collectionAdmin: true, tokenOwner: true, restricted: testCase.restrictedMode ? [collectionFT.collectionId] : null,71 collectionAdmin: true, tokenOwner: true, restricted: testCase.restrictedMode ? [collectionFT.collectionId] : null,65 }});72 }});667367 // Nest some tokens as Alice into Bob's token74 // Nest some tokens as Alice into Bob's token68 await collectionFT.mint(alice, 5n, targetToken.nestingAccount());75 await (76 testCase.mode === 'ft'77 ? collectionFT.mint(alice, 5n, targetToken.nestingAccount())78 : collectionFT.transfer(alice, targetToken.nestingAccount(), 5n)79 );698070 // Try to pull it out as Alice still81 // Try to pull it out as Alice still71 await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: bob.address}, 1n))82 await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: bob.address}, 1n))72 .to.be.rejectedWith(/common\.ApprovedValueTooLow/);83 .to.be.rejectedWith(/common\.ApprovedValueTooLow/);73 expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);84 expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);74 });85 });75 });86 }));76});87});7788tests/src/transfer.test.tsdiffbeforeafterboth17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itEth, usingEthPlaygrounds} from './eth/util';18import {itEth, usingEthPlaygrounds} from './eth/util';19import {itSub, Pallets, usingPlaygrounds, expect} from './util';19import {itSub, Pallets, usingPlaygrounds, expect} from './util';20import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';202121describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {22describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {22 let donor: IKeyringPair;23 let donor: IKeyringPair;124125125126126 itSub('[nft] Transfer with not existed collection_id', async ({helper}) => {127 itSub('[nft] Transfer with not existed collection_id', async ({helper}) => {127 const collectionId = (1 << 32) - 1;128 await expect(helper.nft.transferToken(alice, collectionId, 1, {Substrate: bob.address}))128 await expect(helper.nft.transferToken(alice, NON_EXISTENT_COLLECTION_ID, 1, {Substrate: bob.address}))129 .to.be.rejectedWith(/common\.CollectionNotFound/);129 .to.be.rejectedWith(/common\.CollectionNotFound/);130 });130 });131131132 itSub('[fungible] Transfer with not existed collection_id', async ({helper}) => {132 itSub('[fungible] Transfer with not existed collection_id', async ({helper}) => {133 const collectionId = (1 << 32) - 1;134 await expect(helper.ft.transfer(alice, collectionId, {Substrate: bob.address}))133 await expect(helper.ft.transfer(alice, NON_EXISTENT_COLLECTION_ID, {Substrate: bob.address}))135 .to.be.rejectedWith(/common\.CollectionNotFound/);134 .to.be.rejectedWith(/common\.CollectionNotFound/);136 });135 });137136138 itSub.ifWithPallets('[refungible] Transfer with not existed collection_id', [Pallets.ReFungible], async ({helper}) => {137 itSub.ifWithPallets('[refungible] Transfer with not existed collection_id', [Pallets.ReFungible], async ({helper}) => {139 const collectionId = (1 << 32) - 1;140 await expect(helper.rft.transferToken(alice, collectionId, 1, {Substrate: bob.address}))138 await expect(helper.rft.transferToken(alice, NON_EXISTENT_COLLECTION_ID, 1, {Substrate: bob.address}))141 .to.be.rejectedWith(/common\.CollectionNotFound/);139 .to.be.rejectedWith(/common\.CollectionNotFound/);142 });140 });143141tests/src/transferFrom.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itSub, Pallets, usingPlaygrounds, expect} from './util';18import {itSub, Pallets, usingPlaygrounds, expect} from './util';19import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';192020describe('Integration Test transferFrom(from, recipient, collection_id, item_id, value):', () => {21describe('Integration Test transferFrom(from, recipient, collection_id, item_id, value):', () => {21 let alice: IKeyringPair;22 let alice: IKeyringPair;97 });98 });989999 itSub('transferFrom for a collection that does not exist', async ({helper}) => {100 itSub('transferFrom for a collection that does not exist', async ({helper}) => {100 const collectionId = (1 << 32) - 1;101 await expect(helper.collection.approveToken(alice, collectionId, 0, {Substrate: bob.address}, 1n))101 await expect(helper.collection.approveToken(alice, NON_EXISTENT_COLLECTION_ID, 0, {Substrate: bob.address}, 1n))102 .to.be.rejectedWith(/common\.CollectionNotFound/);102 .to.be.rejectedWith(/common\.CollectionNotFound/);103 await expect(helper.collection.transferTokenFrom(bob, collectionId, 0, {Substrate: alice.address}, {Substrate: bob.address}, 1n))103 await expect(helper.collection.transferTokenFrom(bob, NON_EXISTENT_COLLECTION_ID, 0, {Substrate: alice.address}, {Substrate: bob.address}, 1n))104 .to.be.rejectedWith(/common\.CollectionNotFound/);104 .to.be.rejectedWith(/common\.CollectionNotFound/);105 });105 });106106tests/src/util/playgrounds/types.tsdiffbeforeafterboth334import {IKeyringPair} from '@polkadot/types/types';4import {IKeyringPair} from '@polkadot/types/types';56export const NON_EXISTENT_COLLECTION_ID = 4_294_967_295;576export interface IEvent {8export interface IEvent {7 section: string;9 section: string;tests/src/util/playgrounds/unique.tsdiffbeforeafterboth778import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';8import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';9import {SignerOptions} from '@polkadot/api/types/submittable';9import {SignerOptions} from '@polkadot/api/types/submittable';10import '../../interfaces/augment-api-tx';10import '../../interfaces/augment-api';11import {AugmentedSubmittables} from '@polkadot/api-base/types/submittable';11import {AugmentedSubmittables} from '@polkadot/api-base/types/submittable';12import {RpcInterface} from '@polkadot/rpc-core/types';13import {QueryableStorage} from '@polkadot/api-base/types/storage';14import {DecoratedRpc} from '@polkadot/api-base/types/rpc';15import {ApiInterfaceEvents} from '@polkadot/api/types';12import {ApiInterfaceEvents} from '@polkadot/api/types';16import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';13import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';17import {IKeyringPair} from '@polkadot/types/types';14import {IKeyringPair} from '@polkadot/types/types';50} from './types';47} from './types';51import {RuntimeDispatchInfo} from '@polkadot/types/interfaces';48import {RuntimeDispatchInfo} from '@polkadot/types/interfaces';52import type {Vec} from '@polkadot/types-codec';49import type {Vec} from '@polkadot/types-codec';53import {FrameSystemEventRecord} from '@polkadot/types/lookup';50import {FrameSystemEventRecord, PalletBalancesIdAmount} from '@polkadot/types/lookup';545155export class CrossAccountId {52export class CrossAccountId {56 Substrate!: TSubstrateAccount;53 Substrate!: TSubstrateAccount;379type Get2<T, P extends string, E> =376type Get2<T, P extends string, E> =380 P extends `${infer Key}.${infer Key2}` ? Key extends keyof T ? Key2 extends keyof T[Key] ? T[Key][Key2] : E : E : E;377 P extends `${infer Key}.${infer Key2}` ? Key extends keyof T ? Key2 extends keyof T[Key] ? T[Key][Key2] : E : E : E;381type ForceFunction<T> = T extends (...args: any) => any ? T : (...args: any) => Invalid<'not a function'>;378type ForceFunction<T> = T extends (...args: any) => any ? T : (...args: any) => Invalid<'not a function'>;382type ReturnTypeWithArgs<T extends (...args: any[]) => any, ARGS_T> =383 Extract<384 T extends { (...args: infer A1): infer R1; (...args: infer A2): infer R2; (...args: infer A3): infer R3; (...args: infer A4): infer R4; } ? [A1, R1] | [A2, R2] | [A3, R3] | [A4, R4] :385 T extends { (...args: infer A1): infer R1; (...args: infer A2): infer R2; (...args: infer A3): infer R3; } ? [A1, R1] | [A2, R2] | [A3, R3] :386 T extends { (...args: infer A1): infer R1; (...args: infer A2): infer R2; } ? [A1, R1] | [A2, R2] :387 T extends { (...args: infer A1): infer R1; } ? [A1, R1] :388 never,389 [ARGS_T, any]390 >[1]391379392export class ChainHelperBase {380export class ChainHelperBase {393 helperBase: any;381 helperBase: any;498486499 if (xcmChains.indexOf(spec.specName) > -1) return spec.specName;487 if (xcmChains.indexOf(spec.specName) > -1) return spec.specName;500488501 if (['quartz', 'unique'].indexOf(spec.specName) > -1) return spec.specName;489 if (['quartz', 'unique', 'sapphire'].indexOf(spec.specName) > -1) return spec.specName;502 return 'opal';490 return 'opal';503 }491 }5044921756 children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId, blockHashAt]);1744 children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId, blockHashAt]);1757 }1745 }175817461759 return children.toJSON().map((x: any) => {1747 return children.toJSON().map((x: any) => ({collectionId: x.collection, tokenId: x.token}));1760 return {collectionId: x.collection, tokenId: x.token};1761 });1762 }1748 }176317492400 return {free: accountInfo.free.toBigInt(), frozen: accountInfo.frozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};2386 return {free: accountInfo.free.toBigInt(), frozen: accountInfo.frozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};2401 }2387 }23882389 /**2390 * Get total issuance2391 * @returns2392 */2393 async getTotalIssuance(): Promise<bigint> {2394 const total = (await this.helper.callRpc('api.query.balances.totalIssuance', []));2395 return total.toBigInt();2396 }240223972403 async getLocked(address: TSubstrateAccount): Promise<[{ id: string, amount: bigint, reason: string }]> {2398 async getLocked(address: TSubstrateAccount): Promise<[{ id: string, amount: bigint, reason: string }]> {2404 const locks = (await this.helper.callRpc('api.query.balances.locks', [address])).toHuman();2399 const locks = (await this.helper.callRpc('api.query.balances.locks', [address])).toHuman();2405 return locks.map((lock: any) => { return {id: lock.id, amount: BigInt(lock.amount.replace(/,/g, '')), reasons: lock.reasons}; });2400 return locks.map((lock: any) => ({id: lock.id, amount: BigInt(lock.amount.replace(/,/g, '')), reasons: lock.reasons}));2406 }2401 }24072408 async getFrozen(address: TSubstrateAccount): Promise<[{ id: string, amount: bigint}]> {2402 async getFrozen(address: TSubstrateAccount): Promise<{ id: string, amount: bigint }[]> {2409 const locks = (await this.helper.callRpc('api.query.balances.freezes', [address])).toHuman();2403 const locks = await this.helper.api!.query.balances.freezes(address);2410 return locks.map((lock: any) => { return {id: lock.id, amount: BigInt(lock.amount.replace(/,/g, ''))}; });2404 return locks.map(lock => ({id: lock.id.toString(), amount: lock.amount.toBigInt()}));2411 }2405 }2412}2406}241324072492 return this.subBalanceGroup.getSubstrateFull(address);2486 return this.subBalanceGroup.getSubstrateFull(address);2493 }2487 }24882489 /**2490 * Get total issuance2491 * @returns2492 */2493 getTotalIssuance(): Promise<bigint> {2494 return this.subBalanceGroup.getTotalIssuance();2495 }249424962495 /**2497 /**2496 * Get locked balances2498 * Get locked balances2497 * @param address substrate address2499 * @param address substrate address2498 * @returns locked balances with reason via api.query.balances.locks2500 * @returns locked balances with reason via api.query.balances.locks2499 */2501 * @deprecated all the methods should switch to getFrozen2502 */2500 getLocked(address: TSubstrateAccount) {2503 getLocked(address: TSubstrateAccount) {2501 return this.subBalanceGroup.getLocked(address);2504 return this.subBalanceGroup.getLocked(address);2502 }2505 }tests/src/vesting.test.tsdiffbeforeafterboth103 expect(balanceSender.reserved).to.eq(0n);103 expect(balanceSender.reserved).to.eq(0n);104 });104 });105105106 itSub.only('cannot send more tokens than have', async ({helper}) => {106 itSub('cannot send more tokens than have', async ({helper}) => {107 const [sender, receiver] = await helper.arrange.createAccounts([1000n, 1n], donor);107 const [sender, receiver] = await helper.arrange.createAccounts([1000n, 1n], donor);108 const schedule = {start: 0n, period: 1n, periodCount: 1n, perPeriod: 100n * nominal};108 const schedule = {start: 0n, period: 1n, periodCount: 1n, perPeriod: 100n * nominal};109 const manyPeriodsSchedule = {start: 0n, period: 1n, periodCount: 100n, perPeriod: 10n * nominal};109 const manyPeriodsSchedule = {start: 0n, period: 1n, periodCount: 100n, perPeriod: 10n * nominal};